1,抓包
Charles+Postern
2,搜索sign,搜索结果太多了。换个关键词,s_locale,就两个。最后定位到
com.xxxxxxi.okretro.f.a
先看d()方法
最后会走到native s()
再看c()
最后同样会走到
frida hook一下
var LibBili=Java.use("com.xxxxx.nativelibrary.Libxxx");
var treemap=Java.use("java.util.TreeMap")
LibBili.s.implementation=function(map){
console.log("com.xxxxx.nativelibrary.Libxxx map==>",treemap.$new(map))
var retval=this.s(map)
console.log("com.xxxxx.nativelibrary.Libxxx retval==>",retval)
return retval
}
打印结果:
// com.xxxxx.nativelibrary.Lixxx map==> {aid=799065621, appkey=1d8b6e7d45233436, build=6180500, c_locale=zh-Hans_CN, channel=shenma069, cid=292549658, mobi_app=android, platform=android, s_locale=zh-Hans_CN, statistics={"appId":1,"platform":3,"version":"6.18.0","abtest":""}}
// com.xxxxx.nativelibrary.Lxxxx retval==> aid=799065621&appkey=1d8b6e7d45233436&build=6180500&c_locale=zh-Hans_CN&channel=shenma069&cid=292549658&mobi_app=android&platform=android&s_locale=zh-Hans_CN&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.18.0%22%2C%22abtest%22%3A%22%22%7D&ts=1657861030&sign=a52cd09b0a83f96daa5d0c0125151804
很显然sign已经出来了。
咱们先主动调用一下native s(),这样方便 调式,不用点击机器了
function invoke(){
Java.perform(function(){
var treemap=Java.use("java.util.TreeMap")
var LibBili=Java.use("com.xxxxxx.nativelibrary.Libxxxx");
var map=treemap.$new()
map.put("aid", "728305240");
map.put("appkey", "1d8b6e7d45233436");
map.put("autoplay_card","11");
map.put("banner_hash","10687342131252771522");
map.put("build","6180500");
map.put("c_locale","zh-Hans_CN");
map.put("channel","shenma069");
map.put("cid","292549658");
map.put("mobi_app","android");
map.put("device_type","0");
map.put("flush","6");
console.log(map)
var sign=LibBili.s(map)
console.log("invoke sign ==>",sign)
})
}
2,so文件分析
打开ida,导出表,没有这个方法,动态注册,hook RegisterNatives
如果感觉看起来比较多,可以修改一下源码,加一个判断就可以了。
if(class_name.indexOf("com.xxxxx.nativelibrary.LibBili")>=0)
hook的时候后面加-o xxxx.txt。可以把保存日志
frida -U -f tv.xxxx.xxx -l hook_RegisterNatives.js --no-pause -o registerNatives.txt
[RegisterNatives] java_class: com.xxxxx.nativelibrary.LibBili name: s sig: (Ljava/util/SortedMap;)Lcom/bilibili/nativelibrary/SignedQuery; fnPtr: 0xbc753c97 fnOffset: 0x1c97 callee: 0xbc753b8f libbili.so!JNI_OnLoad+0x66
知道偏移地址offset=0x1c97
在ida中按G 跳转
进入sub_2F88
按Y修改sub_2F88
然后往下看
sub_6680是个JNI调用是CallBooleanMethod。调用java中的方法返回布尔型在native中转换为jboolean
hook一下 主动调用算法。返回0。
var sub_2F88=addr.add(0x2F88+1)
Interceptor.attach(sub_2F88,{
onEnter:function(args){
},onLeave:function(retval){
console.log("sub_2F88 onLeave:",ptr(retval))
}
})
然后进入sub_3414();
继续往下
调用的该类的r()方法
就是将map转为&连接的字符串
接着往下看
hook sub_22B0()
//sub_22B0
var sub_22B0=addr.add(0x22B0+1)
Interceptor.attach(sub_22B0,{
onEnter:function(args){
console.log("0x22B0 onEnter:",hexdump(args[1], {length: args[2].toInt32()}));
console.log("\n0x22B0 Length:"+args[2]);
},onLeave:function(retval){
console.log("0x22B0 onLeave:",ptr(retval))
}
})
算法还原
sub_22B0()也就是MD5 会被调用7次
分别在
多次调用算法,发现这四个数据块时固定的,参数和四个数据块拼接到一起MD5
最后5次MD5拼接到一起,就是sign
aid=728305240&appkey=1d8b6e7d45233436&autoplay_card=11&banner_hash=10687342131252771522&build=6180500&c_locale=zh-Hans_CN&channel=shenma069&cid=292549658&device_type=0&flush=6&mobi_app=android&ts=1657877030&sign=71739fc69a301b43ad920e2820e97b31
入参:aid=728305240&appkey=1d8b6e7d45233436&autoplay_card=11&banner_hash=10687342131252771522&build=6180500&c_locale=zh-Hans_CN&channel=shenma069&cid=292549658&device_type=0&flush=6&mobi_app=android&ts=1657877030
还原完成