计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
reverse-engineering-ios-app-with-frida【效率与协作】使用 Frida 动态插桩对 iOS 应用进行逆向工程,在无源代码的情况下理解内部逻辑、 提取加密密钥、绕过安全控制并发现隐藏功能。适用于授权 iOS 渗透测试、分析专有协议、 理解混淆逻辑或从 iOS 二进制文件中提取运行时机密。适合 iOS 逆向工程、Frida iOS Hook、 Objective-C/Swift 方法追踪或 iOS 二进制分析相关请求。
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
适用于以下情况:
不适用场景:不得用于违反服务条款或知识产权法律的未授权逆向工程。
frida-tools(pip install frida-tools)# 在越狱设备上找到应用二进制文件
ssh root@<device_ip>
find /var/containers/Bundle/Application/ -name "TargetApp" -type f
# 拉取解密后的二进制文件(App Store 应用使用 FairPlay 加密)
# 使用 frida-ios-dump 或 Clutch 进行解密
pip install frida-ios-dump
dump.py com.target.app
# 提取 Objective-C 类头文件
class-dump -H decrypted_binary -o headers/
ls headers/ # 列出所有类头文件
// enumerate_classes.js - 列出所有已加载的类
Java.perform(function() {}); // iOS 不适用
// iOS 使用 ObjC 运行时
if (ObjC.available) {
var classes = ObjC.classes;
for (var className in classes) {
if (className.indexOf("Target") !== -1 ||
className.indexOf("Auth") !== -1 ||
className.indexOf("Crypto") !== -1) {
console.log("[Class] " + className);
// 列出方法
var methods = classes[className].$ownMethods;
for (var i = 0; i < methods.length; i++) {
console.log(" [Method] " + methods[i]);
}
}
}
}
frida -U -n TargetApp -l enumerate_classes.js
# 追踪某个类的所有方法
frida-trace -U -n TargetApp -m "*[TargetAuth *]"
# 追踪特定模式
frida-trace -U -n TargetApp -m "*[*Crypto* *]"
frida-trace -U -n TargetApp -m "*[*KeyChain* *]"
frida-trace -U -n TargetApp -m "*[*Token* *]"
# 追踪 Swift 方法(混淆名称)
frida-trace -U -n TargetApp -m "*[*$s*Auth*]"
// hook_auth.js - 拦截认证逻辑
if (ObjC.available) {
// Hook Objective-C 方法
var AuthManager = ObjC.classes.AuthManager;
if (AuthManager) {
Interceptor.attach(AuthManager["- validateToken:"].implementation, {
onEnter: function(args) {
// args[0]=self, args[1]=selector, args[2+]=方法参数
var token = new ObjC.Object(args[2]);
console.log("[Auth] validateToken 调用,参数: " + token.toString());
},
onLeave: function(retval) {
console.log("[Auth] validateToken 返回: " + retval);
// 可选:修改返回值
// retval.replace(ptr(1)); // 强制返回 true
}
});
}
// Hook CommonCrypto 进行加密分析
var CCCrypt = Module.findExportByName("libcommonCrypto.dylib", "CCCrypt");
if (CCCrypt) {
Interceptor.attach(CCCrypt, {
onEnter: function(args) {
this.operation = args[0].toInt32(); // 0=加密, 1=解密
this.algorithm = args[1].toInt32(); // 0=AES128, 1=DES, 2=3DES
this.keyLength = args[4].toInt32();
this.key = Memory.readByteArray(args[3], this.keyLength);
console.log("[CCCrypt] 操作:" + (this.operation === 0 ? "加密" : "解密"));
console.log("[CCCrypt] 密钥: " + hexify(this.key));
},
onLeave: function(retval) {
console.log("[CCCrypt] 状态: " + retval);
}
});
}
}
function hexify(buffer) {
var bytes = new Uint8Array(buffer);
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push(("0" + bytes[i].toString(16)).slice(-2));
}
return hex.join("");
}
// swift_analysis.js - Hook Swift 方法
// Swift 方法使用名称混淆:$s<模块><类><方法>
// 先用 frida-trace 发现实际混淆名称
if (ObjC.available) {
// 继承自 NSObject 的 Swift 类可通过 ObjC 运行时访问
var swiftClasses = Object.keys(ObjC.classes).filter(function(name) {
return name.indexOf("_TtC") === 0 || name.indexOf("TargetApp.") !== -1;
});
swiftClasses.forEach(function(className) {
console.log("[Swift] " + className);
var methods = ObjC.classes[className].$ownMethods;
methods.forEach(function(method) {
console.log(" " + method);
});
});
}
// 对于纯 Swift(未桥接到 ObjC),使用 Module.enumerateExports
Module.enumerateExports("TargetApp", {
onMatch: function(exp) {
if (exp.name.indexOf("Auth") !== -1 || exp.name.indexOf("Crypto") !== -1) {
console.log("[Export] " + exp.name + " @ " + exp.address);
}
},
onComplete: function() {}
});
// extract_secrets.js
if (ObjC.available) {
// Hook NSUserDefaults
var NSUserDefaults = ObjC.classes.NSUserDefaults;
Interceptor.attach(NSUserDefaults["- objectForKey:"].implementation, {
onEnter: function(args) {
this.key = new ObjC.Object(args[2]).toString();
},
onLeave: function(retval) {
if (retval.isNull()) return;
var value = new ObjC.Object(retval);
console.log("[NSUserDefaults] " + this.key + " = " + value.toString());
}
});
// Hook 钥匙串访问
var SecItemCopyMatching = Module.findExportByName("Security", "SecItemCopyMatching");
Interceptor.attach(SecItemCopyMatching, {
onEnter: function(args) {
var query = new ObjC.Object(args[0]);
console.log("[Keychain] 查询: " + query.toString());
},
onLeave: function(retval) {
console.log("[Keychain] 结果: " + retval);
}
});
}
| 术语 | 定义 |
|---|---|
| Objective-C 运行时 | 支持运行时方法分发、类自省和方法替换(Method Swizzling)的动态运行时 |
| Swift 名称混淆 | 编译器将 Swift 函数签名编码为链接器兼容符号名称的技术 |
| FairPlay DRM | Apple 对 App Store 二进制文件应用的加密;静态分析前必须先解密 |
| class-dump | 从 Mach-O 二进制文件提取 Objective-C 类声明的工具,用于头文件级分析 |
| CommonCrypto | Apple 的 C 级加密库;通过 Frida Hook 提取加密密钥的主要目标 |
@objc 注解的纯 Swift 类无法通过 ObjC.classes 查看,改用 Module.enumerateExports()。