李恒道 发表于 2020-12-8 15:57:21

Windows输入法注入原理

            
[*]引言
[*]输入法简介
[*]输入法安装
[*]输入法初始化
[*]输入法注入
[*]输入法激活
[*]输入法卸载
[*]输入法标号的获取
引言
国内输入法相关的资料相对缺乏,大部分都是抄来抄去,我参考了一部分源码和代码总结出来了这篇文章,可能依然有一定的错误(由于本人薄弱的编程功底)
推荐一部分相关的资料
IME输入:https://www.jianshu.com/p/ba7ef776112e
IME输入:https://www.cnblogs.com/freedoms ... 0/ime_learning.html
第二个好像是正版
IME输入法编程溯源https://www.cnblogs.com/freedoms ... /ime-resources.html
加密与解密第四版:https://detail.tmall.com/item.ht ... 09&ns=1&abbucket=10
易语言输入法注入:http://www.511yj.com/eyuyan-zr-srf.html
dll技术之输入法注入:https://blog.csdn.net/qq446569365/article/details/71155557
精益模块注入法注入:http://ec.125.la/
输入法简介
输入法注入利用的是ime文件,ime是一个符合windows平台输入法接口规范的dll
有以下标准接口
ImeConversionList
ImeConfigure
ImeDestroy
ImeEscape
ImeInquire
ImeProcessKey
ImeSelect
ImeSetActiveContext
ImeSetCompositionString
ImeToAsciiEx
NotifyIME
ImeRegisterWord
ImeUnregisterWord
ImeGetRegisterWordStyle
ImeEnumRegisterWord
UIWndProc
StatusWndProc
CompWndProc
CandWndProc在此贴上网上的功能解释段

ImeConversionList         //将字符串或字符转换成目标字串      

ImeConfigure                //配置当前ime参数函数      

ImeDestroy                  //退出当前使用的IME      

ImeEscape                   //应用软件访问输入法的接口函数      

ImeInquire                  //启动并初始化当前ime输入法      

ImeProcessKey               //ime输入键盘事件管理函数      

ImeSelect                   //启动当前的ime输入法      

ImeSetActiveContext         //设置当前的输入处于活动状态      

ImeSetCompositionString   //由应用程序设置输入法编码      

ImeToAsciiEx                //将输入的键盘事件转换为汉字编码事件      

NotifyIME                   //ime事件管理函数      

ImeRegisterWord             //向输入法字典注册字符串      

ImeUnregisterWord         //删除被注册的字符串      

ImeGetRegisterWordStyle      

ImeEnumRegisterWord      

UIWndProc      //用户界面接口函数      

StatusWndProc    //状态窗口注册函数      

CompWndProc      //输入编码窗口注册函数      

CandWndProc      //选择汉字窗口注册函数
输入法安装

当目标进程切换输入法的时候imme32.dll(输入法管理dll)会加载对应ime模块
我们一般是调用ImmInstallIME进行安装输入法
ImmInstallIME函数原型:HKL ImmInstallIME(LPCTSTR lpszIMEFileName, LPCTSTR lpszLayoutText);函数的两个参数分别为输入法IME文件的文件名和在控制面板的是输入法选项中显示的输入法名称。函数调用后将返回一个被安装输入法的输入法标识符(或称做输入法句柄)。示例代码:HKL hKL = ImmInstallIME("c:\\winwb86.ime", "王码五笔型输入法86版");输入法初始化输入法初始化过程调用的是ImeInquire,会在dllmain调用后第一个调用这个

BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption)
{
    // 输入法初始化过程
    lpIMEInfo->dwPrivateDataSize = 0; //系统根据它为INPUTCONTEXT.hPrivate分配空间

    lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST |
                           IME_PROP_IGNORE_UPKEYS |
                           IME_PROP_END_UNLOAD;

    lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE |
                              IME_CMODE_NATIVE;

    lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE;
    lpIMEInfo->fdwUICaps = UI_CAP_2700;

    lpIMEInfo->fdwSCSCaps = 0;

    lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;

    _tcscpy(lpszUIClass,CLSNAME_UI);// 注意该输入法基本窗口类必须注册,否则输入法不能正常运行

    return TRUE;
}
<code class=""></code>输入法注入
然后向输入法注入dll,使用的是IMESetPubString
tmpStr是dll的路径
UnloadDLL是输入法退出的时候是否卸载dll 0代表是 1代表否
loadNextIme切换目标输入法的时候是否直接切换到下一个输入法0代表否 1代表是
DllData1 数据1
DllData2 数据2
DllData3 数据3
int WINAPI IMESetPubString(LPCTSTR tmpStr,DWORD UnloadDLL,DWORD loadNextIme,DWORD DllData1,DWORD DllData2,DWORD DllData3)
{
    CallBackData1=DllData1;
    CallBackData2=DllData2;
    CallBackData3=DllData3;
    OnloadDllWhenExit=UnloadDLL;
    LoadNextWhenActive=loadNextIme;

    memset(g_IMEDLLString,0,802);
    if (lstrlen(tmpStr)>800)
    {
      lstrcpyn(g_IMEDLLString,tmpStr,800);
    }
    else
    {
      lstrcpy(g_IMEDLLString,tmpStr);
    }
    return 1;
}<code class=""></code>输入法激活

激活的时候调用SendMessageA (WinHwnd, 80, 1, ImeHwnd)
WinHwnd是对应窗口的句柄
ImwHwnd是输入法的句柄
这里目测应该是用过spy抓取消息获取的
输入法停止注入

停止注入的时候调用IMEClearPubString
附上IMEClearPubString的源码
int WINAPI IMEClearPubString()
{
    CallBackData1=0;
    CallBackData2=0;
    CallBackData3=0;
    OnloadDllWhenExit=0;
    LoadNextWhenActive=0;

    memset(g_IMEDLLString,0,802);
    return 1;
}

输入法卸载

卸载输入法的时候首先要获取输入法的标号
输入法标号的获取
输入法标号的获取首先调用api GetKeyboardLayoutList来获取输入法总数然后循环调用api LoadKeyboardLayoutA获取每个输入法的句柄通过判断输入法的句柄是否相等来获得输入法标号删除以下注三个册表内的输入法标号
“Keyboard Layout\Preload\”
“SYSTEM\CurrentControlSet\Control\Keyboard Layouts\”
“S-1-5-21-1060284298-606747145-682003330-500\Keyboard Layout\Preload”<code class=""></code>然后调用api UnloadKeyboardLayout卸载键盘布局
并且删除目录下的对应ime文件以及缓存文件
缓存文件的路径以及名称在注册表的“SYSTEM\CurrentControlSet\Control\Keyboard Layouts\”下
输入法的表示路径在注册表的 “Keyboard Layout\Preload\”下      

王一之 发表于 2020-12-8 16:25:57

https://bbs.tampermonkey.net.cn/data/attachment/forum/202012/08/124813qwh9h9ercuw7nscr.jpg

L_demon 发表于 2020-12-17 10:58:33

膜拜大佬(⊙x⊙;)

小易哥哥 发表于 2020-12-17 21:34:06

大佬大佬

widcardw 发表于 2021-1-14 21:06:37

回想起学Window(win32api)时的恐惧,并表示win32这玩意再也不会去碰了(哭

懒男孩 发表于 2021-1-14 22:35:32

我来水点经验

懒男孩 发表于 2021-1-14 22:35:47

ggnb,ggnb,ggnb

李恒道 发表于 2021-1-15 10:44:12

TQ1231 发表于 2021-1-14 22:35
ggnb,ggnb,ggnb

哥哥nb

李恒道 发表于 2021-1-21 23:02:04

widcardw 发表于 2021-1-14 21:06
回想起学Window(win32api)时的恐惧,并表示win32这玩意再也不会去碰了(哭

我学桌面学吐了...最后找不到工作,mmp
页: [1]
查看完整版本: Windows输入法注入原理