进程注入技术
VirtualAllocEx() 介绍:
功能:在指定进程的虚拟地址空间中保留、提交或更改内存区域的状态。函数初始化分配给零的内存。
函数原型:LPVOID WINAPI VirtualAllocEx(
HANDLE hProcess, // 进程的句柄。该函数在该进程的虚拟地址空间中分配内存。
LPVOID lpAddress, // 指定要分配的页面区域所需的起始地址的指针。若为 NULL,则自动分配。
SIZE_T dwSize, // 要分配的内存区域的大小。
DWORD flAllocationType, // 内存分配的类型。通常为 MEM_COMMIT。
DWORD flProtect // 要分配的页区域的内存保护。
);
返回值:如果函数成功, 则返回值是分配的页区域的基地址。如果函数失败, 返回值为 NULL。
WriteProcessMemory() 介绍:
功能:将数据写入指定进程中的内存区域。
函数原型:BOOL WINAPI WriteProcessMemory(
HANDLE hProcess, // 要修改的进程内存的句柄。
LPVOID lpBaseAddress, // 指向指定进程中写入数据的基地址的指针。
LPCVOID lpBuffer, // 指向包含要在指定进程的地址空间中写入的数据的缓冲区的指针。
SIZE_T nSize, // 要写入指定进程的字节数。
SIZE_T *lpNumberOfBytesWritten // 指向一个变量的指针, 它接收传输到指定进程中的字节数。
);
返回值:非零表示成功,零表示失败。
VirtualProtectEx() 介绍:
功能:更改指定进程的虚拟地址空间中已提交页区域的保护。
函数原型:BOOL WINAPI VirtualProtectEx(
HANDLE hProcess, // 要更改其内存保护的进程的句柄。
LPVOID lpAddress, // 指向要更改其访问保护属性的页区域的基地址的指针。
SIZE_T dwSize, // 更改其访问保护属性的区域的大小。
DWORD flNewProtect, // 内存保护选项。
PDWORD lpflOldProtect // 一个指针, 该变量接收指定页面区域中第一页的以前访问保护。
);
返回值:非零表示成功,零表示失败。
VirtualFreeEx() 介绍:
功能:在指定的进程中释放申请的虚拟内存空间。
函数原型:LPVOID WINAPI VirtualFreeEx(
HANDLE hProcess, // 目标进程的句柄。
LPVOID lpAddress, // 指定要释放的虚拟内存空间首地址的指针。
SIZE_T dwSize, // 虚拟内存空间的大小。
DWORD dwFreeType, // 释放内存的类型。
参数 dwFreeType:
MEM_DECOMMIT:表示内存空间不可用,内存页还将存在。
MEM_RELEASE:表示内存空间彻底回收。
返回值:非零表示成功,零表示失败。
DemoCode:
#include<windows.h> #include<stdio.h> #include<tlhelp32.h> BOOL LoadDll(DWORD dwProcessId, LPTSTR lpszDllName); int main(void) { HANDLE hProcessSnap; char lpDllName[MAX_PATH] = TEXT("Dll.dll"); PROCESSENTRY32 ProcessEntry = { 0 }; ProcessEntry.dwSize = sizeof(PROCESSENTRY32); hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); BOOL bRet = Process32First(hProcessSnap, &ProcessEntry); while (bRet) { if (strcmp("calc.exe", ProcessEntry.szExeFile) == 0) { LoadDll(ProcessEntry.th32ProcessID, lpDllName); break; } bRet = Process32Next(hProcessSnap, &ProcessEntry); } return 0; } BOOL LoadDll(DWORD dwProcessId, LPTSTR lpszDllName) { int length; HANDLE hProcess = NULL; HANDLE hThread = NULL; PSTR pszDllFile = NULL; hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == NULL) return FALSE; length = 1 + strlen(lpszDllName); pszDllFile = (PSTR)VirtualAllocEx(hProcess, NULL, length, MEM_COMMIT, PAGE_READWRITE); if (pszDllFile == NULL) return FALSE; if ((WriteProcessMemory(hProcess, (PVOID)pszDllFile, (PVOID)lpszDllName, length, NULL)) == FALSE) return FALSE; PTHREAD_START_ROUTINE pfnThreadRtn =
(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"); if (pfnThreadRtn == NULL) return FALSE; hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, (PVOID)pszDllFile, 0, NULL); if (hThread == NULL) { printf("%d", GetLastError()); return FALSE; } WaitForSingleObject(hThread, INFINITE); VirtualFreeEx(hProcess, (PVOID)pszDllFile, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; }
这段代码的 Dll.dll 可以用 动态链接库 那章含有 MessageBox() 的 dll 文件。
程序在我的本机 Win10(64) 上运行会注入失败,但是在虚拟机 Win7(32) 上没问题。