公众号现在只对常读和星标的公众号才展示大图推送,
建议大家把听风安全设为星标,否则可能就看不到啦!
----------------------------------------------------------------------
微信公众号收到老哥私信,求助逆向一个app并对解密某个数据包。说干就干,掏出我的Google亲儿子开整。
先看老哥的需求
图中说的 data.php 抓包看到内容是长这样子的:
查壳发现目标app使用360加固了,回村匆忙没来得急带家伙事,又让老哥提供了一份脱壳后的dex文件。
拿到dex文件后,先用 d2j-dex2jar.sh 把dex还原成jar包,再把jar包拖到 jadx-gui,后面还是以前的那些三脚猫功夫。在 jadx-gui 中不断 Ctrl + F搜索关键词:Request、Response 中出现的字段和 encrypt、decrypt、AES、secretkey 等关键词。
定位到一处解密代码:
接下来就要对这段代码进行 hook ,看看它都干了些啥。如果不会使用 Frida 或者不熟练,可以像我一样多问问 chatGPT
对以下源码进行 hook
public static String a(String str, String str2) {
try {
if (str2 == null) {
System.out.print("Key為空null");
return null;
} else if (str2.length() != 16) {
System.out.print("Key長度不是16位");
return null;
} else {
SecretKeySpec secretKeySpec = new SecretKeySpec(str2.getBytes("utf-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(2, secretKeySpec);
try {
return new String(cipher.doFinal(Base64.decode(str, 0)), "utf-8");
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
}
} catch (Exception e2) {
System.out.println(e2.toString());
return null;
}
}
先问问chatGPT 怎么对就函数进行hook
整理后(其实是jadx-gui 直接右键导出的)的hook代码:
function main(){
let perform = Java.perform(() =>{
let C0158a = Java.use("cn.tv.player.a");
C0158a["a"].overload('java.lang.String', 'java.lang.String').implementation = function (str, str2) {
console.log('a is called' + ', ' + 'str: ' + str + ', ' + 'str2: ' + str2);
console.log("str2: ",str2)
let ret = this.a(str, str2);
console.log('a ret value is ' + ret);
return ret;
};
frida -U -f tw.qvod.new -l frida.js --no-pause -o a.txt
图中的方法应该是一个AES ECB 的解密算法,str 是密文,str2 是秘钥。
结合burpsuite抓的包进行分析,终端截图中对应的请求应该是:
这串密文复制到AES在线解密网站,使用 ECB模式 PKCS5padding 填充,秘钥 4f3742c93218f004 ,能正确解开,内容就是终端截图中所示明文。
秘钥是怎么生成的,就不具体去分析了,还是以解密data.php 内容为主。
接接看data.php 解密对应的逻辑在哪里。看看都有谁调用了 cn.tv.player.a.a 这个方法 一通搜索后,应该是下面没跑:
如果看不懂Java,那就请 chatGPT , 解释解释神马踏马的叫.......
美滋滋,一下子就看明白这里是啥意思了。
跟进一下下列代码找那个的 a 函数是个什么东西。this.jsonString = new String(a(Base64.decode(this.jsonString, 0)), "UTF-8");
之前hook到的数据保存到了 txt 中,使用对应的秘钥解出来也是一串 乱七八杂的东西,不可读。
分析后确认,他和上述代码中的 new String(a(Base64.decode(this.jsonString, 0)), "UTF-8");
有关系。
对 data.php 数据的整个解密逻辑是:
-
**ChannelDatas**
传进来一上下文 -
通过 this.mySettings = new MySettings(context); 拿到设置内容 -
通过String substring = C0158a.b(SplashActivity.z + new MySettings(PlayerActivity.f1635a).c("rand")).substring(7, 23); 设置生成AES密钥 -
C0186z.a 操作文件 -
一系列替换操作,调用AES进行解密 -
使用bade64 进行decode ,在调用a方法进行解压缩解码
打开之前保存的 a.txt 文件,找到 data.php 那段解密后的数据。
密文:
明文:
编写python解密对这段不可读明文进行处理;
import base64
from io import BytesIO
from zlib import decompress
def a(bArr):
"""
new String(a(Base64.decode(this.jsonString, 0)), "UTF-8");
"""
byte_stream = BytesIO(bArr)
try:
result = decompress(byte_stream.read())
except Exception as e:
print(e)
result = None
byte_stream.close()
return result
decoded_data = base64.b64decode(str)
decoded_data = a(decoded_data)
print(decoded_data.decode("utf-8"))
另一种更快的方法
直接 hook cn.tv.player.model.ChannelDatas 中substring 的值
frida -U -f tw.qvod.new -l frida.js --no-pause -o data.php.txt
frida 带上 -o 参数,将结果保存下来
// cn.tv.player.model.ChannelDatas
function main(){
let perform = Java.perform(() => {
//对象 实例
Java.choose("cn.tv.player.model.ChannelDatas",
{
onMatch:function(instance){
console.log(instance.substring.value)
},
onComplete:function(){
console.log("over........")
}
}
);
});
}
setImmediate(main)
chatGPT 以后就是亲二舅了,回村三天,二舅治好了我的精神内耗,哈哈哈哈
原文始发于微信公众号(听风安全):回村三天,chatGPT教会了我如何简单逆向app并解密数据包
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论