某转逆向分析(环境检测,sign值分析)
字数 1182 2025-08-22 12:22:30
某转APP逆向分析教学文档
一、环境检测机制分析
1. 检测入口发现
- 通过搜索字符串"检测到当前设备存在安全风险"定位到环境检测代码
- 检测类型包括:
- Root检测
- 模拟器检测(未成功反编译)
- 网络环境检测
2. Root检测分析
检测流程概述
-
首先使用美团Robust热更新框架进行补丁检测
- 通过
PatchProxy.proxy方法判断是否加载了补丁 - 如果加载了补丁则直接return,不执行后续检测代码
- 通过
-
主要检测方法:
com.zhuanzhuan.module.util.safe.impl.UtilExport.SAFE.isRoot()
具体检测手段
文件检查方式:
boolean exists = new File("/system/app/Superuser.apk").exists();
- 检查
/system/app/Superuser.apk文件是否存在 - 该文件通常与root权限管理应用相关
命令检查方式:
for (String str : m54412a(new String[]{"/system/bin/sh", "-c", "type su"})) {
if (StringsKt__StringsKt.contains$default((CharSequence) lowerCase,
(CharSequence) "not found", false, 2, (Object) null)) {
bool = Boolean.FALSE;
}
}
- 执行
type su命令检查su命令是否存在 - 如果返回结果包含"not found",则认为设备未root
Build.TAGS检查:
String TAGS = Build.TAGS;
if (!StringsKt__StringsKt.contains$default((CharSequence) TAGS,
(CharSequence) "test-keys", false, 2, (Object) null)) {
return false;
}
- 检查Build.TAGS是否包含"test-keys"
- 这是判断设备是否为测试版的重要标志
辅助函数m54412a分析
// 执行命令并返回结果
ArrayList<String> executeCommand(String[] strArr) {
ArrayList<String> arrayList = new ArrayList<>();
Process exec = Runtime.getRuntime().exec(strArr);
// 读取标准输出
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine != null) {
arrayList.add(readLine);
}
}
// 读取错误输出
BufferedReader errorReader = new BufferedReader(new InputStreamReader(exec.getErrorStream()));
// 同上处理错误流...
return arrayList;
}
3. 网络环境检测
// 检测网络代理
boolean isUsingProxy() {
String proxyHost = System.getProperty("http.proxyHost");
String proxyPort = System.getProperty("http.proxyPort");
return proxyHost != null && proxyPort != null;
}
- 通过系统属性检查是否设置了HTTP代理
- 同时获取代理地址和端口则判断为存在代理
二、Sign签名算法分析
1. 签名定位
- 通过搜索"zzreqsign"定位到签名生成类
- 关键方法:
com.zhuanzhuan.sign.SignUtil.getSign()
2. Frida Hook验证
function main() {
Java.perform(function() {
let SignUtil = Java.use("com.zhuanzhuan.sign.SignUtil");
SignUtil.getSign.overload("java.lang.String", "android.content.Context")
.implementation = function(str, context) {
console.log("SignUtil.getSign is called: str=", str, " context=", context);
let result = this.getSign(str, context);
console.log("SignUtil.getSign result:", result);
return result;
}
})
}
setImmediate(main);
3. Native层签名算法分析
算法流程
-
数据准备阶段:
- 验证应用签名:
get_app_sign_sha1() - 获取输入数据并转换为字节数组
- 获取设备ID并转换为字节数组
- 验证应用签名:
-
数据混淆阶段:
- 分配与输入数据等长的内存
- 使用异或算法混淆数据:
for (i = 0; i < v10; ++i) { v18 = input_data[v13 % input_length]; v19 = (v13 + 1) % device_id_length; v13 += 2; output[i] = device_id[v19] ^ v18; }
-
MD5计算阶段:
- 创建新字节数组(原长度+9)
- 填充混淆后的数据
- 在末尾添加固定字符串"smiletozz"
- 计算最终MD5值
MD5算法验证
// 标准MD5实现,未被魔改
jbyteArray getDigestedBytes(JNIEnv* env, jbyteArray input) {
// 获取MD5实例
// 计算摘要
// 返回结果
}
三、总结与防御方案
1. 环境检测防御方案
-
Root检测绕过:
- 隐藏Superuser.apk文件
- 拦截或伪造
type su命令返回 - 修改Build.TAGS属性
-
网络代理检测绕过:
- 清除系统代理设置
- Hook系统属性获取方法
2. 签名算法防御方案
-
签名算法保护:
- 使用native层实现核心算法
- 添加应用签名校验
- 结合设备唯一标识
-
对抗逆向:
- 使用代码混淆
- 添加反调试检测
- 关键代码动态加载
3. 通用逆向防护建议
- 关键逻辑放在native层实现
- 添加完整性校验防止篡改
- 使用多维度环境检测
- 实现动态密钥生成机制
- 定期更新加密算法和检测逻辑
本教学文档详细分析了某转APP的环境检测机制和签名算法实现,提供了完整的技术细节和防御方案,可作为移动安全研究和APP防护的参考。