hook 9大类

本文介绍了HOOK技术的九种类型,包括消息钩子、IATHOOK、EATHOOK、SSDTHOOK、IDTHOOK、SYSENTRYHOOK、InlineHOOK、OBJECTHOOK和IRPHOOK,详细解释了它们的工作原理及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HOOK技术主要分为两大类,一是内核层HOOK,一是用户层HOOK. 用户层HOOK也就是在ring3环境下hook kenerl32.dll、
User3.dll、Gui32.dll、Advapi.dll等导出的函数。而内核层HOOK就是HOOK只有ring0级别环境下才能操作写入改变的内核
对象,例如SSDT系统服务描述符表等。综合而言,主要有以下9种HOOK技术。


(1)消息钩子
消息钩子是最常见的钩子之一,例如常见的键盘鼠标钩子,很多木马就是通过消息钩子获取密码的。消息钩子是由Win32子
系统提供,用户通过它注册全局钩子。当系统获取某些事件,比如用户按键,键盘driver将扫描码等传入win32k的KeyEvent
处理函数,处理函数判断有无相应hook,有则通过回调函数处理。此时,系统取得Hook对象信息,若目标进程没有装载对应
的Dll,则装载之。


(2)IAT HOOK
IAT HOOK[4]是最常见和普遍的HOOK之一。IAT表示导入地址表(Import Address Table),导入函数就是被程序调用但其执行
代码又不在程序中的函数,当PE 文件被装入内存的时候,Windows 装载器才将DLL 装入,并将调用导入函数的指令和函数
实际所处的地址联系起来(动态连接),这种操作就需要导入表完成。其中导入地址表就指示函数实际地址。程序每个调用的 
API 函数地址都保存在 IAT 表中,而每个调用 API 函数的 CALL 指令所使用的地址都是相应函数登记在 IAT 表的地址。
IATHOOK原理是在将 IAT 表中的地址换成用户自己的 函数地址,这样每个 API 调用都是先调用用户自己的 函数。在这个
函数中我们可以完成函数名称的记录、参数的记录、调用原来的过程,并在返回时记录结果。


(3)EAT HOOK
EAT HOOK的原理是根据替换 PE 格式导出表中的相应函数来实现的。EAT表示导出地址表(Export Address Table),EAT存在
于PE文件中的edata节,保存了可执行文件(如DLL 文件)的导出的可供其他模块来调用的函数和公共变量,包括函数名称
和地址等。通过替换Windows 系统某些重要DLL中的输出函数地址,即可实现目标函数的挂接。EAT记录DLL中可供其他程序
使用的函数,可执行文件装载时会使用相应DLL的EAT表来初始化IAT表。
EAT HOOK原理是通过替换EAT表中的函数地址,使依赖于本DLL的程序得到一个假的地址。


(4)SSDT HOOK
SSDT是最常见的内核层 HOOK。SSDT的全称是系统服务描述符表(System Services Descriptor Table)。SSDT是关联ring3的
Win32 API和ring0的内核API的重要数据结构,它存储着Windows把需要调用的所有内核API地址。
SSDT HOOK原理是将内核层 API地址修改为指向其位于Ring0层的驱动入口,这样每次系统执行到这个函数时,都会通过SSDT表将原始调用引向修改后的模块中。


(5)IDT HOOK
IDT HOOK是Win2000操作系统上常用的一种HOOK。IDT是中断描述表,可以替换其中的中断处理程序。这种方法对于跟踪、分析系统调用来说用的比较多。
IDT HOOK的原理是通过替换 IDT表中的 INT 2E 中断,使之指向新的中断服务处理例程来实现的。它首先保存出特定的中断
向量中断服务程序(ISR), 然后直接修改该中断向量的ISR为自定义的函数,每当这个中断向量对应的中断产生时,就会调用
自定义的函数。由于我们自定义的函数里面执行完我们的功能后再跳转到原ISR处执行。


