模塊隱藏那節(jié)課要求完成兩個(gè)作業(yè),都是隱藏模塊,本文介紹兩種方法分別如何實(shí)現(xiàn)。
方法一:往自己的進(jìn)程注入游戲主模塊
這個(gè)題目的意思是將程序的基址設(shè)置成高地址,將0x400000空出來,然后將游戲主模塊拉伸,修復(fù)IAT之后,注入進(jìn)去。這樣做的好處主要是簡(jiǎn)單,因?yàn)椴恍枰迯?fù)重定位表了。缺點(diǎn)也很明顯,很多時(shí)候根本沒辦法在0x400000處申請(qǐng)足夠大的內(nèi)存容納游戲程序。,還有就是有些程序跳轉(zhuǎn)到OEP之后會(huì)卡住,具體原因我也不知道。我這里用dbgview.exe測(cè)試,能夠正常啟動(dòng),這足夠說明我的代碼沒有大的錯(cuò)誤。
任務(wù)管理器中只會(huì)看到控制臺(tái)的進(jìn)程,看不到dbgview的進(jìn)程:
所謂修復(fù)IAT,就是指,將游戲PE的IAT表修復(fù)成函數(shù)地址,做法也很簡(jiǎn)單,遍歷IAT表,loadlibary獲取dll句柄,然后遍歷函數(shù)名或函數(shù)序號(hào),一個(gè)個(gè)getprocaddress,將獲取到的函數(shù)地址寫入到IAT表就算修復(fù)好了。
下面是我的代碼,我只給出關(guān)鍵的兩個(gè)函數(shù),一個(gè)是修復(fù)IAT表,一個(gè)是注入的函數(shù),完整代碼放在文章最后。
注入代碼
void GameInjectMe()
{ if ((DWORD
)GetModuleHandle(NULL) != (DWORD
)0x20000000){printf("當(dāng)前進(jìn)程句柄: 0x%X\n", (DWORD
)GetModuleHandle(NULL));printf("請(qǐng)修改鏈接設(shè)置,將ImageBase設(shè)置為0x20000000\n");return;}LPVOID pFileBuffer
= NULL;FileToMemory(TEXT("c:\\program32\\dbgview.exe"), &pFileBuffer
);LPVOID pImageBuffer
= NULL;DWORD dwImageSize
= FileBufferToImageBuffer(pFileBuffer
, &pImageBuffer
);PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
)); LPVOID pImageBase
= VirtualAlloc((LPVOID
)pOptionHeader
->ImageBase
, dwImageSize
,MEM_COMMIT
, PAGE_READWRITE
); if (pImageBase
!= (LPVOID
)pOptionHeader
->ImageBase
){printf("錯(cuò)誤碼:0x%X 在ImageBase(0x%X)處VirtualAlloc失敗\n",GetLastError(),pOptionHeader
->ImageBase
);return;}RepairIAT(pImageBuffer
); memcpy(pImageBase
, pImageBuffer
, dwImageSize
);DWORD dwOEP
= pOptionHeader
->AddressOfEntryPoint
+ pOptionHeader
->ImageBase
;__asm
{jmp dwOEP
}
}
修復(fù)IAT代碼
void RepairIAT(LPVOID pImageBuffer
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pDosHeader
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);
PIMAGE_IMPORT_DESCRIPTOR pImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)((DWORD
)pImageBuffer
+ \pOptionHeader
->DataDirectory
[1].VirtualAddress
);while (pImportTable
->OriginalFirstThunk
|| pImportTable
->FirstThunk
){HMODULE hModule
= LoadLibraryA((LPCSTR
)(pImportTable
->Name
+ (DWORD
)pImageBuffer
));if (NULL == hModule
){printf("獲取模塊句柄失敗,模塊名: %s\n",(LPCSTR
)(pImportTable
->Name
+ (DWORD
)pImageBuffer
));}PIMAGE_THUNK_DATA32 pThunkData
= (PIMAGE_THUNK_DATA32
)((DWORD
)pImageBuffer
+ \pImportTable
->FirstThunk
);while (*((PDWORD
)pThunkData
) != 0){if ((*((PDWORD
)pThunkData
) & 0x80000000) == 0x80000000){DWORD dwProcAddress
= (DWORD
)GetProcAddress(hModule
,MAKEINTRESOURCE((*((PDWORD
)pThunkData
) & 0x7FFFFFFF))); *((PDWORD
)pThunkData
) = dwProcAddress
;}else{PIMAGE_IMPORT_BY_NAME pIBN
= (PIMAGE_IMPORT_BY_NAME
)(*((PDWORD
)pThunkData
) + \
(DWORD
)pImageBuffer
);DWORD dwProcAddress
= (DWORD
)GetProcAddress(hModule
,(LPCSTR
)pIBN
->Name
);*((PDWORD
)pThunkData
) = dwProcAddress
;}pThunkData
++;}pImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)((DWORD
)pImportTable
+ sizeof(IMAGE_IMPORT_DESCRIPTOR
)); }
}
其實(shí)方法一的局限性我在博客開頭已經(jīng)分析過了,不過我想了一下發(fā)現(xiàn),其實(shí)問題關(guān)鍵就是0x400000處可能會(huì)申請(qǐng)內(nèi)存失敗,實(shí)際上我們不需要非得在這個(gè)地方申請(qǐng)內(nèi)存,而是可以在任意地方申請(qǐng),然后根據(jù)重定位表,修復(fù)地址即可。而這種方式,在方法二里面用到了。
以上是第一種方法的做法,下面是第二種做法,往游戲里注入自己,然后跳轉(zhuǎn)到入口函數(shù):
方法二:往游戲進(jìn)程注入自己的主模塊
這種方式不需要手工修復(fù)IAT,因?yàn)樽陨磉M(jìn)程啟動(dòng)時(shí)操作系統(tǒng)幫我們修復(fù)了,我們只需要修復(fù)重定位表即可。
原理上圖已經(jīng)解釋的非常明白了,下面給出關(guān)鍵代碼:
重定位表修復(fù)代碼
VOID
SetNewImageBase2(LPVOID pImageBuffer
, DWORD dwNewImageBase
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pDosHeader
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);PIMAGE_BASE_RELOCATION pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pImageBuffer
+ \pOptionHeader
->DataDirectory
[5].VirtualAddress
);DWORD dwImageBaseDelta
= dwNewImageBase
- pOptionHeader
->ImageBase
; while (pRelocationTable
->VirtualAddress
|| pRelocationTable
->SizeOfBlock
){size_t n
= (pRelocationTable
->SizeOfBlock
- 8) / 2; PWORD pOffset
= (PWORD
)((DWORD
)pRelocationTable
+ 8); for (size_t i
= 0; i
< n
; i
++){if ((pOffset
[i
] & 0xF000) == 0x3000){DWORD dwRva
= pRelocationTable
->VirtualAddress
+ (pOffset
[i
] & 0x0FFF); PDWORD pData
= (PDWORD
)((DWORD
)pImageBuffer
+ dwRva
);*pData
+= dwImageBaseDelta
;}} pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pRelocationTable
+ pRelocationTable
->SizeOfBlock
);}pOptionHeader
->ImageBase
= dwNewImageBase
;
}
注入代碼
void MeInjectGame()
{HMODULE hModule
= GetModuleHandle(NULL);LPVOID pImageBuffer
= (LPVOID
)hModule
; PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
)); DWORD dwSizeOfImage
= pOptionHeader
->SizeOfImage
;pImageBuffer
= malloc(dwSizeOfImage
);memcpy(pImageBuffer
, hModule
, dwSizeOfImage
);HWND hWnd
= FindWindowA(NULL, "LittleGame");DWORD dwPID
= 0;GetWindowThreadProcessId(hWnd
, &dwPID
);printf("進(jìn)程id: %d\n", dwPID
); HANDLE hProcess
= OpenProcess(PROCESS_ALL_ACCESS
,FALSE
,dwPID
);LPVOID pGameImageBase
= VirtualAllocEx(hProcess
,NULL,dwSizeOfImage
,MEM_COMMIT
,PAGE_EXECUTE_READWRITE
);if (NULL == pGameImageBase
){printf("在游戲進(jìn)程申請(qǐng)內(nèi)存失敗,錯(cuò)誤碼: %d\n", GetLastError());return;}SetNewImageBase2(pImageBuffer
, (DWORD
)pGameImageBase
);WriteProcessMemory(hProcess
,pGameImageBase
,pImageBuffer
,dwSizeOfImage
,NULL);DWORD dwProcOffset
= (DWORD
)InjectEntry
- (DWORD
)hModule
+ (DWORD
)pGameImageBase
;CreateRemoteThread(hProcess
,NULL,NULL,(LPTHREAD_START_ROUTINE
)dwProcOffset
,NULL,NULL,NULL);
}
入口代碼
DWORD WINAPI
InjectEntry(LPVOID param
)
{while (TRUE
){MessageBox(0,0,0,0);Sleep(5000);}return 0;
}
完整代碼
最后,給出項(xiàng)目完整的代碼。
PE.H
#ifndef PE_HPP_
#define PE_HPP_#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif #include <stdio.h>
#include <WINDOWS.H>
#include <STRING.h>
#include <MALLOC.H>DWORD
FileToMemory(LPCSTR lpszFile
, LPVOID
*pFileBuffer
);
BOOL
MemoryToFile(LPVOID pMemBuffer
, DWORD dwSize
, LPCSTR lpszFile
);
BOOL
Is32PEFile(LPVOID pFileBuffer
, DWORD dwSize
);
DWORD
FileBufferToImageBuffer(LPVOID pFileBuffer
, LPVOID
*pImageBuffer
);
DWORD
ImageBufferToFileBuffer(LPVOID pImageBuffer
, LPVOID
*pFileBuffer
);
DWORD
Align(DWORD dwOffset
, DWORD dwAlign
);
DWORD
RvaToFoa(LPVOID pFileBuffer
, DWORD dwRva
);
DWORD
FoaToRva(LPVOID pFileBuffer
, DWORD dwFoa
);
DWORD
MoveNTHeaderAndSectionHeadersToDosStub(LPVOID pFileBuffer
);
VOID
SetNewImageBase(LPVOID pFileBuffer
, DWORD dwNewImageBase
);
void RepairIAT(LPVOID pImageBuffer
);
DWORD
FileToMemory(LPCSTR lpszFile
, LPVOID
*pFileBuffer
)
{FILE
*pFile
= NULL;DWORD dwFileSize
= 0;pFile
= fopen(lpszFile
, "rb");if (pFile
== NULL){printf("打開文件失敗\n");return 0;}fseek(pFile
, 0, SEEK_END);dwFileSize
= ftell(pFile
);fseek(pFile
, 0, SEEK_SET);*pFileBuffer
= malloc(dwFileSize
);if (*pFileBuffer
== NULL){printf("分配內(nèi)存失敗\n");fclose(pFile
);return 0;}DWORD dwRead
= fread(*pFileBuffer
, 1, dwFileSize
, pFile
);fclose(pFile
);if (dwRead
!= dwFileSize
){free(*pFileBuffer
);return 0;}return dwRead
;
}
BOOL
Is32PEFile(LPVOID pFileBuffer
, DWORD dwSize
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);if (*((PWORD
)pDosHeader
) != IMAGE_DOS_SIGNATURE
){printf("不是有效的MZ標(biāo)志\n");return FALSE
;}if (pNTHeader
->Signature
!= IMAGE_NT_SIGNATURE
){printf("不是有效的PE標(biāo)記\n");return FALSE
;}return TRUE
;
}
DWORD
FileBufferToImageBuffer(LPVOID pFileBuffer
, LPVOID
*pImageBuffer
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);*pImageBuffer
= malloc(pOptionHeader
->SizeOfImage
);if (*pImageBuffer
== NULL){printf("分配內(nèi)存失敗\n");return 0;}memset(*pImageBuffer
, 0, pOptionHeader
->SizeOfImage
);memcpy(*pImageBuffer
, pFileBuffer
, pOptionHeader
->SizeOfHeaders
);for (int i
= 0; i
< pPEHeader
->NumberOfSections
; i
++){memcpy((LPVOID
)((DWORD
)(*pImageBuffer
) + pSectionHeader
[i
].VirtualAddress
), \
(LPVOID
)((DWORD
)pFileBuffer
+ pSectionHeader
[i
].PointerToRawData
), \pSectionHeader
[i
].SizeOfRawData
);}return pOptionHeader
->SizeOfImage
;
}
DWORD
ImageBufferToFileBuffer(LPVOID pImageBuffer
, LPVOID
*pFileBuffer
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);PIMAGE_SECTION_HEADER pLastSectionHeader
= pSectionHeader
+ pPEHeader
->NumberOfSections
- 1;DWORD dwFileBufferSize
= pLastSectionHeader
->PointerToRawData
+ pLastSectionHeader
->SizeOfRawData
;*pFileBuffer
= malloc(dwFileBufferSize
);if (*pFileBuffer
== NULL){printf("分配內(nèi)存失敗\n");return 0;}memset(*pFileBuffer
, 0, dwFileBufferSize
);memcpy(*pFileBuffer
, pImageBuffer
, pOptionHeader
->SizeOfHeaders
);for (int i
= 0; i
< pPEHeader
->NumberOfSections
; i
++){memcpy((LPVOID
)((DWORD
)(*pFileBuffer
) + pSectionHeader
[i
].PointerToRawData
), \
(LPVOID
)((DWORD
)pImageBuffer
+ pSectionHeader
[i
].VirtualAddress
), \pSectionHeader
[i
].SizeOfRawData
);}return dwFileBufferSize
;
}
BOOL
MemoryToFile(LPVOID pMemBuffer
, DWORD dwSize
, LPCSTR lpszFile
)
{FILE
*fp
= NULL;fp
= fopen(lpszFile
, "wb+");if (fp
== NULL){printf("打開文件失敗\n");return FALSE
;}DWORD dwWritten
= fwrite(pMemBuffer
, 1, dwSize
, fp
);if (dwWritten
!= dwSize
){printf("寫入了 %d 字節(jié),不等于 %d\n", dwWritten
, dwSize
);fclose(fp
);return FALSE
;}fclose(fp
);return TRUE
;
}
DWORD
Align(DWORD dwOffset
, DWORD dwAlign
)
{if (dwOffset
<= dwAlign
) return dwAlign
;if (dwOffset
% dwAlign
){return (dwOffset
/ dwAlign
+ 1) * dwAlign
;}return dwOffset
;
}
DWORD
RvaToFoa(LPVOID pFileBuffer
, DWORD dwRva
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pFileBuffer
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);if (dwRva
< pOptionHeader
->SizeOfHeaders
){return dwRva
;}for (int i
= 0; i
< pPEHeader
->NumberOfSections
; i
++){if (dwRva
>= pSectionHeader
[i
].VirtualAddress
&& \dwRva
< pSectionHeader
[i
].VirtualAddress
+ pSectionHeader
[i
].Misc
.VirtualSize
){int offset
= dwRva
- pSectionHeader
[i
].VirtualAddress
;return pSectionHeader
[i
].PointerToRawData
+ offset
;}}printf("找不到RVA %x 對(duì)應(yīng)的 FOA,轉(zhuǎn)換失敗\n", dwRva
);return 0;
}
DWORD
FoaToRva(LPVOID pFileBuffer
, DWORD dwFoa
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pFileBuffer
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);if (dwFoa
< pOptionHeader
->SizeOfHeaders
){return dwFoa
;}for (int i
= 0; i
< pPEHeader
->NumberOfSections
; i
++){if (dwFoa
>= pSectionHeader
[i
].PointerToRawData
&& \dwFoa
< pSectionHeader
[i
].PointerToRawData
+ pSectionHeader
[i
].SizeOfRawData
){int offset
= dwFoa
- pSectionHeader
[i
].PointerToRawData
;return pSectionHeader
[i
].VirtualAddress
+ offset
;}}printf("找不到FOA %x 對(duì)應(yīng)的 RVA,轉(zhuǎn)換失敗\n", dwFoa
);return 0;
}
DWORD
MoveNTHeaderAndSectionHeadersToDosStub(LPVOID pFileBuffer
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);LPVOID pDst
= (LPVOID
)((DWORD
)pDosHeader
+ sizeof(IMAGE_DOS_HEADER
)); DWORD dwRet
= (DWORD
)pNTHeader
- (DWORD
)pDst
; DWORD dwSize
= 4 + sizeof(IMAGE_FILE_HEADER
) + pPEHeader
->SizeOfOptionalHeader
+ \
sizeof(IMAGE_SECTION_HEADER
) * pPEHeader
->NumberOfSections
; LPVOID pSrc
= malloc(dwSize
);if (pSrc
== NULL){printf("分配內(nèi)存失敗\n");return 0;}memcpy(pSrc
, (LPVOID
)pNTHeader
, dwSize
); memset((LPVOID
)pNTHeader
, 0, dwSize
); memcpy(pDst
, pSrc
, dwSize
); free(pSrc
);pDosHeader
->e_lfanew
= sizeof(IMAGE_DOS_HEADER
); return dwRet
;
}
VOID
SetNewImageBase(LPVOID pFileBuffer
, DWORD dwNewImageBase
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pDosHeader
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);PIMAGE_BASE_RELOCATION pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pFileBuffer
+ \
RvaToFoa(pFileBuffer
, pOptionHeader
->DataDirectory
[5].VirtualAddress
));DWORD dwImageBaseDelta
= dwNewImageBase
- pOptionHeader
->ImageBase
; while (pRelocationTable
->VirtualAddress
|| pRelocationTable
->SizeOfBlock
){size_t n
= (pRelocationTable
->SizeOfBlock
- 8) / 2; PWORD pOffset
= (PWORD
)((DWORD
)pRelocationTable
+ 8); for (size_t i
= 0; i
< n
; i
++){if ((pOffset
[i
] & 0xF000) == 0x3000){DWORD dwRva
= pRelocationTable
->VirtualAddress
+ (pOffset
[i
] & 0x0FFF);DWORD dwFoa
= RvaToFoa(pFileBuffer
, dwRva
);PDWORD pData
= (PDWORD
)((DWORD
)pFileBuffer
+ dwFoa
);*pData
+= dwImageBaseDelta
;}}pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pRelocationTable
+ pRelocationTable
->SizeOfBlock
);}pOptionHeader
->ImageBase
= dwNewImageBase
;
}
VOID
SetNewImageBase2(LPVOID pImageBuffer
, DWORD dwNewImageBase
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pDosHeader
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);PIMAGE_BASE_RELOCATION pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pImageBuffer
+ \pOptionHeader
->DataDirectory
[5].VirtualAddress
);DWORD dwImageBaseDelta
= dwNewImageBase
- pOptionHeader
->ImageBase
; while (pRelocationTable
->VirtualAddress
|| pRelocationTable
->SizeOfBlock
){size_t n
= (pRelocationTable
->SizeOfBlock
- 8) / 2; PWORD pOffset
= (PWORD
)((DWORD
)pRelocationTable
+ 8); for (size_t i
= 0; i
< n
; i
++){if ((pOffset
[i
] & 0xF000) == 0x3000){DWORD dwRva
= pRelocationTable
->VirtualAddress
+ (pOffset
[i
] & 0x0FFF); PDWORD pData
= (PDWORD
)((DWORD
)pImageBuffer
+ dwRva
);*pData
+= dwImageBaseDelta
;}} pRelocationTable
= (PIMAGE_BASE_RELOCATION
)((DWORD
)pRelocationTable
+ pRelocationTable
->SizeOfBlock
);}pOptionHeader
->ImageBase
= dwNewImageBase
;
}
void RepairIAT(LPVOID pImageBuffer
)
{PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)(pDosHeader
->e_lfanew
+ (DWORD
)pDosHeader
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
));PIMAGE_SECTION_HEADER pSectionHeader
= \
(PIMAGE_SECTION_HEADER
)((DWORD
)pOptionHeader
+ pPEHeader
->SizeOfOptionalHeader
);PIMAGE_IMPORT_DESCRIPTOR pImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)((DWORD
)pImageBuffer
+ \pOptionHeader
->DataDirectory
[1].VirtualAddress
); while (pImportTable
->OriginalFirstThunk
|| pImportTable
->FirstThunk
){HMODULE hModule
= LoadLibraryA((LPCSTR
)(pImportTable
->Name
+ (DWORD
)pImageBuffer
));if (NULL == hModule
){printf("獲取模塊句柄失敗,模塊名: %s\n",(LPCSTR
)(pImportTable
->Name
+ (DWORD
)pImageBuffer
));}PIMAGE_THUNK_DATA32 pThunkData
= (PIMAGE_THUNK_DATA32
)((DWORD
)pImageBuffer
+ \pImportTable
->FirstThunk
);while (*((PDWORD
)pThunkData
) != 0){if ((*((PDWORD
)pThunkData
) & 0x80000000) == 0x80000000){DWORD dwProcAddress
= (DWORD
)GetProcAddress(hModule
,MAKEINTRESOURCE((*((PDWORD
)pThunkData
) & 0x7FFFFFFF))); *((PDWORD
)pThunkData
) = dwProcAddress
;}else{PIMAGE_IMPORT_BY_NAME pIBN
= (PIMAGE_IMPORT_BY_NAME
)(*((PDWORD
)pThunkData
) + \
(DWORD
)pImageBuffer
);DWORD dwProcAddress
= (DWORD
)GetProcAddress(hModule
,(LPCSTR
)pIBN
->Name
);*((PDWORD
)pThunkData
) = dwProcAddress
;}pThunkData
++;}pImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)((DWORD
)pImportTable
+ sizeof(IMAGE_IMPORT_DESCRIPTOR
)); }
}#endif
main.cpp
#include "stdafx.h"
#include "PE.h"
#include <MALLOC.H>void GameInjectMe();
void MeInjectGame();
BOOL
EnableDebugPrivilege();
DWORD WINAPI
InjectEntry(LPVOID param
);int main(int argc
, char* argv
[])
{EnableDebugPrivilege(); MeInjectGame();return 0;
}
void GameInjectMe()
{ if ((DWORD
)GetModuleHandle(NULL) != (DWORD
)0x20000000){printf("當(dāng)前進(jìn)程句柄: 0x%X\n", (DWORD
)GetModuleHandle(NULL));printf("請(qǐng)修改鏈接設(shè)置,將ImageBase設(shè)置為0x20000000\n");return;}LPVOID pFileBuffer
= NULL;FileToMemory(TEXT("c:\\program32\\dbgview.exe"), &pFileBuffer
);LPVOID pImageBuffer
= NULL;DWORD dwImageSize
= FileBufferToImageBuffer(pFileBuffer
, &pImageBuffer
);PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pFileBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
)); LPVOID pImageBase
= VirtualAlloc((LPVOID
)pOptionHeader
->ImageBase
, dwImageSize
,MEM_COMMIT
, PAGE_READWRITE
); if (pImageBase
!= (LPVOID
)pOptionHeader
->ImageBase
){printf("錯(cuò)誤碼:0x%X 在ImageBase(0x%X)處VirtualAlloc失敗\n",GetLastError(),pOptionHeader
->ImageBase
);return;}RepairIAT(pImageBuffer
); memcpy(pImageBase
, pImageBuffer
, dwImageSize
);DWORD dwOEP
= pOptionHeader
->AddressOfEntryPoint
+ pOptionHeader
->ImageBase
;__asm
{jmp dwOEP
}
}
void MeInjectGame()
{HMODULE hModule
= GetModuleHandle(NULL);LPVOID pImageBuffer
= (LPVOID
)hModule
; PIMAGE_DOS_HEADER pDosHeader
= (PIMAGE_DOS_HEADER
)pImageBuffer
;PIMAGE_NT_HEADERS pNTHeader
= (PIMAGE_NT_HEADERS
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
);PIMAGE_FILE_HEADER pPEHeader
= (PIMAGE_FILE_HEADER
)((DWORD
)pDosHeader
+ pDosHeader
->e_lfanew
+ 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader
= (PIMAGE_OPTIONAL_HEADER32
)((DWORD
)pPEHeader
+ sizeof(IMAGE_FILE_HEADER
)); DWORD dwSizeOfImage
= pOptionHeader
->SizeOfImage
;pImageBuffer
= malloc(dwSizeOfImage
);memcpy(pImageBuffer
, hModule
, dwSizeOfImage
);HWND hWnd
= FindWindowA(NULL, "LittleGame");DWORD dwPID
= 0;GetWindowThreadProcessId(hWnd
, &dwPID
);printf("進(jìn)程id: %d\n", dwPID
); HANDLE hProcess
= OpenProcess(PROCESS_ALL_ACCESS
,FALSE
,dwPID
);LPVOID pGameImageBase
= VirtualAllocEx(hProcess
,NULL,dwSizeOfImage
,MEM_COMMIT
,PAGE_EXECUTE_READWRITE
);if (NULL == pGameImageBase
){printf("在游戲進(jìn)程申請(qǐng)內(nèi)存失敗,錯(cuò)誤碼: %d\n", GetLastError());return;}SetNewImageBase2(pImageBuffer
, (DWORD
)pGameImageBase
);WriteProcessMemory(hProcess
,pGameImageBase
,pImageBuffer
,dwSizeOfImage
,NULL);DWORD dwProcOffset
= (DWORD
)InjectEntry
- (DWORD
)hModule
+ (DWORD
)pGameImageBase
;CreateRemoteThread(hProcess
,NULL,NULL,(LPTHREAD_START_ROUTINE
)dwProcOffset
,NULL,NULL,NULL);
}DWORD WINAPI
InjectEntry(LPVOID param
)
{while (TRUE
){MessageBox(0,0,0,0);Sleep(5000);}return 0;
}
BOOL
EnableDebugPrivilege()
{HANDLE hToken
;BOOL fOk
=FALSE
;if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES
,&hToken
)){TOKEN_PRIVILEGES tp
;tp
.PrivilegeCount
=1;LookupPrivilegeValue(NULL,SE_DEBUG_NAME
,&tp
.Privileges
[0].Luid
);tp
.Privileges
[0].Attributes
=SE_PRIVILEGE_ENABLED
;AdjustTokenPrivileges(hToken
,FALSE
,&tp
,sizeof(tp
),NULL,NULL);fOk
=(GetLastError()==ERROR_SUCCESS
);CloseHandle(hToken
);}return fOk
;
}
總結(jié)
以上是生活随笔為你收集整理的隐藏模块(无模块注入)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。