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
+63
View File
@@ -0,0 +1,63 @@
### 如何不在编码时直接导入相关 API 的前提下进行攻击
从攻击者的角度来看,**不在编码时直接导入相关 API** 是一个核心的规避手段。这种技术通常被称为**动态 API 调用**或**运行时 API 解析**,其主要目的是:
1. **绕过签名检测:** 传统的杀毒软件和安全工具会扫描可执行文件中的**导入表**。如果导入表里有 `CreateRemoteThread``WriteProcessMemory``LoadLibrary` 等高危函数,文件就会被标记为可疑。动态调用 API 可以让导入表看起来非常“干净”,从而躲过静态扫描
2. **增加逆向分析难度:** 逆向工程师通常会从导入表入手,快速了解程序的功能。如果导入表是空的或只导入了少数几个基础函数,逆向分析师就必须花费大量时间去跟踪程序的运行时行为,才能发现其真正意图
3. **支持多操作系统版本和架构:** 有些 API 的地址在不同版本的 Windows 上可能会有细微差异。动态获取 API 地址可以确保代码在不同系统上都能正确运行,提高攻击的通用性
4. **按需加载:** 只有在需要执行特定恶意行为时才去获取和调用相应的 API,这可以减少不必要的代码和数据,使恶意程序更小、更精简
下面是几种具体的技术实现,从初级到高级:
**1. 使用 `LoadLibrary` 和 `GetProcAddress`**
这是最基础、最常见的方法。攻击者只需要在代码中静态导入 `LoadLibraryA/W``GetProcAddress` 这两个函数,然后用它们来动态获取所有其他需要的 API
**实现步骤:**
1. **加载 DLL** 调用 `LoadLibraryA`,传入需要加载的 DLL 名称(例如 "kernel32.dll")。这个函数会返回该 DLL 在内存中的基址
2. **获取函数地址:** 调用 `GetProcAddress`,传入 DLL 的基址和需要获取的函数名称(例如 "CreateRemoteThread")。这个函数会返回该 API 的内存地址
3. **函数指针调用:** 将获取到的地址赋值给一个函数指针,然后通过这个指针像调用普通函数一样来调用它
```c
// 伪代码
#include <windows.h>
#include <stdio.h>
int main() {
HMODULE hKernel32 = LoadLibraryA("kernel32.dll");
if (hKernel32 == NULL) {
// 处理错误
return 1;
}
// 定义一个函数指针类型
typedef HANDLE (WINAPI* CreateRemoteThread_t)(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
// 获取 CreateRemoteThread 的地址
CreateRemoteThread_t pCreateRemoteThread = (CreateRemoteThread_t)GetProcAddress(hKernel32, "CreateRemoteThread");
if (pCreateRemoteThread == NULL) {
// 处理错误
return 1;
}
// 现在可以使用 pCreateRemoteThread 来调用 CreateRemoteThread 函数了
// pCreateRemoteThread(..., ..., ...);
return 0;
}
```
这种方法虽然简单,但 `LoadLibrary``GetProcAddress` 依然会出现在程序的导入表中,因此安全软件仍然可以进行识别
**2. 手动解析 PEB**
这是更高级、更隐蔽的方法。其核心是**完全不依赖任何静态导入**,通过**手动遍历内存中的数据结构**来找到所需的 API 地址
**实现步骤:**
1. **获取 PEB 地址:** 在 32 位系统上,PEB 的地址可以通过 `FS:[0x30]` 寄存器来获取;在 64 位系统上,可以通过 `GS:[0x60]` 来获取
2. **遍历 PEB LDR 数据结构:** PEB 结构体中包含一个指向已加载模块列表的指针(`LDR_DATA`)。攻击者可以遍历这个列表,找到 `ntdll.dll``kernel32.dll` 等已加载的 DLL 模块
3. **解析 DLL 的导出表(EAT):** 找到目标 DLL 的基址后,手动解析其**导出地址表 (EAT)**。EAT 是一个包含所有导出函数名称和地址的结构
4. **哈希值匹配:** 为了避免在代码中硬编码函数名称字符串(字符串会暴露恶意意图),攻击者通常会为每个函数名称计算一个哈希值。遍历 EAT 中的函数名称,计算哈希值,然后与预设的目标哈希值进行匹配。如果匹配成功,就找到了所需 API 的地址
5. **函数指针调用:** 获取到地址后,同样通过函数指针进行调用