(6)SYSENTRY HOOK
SYSENTRY是Windows XP之后的操作系统进入ring0的函数。Win2000中通过 int2e系统调用机制,涉及到的
Interrupt/Exception Handler的调用都是通过 call/trap/task这一类的gate来实现的,这种方式会进行栈切换,并且系统
栈的地址等信息由TSS提供,可能会引起多次内存访问 (来获取这些切换信息),系统开销较大。SYSENTER通过汇编指令实现快速系统调用机制。
SYSENTER HOOK的原理是首先Ntdll 加载相应的请求服务号到EAX 寄存器中,同时EDX 寄存器存贮当前的栈指针ESP,然后
Ntdll发出SYSENTER 指令,该指令转移控制权到寄存器IA32_SYSENTER_EIP 存贮的地址中[21],通过修改这个地址,可实现
相应的挂接。


(7)Inline HOOK
inline hook是直接在以前的函数体内修改指令,用一个跳转或者其他指令来实现挂钩的目的。 
而普通的hook只是修改函数的调用地址,而不是在原来的函数体里面做修改。
Inline hook原理是解析函数开头的几条指令,把他们Copy到数组保存起来,然后用一个调用我们的函数的几条指令来替换
,如果要执行原函数,则在我们函数处理完毕,再执行我们保存起来的开头几条指令,然后调回我们取指令之后的地址执行
。它需要在程序中嵌入汇编代码(Inline Assembly)以操作堆栈和执行内核API对应的部分汇编指令。


(7)OBJECT HOOK
OBJECT HOOK是相对于IAT HOOK之类的 API HOOK而言,API HOOK是挂钩应用层函数,而OBJECT HOOK是挂钩内核层函数。其原理与API HOOK类似。


(9)IRP HOOK
IRP是 I/O request packets,在Windows中几乎所有的I/O都是通过包(packet)驱动的,每个单独的I/O由一个工作命令描
述,此命令将会告诉驱动程序需要一些什么操作,并通过I/O子系统跟踪处理过程。这些工作命令就表现为一个个被称为IRP
的数据结构。
IRP HOOK原理是拦截管理器发向文件或网络系统等驱动程序的IRP。一般通过创建一个上层过滤器设备对象并将之加入系统
设备所在的设备堆栈中。也有部分IRP HOOK通过拦截传递IRP请求包的函数IofCallDriver或MajorFunction函数表来实现的。

转载于:https://www.cnblogs.com/hshy/p/10609275.html

