欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 关于 Frida:常用 Hook 函数

关于 Frida:常用 Hook 函数

2025/5/19 8:15:40 来源:https://blog.csdn.net/Triste__chengxi/article/details/148036447  浏览:    关键词:关于 Frida:常用 Hook 函数

一、Java 层

  • 目标:Android Java 应用层代码(Java/Kotlin)

  • 方式:通过 Java.perform() 进入 Java 虚拟机上下文,使用 Java.use() 获取类,重写方法实现。

  • 用途:拦截 Java 方法调用、修改参数和返回值、监控对象状态、Hook 构造函数、静态方法等。

1. Java.use

加载并操作 Java 层的类,是进行任何 Java Hook 的第一步。必须传入完整类名,返回的是一个可 Hook 的类对象。

Java.perform(function () {var TargetClass = Java.use("com.example.app.MainActivity");console.log("[*] Loaded Class:", TargetClass);
});

2. overload

Android 支持方法重载,这个函数用于指定具体参数类型的重载方法。必须精确指定参数类型,才能 Hook 到正确的函数版本。

Java.perform(function () {var Target = Java.use("com.example.app.MainActivity");Target.login.overload("java.lang.String", "java.lang.String").implementation = function (user, pass) {console.log("[*] login called with:", user, pass);return this.login(user, pass);};
});

3. $init(构造函数)

Hook 构造函数的专用方法,$init 代表 Java 类的构造函数。overload 与 $init 搭配可以精确匹配构造方法签名。

Java.perform(function () {var Target = Java.use("com.example.app.MainActivity");Target.$init.overload().implementation = function () {console.log("[*] 构造函数被调用");return this.$init();};
});

4. implementation(修改函数实现)

用于替换原方法的逻辑,在里面可以打印参数、修改返回值或调用原方法。是最常用的 Hook 手段之一。

Java.perform(function () {var Target = Java.use("com.example.app.MainActivity");Target.getData.implementation = function () {console.log("[*] getData 被调用");return "FakeData";};
});

5. 调用实例方法或类方法(主动调用)

可以在 Frida 中调用原始类或实例方法,以辅助逆向分析。常用于主动调用以触发逻辑。

Java.perform(function () {var Target = Java.use("com.example.app.MainActivity");var result = Target.getAppVersion();console.log("[*] App Version:", result);
});

6. Java.choose

枚举运行时实例,找出已加载的类对象,可操作现有实例。常用于找出 Activity、Context 或网络类实例进行分析。

Java.perform(function () {Java.choose("com.example.app.MainActivity", {onMatch: function (instance) {console.log("[*] 找到实例:", instance);},onComplete: function () {console.log("[*] 枚举完成");}});
});

7. Java.openClassFile + Dex 注入

向目标应用注入一个新的 dex 文件,可以让我们加载自定义代码。常用于突破反调试或绕过壳逻辑。

Java.perform(function () {Java.openClassFile("/data/local/tmp/hook.dex").load();var Injected = Java.use("com.inject.HookUtil");Injected.doWork();
});

8. Java.enumerateLoadedClasses

枚举所有已加载的 Java 类名,可以用于类发现与模糊匹配。搭配关键字搜索可以快速定位目标类。

Java.perform(function () {Java.enumerateLoadedClasses({onMatch: function (name) {if (name.indexOf("MainActivity") >= 0) console.log("[*] 类:", name);},onComplete: function () {console.log("[*] 枚举完成");}});
});

9. Java.enumerateClassLoaders

枚举 ClassLoader 是在多 dex/动态加载的应用中找到目标类的关键方法。可结合 loader.findClass 精确定位类存在于哪个 loader 中。

Java.perform(function () {Java.enumerateClassLoaders({onMatch: function (loader) {try {if (loader.findClass("com.example.app.MainActivity")) {console.log("[*] 找到合适的 ClassLoader");}} catch (e) {}},onComplete: function () {}});
});

10. Java.cast(强制类型转换)

将一个 Java 对象强制转换为指定类型,便于调用其方法。通常用于从 generic Object 中获取真实类。

