還是沒弄會,,連日記也沒心情寫,,看了pe的文章,,<<箴言>>裡的程式都沒注釋,,梁這不是打自己嘴巴子麼?也不替我們這樣的新手考慮考慮,,寫書幹嘛呀,,難道就讓我知道這些你早逗會了?? 哎,,發啥牢騷啊,,畢竟自己從梁大哥那裡學了不少 :) 今天hook還是沒成功,,已經是第2中方法了,,把他的程式給做了遍注釋,,程式倒是理解了,,可不成功的原因沒找到,,,估計自己還算不上理解
#include "stdio.h"
#include "windows.h"
#include "imagehlp.h"
#include "tlhelp32.h"
#pragma comment(lib,"imagehlp.lib")
#pragma comment(lib,"kernel32.lib")
typedef struct _APIHOOK32_ENTRY
{
LPCTSTR pszAPINAme;
LPCTSTR pszCAllerModuleNAme;
PROC pfnOriginApiAddress;
PROC pfnDummyFuncAddress;
HMODULE hModCAllerModule;
}APIHOOK32_ENTRY,*PAPIHOOK32_ENTRY;
BOOL _SetApiHookUp(PAPIHOOK32_ENTRY phk)
{
PIMAGE_THUNK_DATA pThunk;
ULONG size;
//每個IMAGE_IMPORT_DESCRIPTOR代表一個DLL,這裡的 pImportDesc 為NULL是表示遍曆了所有的引入的DLL
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
phk->hModCAllerModule ,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&size);
if (pImportDesc == NULL){
return FALSE;
}
//遍曆DLL,,第一層迴圈
for(;pImportDesc->Name ;pImportDesc++){
//這裡不理解,,為什麼要把pImportDesc->NAme和phk->hModCAllerModule加起來
//IMAGE_DESCRIPTOR中的NAme是一個RVA指向一個ASCII字串,是dll的名字,,那下面這句就更不理解了
PSTR pszDllNAme = (LPSTR)((PBYTE)phk->hModCAllerModule + pImportDesc->Name );////哈哈,,單步時這裡果然和我想的一樣,,加上基址後變為虛擬位址,,然後,,比如這次把 其值就是 0x77ebcd79 "NTDLL.DLL"
//這樣比較肯定不相等了啊
//找到相等的後
if (strcmp(pszDllNAme,phk->pszCAllerModuleNAme )==0) break;
}
//看是否真的找到了
if (pImportDesc->Name == NULL){
return FALSE;
}
//IMAGE_IMPORT_DESCRIPTOR結構裡的FirstThunk指向一個DWORD數組,每個DWORD都是一個RVA,是輸入函數的入口地址,這個數組可以叫輸入地址表
//現在關鍵是弄清楚phk->hModCAllerModule到底是個什麼???????????????????????????
//大概是這樣吧,,phk->hModCAllerModule是個HMODULE類型,,也許是通過它把RVA變成真實的虛擬位址吧,,它起了個載入基址的作用,,
//哎 不知道對不對,,看看它的值才知道
pThunk = (PIMAGE_THUNK_DATA)((PBYTE)phk->hModCAllerModule + pImportDesc->FirstThunk );//IAT
//現在開始是第2層迴圈 IMAGE_THUNK_DATA 結構如下
//* typedef struct _IMAGE_THUNK_DATA32 {
//* union {
//* PBYTE ForwarderString;
//* PDWORD Function;
//* DWORD Ordinal;
//* PIMAGE_IMPORT_BY_NAME AddressOfData;
//* } u1;
//* } IMAGE_THUNK_DATA32;
//*typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
//這裡不懂,,PThunk指向一個DWORD數組,在遍曆時應該用pThunk++嗎?好象也可以,,但自己不清楚,,
//因為pThunk裡面就一個u1,pThunk->u1.Function++等於pThunk++嗎??????????
for (;pThunk->u1 .Function ;pThunk++){
PROC* ppfn = (PROC*)&pThunk->u1 .Function ;
//做比較,,看是否是要找的函數,,如果是,,就把地址改寫
if(*ppfn == phk->pfnOriginApiAddress ){
WriteProcessMemory(GetCurrentProcess(),
ppfn,
&(phk->pfnDummyFuncAddress),
sizeof(phk->pfnDummyFuncAddress ),
NULL);
return TRUE;
}
}
return TRUE;
}
//------------------------------------------------------------------------------
BOOL SetWindowsAPIHook(PAPIHOOK32_ENTRY phk)
{
//The MEMORY_BASIC_INFORMATION structure contains information about a range of pages
//in the virtual address space of a process. The VirtualQuery and VirtualQueryEx
// functions use this structure
//*typedef struct _MEMORY_BASIC_INFORMATION { // mbi
//* PVOID BaseAddress; // base address of region
//* PVOID AllocationBase; // allocation base address
//* DWORD AllocationProtect; // initial access protection
//* DWORD RegionSize; // size, in bytes, of region
//* DWORD State; // committed, reserved, free
//* DWORD Protect; // current access protection
//* DWORD Type; // type of pages
//*} MEMORY_BASIC_INFORMATION;
//*typedef MEMORY_BASIC_INFORMATION *PMEMORY_BASIC_INFORMATION;
MEMORY_BASIC_INFORMATION mInfo;
HMODULE hModHookDll;
HANDLE hSnApShot;
BOOL bOk;
//Describes an entry from a list that enumerates the modules used by a specified process.
//*typedef struct tagMODULEENTRY32 {
//* DWORD dwSize;
//* DWORD th32ModuleID;
//* DWORD th32ProcessID;
//* DWORD GlblcntUsage;
//* DWORD ProccntUsage;
//* BYTE * modBaseAddr;
//* DWORD modBaseSize;
//* HMODULE hModule;
//* char szModule[MAX_MODULE_NAME32 + 1];
//* char szExePath[MAX_PATH];
//*} MODULEENTRY32;
//*typedef MODULEENTRY32 * PMODULEENTRY32;
//*typedef MODULEENTRY32 * LPMODULEENTRY32;
MODULEENTRY32 me = {sizeof(MODULEENTRY32)};
if (phk->pszAPINAme == NULL||phk->pszCAllerModuleNAme == NULL
||phk->pfnOriginApiAddress == NULL){
return FALSE;
}
//如果phk->hModCAllerModule 是 NULL 的話,,表示hook自己??還得往下看才知道
if (phk->hModCAllerModule == NULL){
//取得從_SetApiHookUp地址開始的一個頁面的資訊
VirtualQuery(_SetApiHookUp,&mInfo,sizeof(mInfo));
//得到函數_SetApiHookUp的地址
hModHookDll = (HMODULE)mInfo.AllocationBase ;///我靠! 沒錯,,逗是基址 單步的時候看到這裡是0x00400000
//快照,,以前在pslist裡用過的
//TH32CS_SNAPMODULE Includes the module list of the specified process in the snapshot.
//還好,,:) 是在指定進程內的
hSnApShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
//找到一個了
//這個迴圈看上去很瘋狂啊
//只要不是自己所在的MODULE,全都給_SetApiHookUp一遍,,但全是本進程的
//me.hModule是Handle to the module in the context of the owning process.
//那它是不是地址呢???????如果不是的話,,那上邊的那個問題怎麼解決???
//(pThunk = (PIMAGE_THUNK_DATA)((PBYTE)phk->hModCAllerModule + pImportDesc->FirstThunk );)
bOk = Module32First(hSnApShot,&me);////單步時,,me.hModule是0x00400000 恩,,基址,,沒錯
while(bOk){
if (me.hModule != hModHookDll){ ////單步時 第一次me.hModule和hModHookDll都是0x00400000可能這時是同一個Module,第2次就不一樣了,,開始是本進程中的其他Module了
phk->hModCAllerModule = me.hModule ;
_SetApiHookUp(phk);
}
bOk = Module32Next(hSnApShot,&me);
}
phk->hModCAllerModule = NULL;
return FALSE;
}else{
//如果指定了phk->hModCAllerModule的話,,就不會隨便_SetApiHookUp
return _SetApiHookUp(phk);
}
return FALSE;
}
//------------------------------------------------------------------------------
BOOL UnhookWindowsAPIHooks(PAPIHOOK32_ENTRY lpHk)
{
//整個一個逆過程 pfnOriginApiAddress 和 pfnDummyFuncAddress調個個兒
PROC temp;
temp = lpHk->pfnOriginApiAddress ;
lpHk->pfnOriginApiAddress = lpHk->pfnDummyFuncAddress ;
lpHk->pfnDummyFuncAddress = temp;
return SetWindowsAPIHook(lpHk);
}
//------------------------------------------------------------------------------
//儲存原地址
PROC lpAdder = MessageBoxA;
int WINAPI MyMessAgeBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCAption,UINT uType)
{
return lpAdder(NULL,"new","new",MB_OK);
}
//------------------------------------------------------------------------------
int main(void)
{
//哈哈 終於開始啦
APIHOOK32_ENTRY pe;
pe.pszAPINAme = "MessageBoxA";
pe.pszCAllerModuleNAme = "USER32.DLL";//區分大小寫
pe.pfnOriginApiAddress = MessageBoxA;
pe.pfnDummyFuncAddress = MyMessAgeBoxA;
pe.hModCAllerModule = NULL;
//lpAdder = MessageBoxA;
SetWindowsAPIHook(&pe);
MessageBox(NULL,"old","old",MB_OK);
UnhookWindowsAPIHooks(&pe);
MessageBox(NULL,"old","old",MB_OK);
}
//------------------------------------------------------------------------------