1,拉伸文件
2,打开进程
3,分配空间
4,修复重定位表
5,修复IAT表
6,写入模块
7,创建远程线程
//内存写入注入
CHAR* SrcBuffer; //
CHAR* ImageBuffer; //拉伸后的源文件
DWORD SizeOfImage;
DWORD ImageBase;
DWORD OEP;
LPVOID lp; //VirtualAllocEx返回的地址
BOOL HasReloc = FALSE;
BOOL ExtendSrc() {
WORD peCheck = *(WORD*)(SrcBuffer);
if (peCheck != 0x5A4D) {
return FALSE;
}
DWORD e_lfanew = *(DWORD*)(SrcBuffer + 0x3c);
CHAR* peHeader = SrcBuffer + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
DWORD SectionAlignment = *(DWORD*)(opHeader + 0x20);
SizeOfImage = *(DWORD*)(opHeader + 0x38);
ImageBase = *(DWORD*)(opHeader + 0x1c);
OEP = *(DWORD*)(opHeader + 0x10);
if (*(DWORD*)(opHeader + 0x60 + 0x28) != NULL) {
HasReloc = TRUE;
}
DWORD SizeoOfHeaders = *(DWORD*)(opHeader + 0x3c);
WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
ImageBuffer = (CHAR*)malloc(SizeOfImage + 1);
if (ImageBuffer == NULL) {
return FALSE;
}
else {
memset(ImageBuffer, 'x00', SizeOfImage + 1);
}
memcpy(ImageBuffer, SrcBuffer, SizeoOfHeaders);
DWORD Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
for (DWORD j = 0; j < NumberOfSections; j++) {
Misc = *(DWORD*)(Sections_addr + 0x8);
VirtualAddress = *(DWORD*)(Sections_addr + 0xc);
SizeOfRawData = *(DWORD*)(Sections_addr + 0x10);
PointerToRawData = *(DWORD*)(Sections_addr + 0x14);
if (SizeOfRawData == NULL) {
Sections_addr = Sections_addr + 0x28;
continue;
}
if (Misc > SizeOfRawData) {
memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, Misc);
}
else {
memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, SizeOfRawData);
}
Sections_addr = Sections_addr + 0x28;
}
free(SrcBuffer);
SrcBuffer = NULL;
return TRUE;
}
VOID repairReloc(DWORD newAddr) {
DWORD e_lfanew = *(DWORD*)(ImageBuffer + 0x3c);
CHAR* peHeader = ImageBuffer + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
DWORD relocRVA = *(DWORD*)(opHeader + 0x60 + 0x28);
CHAR* addr = ImageBuffer + relocRVA;
CHAR* size = addr + 4;
CHAR* data = size + 4;
while (*(DWORD*)addr != 0 && *(DWORD*)size != 0) {
DWORD num = (*(DWORD*)size - 8) / 2;
for (DWORD i = 0; i < num; i++) {
WORD Characteristics = (*(WORD*)data & 0xf000) >> 12;
WORD offset = *(WORD*)data & 0x0fff;
if (Characteristics == 0x3) {
DWORD NewData = *(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) - ImageBase + newAddr;
*(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) = NewData;
}
data += 2;
}
addr += *(DWORD*)size;
size = addr + 4;
data = size + 4;
}
}
VOID repairIAT() {
ULONG uSize;
PIMAGE_IMPORT_DESCRIPTOR PImport;
CHAR* PThunk;
CHAR* POriginalFirstThunk;
CHAR* szModule;
CHAR* szFunc;
PImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToDataEx(ImageBuffer, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &uSize, NULL);
while (TRUE) {
szModule = (CHAR*)ImageBuffer + PImport->Name;
if (strcmp(szModule, "KERNEL32.dll") == 0) {
break;
}
PImport++;
}
HMODULE hKernel = GetModuleHandleA("KERNEL32.dll");
POriginalFirstThunk = (CHAR*)ImageBuffer + PImport->OriginalFirstThunk;
PThunk = (CHAR*)ImageBuffer + PImport->FirstThunk;
while (*(DWORD*)POriginalFirstThunk != 0) {
if ((*(DWORD*)POriginalFirstThunk & 0x80000000) == 0) {
szFunc = (CHAR*)ImageBuffer + *(DWORD*)POriginalFirstThunk + 0x2;
DWORD ret = (DWORD)GetProcAddress(hKernel, szFunc);
*(DWORD*)PThunk = ret;
}
else {
DWORD ret = (DWORD)GetProcAddress(hKernel, (LPCSTR)(*(DWORD*)POriginalFirstThunk & 0x7ffffff));
*(DWORD*)PThunk = ret;
}
POriginalFirstThunk += 4;
PThunk += 4;
}
}
BOOL MyAlloc(HANDLE p) {
if (HasReloc) {
lp = VirtualAllocEx(p, NULL, SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lp == NULL) {
return FALSE;
}
repairReloc((DWORD)lp);
repairIAT();
}
else
{
return FALSE;
}
return TRUE;
}
BOOL inject(DWORD PID) {
FILE* fp;
WCHAR fileName[] = L"testDll.dll";
_wfopen_s(&fp, fileName, L"rb");
if (fp == NULL) {
MessageBox(0, L"can't open file", 0, MB_OK);
return FALSE;
}
fseek(fp, 0, SEEK_END);
DWORD len = ftell(fp);
fseek(fp, 0, SEEK_SET);
SrcBuffer = (CHAR*)malloc(len + 1);
if (SrcBuffer != NULL) {
fread(SrcBuffer, len + 1, 1, fp);
}
fclose(fp);
//拉伸文件
BOOL isExtend = ExtendSrc();
if (isExtend == FALSE) {
free(SrcBuffer);
SrcBuffer = NULL;
return FALSE;
}
//打开进程
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL) {
MessageBox(0, L"无法打开进程", 0, 0);
return FALSE;
}
//分配空间,修复重定位表
BOOL allocCheck = MyAlloc(hProcess);
if (allocCheck == FALSE) {
free(ImageBuffer);
ImageBuffer = NULL;
return FALSE;
}
//内存写入
BOOL writeCheck = WriteProcessMemory(hProcess, lp, ImageBuffer, SizeOfImage, NULL);
if (writeCheck == FALSE) {
free(ImageBuffer);
ImageBuffer = NULL;
return FALSE;
}
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, NULL,
(LPTHREAD_START_ROUTINE)((CHAR*)lp+0x117e0),
NULL, NULL, NULL);
return TRUE;
}
线程函数
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
typedef int(__stdcall* pfMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
pfMessageBoxA MessageBoxA = NULL;
BOOL res = FALSE;
HMODULE m = LoadLibraryA("User32.dll");
if (m) {
MessageBoxA = (pfMessageBoxA)GetProcAddress(m, "MessageBoxA");
MessageBoxA(0, 0, 0, 0);
FreeLibrary(m);
}
return 0;
}
因为只修复了KERNEL32.dll,使用API要显式调用,也可以在线程函数中进一步修复IAT表