<think>嗯,用户之前问过如何Hook同名的问题,现在他们想了解如何Hook Android中的的成员变量。我需要回忆一下Android开发中常用的Hook方法,尤其是针对成员变量的部分。 首先,用户可能是在进行逆向工程或者动态调试,想要修改某个的成员变量的值。在Android中,通常使用Java反射或者Xposed框架来实现这样的Hook。不过用户提到的是成员变量,而不仅仅是方法,所以需要特别处理字段。 Java的反射机制允许获取和修改的字段。使用Field的get和set方法可以实现这一点。比如,通过Class.getDeclaredField获取字段对象,然后设置accessible为true来绕过访问权限,再调用set方法修改值。这个方法适用于当前运行的应用程序,但如果是系统或者需要更底层的Hook,可能需要Xposed的帮助。 Xposed框架基于Android的ART/Dalvik虚拟机,可以在不修改APK的情况下拦截方法调用和字段访问。用户可能需要了解如何用Xposed来Hook字段。比如,使用XposedHelpers.findAndHookMethod来监听某个方法,然后在回调中修改字段的值。或者直接使用XposedHelpers的findClass和getObjectField等方法。 不过,用户可能混淆了Hook方法和Hook字段的区别。Hook方法通常替换方法的实现,而Hook字段则是读取或修改其值。可能需要解释这两者的不同,并给出具体的步骤。 另外,需要注意不同Android版本对反射的限制,比如Android P之后的非公开API限制。这时候可能需要使用更高级的技术,比如使用Unsafe或者修改内存地址,但这比较复杂且风险较高。 用户可能还关心如何持久化Hook,确保每次应用启动时都生效,这时候Xposed模块是更好的选择,因为它可以在应用启动时注入代码。而纯反射的方式可能需要在每次应用启动后重新执行Hook。 最后,需要考虑安全性和稳定性,不当的Hook可能导致应用崩溃或者不可预期的行为。建议用户先进行充分的测试,并确保了解目标的实现细节。</think>在 Android 开发中,**Hook 的成员变量**需要借助反射或 Hook 框架(如 Xposed)来实现。以下是具体实现方案和注意事项: --- ### **1. 基础反射方案** 通过 Java 反射直接修改成员变量(适用于当前进程): ```java public class FieldHooker { // 目标示例 public static class TargetClass { private String secret = "Original Value"; } public static void hookField() { try { // 获取目标的 Class 对象 Class<?> clazz = TargetClass.class; // 获取私有成员变量(参数为变量名) Field field = clazz.getDeclaredField("secret"); // 突破访问权限限制 field.setAccessible(true); // 修改静态变量(若为实例变量需传入对象实例) TargetClass obj = new TargetClass(); field.set(obj, "Hooked Value"); // 修改值 // 验证结果 Log.d("Hook", "Current Value: " + field.get(obj)); } catch (Exception e) { e.printStackTrace(); } } } ``` #### **关键点** - `getDeclaredField()`:获取中声明的字段(包括私有字段) - `setAccessible(true)`:绕过 Java 访问检查 - `set()/get()`:动态修改/读取字段值 --- ### **2. Xposed 框架方案** 若需 Hook 系统或第三方应用(需 Root 或 Magisk 环境): #### **步骤 1:创建 Xposed 模块** 在 `assets/xposed_init` 中声明入口: ``` com.example.MyXposedModule ``` #### **步骤 2:Hook 目标字段** ```java public class MyXposedModule implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) { // 仅处理目标应用 if (!lpparam.packageName.equals("com.target.app")) return; XposedHelpers.findAndHookMethod( "com.target.app.TargetClass", lpparam.classLoader, "methodContainingFieldAccess", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // 获取目标的实例(假设 methodContainingFieldAccess 是成员方法) Object instance = param.thisObject; // 修改字段值 XposedHelpers.setObjectField(instance, "targetField", "Hooked Value"); } } ); } } ``` #### **替代方案:直接操作字段** ```java // 获取目标 Class<?> targetClass = XposedHelpers.findClass( "com.target.app.TargetClass", lpparam.classLoader ); // Hook 字段写入操作 XposedHelpers.findAndHookMethod( targetClass, "setTargetField", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // 篡改输入值 param.args[0] = "Hooked Value"; } } ); ``` --- ### **3. 进阶:内存直接修改(Unsafe )** 适用于绕过部分防护机制(需 API 兼容性处理): ```java public class UnsafeFieldHook { public static void hook() throws Exception { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); // 获取目标字段偏移量 Field targetField = TargetClass.class.getDeclaredField("secret"); long offset = unsafe.objectFieldOffset(targetField); // 强制修改内存值 TargetClass obj = new TargetClass(); unsafe.putObject(obj, offset, "Hacked by Unsafe"); } } ``` --- ### **注意事项** 1. **访问权限限制** - 私有字段需 `setAccessible(true)` - Android 9+ 对隐藏 API 的限制需特殊处理(如使用 `@Hide` 注解绕过) 2. **线程安全** - 多线程环境下需同步字段访问(`synchronized` 或 `volatile`) 3. **字段型匹配** - 使用 `setInt()/getInt()` 处理基本型 - 对象型使用 `set()/get()` 4. **Xposed 兼容性** - 不同 Android 版本需测试 ART 兼容性 - 使用 `XposedBridge.log()` 输出调试信息 --- ### **典型应用场景** | 场景 | 技术方案 | |--------------------------|--------------------------| | 调试当前应用 | Java 反射 | | 修改系统服务 | Xposed + Root 权限 | | 对抗字段混淆 | 内存偏移计算 + Unsafe | | 动态监控字段变化 | Hook 字段的 getter/setter | --- ### **总结** - **反射方案**:简单直接,但受限于当前进程 - **Xposed 方案**:系统级 Hook,需设备 Root - **Unsafe 方案**:底层操作,兼容性风险高 建议优先使用 Xposed 框架,结合字段关联的 getter/setter 方法进行间接 Hook,可提高稳定性和兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值