原创64位输入法注入方案.

 

微软两种输入法方案

XP和XP以前是imm(Input Method Manager)输入方案.

xp之后的系统是imm和TSF(Text Service Framework)输入方案.共存.

 

win8 64位还有win 10 64位, IMM方案的输入法基本没法生存.

如果你在win10 64位上安装了IMM方案的输入法,能输入, 但是你会看到一个  "某某拼音 仅桌面" .

一般32位程序它能输入,64位程序 和win app 是没办法输入的.

 

 

输入法工作原理

 

无论是TSF还是IMM方案的输入法的本质就是一个DLL文件

 

IMM方案

imm方案的输入法是API接口机制,它好像有19个必须导出函数.

另外还有几个要求:

 

  1. 后缀为IME格式.
  2. DLL的版本信息,要添加输入法标识.
  3. 输入法必须在window目录

 

 

然后让外部程序调用微软 ImmInstallIME ,安装输入法

ImeHandle := ImmInstallIME(PChar(ImePath), 'Y.A.K.E输入法');

 

ImeHandle为安装句柄,一个数字.

安装后会在注册表

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Keyboard Layouts\ImeHandle

 

 

TSF方案

 

TSF方案本质也是一个DLL文件,而本质是一个DLL后缀的COM组件.

它不限制路径和后缀名.

 

安装方式

regsvr32.exe 输入法DLL

 

如果输入法DLL是64位,安装后在注册表有两个路径

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CTF\TIP\#IMECCCID#\LanguageProfile\0x00000804\#IMEPPPID#

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\CTF\TIP\#IMECCCID#\LanguageProfile\0x00000804\#IMEPPPID#

 

 

输入法注入原理

再回到前面说的,输入法本质就是一个DLL,无论是API接口的DLL,还是COM接口的DLL.

 

只要你某个程序,激活这个输入法之后,那么那个程序,就会自动载入该输入法DLL.

剩下的输入工作全部,就交给这个输入法DLL了.

直到你换其他输入法.或者离开该程序.

 

我们只需要参考输入法编写基本要求,制作一个山寨DLL输入法.

并在输入法的 DLLMAIN函数中,载入其他的DLL文件.

这样就相当于运行输入法,就运行我们DLL.

当然,你可以加入一些逻辑代码,并不是每个程序都是"目标程序"

 

大致流程:

  1. 安装山寨输入法.
  2. 在目标程序激活山寨输入法
  3. 目标程序 自动载入 山寨输入法DLL文件.
  4. 山寨输入法DLL 调用 我们自定义的DLL文件.
  5. 卸载输入法.

 

这样,就实现 让目标程序 调用 我们自定义DLL程序.

 

好处就是可以注入一个有保护的进程.其他方式不方便注入的场景.

 

 

TSF注入整体方案

好了正文开始了

自己做的大致流程图,流程图word做的...

 

 

整体参与者就是4部分

  • 注入器exe
  • 输入法DLL
  • 目标程序EXE
  • 自定义DLL

 

如果目标程序是64位,那么输入法也64位,自定义DLL也是64位.

同理,32位也是.

注入器没有要求.

这里面涉及到一个原因,64位程序或者64位DLL,只能调用64位DLL.

因为64位和32位程序,两者的地址空间,寄存器,代码指令,地址长度都不一致.不能简单调用.

 

注:题外话, 之前虽然在看雪论坛有64位程序调用32位DLL的.但是方案非常极端.咱普通玩家还是不考虑.

 

 

 

代码和流程

输入法微软开源,自己github上找.改一改就能用.

 

第一步

选择一个目标程序,然后安装输入法.写入配置文件.

 

 

 

第二步

检测最前面的窗口是不是目标程序,核心代码就两个API

 

因为输入法安装之后是全局的,

每个程序都能显示我们山寨输入法.

如果其他程序不小心激活这个输入法,那个程序也会调用山寨输入法DLL文件.

 

为了尽量避免这个情况,需要判断下.防止其他程序调用我们的山寨输入法.

最根本是为了避免 注入器自身 和 资源管理器 还有一些系统进程 意外调用山寨输入法.

 

 

 

 

第三步

如果目标程序位用最前,那么输入法就显示.

并手动激活输入法.

 

注:如果IMM方案可以通过PostMessage WM_INPUTLANGCHANGEREQUEST 消息让目标窗口直接激活输入法.

 

但是TSF方案好像只有微软自带的输入法才有原来的窗口消息.

自己山寨的输入法DLL激活貌似没有输入法切换的窗口消息.

不知道是不是山寨输入法山寨的不完全.

而微软的TSF 相关API只能让注入器自身改变输入法.

不能让其他程序改变输入法.

 

这里我后面找找看看哪里问题.

 

 

第四步

当目标程序(我这里用的记事本),激活山寨输入法.那么山寨输入法自动调用自定义DLL

 

我的自定义DLL就两个导出函数. 只做演示,功能只有弹出一个消息框.

这里就实现了,记事本 调用 我自定义的DLL代码

 

第五步

卸载输入法.

 

 

因为输入法没有激活前,整个注入过程属于待命状态.

当输入法程序激活后,那么整个流程就走完了.就可以卸载了

 

至于为啥要卸载输入法,这里说下

 

1,为了防止一个程序多次注入.(山寨输入法->微软拼音  ->山寨输入法 会再次执行山寨输入法DLL)

2,为了其他程序能注入. (配置文件位置固定.目标程序的PID写在上面)

 

卸载输入法我的方案是

山寨输入法DLL调用后,给注入器发送一个自定义窗口消息,让注入器卸载输入法.

 

山寨输入法DLL 发送消息函数

 

 

注入器接收自定义消息

 

 

 

收到山寨输入法DLL返回的消息,就卸载输入法,并显示返回结果.

 

到这里,一次注入就完成了.

 

 

当然,这里还一个问题

就是注入器因为要安装输入法,写注册表,所以需要管理员权限.

因为UAC隔离机制.

如果山寨输入法DLL的目标程序非管理员权限的程序,是无法给注入器发送窗口消息的.

那么只需要在注入器中加一个行代码即可解决

ChangeWindowMessageFilter(WM_MyImeMessage, MSGFLT_ADD);

这样注入器可以接收低权限发送的窗口消息.

 

 

 

这是山寨输入法DLL一次运行的日志