过某TV App Root监测及协议分析
字数 1230 2025-08-06 08:34:57
某TV App Root检测绕过及登录协议逆向分析教程
1. Root检测绕过分析
1.1 Root检测原理分析
该TV App在启动时会检测设备是否已root,如果检测到root环境,会显示Toast提示:"当前设备可能处于root环境,继续运行应用将有风险"。
通过逆向分析发现,检测逻辑位于WelcomeActivity$2$1.run方法中,主要调用了两个检测方法:
SystemUtils.checkSuFile()- 通过执行which su命令检测su文件是否存在SystemUtils.checkRootFile()- 检查常见root相关文件路径是否存在
1.2 绕过Root检测的方法
使用Frida hook这两个检测方法,强制返回非root的结果:
Java.perform(function() {
let SystemUtils = Java.use("com.xxxx.xxxxxxx.xxxxxxx.xxxx.system.SystemUtils");
SystemUtils["checkSuFile"].implementation = function() {
console.log(`SystemUtils.checkSuFile is called`);
return false;
};
SystemUtils["checkRootFile"].implementation = function() {
console.log(`SystemUtils.checkRootFile is called`);
return null;
}
});
2. 登录协议分析
2.1 请求头分析
登录请求包含以下关键请求头:
X-API-VERSION: App版本号X-API-TIMESTAMP: 时间戳X-API-KEY: 固定值X-API-SIGNATURE: 需要逆向分析的签名值
2.2 签名生成流程
签名生成流程如下:
- 获取版本号:
Util.getVersionName(instance) - 生成随机数据:
SecurityUtil.getRandomData(6) - 通过反射调用native方法:
com.xxxx.xxxxxxx.jni.Utils.signature(objArray1)
关键Java代码:
String versionName = Util.getVersionName(instance);
String randomData = SecurityUtil.getRandomData(6);
objArray1[i] = versionName;
objArray1[1] = randomData;
Class uClass = Class.forName("com.xxxx.xxxxxxx.jni.Utils");
Method declaredMeth = uClass.getDeclaredMethod("signature", uClassArray);
str1 = declaredMeth.invoke(uClass.newInstance(), objArray1);
str = Base64.encode(str1.getBytes());
2.3 Native层签名算法分析
signature是native方法,位于libm2o_jni.so中,算法流程如下:
- 拼接字符串:
"877a9ba7a98f75b90a9d49f53f15a858&NjhhMDRiODE3N2JkYzllNWUxNmE4OWU2Nzc3YTdiNjY=&" + versionName + "&" + randomData - 对拼接后的字符串进行SHA1哈希计算
关键C代码:
snprintf(v11, v9 + 80, "%s&%s&%s&%s",
"877a9ba7a98f75b90a9d49f53f15a858",
"NjhhMDRiODE3N2JkYzllNWUxNmE4OWU2Nzc3YTdiNjY=",
v5, v7);
sha1_encode(v11, v9 + 79, &p);
SHA1计算函数:
int __fastcall sha1_encode(void *a1, int a2, char **a3) {
// 初始化SHA1上下文
SHA1_Init(v10);
// 更新要计算的数据
SHA1_Update((int)v10, a1);
// 获取最终结果
SHA1_Final(v11, v10);
// 将结果转换为十六进制字符串
for (i = 0; i != 20; ++i) {
v9 = (unsigned __int8)v11[i];
sprintf(v7, "%s%02x", v7, v9);
}
*a3 = v7;
return result;
}
2.4 Frida Hook Native方法
let sha1_encodeAddr = Module.findExportByName("libm2o_jni.so", "sha1_encode")
console.log(sha1_encodeAddr)
Interceptor.attach(sha1_encodeAddr, {
onEnter: function(args) {
console.log("onEnter args0 => ", args[0].readCString())
console.log("onEnter args1 => ", args[1].toInt32())
this.args2 = args[2]
},
onLeave: function(retval) {
let args2Pointer = this.args2.readPointer()
console.log("onLeave args2 => ", args2Pointer.readCString())
}
})
2.5 Frida主动调用签名方法
function callSignature() {
Java.perform(function() {
let SystemUtils = Java.use("com.xxxx.xxxxxxx.jni.Utils");
let str = "4.0.0";
let str2 = "1689690618994is9eCh";
let utils = SystemUtils.$new();
let result = utils.signature(str, str2);
console.log("result =>", result);
})
}
3. 逆向工具使用技巧
-
使用多款反编译工具互补:
- Jadx
- GDAE
- Jeb
- 不同工具对混淆代码的反编译效果不同
-
动态分析工具组合:
- Objection:用于快速hook Java方法
- Frida:用于详细hook和主动调用
- IDA Pro:用于静态分析so文件
4. 总结
-
Root检测绕过:
- 定位检测方法
- 使用Frida修改返回值
-
协议逆向:
- 通过hook定位关键方法
- 分析Java层反射调用
- 深入so层分析算法实现
- 使用Frida验证分析结果
-
逆向技巧:
- 多工具互补使用
- 动静结合分析
- 关注关键字符串和方法调用栈
通过本教程,我们完整分析了某TV App的root检测机制和登录协议签名算法,掌握了从Java层到Native层的完整逆向流程。