输入法注入

  • 引言
  • 输入法简介
  • 输入法安装
  • 输入法初始化
  • 输入法注入
  • 输入法激活
  • 输入法卸载
    • 输入法标号的获取

引言

国内输入法相关的资料相对缺乏,大部分都是抄来抄去,我参考了一部分源码和代码总结出来了这篇文章,可能依然有一定的错误(由于本人薄弱的编程功底)
推荐一部分相关的资料
IME输入:https://www.jianshu.com/p/ba7ef776112e
IME输入:https://www.cnblogs.com/freedomshe/archive/2012/11/30/ime_learning.html
第二个好像是正版
IME输入法编程溯源https://www.cnblogs.com/freedomshe/archive/2012/11/13/ime-resources.html
加密与解密第四版:https://detail.tmall.com/item.htm?spm=a230r.1.14.16.1e7d38f5rT1yMd&id=580607194609&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
有以下标准接口

IMESetPubString
IMEClearPubString
ImeConversionList
ImeConfigure
ImeDestroy
ImeEscape
ImeInquire
ImeProcessKey
ImeSelect
ImeSetActiveContext
ImeSetCompositionString
ImeToAsciiEx
NotifyIME
ImeRegisterWord
ImeUnregisterWord
ImeGetRegisterWordStyle
ImeEnumRegisterWord
UIWndProc
StatusWndProc
CompWndProc
CandWndProc


在此贴上网上的功能解释段

在CODE上查看代码片派生到我的代码片

    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;
}

输入法注入

然后向输入法注入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;
}

输入法激活

激活的时候调用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”

然后调用api UnloadKeyboardLayout卸载键盘布局
并且删除目录下的对应ime文件以及缓存文件

缓存文件的路径以及名称在注册表的“SYSTEM\CurrentControlSet\Control\Keyboard Layouts\”下
输入法的表示路径在注册表的 “Keyboard Layout\Preload\”下

留下评论