-
-
[原创]输入法故障处理日记
-
发表于: 2012-2-19 18:31 10749
-
输入法故障处理日记
搜狗输入法经常碰到明明已经切到该输入法了,可是却看不到如下输入法的窗口,在编辑窗口也打不出字,如果刚好碰到和MM聊天,那就要郁闷坏了,于是决定好好研究下,首先经过搜索找到http://bbs.pediy.com/showthread.php?t=144962 ,了解到输入法文件是个特殊的DLL文件,它定义一套标准的接口函数,部分函数如下:(相关函数定义可以查阅MSDN)
ImeConversionList 将字符或字符串转换成目标字符
ImeConfigure 配置当前ime参数函数
ImeDestroy 退出当前使用的IME
ImeEscape
ImeInquire ;启动并初始化当前IME输入法
ImeProcessKey ;IME输入键盘事件管理函数
ImeSelect ;初始化
ImeSetActiveContext ;设置当前的输入处于活动状态
ImeToAsciiEx ;编码转换函数
NotifyIME ;IME通知管理函数
ImeRegisterWord ;向输入法字典注册字符串
ImeUnregisterWord
ImeGetRegisterWordStyle
ImeEnumRegisterWord
ImeSetCompositionString
可以将sogoupy.ime复制一份改名为sogoupy.dll,用depends查看其输出函数,有了初步了解后我们来尝试分析解决问题。
首先打开记事本,用XT显示其模块,发现有默认输入法模块MSCTFIME.IME,切换输入法,发现进程会加载相应的模块(如IMSC40A.IME 微软拼音输入法,winabc智能ABC),郁闷的是切换到搜狗输入法,进程并未加载相应的模块sogoupy.ime,所以才导致看不见如下的窗口,也无法输入中文等等。
问题初步原因找到了,尝试解决如下:
一、在语言栏设置里删除搜狗输入法再重新添加,无效
二、设想手动注入该模块,于是使用process hacker工具,将sogoupy.ime注入notepad.exe进程,可惜切换输入法后输入仍然无效。
三、难道要重新注册?首先在语言栏设置里将搜狗拼音删除,然后使用ImmInstallIME添加,ImmInstallIME原型如下:
HKL ImmInstallIME(
LPCTSTR lpszIMEFileName,
LPCTSTR lpszLayoutText
);
Return Values:The function returns the input locale identifier for the IME.注意它的返回值是输入法的ID.
具体代码如下,执行后惊奇的发现语言栏设置里重新添加了搜狗输入法,并变成如下摸样,呵呵
.386
.model flat,stdcall
option casemap:none
include kernel32.inc
include imm32.inc
includelib kernel32.lib
includelib imm32.lib
.data
filename db "c:\windows\system32\SogouPY.ime",0
imename db "sou gou",0
.code
start:
invoke ImmInstallIME,addr filename,addr imename ;函数返回值EAX里为搜狗输入法的ID=E0210804。
invoke ExitProcess,0
end start
不过很可惜,该方法仍然无效。
看样子必须对系统如何启动以及使用输入法做深入研究了(可惜后来我用结束EXPLORER.EXE进程,重新添加输入法解决了,所以下面的分析是基于正常情况下的)
首先用OD载入记事本,然后更改OD-调试设置选项--中断于新模块,F9运行,观察直到新模块为msctfime.ime,在堆栈回溯如下:
0007F6F4 |77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C
0007F6F8 |77D6C95B USER32.77D6C95B ;消息处理函数
0007F6FC |000B0528
0007F700 |00000081 ;WM_NCCREATE消息
0007F704 |00000000
0007F708 |0007F814 ;LPCREATESTRUCT
查看LPCREATESTRUCT数据如下
typedef struct tagCREATESTRUCT {
LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCTSTR lpszName;
LPCTSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCT, *LPCREATESTRUCT;
0007F814 |00000000
0007F818 |01000000 notepad.01000000
0007F81C |00000000
0007F820 |00060182
0007F824 |00000000
0007F828 |00000000
0007F82C |00000000
0007F830 |00000000
0007F834 |88000000
0007F838 |0007F850 UNICODE "Default IME" ;lpszName窗口的名字
0007F83C |0000C026
0007F840 |00000000
0007F688 |77D6C6F9 返回到 USER32.77D6C6F9 来自 IMM32.CtfImmDispatchDefImeMessage
0007F30C |76313B26 返回到 IMM32.76313B26 来自 kernel32.LoadLibraryW
0007F310 |0007F470 UNICODE "C:\WINDOWS\system32\msctfime.ime"
大致过程是进程处理WM_NCCREATE消息---调用IMM32.CtfImmDispatchDefImeMessage---加载msctfime.ime
继续F9,程序运行起来,切换到记事本窗口,按下ctrl+空格,中断在OD里面,在堆栈回溯,发现
0007FE10 |77D18816 返回到 user32.77D18816 来自 user32.77D1870C
0007FE14 |771A3DDA comctl32.771A3DDA ;消息处理函数
0007FE18 |000C03DC
0007FE1C |00000050
0007FE20 |00000001
0007FE24 |E0210804
其中控件消息处理函数771A3DDA,控件应该就是记事本的EDIT控件,使用OD插件窗口工具,可以看到EDIT控件窗口句柄为C03DC,刚好与消息的HWND参数符合,消息码为50H,经查为WM_INPUTLANGCHANGEREQUEST,在MSDN里查找得到如下信息
The WM_INPUTLANGCHANGEREQUEST message is posted to the window with the focus when the user chooses a new input language, either with the hotkey (specified in the Keyboard control panel application) or from the indicator on the system taskbar. An application can accept the change by passing the message to the DefWindowProc function or reject the change (and prevent it from taking place) by returning immediately.
A window receives this message through its WindowProc function.
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_INPUTLANGCHANGEREQUEST
WPARAM wParam, // input locale information
LPARAM lParam // input locale identifier (HKL)
);
也就是当用户使用热键或者点击任务栏上语言栏选择一种新的输入法时,系统会产生该消息发送给焦点所在窗口,其中lParam 为Input locale identifier,E0210804刚好与我们安装搜狗输入法返回的ID相符
让我们看看程序从接收到这个消息开始到最后加载对应输入法过程,
重载程序,F9运行起来,在77d1870c下条件断点(即消息断点),[esp+c]==50h,切换到记事本窗口,按下ctrl+空格,在OD里中断下来,将77D1870C改为直接断点,并更改OD-调试设置选项--中断于新模块,F9运行,中断下来,回溯堆栈发现又是由IMM32加载SOGOUPY.IME文件
0007F5C4 |763071F4 返回到 IMM32.763071F4 来自 kernel32.LoadLibraryW
0007F5C8 |0007F5E0 UNICODE "C:\WINDOWS\system32\SOGOUPY.IME"
查看代码如下:
763071ED 50 PUSH EAX 763071EE FF15 3C113076 CALL DWORD PTR DS:[<&KERNEL32.LoadLibrar>; kernel32.LoadLibraryW 763071F4 85C0 TEST EAX,EAX 763071F6 8943 04 MOV DWORD PTR DS:[EBX+4],EAX 763071F9 0F84 F9010000 JE IMM32.763073F8 763071FF 8B35 40113076 MOV ESI,DWORD PTR DS:[<&KERNEL32.GetProc>; kernel32.GetProcAddress 76307205 68 D4753076 PUSH IMM32.763075D4 ; ASCII "ImeInquire" 7630720A 50 PUSH EAX 7630720B FFD6 CALL ESI 7630720D 85C0 TEST EAX,EAX 7630720F 8943 54 MOV DWORD PTR DS:[EBX+54],EAX 76307212 0F84 E0010000 JE IMM32.763073F8 76307218 68 C0753076 PUSH IMM32.763075C0 ; ASCII "ImeConversionList" 7630721D FF73 04 PUSH DWORD PTR DS:[EBX+4] 76307220 FFD6 CALL ESI 76307222 85C0 TEST EAX,EAX 76307224 8943 58 MOV DWORD PTR DS:[EBX+58],EAX 76307227 0F84 CB010000 JE IMM32.763073F8 7630722D 68 B0753076 PUSH IMM32.763075B0 ; ASCII "ImeRegisterWord" 76307232 FF73 04 PUSH DWORD PTR DS:[EBX+4] 76307235 FFD6 CALL ESI 76307237 85C0 TEST EAX,EAX 76307239 8943 5C MOV DWORD PTR DS:[EBX+5C],EAX 7630723C 0F84 B6010000 JE IMM32.763073F8 7630734A 68 D0743076 PUSH IMM32.763074D0 ; ASCII "ImeGetImeMenuItems" 7630734F FF73 04 PUSH DWORD PTR DS:[EBX+4] 76307352 FFD6 CALL ESI
0007F81C 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F820 771A3DDA comctl32.771A3DDA 0007F824 000D03DC 0007F828 00000282 ;282h为WM_IME_NOTIFY , 0007F82C 00000001 ;IMN_CLOSESTATUSWINDOW 0007F830 00000000 0007F5CC 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F5D0 7365912A msctfime.UIWndProc 0007F5D4 000E03D8 0007F5D8 00000282 ;282h为WM_IME_NOTIFY , 0007F5DC 00000001 ;IMN_CLOSESTATUSWINDOW 0007F5E0 00000000 关闭默认输入法状态窗口 0007F828 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F82C 7365912A msctfime.UIWndProc 0007F830 000E03D8 0007F834 00000285 ;WM_IME_SELECT 0007F838 00000000 ;为0即取消选择该输入法,为1为选择该输入法 0007F83C 04090409 ;输入法的ID 0007F7E0 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F7E4 7365912A msctfime.UIWndProc 0007F7E8 000E03D8 0007F7EC 00000002 ;WM_DESTROY 0007F7F0 00000000 0007F7F4 00000000 消除默认输入法客户端窗口 0007F7D8 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F7DC 7365912A msctfime.UIWndProc 0007F7E0 000E03D8 0007F7E4 00000082 ;WM_NCDESTROY 0007F7E8 00000000 0007F7EC 00000000 消除默认输入法非客户端窗口 调用SOGOUPY.imeselect 0007F8AC 7630346E 返回到 IMM32.7630346E 0007F8B0 5CE50417 ;输入法上下文的句柄 0007F8B4 00000001 ;为1即初始化,为0为卸载,释放资源 0007F044 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F048 100A51E0 SogouPY.100A51E0 0007F04C 000F03D8 0007F050 00000081 ;WM_NCCREATE 0007F054 00000000 0007F058 0007F164 ;LPCREATESTRUCT,查看该结构数据,发现窗口为“SOPY_UI" 0007F088 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F08C 100A51E0 SogouPY.100A51E0 0007F090 000F03D8 0007F094 00000083 ;WM_NCCALCSIZE 0007F098 00000000 0007F09C 0007F18C ;LPRECT 0007F030 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007F034 100A51E0 SogouPY.100A51E0 0007F038 000F03D8 0007F03C 00000001 ;WM_CREATE 0007F040 00000000 0007F044 0007F150 ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_UI" 0007E828 77D18816 返回到 user32.77D18816 来自 user32.77D1870C 0007E82C 10111060 SogouPY.10111060 0007E830 002609B4 0007E834 00000081 ;WM_NCCREATE 0007E838 00000000 0007E83C 0007E948 ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_HINT" 0007E86C 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007E870 10111060 SOGOUPY.10111060 0007E874 002609B4 0007E878 00000083 ;WM_NCCALCSIZE 0007E87C 00000000 0007E880 0007E970 ;LPRECT 0007E814 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007E818 10111060 SOGOUPY.10111060 0007E81C 002609B4 0007E820 00000001 ;WM_CREATE 0007E824 00000000 0007E828 0007E934 ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_HINT" 0007E878 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007E87C 10111060 SOGOUPY.10111060 0007E880 002609B4 0007E884 00000005 ;WM_SIZE 0007E888 00000000 ;SIZE_RESTORED 0007E88C 00000000 0007E878 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007E87C 10111060 SOGOUPY.10111060 0007E880 002609B4 0007E884 00000003 ;WM_MOVE 0007E888 00000000 0007E88C 00000000 0007F828 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F82C 100A51E0 SOGOUPY.100A51E0 0007F830 002809A6 0007F834 00000285 ;WM_IME_SELECT 0007F838 00000001 ;为1为选择该输入法 0007F83C E0210804 ;输入法的ID 0007F81C 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F820 771A3DDA COMCTL32.771A3DDA 0007F824 000809A0 0007F828 00000282 ;282h为WM_IME_NOTIFY , 0007F82C 00000002 ;IMN_OPENSTATUSWINDOW 0007F830 00000000 0007F5CC 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F5D0 100A51E0 SOGOUPY.100A51E0 0007F5D4 002809A6 0007F5D8 00000282 0007F5DC 00000002 0007F5E0 00000000 0007FB6C 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007FB70 771A3DDA COMCTL32.771A3DDA 0007FB74 000809A0 0007FB78 00000051 ;WM_INPUTLANGCHANGE 0007FB7C 00000086 0007FB80 E0210804 调用SOGOUPY.NotifyIME函数 0007FA08 76303F5F 返回到 IMM32.76303F5F 0007FA0C 5CE50417 0007FA10 00000003 0007FA14 00000000 0007FA18 0000000A 0007F948 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F94C 771A3DDA COMCTL32.771A3DDA 0007F950 000809A0 0007F954 00000282 ;282h为WM_IME_NOTIFY 0007F958 0000000A ;IMN_SETCOMPOSITIONFONT 设置字体 0007F95C 00000000 0007F6F8 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F6FC 100A51E0 SOGOUPY.100A51E0 0007F700 002809A6 0007F704 00000282 0007F708 0000000A 0007F70C 00000000 0007FA60 76303F5F 返回到 IMM32.76303F5F 0007FA64 5CE50417 0007FA68 00000003 0007FA6C 00000000 0007FA70 0000000C 0007F9A0 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F9A4 771A3DDA COMCTL32.771A3DDA 0007F9A8 000809A0 0007F9AC 00000282 0007F9B0 0000000B 0007F750 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F754 100A51E0 SOGOUPY.100A51E0 0007F758 002809A6 0007F75C 00000282 0007F760 0000000B ; IMN_SETCOMPOSITIONWINDOW 0007F764 00000000 0007F880 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F884 771A3DDA COMCTL32.771A3DDA 0007F888 000809A0 0007F88C 00000282 0007F890 00000008 0007F894 00000000 0007F630 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F634 100A51E0 SOGOUPY.100A51E0 0007F638 002809A6 0007F63C 00000282 0007F640 00000008 ;IMN_SETOPENSTATUS 0007F644 00000000 0007F880 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F884 771A3DDA COMCTL32.771A3DDA 0007F888 000809A0 0007F88C 00000282 0007F890 00000006 0007F894 00000000 0007F630 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F634 100A51E0 SOGOUPY.100A51E0 0007F638 002809A6 0007F63C 00000282 0007F640 00000006 ;IMN_SETCONVERSIONMODE 0007F644 00000000 0007F880 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F884 771A3DDA COMCTL32.771A3DDA 0007F888 000809A0 0007F890 00000007 0007F894 00000000 0007F630 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007F634 100A51E0 SOGOUPY.100A51E0 0007F638 002809A6 0007F63C 00000282 0007F640 00000007 ;IMN_SETSENTENCEMODE 0007F644 00000000 0007FDB4 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007FDB8 01003429 notepad.01003429 0007FDBC 000B0182 0007FDC0 00000088 ;WM_SYNCPAINT 0007FDC4 00000004 0007FDC8 00000000 0007FCF8 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007FCFC 771A3DDA COMCTL32.771A3DDA 0007FD00 000809A0 0007FD04 000000D8 ;EM_SETIMESTATUS 0007FD08 00000001 0007FD0C 00000000 0007FE10 77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C 0007FE14 100A51E0 SOGOUPY.100A51E0 0007FE18 002809A6 0007FE1C 000083F1 ;自定义消息 0007FE20 00000000 0007FE24 00000000
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课