初中生
 
- 金币
- 259
- 好评
- 1
- 信誉
- 100
|
本帖最后由 xendal 于 2026-8-24 13:12 编辑
教程是本人先逆向一次,然后写教程再逆向一次,所以有些地方可能会跳过,教程写的不是很详细,欢迎大佬们点评
不知道为啥图片都没了,这里放一个笔记链接,点我进入
xx菜谱大全frida逆向
包名:cn.lilaitech.wpcpdq
逆向参数:
请求体:APIDATA
响应解密
工具:reqable、mt、termux、frida
注意:手机需要root
类型:请求、响应加密
难度:简单
日期:
一、安装frida
- 授予 termux 文件访问权限:termux-setup-storage
- 下载frida-server(可以下载魔改版),并放入 data/local/tmp 中,并授予执行权限:chmod 777 frida文件名
- 在termux安装frida相关需要:
- pkg install root-repo
- pkg install frida-python
复制代码
二、分析
打开抓包工具和外婆菜谱大全
为了方便分析,抓包选择对应APP

启动抓包,并滑动页面加载数据


一般都是搜索标题内容,但是这里搜索没有

一开始以为没抓到包,但是搜索 蛋糕 后就有我们要的数据


可以发现请求体和响应都是加密的


通过测试发现请求体 APIDATA 是必须的
三、逆向
一)请求体APIDATA
打开mt管理器,提取安装包,发现有加固,先去脱修,这里就不展示了


在 dex++中搜索 APIDATA,可以发现只有一个结果


点击进入后,转为 JAVA,方便分析

可以发现 APIDATA 由 str 获取

并且 str = new a().e(jSONObject.toString().getBytes());
这时可以试着使用frida hook该值
- function hookParma() {
- // Hook f.a.e 方法
- var A = Java.use("f.a");
- A.e.implementation = function(byteArray) {
- // 打印传入的字节数组长度
- console.log("[f.a.e] byteArray length: " + byteArray.length);
- // 将字节转为字符串(假设为 UTF-8)
- var jsonString = Java.use("java.lang.String").$new(byteArray, "UTF-8");
- console.log("[f.a.e] JSON data: " + jsonString);
- // 调用原方法,获得加密后的字符串
- var result = this.e(byteArray);
- console.log("[f.a.e] encrypted result: " + result);
- // 可选:修改返回值(例如 result = "fake_data")
- return result;
- };
- // Hook FormBody.Builder.add(String, String)
- var Builder = Java.use("okhttp3.FormBody$Builder");
- Builder.add.overload('java.lang.String', 'java.lang.String').implementation = function(key, value) {
- if (key === "APIDATA") {
- console.log("[Builder.add] APIDATA value: " + value);
- // 可选:修改 value,例如 value = "modified";
- // 注意修改后会影响最终 POST 请求体
- }
- // 调用原方法
- return this.add(key, value);
- };
- }
- Java.perform(function() {
- hookParma();
- });
复制代码 打开 termux,启动frida-server
- su
- ~/data/local/tmp/frida/rusda-server-17.15 127.0.0.1:27042
复制代码 打开新的终端

启动hook脚本
- frida -H 127.0.0.1:27042 -N 包名 -l hookjs文件
- 如:
- frida -H 127.0.0.1:27042 -N cn.lilaitech.wpcpdq -l hook.js
复制代码 启动后将termux切到小窗口,并且打开抓包

之后还是加载数据,这时frida就有内容输出

暂停抓包和退出frida,进入termux可以发现加密前和加密后的值

将加密后的值随便复制一段

进入抓包软件,搜索复制的值,可以看到有匹配的包,将匹配的包里的 APIDATA 值复制下来

在将hook的值复制下来对比,可以发现是一样的

说明方向正确,接下来就是进入 a.e()函数中

进入e函数后再次转成JAVA,可以发现有 AES关键字

直接将这段代码丢给 AI 分析,简单给出结论