Java.perform(function () {var activityThread = Java.use("android.app.ActivityThread");var currentApp = activityThread.currentApplication();var context = Java.cast(currentApp, Java.use("android.content.Context"));console.log("[*] 当前 context:", context);
});

二、Native 层

  • 目标:Android 原生库(.so 文件)、系统调用、本地方法

  • 方式:通过 Module.findExportByName() 找到函数地址,Interceptor.attach() 监控函数调用,或用 Interceptor.replace() 替换函数实现。

  • 用途:Hook 加密算法、本地校验、系统调用、内存读写等。

1. Module.findExportByName

查找某个模块导出的函数地址,是 Native Hook 的前提。第一个参数是模块名,第二个是函数名。

Java.perform(function () {var addr = Module.findExportByName("libc.so", "open");console.log("[*] open() 地址:", addr);
});

2. Interceptor.attach 

在函数执行前后插入自定义逻辑,是最常用的 Native Hook 工具。可以监控参数、修改返回值。

Java.perform(function () {var openPtr = Module.findExportByName("libc.so", "open");Interceptor.attach(openPtr, {onEnter: function (args) {console.log("[*] open 调用, path:", Memory.readUtf8String(args[0]));},onLeave: function (retval) {console.log("[*] 返回值:", retval);}});
});

3. Interceptor.replace

替换整个原生函数的实现,是一种高强度 Hook 方法。可以实现完全绕过或伪造原始行为。

Java.perform(function () {var strlen = Module.findExportByName(null, "strlen");Interceptor.replace(strlen, new NativeCallback(function (str) {return 42;}, "int", ["pointer"]));
});

4. NativeFunction

用于主动调用 native 层的导出函数,比如调用 puts、malloc 等。需要指定函数地址、返回值类型和参数类型。

Java.perform(function () {var putsAddr = Module.findExportByName(null, "puts");var puts = new NativeFunction(putsAddr, "int", ["pointer"]);puts(Memory.allocUtf8String("Hello from NativeFunction"));
});

5. Memory.allocUtf8String

将字符串写入内存中,返回的是指针,可用于传递给 native 函数。常与 NativeFunction 搭配使用。

Java.perform(function () {var ptr = Memory.allocUtf8String("test string");console.log("[*] 内存地址:", ptr);
});

6. Memory.readUtf8String / readByteArray

从指定内存地址读取字符串或字节数组。常用于读取参数、数据包、返回值。

Java.perform(function () {var addr = ptr("0x12345678");var str = Memory.readUtf8String(addr);console.log("[*] 读取到:", str);
});

7. Memory.scan

扫描模块内存找特定字节序列,常用于找签名、关键代码段。可配合模块基地址使用。

Java.perform(function () {var base = Module.findBaseAddress("libtarget.so");Memory.scan(base, 0x10000, "12 34 ?? 56", {onMatch: function (address, size) {console.log("[*] 匹配地址:", address);},onComplete: function () {console.log("[*] 扫描完成");}});
});

8. Thread.backtrace 打印栈信息

获取当前执行点的调用栈信息,便于调试函数调用路径。可用 Accurate 模式获取详细调试信息。

