某游戏盒App的So层逆向
字数 2327 2025-08-06 08:34:57
某游戏盒App的So层逆向分析教学文档
1. 目标分析
- 目标App:某游戏盒App
- 加密位置:请求头中的
sign和password字段在So层进行加密 - 分析工具:Frida、IDA Pro、GDAE、抓包工具(如Charles/Fiddler)
2. 抓包分析
- 登录请求:
- 输入账号:
15026818188,密码:123456789。 - 抓包发现请求参数中
sign和password为加密字段。 - 明文参数:其他字段如手机号、时间戳等可见。
- 输入账号:
3. Java层逆向
-
关键类定位:
- 使用GDAE搜索
sign和password,发现两者均通过AppNativeHelper类调用So层方法。 AppNativeHelper加载libNativeHelper.so,调用native方法生成加密值。
- 使用GDAE搜索
-
Hook验证:
- 尝试Hook
java.lang.String.getBytes,但数据量过大,难以定位关键方法。 - 直接通过静态分析确认加密逻辑在So层。
- 尝试Hook
4. So层关键函数定位
- Hook
NewStringUTF:- So层返回加密字符串时会调用
NewStringUTF(位于libart.so)。 - Frida脚本:
var artSym = Module.enumerateSymbols("libart.so"); var NewStringUTFAddr = null; for (var i = 0; i < artSym.length; i++) { if (artSym[i].name.indexOf("NewStringUTF") !== -1) { NewStringUTFAddr = artSym[i].address; } } Interceptor.attach(NewStringUTFAddr, { onEnter: function(args) { console.log("NewStringUTF input:", args[1].readCString()); } }); - 输出中过滤
sign和password的返回值,定位到libNativeHelper.so的偏移量:sign:0x4eefpassword:0x5ba5
- So层返回加密字符串时会调用
5. So层sign逆向
-
函数分析:
- 反编译
sub_4DF0(sign生成函数):- 输入:时间戳、设备标识符、固定字符串等拼接。
- 输出:MD5哈希值。
- 关键步骤:
- 字符串拼接:
dateline + deviceIdentifier + info + password密文 + 手机号 + 固定字符串。 - 调用MD5算法:
sub_4538:初始化MD5常量。sub_4564:MD5核心运算。
- 结果转换为16进制字符串。
- 字符串拼接:
- 反编译
-
Hook验证:
- Hook
sub_4564(MD5运算):let md5FuncAddr = Module.findBaseAddress("libNativeHelper.so").add(0x4564); Interceptor.attach(md5FuncAddr, { onEnter: function(args) { console.log("MD5 input:", hexdump(args[1])); } }); - 确认输入明文与抓包数据一致。
- Hook
-
结论:
sign=MD5(时间戳 + 设备标识符 + "1" + password密文 + 手机号 + "ef2vx#sf*^FlklSD*9sdf(m$&qw%d7po")。
6. So层password逆向
-
函数分析:
- 反编译
sub_5AEC(password生成函数):- 输入:明文密码(如
123456789)。 - 输出:Base64编码的DES加密结果。
- 输入:明文密码(如
- 关键步骤:
- PKCS7填充:密码长度不足8的倍数时填充
0x07(如123456789填充为3132333435363739070707070707)。 - DES加密:
- 模式:CBC。
- 密钥:
u!~#7@w0(ASCII转为Hex)。 - IV:
0x1234567890ABCDEF。
- Base64编码:对DES结果编码。
- PKCS7填充:密码长度不足8的倍数时填充
- 反编译
-
Hook验证:
- Hook
sub_5BCC(DES加密):let desFuncAddr = Module.findBaseAddress("libNativeHelper.so").add(0x5BCC); Interceptor.attach(desFuncAddr, { onEnter: function(args) { console.log("DES input:", hexdump(args[0])); console.log("DES key:", hexdump(args[3])); } }); - 确认密钥和IV与静态分析一致。
- Hook
-
结论:
password=Base64(DES_CBC(key="u!~#7@w0", iv="1234567890ABCDEF", data=PKCS7填充后的密码))。
7. 加密算法复现
-
sign生成(Python示例):
import hashlib plaintext = "16903430550c4435e8b8caa1541ytHJhV3wqmTDO9tMncVHgg==15026818188ef2vx#sf*^FlklSD*9sdf(m$&qw%d7po" sign = hashlib.md5(plaintext.encode()).hexdigest() -
password生成(Python示例):
from Crypto.Cipher import DES import base64 key = b"u!~#7@w0" iv = b"\x12\x34\x56\x78\x90\xAB\xCD\xEF" plaintext = b"123456789" + b"\x07" * 7 # PKCS7填充 cipher = DES.new(key, DES.MODE_CBC, iv) encrypted = cipher.encrypt(plaintext) password = base64.b64encode(encrypted).decode()
8. 总结与技巧
-
So层逆向要点:
- 熟悉加密算法特征(如MD5常量、DES填充模式)。
- 通过Hook关键函数(如
NewStringUTF、内存操作函数)定位逻辑。 - 结合静态分析(IDA反编译)与动态验证(Frida Hook)。
-
常见加密识别:
- MD5:初始化常量
0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476。 - DES/CBC:固定8字节IV,PKCS7填充(补
0x07)。 - Base64:包含字符集
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/。
- MD5:初始化常量
-
工具链:
- 静态分析:IDA Pro(C/C++)、GDAE(Java)。
- 动态分析:Frida、Xposed。
- 调试:GDB(Linux)、LLDB(Android)。
9. 附录
-
So层函数表:
偏移量 功能 备注 0x4eef sign生成 MD5哈希 0x5ba5 password生成 DES+CBC+Base64 0x4538 MD5初始化 填充标准常量 0x4564 MD5核心运算 包含K值数组 0x5BCC DES加密 接受密钥和IV 0x209C Base64编码 自定义字符集 -
参考链接:
- OpenSSL DES加密文档:https://www.openssl.org/docs/
- MD5算法标准:RFC 1321