环境
复制 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
层
找到 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
相关的堆栈
我们尝试 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
层
使用 objection
进行分析, 先列出所有的模块看看
复制 objection -g com.alibaba.aliexpresshd explore