mcpField
R
reverse-engineering-ios-app-with-frida

reverse-engineering-ios-app-with-frida

github.com/mukul975安全35.2k159 次安装8 周前更新
代码仓库

关于 reverse-engineering-ios-app-with-frida

这是一份面向授权安全评估的 iOS 应用 Frida 动态分析技能,适用于没有源代码的场景。内容涵盖运行时追踪、方法 Hook、Swift 分析及安全机制测试。

主要功能

  1. 01枚举运行时类与方法
  2. 02追踪 Objective-C 方法调用
  3. 03Hook 并修改方法行为
  4. 04分析 Swift 运行时逻辑
  5. 05检查加密与安全机制

适用场景

  1. 01授权评估中分析 iOS 应用
  2. 02追踪混淆的 Swift 或 Objective-C 逻辑
  3. 03检查应用的加密与 API 数据处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill reverse-engineering-ios-app-with-frida

安装后在 Claude Code 中输入/reverse-engineering-ios-app-with-frida确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.py

详细介绍

使用 Frida 逆向工程 iOS 应用

何时使用

在以下情况使用本技能:

  • 在获得授权的安全评估中,在没有源代码的情况下分析 iOS 应用内部机制
  • 从正在运行的 iOS 应用中提取加密密钥、API 密钥或专有协议细节
  • 通过运行时方法追踪理解经过混淆的 Swift/Objective-C 逻辑
  • 绕过复杂的安全机制(越狱检测、防篡改、反调试)

不要使用本技能进行违反服务条款或知识产权法的未授权逆向工程。

前提条件

  • 已越狱的 iOS 设备,并通过 Cydia/Sileo 安装了 Frida server,或未越狱但通过 Frida Gadget 注入 IPA 的设备
  • Python 3.10+ 及 frida-tools(pip install frida-tools)
  • 与 iOS 设备的 USB 连接
  • 用于提取 Objective-C 头文件的 class-dump 或 dsdump
  • 用于静态二进制分析的 Hopper Disassembler 或 Ghidra(互补)
  • 了解 Objective-C 运行时和 Swift 名称修饰

工作流

第 1 步:提取并分析二进制文件
# On jailbroken device, find app binary
ssh root@<device_ip>
find /var/containers/Bundle/Application/ -name "TargetApp" -type f

# Pull decrypted binary (apps from App Store are encrypted with FairPlay)
# Use frida-ios-dump or Clutch for decryption
pip install frida-ios-dump
dump.py com.target.app

# Extract Objective-C class headers
class-dump -H decrypted_binary -o headers/
ls headers/  # Lists all class header files
第 2 步:在运行时枚举类和方法
// enumerate_classes.js - List all loaded classes
Java.perform(function() {});  // N/A for iOS

// iOS uses ObjC runtime
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);

            // List methods
            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
第 3 步:使用 frida-trace 追踪方法调用
# Trace all methods of a class
frida-trace -U -n TargetApp -m "*[TargetAuth *]"

# Trace specific patterns
frida-trace -U -n TargetApp -m "*[*Crypto* *]"
frida-trace -U -n TargetApp -m "*[*KeyChain* *]"
frida-trace -U -n TargetApp -m "*[*Token* *]"

# Trace Swift methods (mangled names)
frida-trace -U -n TargetApp -m "*[*$s*Auth*]"
第 4 步:Hook 并修改方法行为
// hook_auth.js - Intercept authentication logic
if (ObjC.available) {
    // Hook Objective-C method
    var AuthManager = ObjC.classes.AuthManager;
    if (AuthManager) {
        Interceptor.attach(AuthManager["- validateToken:"].implementation, {
            onEnter: function(args) {
                // args[0] = self, args[1] = selector, args[2+] = method args
                var token = new ObjC.Object(args[2]);
                console.log("[Auth] validateToken called with: " + token.toString());
            },
            onLeave: function(retval) {
                console.log("[Auth] validateToken returned: " + retval);
                // Optionally modify return value
                // retval.replace(ptr(1));  // Force return true
            }
        });
    }

    // Hook CommonCrypto for encryption analysis
    var CCCrypt = Module.findExportByName("libcommonCrypto.dylib", "CCCrypt");
    if (CCCrypt) {
        Interceptor.attach(CCCrypt, {
            onEnter: function(args) {
                this.operation = args[0].toInt32();  // 0=encrypt, 1=decrypt
                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] Op:" + (this.operation === 0 ? "Encrypt" : "Decrypt"));
                console.log("[CCCrypt] Key: " + hexify(this.key));
            },
            onLeave: function(retval) {
                console.log("[CCCrypt] Status: " + 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("");
}
第 5 步:分析 Swift 代码
// swift_analysis.js - Hook Swift methods
// Swift methods use name mangling: $s<module><class><method>
// Use frida-trace to discover actual mangled names first

if (ObjC.available) {
    // Swift classes that inherit from NSObject are accessible via ObjC runtime
    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);
        });
    });
}

// For pure Swift (non-ObjC-bridged), use 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() {}
});
第 6 步:提取密钥和专有数据
// 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 Keychain access
    var SecItemCopyMatching = Module.findExportByName("Security", "SecItemCopyMatching");
    Interceptor.attach(SecItemCopyMatching, {
        onEnter: function(args) {
            var query = new ObjC.Object(args[0]);
            console.log("[Keychain] Query: " + query.toString());
        },
        onLeave: function(retval) {
            console.log("[Keychain] Result: " + retval);
        }
    });
}

关键概念

术语定义
Objective-C 运行时动态运行时,支持运行时的方法分派、类内省和方法交换
Swift 名称修饰编译器将 Swift 函数签名编码为链接器兼容的符号名称
FairPlay DRMApple 应用于 App Store 二进制文件的加密;必须在静态分析前解密
class-dump从 Mach-O 二进制文件中提取 Objective-C 类声明以进行头文件级分析的工具
CommonCryptoApple 的 C 级加密库;通过 Frida hook 提取加密密钥的主要目标

工具与系统

  • Frida:用于 iOS 运行时 hook 和方法拦截的动态插桩框架
  • frida-trace:自动追踪工具,为匹配的方法生成处理器存根
  • frida-ios-dump:通过内存转储解密受 FairPlay 保护的 iOS 应用的工具
  • class-dump / dsdump:从 Mach-O 二进制文件中提取 Objective-C 头文件
  • Ghidra:NSA 的逆向工程框架,用于对 iOS 应用进行静态 ARM64 二进制分析

常见陷阱

  • FairPlay 加密:从 App Store 下载的应用是加密的。必须在静态分析前解密。在已越狱设备上使用 frida-ios-dump。
  • 纯 Swift 类:没有 @objc 注解的纯 Swift 类无法通过 ObjC.classes 看到。改用 Module.enumerateExports()。
  • 剥离符号的二进制文件:发布版本会剥离调试符号。将 frida-trace 与 class-dump 输出结合以进行有效分析。
  • 反 Frida 措施:复杂的应用会检查 Frida 痕迹(frida-server 进程、内存中的 Frida agent 字符串、dyld 中注入的库)。使用隐蔽的 Frida 构建或 Frida Gadget 注入。

评论

支持 Markdown