iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Security

我逆向你逆向我的逆向工程膩系列 第 17

Dx17 - Hook : 勾走你的鍵盤

  • 分享至 

  • xImage
  •  

Hook

想像一下 : 有一群壞人想帶著武器去劫機,但是他們在過層層安檢的時候總會被檢查到並被驅離

https://ithelp.ithome.com.tw/upload/images/20221001/201356754xMrBh5wiP.png

但是,這群壞人有一天賄絡了某一層的警察,使他們可以直接走自己的流程,這樣就不會被抓了

https://ithelp.ithome.com.tw/upload/images/20221001/20135675FZ5EHPTQad.png

那麼,在程式上賄絡的行為是在安裝 ”Hook” ,而這樣透過"鉤子”來獲取或改變程序的行為稱為 “Hooking”。

Hooking with DLL

來試試看對記事本進行 Hooking,使他收不到來自鍵盤的信息。

Hooking 記事本之前,我們要瞭解把文字輸入到 notepad.exe 時電腦會發生甚麼事?

在應用程式中,我們常常會用到許多硬體消息。主要會發生這些事 :

  1. 使用者按了 ‘A’ 兩秒。
  2. 一開始,鍵盤收到了 ‘A’ 被按下的消息,兩秒後收到 ‘A’ 被放開。
  3. 把收到的訊息放到 System message quene ( 系統訊息佇列 )
  4. 系統把在系統訊息佇列的訊息分給需要的程序,也就是 Thread message quene ( 執行緒的訊息佇列 )
  5. 程式確認接收到訊息並把訊息刪掉
  6. 在螢幕上顯示 ‘AAAAAAA’ ( 因為按了兩秒 )

https://ithelp.ithome.com.tw/upload/images/20221001/20135675nmEKeecMZP.png

官方文件
https://learn.microsoft.com/zh-tw/windows/win32/inputdev/about-keyboard-input

那如果要接上 hook 後,打算不讓筆記本不要收到訊息則是這樣 :

  1. 使用者按了 ‘A’ 兩秒。
  2. 一開始,鍵盤收到了 ‘A’ 被按下的消息,兩秒後收到 ‘A’ 被放開。
  3. 把收到的訊息放到系統訊息佇列
  4. 系統把在系統訊息佇列的訊息分給執行緒訊息佇列
  5. 觸發鍵盤事件,鉤子 [ keyHook.dll ] 被注入並拿走訊息不告訴 notepad.exe。
  6. 記事本認為他沒收到訊息。

這邊有一個程式,請在 x64 環境下執行它 ( 我在windows10 環境下沒問題 )。

https://github.com/Dinlon5566/IT_Reverse_Engineering/tree/main/Dx17

HookMain.exe 來執行程式
https://ithelp.ithome.com.tw/upload/images/20221001/20135675GaXzyCVPIG.png

打開記事本,會發現不能打字,但其他程式可以。
https://ithelp.ithome.com.tw/upload/images/20221001/20135675GSC1mlUpps.png

這就是因為在 KeyHook.dll 中有中斷文字傳輸的功能,導致記事本收不到訊息。

簡單看一下 HookMain.exe 主要程式碼

// HookMain.cpp
	HookStart();

	printf("press 'q' to quit!\n");
	while (_getch() != 'q');

	HookStop();

其中,HookStart()HookStop() 是 KeyHook.dll 的函數。

mainDll.dll 主要程式碼

//dllMain.cpp
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	char szPath[MAX_PATH] = { 0, };
	char* p = NULL;

	if (nCode >= 0)
	{
		// 若鍵盤有狀態,第31位元會是 1。
		if (!(lParam & 0x80000000))
		{
			//取得並比較是否為 "notepad.exe"
			GetModuleFileNameA(NULL, szPath, MAX_PATH);
			p = strrchr(szPath, '\\');
			
			//如果是就直接退出
			if (!_stricmp(p + 1, DEF_PROCESS_NAME))
				return 1;
		}
	}

//其他程序則接到下一個鉤子或程式。
	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

__declspec(dllexport) void HookStart()
	{
		//接上 Hook
		g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
	}

	__declspec(dllexport) void HookStop()
	{
		//拔掉 Hook
		if (g_hHook)
		{
			UnhookWindowsHookEx(g_hHook);
			g_hHook = NULL;
		}
	}

其中 SetWindowsHookEx 可以用來設置勾點,這次使用 WH_KEYBOARD 來監視鍵盤系統事件

解說一下這個功能在 winuser.h 的定義

HHOOK SetWindowsHookExA(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId
);
  • idHook : Hook 類型,這次的 WH_KEYBOARD 屬於這邊,值為2
  • lpfn : 指向掛鉤的指針
  • hmod : 鉤子所屬的 Handle
  • dwThreadId : 想要掛鉤的 PID,若是 0 則是全部。

MS 說明書 : 使用勾點
https://learn.microsoft.com/zh-tw/windows/win32/winmsg/using-hooks
MS 說明書 : SetWindowsHookExA function
https://learn.microsoft.com/zh-tw/windows/win32/api/winuser/nf-winuser-setwindowshookexa

當程式被勾上後,只要鍵盤有操作系統就會把 dll 注入到程序哩,然後啟動 KeyboardProc() 這個 DLL程序。

https://ithelp.ithome.com.tw/upload/images/20221001/20135675baCuoCYhZe.png


上一篇
Dx16 - 內嵌代碼補丁製作 - 製作篇
下一篇
Dx18 - Hook : 找回你的鍵盤
系列文
我逆向你逆向我的逆向工程膩31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言