1,抓包? 使用Charles+postern? 代理抓包
签名是sign。
2,反编译app 搜索,最后定位到getSignFromJni()
?3.开始分析getSignFromJni()方法的入参,顺便打印一下调用栈
var getsign=Java.use("com.jixxxxxx.common.utils.BitmapkitUtils")
console.log("getSignFromJni Start Hook")
getsign.getSignFromJni.overload('android.content.Context', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation=function(context,str,str1,str2,str3,str4){
printStack();
console.log("getSignFromJni-->"+"str-->",str+"\n","str1-->",str1+"\n","str2-->",str2+"\n","str3-->",str3+"\n","str4-->",str4+"\n")
var ret=this.getSignFromJni(a,b,c,d,e,f);
console.log("getSignFromJni reture sign-->"+ret)
return ret;
}
这里启动frida 需要改端口。里面有端口检测。
./fri1280x64 -l 127.0.0.1:8989
adb forward tcp:8989 tcp:8989
frida -H 127.0.0.1:8989 com.xxxxx.app.mall -l hook.js
端口改好,attach模式注入。自动退出了,新版本增加检测位置了。
var strStr = Module.findExportByName("libc.so", "strstr");
console.log("[*] strstr addr: " + strStr);
Interceptor.attach(strStr,{
onEnter: function(args){
// console.log("[*] strstr hooked");
var arg0= ptr(args[0]).readCString();
var arg1= ptr(args[1]).readCString();
if(arg1.indexOf(":69A2")>=0){
console.log("[*] strstr 69A2 hooked"+arg0+","+arg1+")");
this.a2=false
}
if(arg1.indexOf("libfrida")>=0){
console.log("[*] strstr LIBFRIDA hooked"+arg0+","+arg1+")");
this.LIBFRIDA = true;
}
if(arg1.indexOf("frida")>=0){
console.log("[*] strstr frida hooked"+arg0+","+arg1+")");
this.frida = true;
}
},
onLeave: function(retval){
if(this.a2){
//console.log("[*] a2 hooked"+retval);
retval.replace(0x0);
}
if(this.libfrida){
// console.log("[*] the libfrida result: "+retval);
retval.replace(0x0)
}
if(this.frida){
// console.log("[*] the frida result: "+retval);
retval.replace(0x0)
}
}
});
可以了。再次注入。又退出了。再次尝试spawn注入。停在了欢迎页面。
清空数据。重新用spawn模式启动。ok注入成功
str--> discZdmGoodsList
str1--> {"channel":"worthbuy","page":2,"pageSize":15,"params":{"channel":"home","innerIndex":1,"innerLink":"[{\"rt\":\"12\",\"innerAnchor\":\"100006596471\",\"innerExtId\":\"240055399\"},{\"rt\":\"12\",\"innerAnchor\":\"1317235\",\"innerExtId\":\"233288758\"}]","innerSkuImgUrl":"https://m15.360buyimg.com/mobilecms/s240x240_jfs/t1/152660/32/5527/308643/5fac974fEe5190adc/ca601ac93b46f4f1.jpg!q70.jpg.dpg.webp"},"subPosition":-1,"tabId":"229","type":"goods"}
str2--> 2fa58c61aa871a37
str3--> android
str4--> 10.3.2
str:url路径
str1:请求body信息
str2:2fa58c61aa871a37 UUID com.jixxxxx.common.utils.DeviceInfoHelper.getInstallationId()
str3:android 为平台
str4:版本号
?调用栈,frida hook?com.jingdong.jdsdk.network.toolbox.l.a(),看下
=============================Stack strat=======================
com.jixxxxxx.common.utils.BitmapkitUtils.getSignFromJni(Native Method)
com.jixxxxxx.common.network.JDNetworkDependencyFactory$3.signature(JDNetworkDependencyFactory.java:190)
com.jixxxxxx.jdsdk.network.toolbox.l.a(HttpSettingTool.java:540)
com.jixxxxxx.jdsdk.network.toolbox.l.a(Native Method)
com.jixxxxxx.jdsdk.network.toolbox.l.b(HttpSettingTool.java:100)
com.jixxxxxx.jdsdk.network.toolbox.l.a(HttpSettingTool.java:60)
com.jixxxxxx.jdsdk.network.toolbox.HttpGroupAdapter$RequestTask.run(HttpGroupAdapter.java:170)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
java.lang.Thread.run(Thread.java:764)
=============================Stack end=======================
?这个类是动态加载,又两种方法,遍历类加载器,和遍历类。
Java.enumerateLoadedClasses({
"onMatch": function(name, handle) {
if (name.indexOf("com.jixxxxxx.jdsdk.network.toolbox.l") >= 0 ) {
console.log(name);
var BitmapkitUtils = Java.use(name);
BitmapkitUtils.a.overload('com.jixxxxxx.jdsdk.network.toolbox.HttpSetting', 'java.lang.String', 'java.lang.String').implementation = function (d,b,c) {
console.log("BitmapkitUtils-->", "context",d+"\n","str2",b+"\n","str3",c);
return this.a(d,b,c);
};
BitmapkitUtils.c .overload('com.jixxxxxx.jdsdk.network.toolbox.HttpSetting').implementation=function(HttpSetting){
var retval=this.c(HttpSetting)
console.log("ret boby ==>",retval)
return retval;
};
}
},
"onComplete": function() {
console.log("success");
}
})
4,分析JNI
getSignFromJni()->
?静态注册;
sub_1261C()是对拼接完成后进行字节码处理,
?
?进入sub_126AC,
?通过生成的随机数来控制生成不同的签名算法,hook native时有检测。?
v14=密钥,v18=1,v17=input,_en_input_len
?进入算法位置
?接着往下看,
sub_18B8
?是Base64
sub_227C
MD5的常量
大致流程:?
?字符串拼接---->sub_126AC---->sub_126AC---->sub_18B8---->sub_227C---->sign
|