-
-
[原创]【银行逆向百例】16Android逆向之算法助手 frida绕过环境检测分析加密算法
-
发表于: 2小时前 79
-
“ 你打算怎么活,今后,在我死之后,你打算过怎样的生活,托尔芬。——《冰海战记》S1E24 ”
01环境版本
环境:
电脑,Windows 11 专业版 23H2
69aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6v1K9h3q4G2f1%4g2u0L8X3k6G2f1$3g2U0i4K6u0r3d9X3W2S2L8#2y4#2d9h3&6X3L8#2y4W2j5#2)9#2k6W2b7H3x3r3I4K6i4K6g2X3g2$3W2F1x3e0p5`.
软件:
Mumu模拟器,5.3.4
https://mumu.163.com/download/
Kitsune Mask,27.2
5d2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1j5I4M7e0t1K6L8s2W2U0y4o6g2Q4x3V1k6w2K9i4c8K6N6h3&6W2e0h3q4Y4K9i4y4C8i4K6u0r3M7X3g2D9k6h3q4K6k6i4x3`.
算法助手,1.0.9
https://www.123865.com/s/7G8aTd-bKH4H
LSPosed,1.9.2
03aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3f1#2m8G2M7$3g2V1i4K6u0r3e0q4y4b7L8%4y4W2k6q4)9J5c8Y4u0W2L8r3g2S2M7$3g2K6i4K6u0r3N6r3q4Y4i4K6u0r3N6U0p5`..9.2
brook,20230606.5
3cdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6@1P5s2c8Z5K9h3&6C8K9h3&6Y4i4K6u0r3j5Y4u0G2L8$3D9`.
frida-server,16.1.8
ebdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3M7X3W2V1j5g2)9J5c8X3k6J5K9h3c8S2i4K6u0r3M7X3g2D9k6h3q4K6k6i4y4Q4x3V1k6@1j5h3N6Q4x3V1j5`.16.1.8
burpsuite,2025.1
973K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3L8%4u0@1M7%4N6A6k6$3N6W2M7W2)9J5k6h3&6W2N6q4)9J5c8X3u0#2M7Y4m8Q4x3V1k6J5k6h3I4W2j5i4y4W2M7H3`.`.
Charles,5.0.2
01fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0K9r3q4J5L8r3g2K6M7s2u0G2P5s2W2Q4x3X3g2U0L8$3#2Q4x3V1k6V1L8%4N6F1L8r3!0S2k6q4)9J5c8R3`.`.
02操作步骤
1、弹窗提示设备环境风险,点击确定自动退出APP

2、可写系统盘
https://mumu.163.com/help/20240202/35044_1136675.html

3、安装KitsuneMagisk
f12K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1j5I4M7e0t1K6L8s2W2U0y4o6g2Q4x3V1k6w2K9i4c8K6N6h3&6W2e0h3q4Y4K9i4y4C8i4K6u0r3M7X3g2D9k6h3q4K6k6i4x3`.

4、安装算法助手
https://www.123865.com/s/7G8aTd-bKH4H

5、下载LSPosed-v1.9.2-7024-zygisk-release
e3cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3f1#2m8G2M7$3g2V1i4K6u0r3e0q4y4b7L8%4y4W2k6q4)9J5c8Y4u0W2L8r3g2S2M7$3g2K6i4K6u0r3N6r3q4Y4i4K6u0r3N6U0p5`..9.2

6、允许root权限

7、安装

8、直接安装

9、开启Zygisk

10、关闭模拟器

11、模块安装LSPosed-v1.9.2-7024-zygisk-release

12、关闭模拟器

13、下拉进入LSPosed

14、模块启用算法助手

15、启用模块后关闭模拟器

16、算法助手勾选目标APP

17、弹窗定位,启动APP

18、查看日志

19、复制调用堆栈

20、分析日志,最后调用了AlertMessageDialog.showIosAlert

21、启动frida-server
67cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3M7X3W2V1j5g2)9J5c8X3k6J5K9h3c8S2i4K6u0r3M7X3g2D9k6h3q4K6k6i4y4Q4x3V1k6@1j5h3N6Q4x3V1j5`.16.1.8

adb push .\frida-server-16.1.8-android-x86_64 /data/local/tmp
adb shell
su
cd /data/local/tmp
chmod +x frida-server-16.1.8-android-x86_64
./frida-server-16.1.8-android-x86_64
22、获取包名
frida-ps -Uai

23、hook弹窗通用方法Dialog.show,如果调用堆栈包含AlertMessageDialog关键字就返回空,成功绕过弹窗

Java.perform(function() {
var Dialog = Java.use("android.app.Dialog");
Dialog.show.implementation = function() {
if (Java.use("java.lang.Thread").currentThread().getStackTrace().toString().indexOf("AlertMessageDialog") !== -1) {
console.log("[+] 拦截环境检测弹窗");
return;
}
return this.show();
};
});
24、网络环境勾选

25、抓包请求加密
d48K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5`.11263

26、算法助手勾选算法分析

27、复制调用堆栈日志

