64位输入法DLL注入 (TSF)方案
文章目录
原创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个必须导出函数.
另外还有几个要求:
- 后缀为IME格式.
- DLL的版本信息,要添加输入法标识.
- 输入法必须在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.
当然,你可以加入一些逻辑代码,并不是每个程序都是"目标程序"
大致流程:
- 安装山寨输入法.
- 在目标程序激活山寨输入法
- 目标程序 自动载入 山寨输入法DLL文件.
- 山寨输入法DLL 调用 我们自定义的DLL文件.
- 卸载输入法.
这样,就实现 让目标程序 调用 我们自定义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一次运行的日志