Java.perform(function () {var openAddr = Module.findExportByName(null, "open");Interceptor.attach(openAddr, {onEnter: function (args) {console.log("[*] 调用栈:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));}});
});

9. Module.findBaseAddress

获取模块的加载基地址,是 Memory 操作的基础。搭配 scan、偏移可精确定位函数或数据。

Java.perform(function () {var base = Module.findBaseAddress("libc.so");console.log("[*] libc.so 基地址:", base);
});

10. Module.enumerateExports

枚举模块导出的函数和变量,可用于分析可 Hook 的原生接口。常用于配合 findExportByName 精准定位。

Java.perform(function () {var exports = Module.enumerateExports("libc.so");exports.forEach(function (e) {if (e.name.indexOf("open") >= 0) console.log(e.name, e.address);});
});

11. Module.enumerateImports

枚举模块导入的函数,是分析动态链接依赖的好方法。可找出目标模块调用了哪些外部函数。

Java.perform(function () {var imports = Module.enumerateImports("libtarget.so");imports.forEach(function (imp) {console.log("[*] import:", imp.name, imp.module);});
});

12. Module.load

加载一个未自动加载的 so 文件,用于自定义注入。搭配 findExportByName 使用。

Java.perform(function () {var mymod = Module.load("/data/local/tmp/libcustom.so");var addr = mymod.findExportByName("custom_function");console.log("[*] 地址:", addr);
});

三、Objective-C / Swift 层(iOS 特有)

  • 目标:iOS 应用 Objective-C Runtime

  • 方式:通过 ObjC.classes 访问类,重写方法实现。

  • 用途:Hook iOS 应用方法、系统 API、私有 API。

1. Objective-C 实例方法

- 表示实例方法,重写该方法实现可以打印参数、修改返回值或绕过逻辑。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;MyClass["- myInstanceMethod:"].implementation = function (arg) {console.log("[*] 实例方法 myInstanceMethod: 被调用,参数:", arg.toString());var ret = this["- myInstanceMethod:"](arg);  // 调用原始实现console.log("[*] 原始返回值:", ret);return ret;};} else {console.log("[-] ObjC 环境不可用");}
});

2. Objective-C 类方法

+ 表示类方法,常用于 Hook 工厂方法、单例获取等。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;MyClass["+ myClassMethod"].implementation = function () {console.log("[*] 类方法 myClassMethod 被调用");var ret = this["+ myClassMethod"]();return ret;};}
});

3. Swift 方法(借助 ObjC Runtime)

Swift 编译后方法名通常带有混淆,但用 ObjC 方式访问可 Hook。

Swift 与 ObjC 混合编译项目中,可以用 ObjC runtime 方式 Hook Swift 暴露的方法。

Java.perform(function () {if (ObjC.available) {var SwiftClass = ObjC.classes.SwiftClassName;  // 先找类名// 查看所有方法名,辅助确定函数签名var methods = SwiftClass.$ownMethods;console.log("[*] SwiftClass 方法列表:", methods);// 假设要 Hook 方法 -someSwiftMethod:SwiftClass["- someSwiftMethod:"].implementation = function (arg) {console.log("[*] Swift 方法被调用,参数:", arg);return this["- someSwiftMethod:"](arg);};}
});

4. Objective-C 构造方法(init 系列)

可以 Hook init 系列构造方法,监控对象创建过程。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;MyClass["- init"].implementation = function () {console.log("[*] MyClass init 构造方法被调用");return this["- init"]();};}
});

5. Objective-C Block(闭包)

Hook 传入 Block 的方法,可以监控回调执行,修改回调行为。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;MyClass["- methodTakingBlock:"].implementation = function (block) {console.log("[*] 收到 Block 参数");var blockObj = new ObjC.Block(block);blockObj.implementation = function () {console.log("[*] Block 被调用");return blockObj.apply(this, arguments);};return this["- methodTakingBlock:"](blockObj);};}
});

6. Objective-C 属性 Getter / Setter

属性访问本质是 getter/setter 方法,Hook 它们可监控属性读取和修改。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;// Hook getterMyClass["- propertyName"].implementation = function () {var ret = this["- propertyName"]();console.log("[*] 获取属性 propertyName:", ret);return ret;};// Hook setterMyClass["- setPropertyName:"].implementation = function (value) {console.log("[*] 设置属性 propertyName 为:", value);this["- setPropertyName:"](value);};}
});

7. Objective-C 消息发送(Message Send)

Hook 底层消息发送函数,可以捕获所有 ObjC 方法调用,范围极广,适合全局监控。

Java.perform(function () {if (ObjC.available) {var objc_msgSend = Module.findExportByName(null, "objc_msgSend");Interceptor.attach(objc_msgSend, {onEnter: function (args) {var receiver = new ObjC.Object(args[0]);var selector = ObjC.selectorAsString(args[1]);console.log("[*] objc_msgSend 目标类:", receiver.$className, "方法:", selector);}});}
});