28、分析调用堆栈
用户名,调用 RSAUtils.IdNoEncrypt() → 内部调用 RSAUtils.encrypt() 进行 RSA 加密
com.xxx.utils.keyboardutil.RSAUtils.encrypt
com.xxx.utils.keyboardutil.RSAUtils.IdNoEncrypt
密码,调用 RSAUtils.PwdRandomRsaEncrypt() → 内部先用 AESUtils.encrypt() 加密密码,再用 RSA 加密 AES 密钥
com.xxx.utils.keyboardutil.AESUtils.encrypt
com.xxx.utils.keyboardutil.AESUtils.encrypt
com.xxx.utils.keyboardutil.RSAUtils.PwdRandomRsaEncrypt

29、hook.js

Java.perform(function() {
console.log("[*] Frida Hook已启动 - 延迟Hook策略");
// 字节转Hex
function bytesToHex(bytes) {
if (!bytes) return "null";
var result = "";
for (var i = 0; i < bytes.length; i++) {
result += ("0" + (bytes[i] & 0xFF).toString(16)).slice(-2);
}
return result;
}
// 打印调用堆栈
function printStackTrace() {
console.log("[调用堆栈]");
var traces = Java.use("java.lang.Thread").currentThread().getStackTrace();
for (var i = 0; i < traces.length && i < 10; i++) {
var line = traces[i].toString();
if (line.indexOf("cn.com.xxx") !== -1 || line.indexOf("xxx") !== -1) {
console.log(" at " + line);
}
}
}
// ==================== 弹窗拦截 ====================
try {
var Dialog = Java.use("android.app.Dialog");
Dialog.show.implementation = function() {
try {
if (Java.use("java.lang.Thread").currentThread().getStackTrace().toString().indexOf("AlertMessageDialog") !== -1) {
console.log("[+] 拦截环境检测弹窗");
return;
}
} catch(e) {}
return this.show();
};
console.log("[+] 弹窗拦截已启用");
} catch(e) {}
// ==================== 延迟Hook目标类 ====================
var rsaHooked = false;
var aesHooked = false;
var hookAttempts = 0;
var maxAttempts = 30;
function tryHookTargetClasses() {
hookAttempts++;
// 尝试Hook RSAUtils
if (!rsaHooked) {
try {
var RSAUtils = Java.use("com.xxx.utils.keyboardutil.RSAUtils");
console.log("[+] RSAUtils 类已加载,开始Hook...");
// Hook encrypt (String, Key)
try {
RSAUtils.encrypt.overload('java.lang.String', 'java.security.Key').implementation = function(data, key) {
console.log("\n================ RSAUtils.encrypt ================");
console.log("[输入] " + data);
var result = this.encrypt(data, key);
console.log("[输出Hex] " + bytesToHex(result));
printStackTrace();
console.log("==================================================");
return result;
};
} catch(e) {}
// Hook IdNoEncrypt
try {
RSAUtils.IdNoEncrypt.implementation = function(idNo) {
console.log("\n================ RSAUtils.IdNoEncrypt ================");
console.log("[输入数据] " + idNo);
var result = this.IdNoEncrypt(idNo);
console.log("[加密结果] " + result);
printStackTrace();
console.log("======================================================");
return result;
};
} catch(e) {}
// Hook PwdRandomRsaEncrypt
try {
RSAUtils.PwdRandomRsaEncrypt.implementation = function(pwd, randomKey) {
console.log("\n================ RSAUtils.PwdRandomRsaEncrypt ================");
console.log("[AES随机密钥] " + pwd);
console.log("[明文密码] " + randomKey);
var result = this.PwdRandomRsaEncrypt(pwd, randomKey);
console.log("[加密结果] " + result);
printStackTrace();
console.log("==============================================================");
return result;
};
} catch(e) {}
rsaHooked = true;
console.log("[+] RSAUtils Hook完成");
} catch(e) {}
}
// 尝试Hook AESUtils
if (!aesHooked) {
try {
var AESUtils = Java.use("com.xxx.utils.keyboardutil.AESUtils");
console.log("[+] AESUtils 类已加载,开始Hook...");
try {
AESUtils.encrypt.overload('java.lang.String', 'java.lang.String').implementation = function(data, key) {
console.log("\n================ AESUtils.encrypt ================");
console.log("[随机密钥] " + data);
console.log("[用户输入] " + key);
var result = this.encrypt(data, key);
console.log("[AES密文] " + result);
printStackTrace();
console.log("==================================================");
return result;
};
} catch(e) {}
aesHooked = true;
console.log("[+] AESUtils Hook完成");
} catch(e) {}
}
// 如果还有类未Hook成功,继续尝试
if ((!rsaHooked || !aesHooked) && hookAttempts < maxAttempts) {
setTimeout(tryHookTargetClasses, 300);
} else if (rsaHooked && aesHooked) {
console.log("[*] 所有目标类Hook完成");
}
}
// 开始尝试Hook
setTimeout(tryHookTargetClasses, 1000);
console.log("[*] Hook设置完成,请操作APP进行登录");
});
30、输出日志与数据包一致

“ 最近在看新的机会,希望能去武汉、深圳或上海发展。个人主要深耕渗透测试方向,平时对逆向工程也有研究。如果有合适的团队或岗位,还望各位大佬多多帮忙留意和推荐,感激不尽!”