首先抓包请出今天的受害者
打开jadx 全局搜发现搜不到,最后定位到服务器接口返回
定位到请求的地方
打开chales抓到接口
需要逆向的有2个,1个p参数,还有data的里面的参数,查看引用定位到
通过调用_u函数最终定位到这2个字段返回的加密结果,
看来是so返回的,这里都是native函数,直接用yang神大佬的脚本hook_registerNatives.js搜索_u函数
https://github.com/lasting-yang/frida_hook_libart
定位到libj.so
查看这个v8引用dword_FB744
通过反射java字段返回结果,直接进入generateDF加密函数
这日志打印的一目了然啊,为咱们分析省下不少功夫,既然找到了目标函数,直接上unidbg调用分析算法
报错缺少类初始化,补上
后面缺字段,同样的道理,缺啥补啥,最终成功
获取2个字段的值,当然咱们不止调用这么简单,目的是分析算法,回过头看代码, 先静态分析一波,从打印的日志可以看出先生成key然后keyMd5加密,然后再进行aes16进制加密 最后rsa加密返回,先看key值是怎么生成的
调用h9函数
随机的时间戳,可以看出动态的key值,再往下看进行md5加密key值
f8就是md5加密直接hook这个函数,因为这是c++的std不能直接打印参数,用到了下面封装好的2个函数获取std的参数
public String readStdString(Pointer strptr) {
Boolean isTiny = (strptr.getByte(0) & 1) == 0;
if (isTiny) {
return strptr.getString(1);
}
return strptr.getPointer(emulator.getPointerSize() * 2L).getString(0);
};
public void writeStdString(Pointer strptr, String content){
Boolean isTiny = (strptr.getByte(0) & 1) == 0;
if(isTiny){
strptr.write(1, content.getBytes(StandardCharsets.UTF_8), 0, content.length());
}
strptr.getPointer(emulator.getPointerSize()* 2L).write(0, content.getBytes(StandardCharsets.UTF_8), 0, content.length());
};
打印结果
因为key是动态生成的,不利于我们分析,直接hook generateKey函数使他返回固定的key值
接下来再看aes部分
v44是md5后的结果,h14是aes加密,从91,92行可以看出将md5后的结果前16字节和后16字节分别传入aes加密函数,a1是我们传的参数,v47是md5前16,v48是后16,进入h14函数
我们传的就是16字节,这个判断告诉我们加密模式就是128cbc模式,再往下看分析aes加密特征可以得出v47,v48就是我们的key,iv,直接hook一波h14函数
看看加密后的结果,这个f11函数是16进制加密,aes加密的16进制返回的就是我们接口data参数
再往下看
初始化这个v63,在135行添加key值进去,在看136行添加v62参数0x7D22
这个0x7D22到底是什么呢?
这时可以得出v56就是我们的key值json串,v53应该是密钥,hook f1函数确认下这2个参数
公钥出来了,h12函数对rsa结果在进行16进制编码,最后通过反射java层字段返回加密后的16进制,java层接收到c的16进制在将data参数转成base64然后发送请求,总结一下,p参数=rsa(生成key值json串),data参数=aes(java参数),接口返回的结果解密,用刚才的aes解密下就行了,python实现下,成功获取到dfid
另外对unidbg不熟的可以加入龙哥星球深造一下
最后经常点外卖的可以关注下这个小程序,每天都能领取大额外卖优惠券红包
文章仅供学习交流,请勿用于非法用途,如有侵犯到贵公司隐私或者利益,请联系我立马删除。
原文始发于微信公众号(逆向客栈):某音乐app dfid参数分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论