再告诉 AI 写一个 frida hook 代码
- // 辅助函数:字节数组转十六进制小写字符串
- function bytesToHex(bytes) {
- if (!bytes) return "";
- var hex = [];
- for (var i = 0; i < bytes.length; i++) {
- var b = bytes[i] & 0xFF;
- hex.push(("0" + b.toString(16)).slice(-2));
- }
- return hex.join("");
- }
- // 辅助函数:字节数组转 Base64(使用 Android 的 Base64 类,显式指定重载)
- function bytesToBase64(bytes) {
- if (!bytes) return "";
- var Base64 = Java.use("android.util.Base64");
- // 显式调用 overload('[B', 'int'),避免自动匹配失败
- return Base64.encodeToString.overload('[B', 'int')(bytes, 2); // NO_WRAP
- }
- // 主 Hook 逻辑
- Java.perform(function () {
- var A = Java.use("f.a");
- // 1. 获取并打印硬编码密钥
- console.log("[*] Creating instance to get key...");
- var instance = A.$new();
- var keyBytes = instance.a.value; // 获取 byte[] 字段
- console.log("[*] AES Key (hex): " + bytesToHex(keyBytes));
- console.log("[*] AES Key (base64): " + bytesToBase64(keyBytes));
- // 2. Hook 加密方法 e(byte[])
- A.e.implementation = function (bArr) {
- console.log("\n[+] e() called");
- // 原始输入 JSON 字符串
- var inputStr = Java.use("java.lang.String").$new(bArr, "UTF-8");
- console.log("[+] Input JSON: " + inputStr);
- // 调用原方法获得加密结果
- var result = this.e(bArr);
- console.log("[+] Encrypted result: " + result);
- return result;
- };
- // 3. Hook 解密方法 d(String)
- A.d.implementation = function (encryptedStr) {
- console.log("\n[+] d() called");
- console.log("[+] Encrypted input: " + encryptedStr);
- var plainBytes = this.d(encryptedStr);
- if (plainBytes !== null) {
- var plainStr = Java.use("java.lang.String").$new(plainBytes, "UTF-8");
- console.log("[+] Decrypted plain JSON: " + plainStr);
- } else {
- console.log("[!] Decryption failed (MAC mismatch or error)");
- }
- return plainBytes;
- };
- // 4. Hook c 方法(AES 加解密)
- A.c.implementation = function (mode, data, key, iv) {
- var modeStr = (mode === 1) ? "ENCRYPT" : "DECRYPT";
- console.log("[*] c() mode=" + modeStr);
- console.log("[*] data length: " + data.length);
- console.log("[*] key (hex): " + bytesToHex(key));
- console.log("[*] iv (hex): " + bytesToHex(iv));
- var result = this.c(mode, data, key, iv);
- console.log("[*] output length: " + (result ? result.length : "null"));
- return result;
- };
- // 5. Hook a 方法(HMAC 计算)
- var aMethod = A.a.overload('f.a', '[B', '[B');
- aMethod.implementation = function (obj, data, key) {
- console.log("[*] a() HMAC-SHA256");
- console.log("[*] data (hex): " + bytesToHex(data));
- console.log("[*] key (hex): " + bytesToHex(key));
- var result = this.a(obj, data, key);
- console.log("[*] HMAC raw (hex): " + bytesToHex(result));
- return result;
- };
- // 6. Hook b 方法(字节转十六进制字符串)
- var bMethod = A.b.overload('f.a', '[B');
- bMethod.implementation = function (obj, bytes) {
- var hexStr = this.b(obj, bytes);
- console.log("[*] b() input length: " + (bytes ? bytes.length : 0) + ", output: " + hexStr);
- return hexStr;
- };
- console.log("[*] All hooks installed successfully.");
- });
复制代码 之后再次启动frida hook

下滑加载数据,会发现有很多,并且还有响应的解密数据,一举两得

- 这时可以加 -o 文件名 来输出成文件
- frida -H 127.0.0.1:27042 -N cn.lilaitech.wpcpdq -l hook.js -o log.txt
复制代码 然后将输出的文件直接丢给 AI,让它来帮我们生成APIDATA加密和响应解密的Python爬虫代码即可
三、测试

|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
-
查看全部评分
总评分:好评 +1
|