一、目标
今天的目标是这个sign和appcode
二、步骤
Jadx没法上了
app加了某梆的企业版,Jadx表示无能为力了。
FRIDA-DEXDump
DexDump出来,木有找到有效的信息。
Wallbreaker
葫芦娃的Wallbreaker可以做些带壳分析,不过这个样本,用Frida的Spawn模式可以载入,Attach模式会失败。而直接用Objection确无法载入。导致用不了Wallbreaker。
r0tracer
今天的新朋友是肉丝大佬的 r0tracer
https://github.com/r0ysue/r0tracer
r0tracer可以根据黑白名单批量追踪类的所有方法。 我们来尝试追踪一下包含 sign 的类或者方法
function main() {
Java.perform(function () {
console.Purple("r0tracer begin ... !")
/*
//以下三种模式,取消注释某一行以开启
*/
//A. 简易trace单个函数
// traceClass("javax.crypto.Cipher")
//B. 黑白名单trace多个函数,第一个参数是白名单(包含关键字),第二个参数是黑名单(不包含的关键字)
// hook("javax.crypto.Cipher", "$");
hook("sign", "$");
//C. 报某个类找不到时,将某个类名填写到第三个参数,比如找不到com.roysue.check类。(前两个参数依旧是黑白名单)
// hook("com.roysue.check"," ","com.roysue.check");
})
}
Spawn模式启动App
$ frida -U -f com.platexx.boxxoota -l r0tracer.js --no-pause -o saveLog1.txt
输出
Spawned `com.platexx.boxxoota`. Resuming main thread!
[MI NOTE Pro::com.platexx.boxxoota]-> r0tracer begin ... !
start
Begin Search Class...
Found Class =>
Tracing Method : com.wxxotel.app.service.signservice.OpenSignService.execute [1 overload(s)]
Tracing Method : com.wxxotel.app.service.signservice.OpenSignService.getPath [1 overload(s)]
Tracing Method : com.wxxotel.app.service.signservice.OpenSignService.$init [1 overload(s)]
木有啥有用的信息,咱们换个 试试 Sign
输出,然后,然后就挂了……
Spawned `com.platexx.boxxoota`. Resuming main thread!
[MI NOTE Pro::com.platexx.boxxoota]-> r0tracer begin ... !
start
Begin Search Class...
Found Class =>
Tracing Method : libcore.reflect.GenericSignatureParser.isStopSymbol [1 overload(s)]
Tracing Method : libcore.reflect.GenericSignatureParser.expect [1 overload(s)]
Tracing Method : libcore.reflect.GenericSignatureParser.parseClassSignature [1 overload(s)]
Tracing Method : libcore.reflect.GenericSignatureParser.parseClassTypeSignature [1 overload(s)]
Tracing Method : libcore.reflect.GenericSignatureParser.parseFieldTypeSignature [1 overload(s)]
Tracing Method : libcore.reflect.GenericSignatureParser.parseForClass [1 overload(s)]
这个 libcore.XXXX类,一看就不像是咱们的菜,过滤掉它再试试。
hook("Sign", "libcore");
啊哈,这下看上去很拉风的样,貌似有戏。
翻了翻输出,
com.besxxxhotel.app.whnetcomponent.utils.SignUtil.getAppCode [1 overload(s)]
com.besxxxhotel.app.whnetcomponent.utils.SignUtil.getSignString [1 overload(s)]
这两兄弟相当可疑,我们这次追踪下 SignUtil
hook("SignUtil", "$");
*** entered com.platexx.boxxoota.app.whnetcomponent.utils.SignUtil.getSignString
arg[0]: 0 => "0"
arg[1]: vadjlr4k3o;qj4io23ug9034uji5rjn34io5u83490u5903huq => "vadjlr4k3o;qj4io23ug9034uji5rjn34io5u83490u5903huq"
arg[2]: 00000000-7e21-1806-0000-00000033c587 => "00000000-7e21-1806-0000-00000033c587"
arg[3]: 1622430128929 => "1622430128929"
arg[4]: 0,0 => "0,0"
arg[5]: 6698 => "6698"
java.lang.Throwable
at com.besxxxhotel.app.whnetcomponent.utils.SignUtil.getSignString(Native Method)
at com.besxxxhotel.app.whnetcomponent.net.JJSignInterceptor.handlerRequest(JJSignInterceptor.java:114)
at com.besxxxhotel.app.whnetcomponent.net.JJSignInterceptor.intercept(JJSignInterceptor.java:38)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:147)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:760)
========================================================================================================================================================================================================
retval: C5F29B0EF472EDA271313155307E8077 => "C5F29B0EF472EDA271313155307E8077"
*** exiting com.besxxxhotel.app.whnetcomponent.utils.SignUtil.getSignString
- 参数 0 1 是固定值
- 参数 2 应该是 did
- 参数 3 是当前时间戳
- 参数 4 也是固定值
- 参数 5 就比较奇怪了, 在日志里面搜索一下,发现 5是 函数 decodeASCII 的返回值, 它的入参是一个 java.util.Map。
在117行微调一下,打印下这个map
var strType = JSON.stringify(arguments[j]);
// console.log(strType);
if(strType.indexOf('HashMap') > 0){
console.log(arguments[j].entrySet().toArray());
}
就知道是本次请求的内容。
systemVersion=7.0,sid=306267,userId=0,clientVersion=5.2.9,deviceType=MI NOTE Pro,did=174670d6754469115964f1387aed0a96,appId=105,deviceCode=,os=android
搞定,收工……
三、总结
趁手的工具多搞几个,技多不压身。
r0tracer的名称过滤,搞成正则表达式会不会更帅?
壳还是要搞一下的,如果把壳脱了,这个App就没啥难度了。
当你走上了不一样的道路,你才有可能看到和别人不一样的风景
关注微信公众号,最新技术干货实时推送