搞出來很久了,看到看雪上不少同學都很期待,干脆發出來。
本文大部分研究成果歸功于mentaldease,欲讀此文,請遵守以下約定:
1. 絕不可利用本文所揭示的技術編寫或者輔助編寫盜號木馬,危害中國網民。
2. 也不可將本文所揭示的技術直接或間接傳授給寫盜號木馬的敗類。
3. 違背以上兩點約定者,天打雷劈,斷子絕孫...(以下省略2000字)。
**********************************************************
?? 不能遵守以上三點約定者,請立即離開!
**********************************************************
在分析某著名IM軟件之前,嘗試直接用低級鍵盤鉤子截獲密碼。
筆者發現可以獲取正確的某著名IM軟件號,但是截獲的某著名IM軟件密碼里面卻有很多虛假按鍵:
事實上,只要將鼠標焦點放在密碼輸入框里,某著名IM軟件就自動產生虛假按鍵。所以,靠低級鍵盤鉤子不能截獲正確的某著名IM軟件密碼。
用XueTr查看系統中的消息鉤子。筆者發現只要用戶雙擊打開某著名IM軟件2009登錄窗口,某著名IM軟件就會創建一個WH_KEYBOARD_LL低級鍵盤鉤子,如圖2
我們知道WH_KEYBOARD_LL鉤子的優先級高于WH_KEYBOARD和WH_GETMESSAGE鉤子。顯然某著名IM軟件2009的低級鍵盤鉤子會比其他類型的鉤子先執行,某著名IM軟件獲取用戶的真實按鍵后再偽造虛假按鍵。
筆者在成功截獲某著名IM軟件2009密碼之后,掛鉤了SetWindowHookEx觀察某著名IM軟件創建WH_KEYBOARD_LL鉤子的過程:
由上圖可見某著名IM軟件2009每隔不到0.2秒就創建一個低級鍵盤鉤子,這樣確保自己的鉤子始終在鉤子隊列的最頂層。
我們對SetWindowHookEx函數下斷,但是斷不下來,顯然是某著名IM軟件在這里有反調試。刪除剛才的斷點,下一個硬件斷點,程序斷下,執行到返回:
來到042437C5處,tssafeed模塊中看到如下指令:
042437BB??? 56????????????? push??? esi
042437BC??? 50????????????? push??? eax
042437BD??? FF75 0C???????? push??? dword ptr [ebp+C]
042437C0??? E8 AB550000???? call??? 04248D70???????????????????????? ; jmp 到 MSVCRT.memcmp
042437C5??? 8B3D 28A02404?? mov???? edi, dword ptr [424A028]???????? ; KERNEL32.GetCurrentProcess
042437CB??? 83C4 0C???????? add???? esp, 0C
042437CE??? 85C0??????????? test??? eax, eax
042437D0??? 0F84 8F000000?? je????? 04243865
猜測這里很可能就是用memcmp 函數校驗SetWindowsHookExA(可能還有其他函數)的代碼。在042437BB 處F2,再F9讓程序運行,把鼠標焦點移到密碼輸入框時,斷下來了:
單步執行到042437C0,看堆棧信息:
果然是對SetWindowsHookExA初的內存進行校驗。memcmp返回0則認為該處內存沒有改變。
在77D311D1處下硬件執行斷點,成功斷下后,堆棧信息如圖:
HookType為13,即是WH_KEYBOARD_LL鉤子,其HookProc為 04260F1B,轉到該地址看看某著名IM軟件的鉤子回調例程:
04260F1B??? 55????????????? push??? ebp
04260F1C??? 8BEC??????????? mov???? ebp, esp
04260F1E??? 83EC 30???????? sub???? esp, 30
04260F21??? 56????????????? push??? esi
04260F22??? 57????????????? push??? edi
04260F23??? C745 FC F00C260>mov???? dword ptr [ebp-4], 4260CF0
04260F2A??? 8D7D D0???????? lea???? edi, dword ptr [ebp-30]
04260F2D??? B9 07000000???? mov???? ecx, 7
04260F32??? 33C0??????????? xor???? eax, eax
04260F34??? FC????????????? cld
04260F35??? F3:AB?????????? rep???? stos dword ptr es:[edi]
04260F37??? 8B45 10???????? mov???? eax, dword ptr [ebp+10]
04260F3A??? 8945 F8???????? mov???? dword ptr [ebp-8], eax
04260F3D??? C745 F4 0000000>mov???? dword ptr [ebp-C], 0
04260F44??? E8 20000000???? call??? 04260F69?????????????????????? ; 跟進
… …
04260F69 處的call:
04260F69??? 5F????????????? pop???? edi
04260F6A??? 8B4D F4???????? mov???? ecx, dword ptr [ebp-C]
04260F6D??? 833C8F 00?????? cmp???? dword ptr [edi+ecx*4], 0
04260F71??? 74 1D?????????? je????? short 04260F90
04260F73??? 8B55 F4???????? mov???? edx, dword ptr [ebp-C]
04260F76??? 8B0497????????? mov???? eax, dword ptr [edi+edx*4]
04260F79??? 50????????????? push??? eax
04260F7A??? 8B4D FC???????? mov???? ecx, dword ptr [ebp-4]
04260F7D??? FF51 50???????? call??? dword ptr [ecx+50]???????????? ; USER32.GetAsyncKeyState
04260F80??? 0FBFD0????????? movsx?? edx, ax
04260F83??? 81E2 00800000?? and???? edx, 8000
04260F89??? 75 05?????????? jnz???? short 04260F90
04260F8B??? FF45 F4???????? inc???? dword ptr [ebp-C]
04260F8E? ^ EB DA?????????? jmp???? short 04260F6A
04260F90??? 8B55 F8???????? mov???? edx, dword ptr [ebp-8]
04260F93??? 8B02??????????? mov???? eax, dword ptr [edx]
04260F95??? C745 F0 0000000>mov???? dword ptr [ebp-10], 0
04260F9C??? E8 3C000000???? call??? 04260FDD????????? ;跟進
… …
這個函數中有很多花指令,這里就不仔細分析了,對GetForegroundWindow下斷,只要將鼠標焦點移到某著名IM軟件登錄窗口,就會斷下,再對CallNextHookEx下斷觀察。它的大概功能猜也猜得出來:某著名IM軟件自己獲取按鍵之后,發送虛假按鍵,然后直接返回。現在就是找出某著名IM軟件2009到底是用什么函數發送虛假按鍵。對keybd_event下硬件執行斷點,沒有斷下,對sendInput下硬件斷點,斷下了:
Sendinput函數原型:
UINT SendInput(
? UINT nInputs,???? // count of input events
? LPINPUT pInputs,? // array of input events
? int cbSize??????? // size of structure
);
typedef struct tagINPUT {
? DWORD?? type;
? union {
????? MOUSEINPUT????? mi;
????? KEYBDINPUT????? ki;
????? HARDWAREINPUT?? hi;
? };
} INPUT, *PINPUT;
觀察堆棧:
數據窗口跟隨到0012FA94:
如圖所示 01表示的是輸入類型INPUT_KEYBOARD,pInouts的結構如下:
typedef struct tagKEYBDINPUT {
? WORD????? wVk;
? WORD????? wScan;
? DWORD???? dwFlags;
? DWORD???? time;
? ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
如圖所示0x38對應的虛擬按鍵是數字8,用我們剛才寫的那個低級鍵盤鉤子可以看到,所接收到的虛假按鍵正是8.
現在我們能夠寫出某著名IM軟件的低級鍵盤鉤子處理例程:
HWND hwnd = GetForegroundWindow();
If( hWnd == hPassEditWnd)
{
? MapVirtualKey();
? SendInput();
? return? 1;
}
else
{
? return? CallNextHookEx(ncode,…);
}
現在2009登錄窗口保護的原理已經分析清楚,獲取某著名IM軟件密碼的方法也就有了。其關鍵就是繞過某著名IM軟件對SetWindowsHookExA等函數的內存校驗,然后hook SetWindowsHookExA,判斷如果是某著名IM軟件的WH_KEYBOARD_LL鉤子,就替換其回調函數,然后在my_KeyboardllProc中截獲密碼,下圖是截獲密碼的效果圖:
PS:某著名IM軟件2009的軟鍵盤也被我和mentaldease兄突破,并成功截獲密碼:
演示程序:GetXXPass.rar
?