Hook是什麼? hook翻譯之後是鉤子的意思,hook的用途主要是用來攔截消息的,看到這裡大家可能會迷茫,What is a hook?所以這時就不得不普及一下操作系統的原理。 舉個例子:假如你是一名游戲熱衷者,在玩游戲時,你要釋放技能那麼你就會對鍵盤滑鼠進行操作,錶面上你是直接操作游戲,其實中間 ...
Hook是什麼?
hook翻譯之後是鉤子的意思,hook的用途主要是用來攔截消息的,看到這裡大家可能會迷茫,What is a hook?所以這時就不得不普及一下操作系統的原理。
舉個例子:假如你是一名游戲熱衷者,在玩游戲時,你要釋放技能那麼你就會對鍵盤滑鼠進行操作,錶面上你是直接操作游戲,其實中間經過了幾個環節。
首先,你操作鍵盤滑鼠,那麼電腦底層鍵盤滑鼠的驅動就會收到一個消息。
然後,這個驅動會把消息傳個操作系統。
其次,操作系統會判斷這個消息是作用在哪個程式上。
最後,操作系統會把這個事件傳給相應的程式,那麼,你就可以看到你操作游戲的樣子了。
做自己的Hook!
好!說了這些,大家想想假如你寫了一個hook,在別人的電腦上攔截了這個消息,操作系統就不知道這個消息,你可以把這個消息通過網路發到你的電腦,那個那臺電腦的一舉一動你都清楚....(當然我教大家這個不是希望你們做壞事,而是同過hook更深入學習計算 機 和保護自己電腦),下麵我來同過一個簡單的程式來讓大家瞭解hook。
1 int main() 2 { 3 MessageBox(NULL, L"Hello world", L"this",MB_OK); 4 system("pause"); 5 return 0; 6 }
這是一段簡單的程式,其功能是為了顯示一個對話視窗。這個對話視窗操作系統已經幫我們寫好了,我們實際上是在調用這段代碼。好!大家想一下我們能不能在調用這個函數之前截斷這個調用,讓程式調用自己的函數。(想想做插件是不是這個原理)答案是肯定的,我們能夠截斷這個消息並讓他調用自己的函數。下麵我們來代碼實現一下。
1 int WINAPI myMSG( HWND hWnd, 2 LPCTSTR IpText, 3 LPCTSTR IpCaption, 4 UINT uType) 5 { 6 7 printf("哈哈你的消息被我截斷了"); 9 return 1; 10 }
這是我寫的一個函數(註意:函數返回值和參數一定要和MessageBox一樣,這樣介面才能對上,不然會報錯),我們要讓程式執行我們的函數,那麼我們就要寫一個鉤子。
1 bool Hook() 2 { 3 //獲取調用代碼的首地址 4 PROC p = GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW"); 5 if (!p) return 0; 6 7 BYTE b[5] = { 0 }; 8 //0xE9無條件跳轉(學過彙編的同學應該知道) 9 b[0] = 0xE9; 10 //計算偏移地址。 偏移地址 = 跳轉地址-MessageBox的地址 11 *(DWORD*)(b + 1) = (DWORD)myMSG - (DWORD)p - 5; 12 /*通過上面三行代碼,這個數組儲存的代碼意思是(無條件跳轉到我的函數地址位置)*/ 13 14 //在計算位置的記憶體中寫入數據 15 WriteProcessMemory(GetCurrentProcess(), p, b, 5, NULL); 16 return 1; 17 }
我已經寫好了一個鉤子,下麵我放出完整程式的代碼
1 #include <stdio.h> 2 #include <Windows.h> 3 4 int WINAPI myMSG( HWND hWnd, 5 LPCTSTR IpText, 6 LPCTSTR IpCaption, 7 UINT uType) 8 { 9 printf("哈哈你的消息被我截斷了"); 10 return 1; 11 } 12 13 bool Hook() 14 { 15 //獲取調用代碼的首地址 16 PROC p = GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW"); 17 if (!p) return 0; 18 19 BYTE b[5] = { 0 }; 20 //0xE9無條件跳轉(學過彙編的同學應該知道) 21 b[0] = 0xE9; 22 //計算偏移地址。 偏移地址 = 跳轉地址-MessageBox的地址 23 *(DWORD*)(b + 1) = (DWORD)myMSG - (DWORD)p - 5; 24 /*通過上面三行代碼,這個數組儲存的代碼意思是(無條件跳轉到我的函數地址位置)*/ 25 26 //在計算位置的記憶體中寫入數據 27 WriteProcessMemory(GetCurrentProcess(), p, b, 5, NULL); 28 return 1; 29 } 30 int main() 31 { 32 Hook(); 33 MessageBox(NULL, L"Hello world", L"this",MB_OK); system("pause"); 34 return 0; 35 }
首先我們把Hook註釋掉運行。運行結果如下。
如何加上hook,你會發現一件令人興奮的事情,並沒有彈出對話框。運行結果如下
通過這個例子相信大家對hook有了一些瞭解,現在大家肯能會有一個疑問,我能跳轉,能不能回去呢,答案是能的。我也給大家提供一個點思路ReadProcessMemory()用這個api來保存原來的段地址和記憶體中的代碼,回去時在利用WriteProcessMemory()再跳轉一次,就可以會到原來調用的代碼處了,這些是不是很棒,大家可以回家自行試驗,也可以鞏固一下今天所學的知識。
如果中間有什麼錯誤,還請高手能幫我指出。