8. Objective-C 动态方法解析(resolveInstanceMethod)

动态方法解析机制,用于补救运行时未实现的方法,Hook 该方法可以监控运行时添加方法行为。

Java.perform(function () {if (ObjC.available) {var MyClass = ObjC.classes.MyClass;MyClass["+ resolveInstanceMethod:"].implementation = function (sel) {var selectorName = ObjC.selectorAsString(sel);console.log("[*] 动态方法解析:", selectorName);return this["+ resolveInstanceMethod:"](sel);};}
});

9. Swift 属性访问(通过 getter/setter)

Swift 属性也会编译成 getter/setter 方法,可以用和 Objective-C 一样的方式 Hook。

Swift 属性访问实际上是方法调用,Hook getter/setter即可。

Java.perform(function () {if (ObjC.available) {var SwiftClass = ObjC.classes.SwiftClassName;// 假设属性名为 swiftProperty,对应 getterSwiftClass["- swiftProperty"].implementation = function () {console.log("[*] Swift 属性 getter 被调用");return this["- swiftProperty"]();};// setterSwiftClass["- setSwiftProperty:"].implementation = function (value) {console.log("[*] Swift 属性 setter 被调用,值:", value);this["- setSwiftProperty:"](value);};}
});

10. Objective-C Runtime 函数

Hook Runtime 函数用于捕获底层动态行为,如方法交换、添加等,是深度逆向利器。

Java.perform(function () {var runtimeFunctions = ["class_addMethod","method_exchangeImplementations","objc_msgSend"];runtimeFunctions.forEach(function (funcName) {var addr = Module.findExportByName(null, funcName);if (addr) {Interceptor.attach(addr, {onEnter: function (args) {console.log("[*] 调用 runtime 函数:", funcName);}});}});
});

四、内存操作层(简)

  • 目标:直接对进程内存读写,扫描字节模式,操作指针

  • 方式:使用 Memory.allocUtf8String()Memory.read*()Memory.write*()Memory.scan()

  • 用途:查找函数指针,修改数据内容,动态插桩。

1. malloc

  • 用于动态申请指定大小的内存空间,是最基础的内存申请函数。

  • Hook malloc 可以监控程序内存申请的大小和调用时机,常用于分析程序内存使用。

var mallocPtr = Module.findExportByName(null, "malloc");
Interceptor.attach(mallocPtr, {onEnter: function (args) {console.log("[malloc] size: " + args[0].toInt32());},onLeave: function (retval) {console.log("[malloc] returned ptr: " + retval);}
});

2. free

  • 用来释放之前申请的内存,防止内存泄漏。

  • Hook free 可以跟踪内存释放操作,帮助发现潜在的内存安全问题(如重复释放)。

var freePtr = Module.findExportByName(null, "free");
Interceptor.attach(freePtr, {onEnter: function (args) {console.log("[free] address: " + args[0]);}
});

3. memcpy

  • 用于内存拷贝,把一块内存的数据复制到另一块内存。

  • Hook memcpy 可以监控敏感数据复制、篡改行为,尤其是密码学或逆向时非常重要。

var memcpyPtr = Module.findExportByName(null, "memcpy");
Interceptor.attach(memcpyPtr, {onEnter: function (args) {console.log("[memcpy] dest: " + args[0] + ", src: " + args[1] + ", size: " + args[2].toInt32());}
});

五、线程和调用栈层(简)

  • 目标:跟踪调用栈,分析调用路径

  • 方式Thread.backtrace(), DebugSymbol.fromAddress()

  • 用途:调试和分析调用链路、定位问题点。

1. Thread.backtrace

  • 获取当前线程的调用栈,能够清晰看到函数调用顺序和调用地址。

  • 非常适合调试定位程序执行路径和逆向分析调用关系。

Java.perform(function () {var openPtr = Module.findExportByName(null, "open");Interceptor.attach(openPtr, {onEnter: function (args) {var stack = Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n");console.log("[Thread.backtrace] 调用栈:\n" + stack);}});
});

2. Thread.sleep

  • 线程休眠函数,使线程暂停指定时间。

  • Hook 可以用来检测和干扰程序的定时等待行为,或加快逆向调试流程。

var sleepPtr = Module.findExportByName(null, "sleep");
Interceptor.attach(sleepPtr, {onEnter: function (args) {console.log("[sleep] 线程休眠秒数: " + args[0].toInt32());}
});

3. pthread_create

  • POSIX 线程创建函数,用于创建新线程执行指定函数。

  • Hook pthread_create 可以监控程序线程创建行为,帮助分析多线程并发流程。

var pthreadCreate = Module.findExportByName(null, "pthread_create");
Interceptor.attach(pthreadCreate, {onEnter: function (args) {console.log("[pthread_create] 新线程创建, 线程函数地址: " + args[2]);}
});

六、指令级 Hook 和追踪(Stalker)(简)

  • 目标:CPU 指令级追踪和分析

  • 方式:使用 Stalker 跟踪指定线程的指令执行,支持条件跳转、寄存器值监控。

  • 用途:深度分析代码执行路径,绕过反调试,动态分析复杂逻辑。

1. Stalker.follow

  • 让 Frida 跟踪指定线程的指令执行,实时捕获 CPU 指令流。

  • 用于动态分析程序执行路径和汇编指令变化,适合逆向复杂逻辑。

Java.perform(function () {var threadId = Process.getCurrentThreadId();console.log("[Stalker] 开始跟踪线程ID:", threadId);Stalker.follow(threadId, {events: {call: true, // 跟踪调用指令ret: true,  // 跟踪返回指令exec: false,block: false,compile: false},onCallSummary: function (summary) {console.log("[Stalker] 调用汇总:", JSON.stringify(summary));},onEvent: function (event) {// 这里可自定义处理事件}});
});

2. Stalker.detach

  • 停止对某个线程的跟踪,释放资源。

  • 通常用于跟踪完成后清理,避免性能影响。

Java.perform(function () {var threadId = Process.getCurrentThreadId();Stalker.follow(threadId);setTimeout(function () {console.log("[Stalker] 停止跟踪线程ID:", threadId);Stalker.detach(threadId);}, 5000); // 5秒后停止跟踪
});

3. Stalker.queueDrain

  • 手动触发 Stalker 队列的处理,及时输出跟踪数据。

  • 用于高频事件场景,防止跟踪数据积压。

Java.perform(function () {var threadId = Process.getCurrentThreadId();Stalker.follow(threadId, {onEvent: function (event) {console.log("[Stalker Event] 类型:", event.type);Stalker.queueDrain();  // 强制刷新事件队列}});
});

其他辅助层(简)

  • ClassLoader 管理层:切换和操作不同 ClassLoader,解决多 Dex 多 ClassLoader 的 Hook 问题。

  • 动态代码注入Java.openClassFile() 加载外部 Dex,动态注入代码扩展 Hook 功能。

1. DebugSymbol.fromAddress

  • 将内存地址解析成函数名、模块名等符号信息。

  • 方便分析调用栈或跟踪时对地址的理解,提升逆向效率。

Java.perform(function () {var addr = Module.findExportByName("libc.so", "open");var symbol = DebugSymbol.fromAddress(addr);console.log("[DebugSymbol] 地址对应符号:", symbol.name, "模块:", symbol.moduleName);
});

2. Interceptor.flush

  • 手动刷新所有挂载的拦截器。

  • 当动态修改 Hook 或存在大量数据缓存时,确保拦截器立即生效。

Java.perform(function () {var openPtr = Module.findExportByName("libc.so", "open");Interceptor.attach(openPtr, {onEnter: function (args) {console.log("[Interceptor] open called");}});// 强制刷新,立即生效所有拦截器Interceptor.flush();
});

3. Process.getCurrentThreadId

  • 获取当前执行线程的 ID,便于精确定位线程级 Hook。

  • 常用于配合 Stalker 或多线程环境的精细控制。

Java.perform(function () {var tid = Process.getCurrentThreadId();console.log("[Thread] 当前线程ID:", tid);
});

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词