引言:最近买了点基金,然后我对象基本过半个小时就提醒我看看基金情况,工位不太好不好摸鱼,所以就想着搞下这个app接口,
然后开发一个桌面应用挂在这里定时轮询,正好最近也想尝试一下jadx的mcp,AI分析到最后告诉我这是flutter开发的,
之前没有接触过flutter逆向,所以搞一下填补一下空白,下面开始正篇。
样本&&工具&&环境:
1.分析接口嘛,肯定先抓个包试试
抓包这里有个坑点,flutter自带SSL校验,这个问了下AI,github上有佬开源的通杀flutter SSL校验,感兴趣的可以去看一下代码实现 b85K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6z5g2V1W2e0e0%4y4W2j5%4g2J5K9i4c8&6i4K6u0r3k6r3W2K6j5h3u0D9k6g2)9J5k6r3k6D9N6i4c8@1k6i4u0Q4x3X3c8@1L8s2y4Q4x3X3c8$3k6i4u0A6k6X3W2U0j5i4c8A6L8$3^5`.
定位到目标接口,头部有一个签名,看长度初步判断是md5 

python3 blutter.py path/to/app/lib/arm64-v8a out_dir
function readDartStringExact(ptr) {
if (ptr.isNull()) return "null";
try {
let lengthSmi = ptr.add(7).readU32();
let length = lengthSmi >> 1;
if (length === 0) return "";
if (length > 10240) return "[String suspiciously long: " + length + " bytes]";
let strDataPtr = ptr.add(15);
let str = strDataPtr.readUtf8String(length);
return str;
} catch (e) {
return "[Error reading string at " + ptr + ": " + e.message + "]";
}
}
function hookMD5() {
let moduleName = "libapp.so";
let libapp = Process.getModuleByName(moduleName);
let targetOffset = 0x70A264;
let targetAddress = libapp.base.add(targetOffset);
console.log("[*] Hooking generateMD5 at: " + targetAddress);
console.log("[*] Waiting for network requests...\n");
Interceptor.attach(targetAddress, {
onEnter: function(args) {
this.inputStringPtr = args[0];
console.log("=========================================");
console.log("[+] MD5 Signature Triggered!");
let plaintext = readDartStringExact(this.inputStringPtr);
console.log("[->] Full Plaintext Input:");
console.log("-----------------------------------------");
console.log(plaintext);
console.log("-----------------------------------------");
console.log("[i] Plaintext Length: " + plaintext.length + " characters");
},
onLeave: function(retval) {
let md5Result = readDartStringExact(retval);
console.log("[<-] MD5 Output Hash : " + md5Result);
console.log("=========================================\n");
}
});
}
setTimeout(function() {
hookMD5();
}, 1000);
- 样本:5YW75Z+65a6d
- ubuntu_22.04.5
- jadx-mcp插件
- IDA 9.2
- frida 16.1.5
- reqable
抓包这里有个坑点,flutter自带SSL校验,这个问了下AI,github上有佬开源的通杀flutter SSL校验,感兴趣的可以去看一下代码实现 1b7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6z5g2V1W2e0e0%4y4W2j5%4g2J5K9i4c8&6i4K6u0r3k6r3W2K6j5h3u0D9k6g2)9J5k6r3k6D9N6i4c8@1k6i4u0Q4x3X3c8@1L8s2y4Q4x3X3c8$3k6i4u0A6k6X3W2U0j5i4c8A6L8$3^5`.
定位到目标接口,头部有一个签名,看长度初步判断是md5 
- flutter开发的应用核心代码打包后都在libapp.so里面

- 先在IDA里面搜索一下字符串 request-sign

- 这里我本来想看交叉引用的,发现没效果,问了下AI,告诉我如下原因和解决方案

- 按blutter官方文档执行以下命令,执行完之后会在你的输出目录生成以下内容
- 输出文件

- 其实到这里如果只是为了搞算法的话就已经可以将输出的asm里面的dio_request.dart导出文件丢给ai去分析就行了,针对这个app因为我已经知道它是一个加盐其未魔改的md5了,所以找盐这种事丢给ai完全可以胜任的

- 但是为了体验flutter逆向全流程和熟悉IDA,我还是按网上教程,在IDA中导入了blutter生成的还原字符的脚本

- 定位到_onRequest函数

- hook盐值,在ida里我们看到了generateMD5函数的起始地址是0x70A264,所以我们只需要hook函数的入参和返回值,就能看到盐值了
- 本次样本逆向全程基本都是由ai完成的,包括思路和分析,我只是给它提供需要的信息,虽然不复杂,不过也是学到一些新东西的,包括怎么去逆flutter,怎么过flutter的SSL校验,基于地址hook so函数等,写的比较水勿喷,只是为了记录一下flutter逆向的流程。感谢AI— ~hhhha
- 算法逆向
- 总结
样本:5YW75Z+65a6dubuntu_22.04.5jadx-mcp插件
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!