3.2 AliExpress
环境
com.alibaba.aliexpresshd = 8.62.2
分析
不多 BB,直接开始 hook
,首先我们观察到 x-mini-wua
是在 headers
的,那么就直接先 hook hashMap
的 put
方法尝试一下
// 获取 Java 的 HashMap
var linkerHashMap = Java.use('java.util.HashMap');
// 重载 put 方法
linkerHashMap.put.implementation = function (key, value) {
if (key == "x-mini-wua") {
console.log("find key: ", value);
// 打印一下堆栈
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
// console.log("key => ", key, " value => ", value)
return this.put(key, value);
}

输出了超级多的堆栈,我们需要逐一分析,这边不做详细的介绍了,都是看这个堆栈慢慢找的,指明两个关键堆栈:
java
层
java
层找到
com.alibaba.aliexpress.gundam.ocean.netscene.GdmOceanNetScene.request
发现
GdmOceanNetScene
这个类里面就有一个getMiniWua
的方法,点进去就可以看到关键的获取代码为:GdmSecurityGuardUtil.h(ApplicationContext.c());
ApplicationContext.c()
是一个android.Context.context
对象,这个有通用的获取方法
RPC
代码如下:
function getWua() {
let result = ""
Java.perform(() => {
var current_application = Java.use('android.app.ActivityThread').currentApplication();
var context = current_application.getApplicationContext();
let GdmSecurityGuardUtil = Java.use("com.alibaba.aliexpress.gundam.ocean.GdmSecurityGuardUtil");
result = GdmSecurityGuardUtil["h"](context)
})
return result
}
尝试获取对比一下,发现没问题(这里还有一个地方有类似的函数,但是那个获取到的是错误的,长度要长很多,所以要注意)

JNI
层
JNI
层通过分析好几个请求会发现,里面有些调用直接输出了 JNI
相关的堆栈

我们尝试 hook
这个 com.taobao.wireless.security.adapter.JNICLibrary.doCommandNative
(因为不知道参数是啥,所以先直接 hook
一下,再根据报错补充参数等等)
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary.doCommandNative');
JNICLibrary.doCommandNative.implementation = () => {
}
但是发现他居然报这个错:java.lang.ClassNotFoundException

这个原因我分析是因为这个函数使用的不是当前的 classLoader
, 所以找不到,所以他肯定是在其他的 so
文件里面,那么我们应该怎么找到这个 so
文件呢?可以使用一下思路:
遍历所有的方法,输出包含特征值的 ClassLoader
const groups = Java.enumerateMethods('*JNICLibrary*!doCommandNative*')
for (let index = 0; index < groups.length; index++) {
const element = groups[index];
console.log("loader=> ", element.loader.toString())
}

发现居然什么都没有输出,这个可能是因为他并没有在一开始就加载,因为我们使用的是 spawn
模式,hook
的太早了,没有关系,我们可以随便修改一下 js
文件保存,那么就会重新 hook
了,这样肯定在加载之后!

果然直接就输出来了,通过输出我们可以看到,so
文件的名字是:libsgmain.so
接下来我们就可以根据这个 so
文件来 hook
这个方法啦!

hook
到了,接下来看看报错,根据报错补充完整参数!

// com.alibaba.aliexpresshd
// com.taobao.wireless.security.adapter.JNICLibrary.doCommandNative
// frida -U -f com.alibaba.aliexpresshd -l aliexpress.js
function main() {
Java.perform(() => {
// 遍历所有的 class loader -> 切换 class loader 为 libsgmain.so
Java.enumerateClassLoaders({
"onMatch": function (loader) {
// 当这个 loader 包含我们的 so 文件时, 进入
if (loader.toString().indexOf("libsgmain.so") >= 0) {
// 将当前class factory中的loader指定为我们需要的
Java.classFactory.loader = loader;
console.log("loader = ", loader.toString());
}
},
"onComplete": function () {
console.log("switch success");
}
}
);
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary');
JNICLibrary.doCommandNative.overload('int', '[Ljava.lang.Object;').implementation = function (a, b) {
console.log("=======================================")
console.log(`a=> ${a}, b=> ${b}`)
let ret = this.doCommandNative(a, b)
console.log(`ret => ${ret}\n\n`)
return ret
}
})
}
setTimeout(main, 2000)
发现直接找到了获取 wua
的地方,并且参数也超级简单,而且都是固定的

并且还有意外之喜,发现 x-sign
之类的加密参数都可以直接拿到

回到 getWua
,发现第一个参数固定是 20102
, 第二个是一个 array
, 元素内容为:
["", "", 8, "", "", 0]
, 直接尝试主动调用发现居然报错了,应该是类型的问题,所以构造一下:

function getWuaJni() {
var ret = ""
Java.perform(() => {
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary');
let String = Java.use("java.lang.String")
let Integer = Java.use("java.lang.Integer")
let a = 20102
let b = Java.array("Ljava.lang.Object;", [String.$new(),String.$new(), Integer.$new(8), String.$new(), String.$new(), Integer.$new(0)]);
ret = JNICLibrary.doCommandNative(a, b)
})
return ret.toString()
}

x-sign
分析方法应该和这个也是类似的,这边不做过多解释与操作了!
So
层
So
层使用 objection
进行分析, 先列出所有的模块看看
objection -g com.alibaba.aliexpresshd explore

最后更新于
这有帮助吗?