Add files via upload

This commit is contained in:
雾島风起時
2025-09-25 04:02:19 +08:00
committed by GitHub
parent 6d955ffc2a
commit 49832f115f
25 changed files with 1001 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
### 如何动态地去找导入表
**为什么要动态地查找?**
静态地查找导入表非常简单,我们只需要解析 PE 文件头中的数据目录(Data Directory),找到导入表的结构体 `IMAGE_IMPORT_DESCRIPTOR`,然后就可以找到所有的导入函数。但这种方法有几个局限性:
1. **脱壳(Unpacking):** 许多恶意软件会使用加壳技术(packer),将原始的 PE 文件压缩或加密。这种情况下,原始的导入表会被隐藏或破坏,静态分析工具无法找到它。当程序运行时,加壳器会自行解压和修复导入表,因此只有在内存中才能找到真正的导入表
2. **动态加载(Dynamic Loading):** 程序可能会使用 `LoadLibrary``GetProcAddress` 等函数在运行时动态加载 DLL 和获取函数地址。这种方式下,导入的函数根本不会出现在 PE 文件的静态导入表中
3. **防止逆向工程:** 有些程序开发者故意混淆或破坏导入表,以增加逆向工程的难度
因此,动态地查找导入表是进行脱壳、恶意软件分析和深入逆向工程的必备技能
**方法一:利用 `EAT` (导出地址表)**
这是最直接、也是最不寻常的方法。如果一个程序(比如一个 DLL)将自己的导入表中的函数地址作为导出函数暴露出来,你就可以通过解析它的**导出表 (Export Address Table, EAT)** 来找到导入表。但这种情况非常少见,通常只在一些特殊的系统 DLL 或驱动程序中出现。这种方法不具有通用性
**方法二:利用函数调用指令**
这是最常见、最实用的方法。当程序调用一个导入函数时,通常会使用 `CALL` 指令,其目标地址就是导入表中的一个条目
**具体步骤:**
1. **调试器附加:** 使用调试器(如 OllyDbg、x64dbg、IDA Pro Debugger)附加到目标进程
2. **设置断点:** 在程序执行的早期,比如 `main` 函数或 `WinMain` 函数的入口点设置断点
3. **单步调试/跟踪:** 逐步执行(Step Over)程序,并密切关注 `CALL` 指令
4. **识别导入调用:**
- **相对 `CALL`:** 如果你看到 `CALL [地址]` 这样的指令,并且这个地址是一个外部函数的地址,那么这个 `[地址]` 就是一个导入表项。例如,`CALL DWORD PTR [EAX]`
- **直接 `CALL`:** 如果你看到 `CALL MessageBoxA`,这通常是 IDA Pro 这样的反汇编器帮你标记的,它已经识别出这个调用指向了一个导入函数
5. **内存转储和分析:** 当你找到一个导入表项的地址后,你可以从这个地址开始,向前和向后扫描内存,寻找连续的、看起来像函数指针的地址序列。这个序列很可能就是完整的导入表。然后你可以将这一块内存转储出来进行进一步分析
这种方法需要对汇编语言有深入理解,并且需要耐心和细致的调试
**方法三:利用内存断点和内存扫描**
当程序加载时,加载器会向导入表写入外部函数的真实地址。我们可以利用这个特性
**具体步骤:**
1. **调试器附加:** 附加到目标进程
2. **查找 `IMAGE_IMPORT_DESCRIPTOR`** 使用静态分析工具(如 PE Explorer、CFF Explorer)找到 PE 文件中导入表的 `RVA` (Relative Virtual Address)
3. **计算内存地址:**`RVA` 加上基址(ImageBase)得到导入表在内存中的实际地址
4. **设置硬件断点:** 在导入表的第一个条目上设置一个硬件写入断点(Hardware Write Breakpoint
5. **运行程序:** 运行程序。当加载器填充导入表时,断点会被触发。这通常发生在 `LoadLibrary` 函数调用之后,但在 `main` 函数之前
6. **分析内存:** 断点触发后,你就可以检查内存中的导入表,它的内容已经被加载器填充好了。如果程序进行了脱壳,此时的导入表才是真实的
**另一种高级变体是:**
- 在程序执行早期,在整个 `.text` 段(代码段)设置一个硬件写入断点。当断点触发时,检查写入的地址是否在代码段内部,并分析写入的指令。这可以用来检测自修改代码,是更高级的逆向技术