特性
因为输入法的本身特性,能注入任何一个程序,还可以开机启动,很是友好
网上大都是一个版本方法,我记录下我自己过程
思路
1.编写一个正常的输入法
2.将它安装到电脑上,并设置为默认输入法,这样就可以在程序打开的时候就调用它的处理函数
因为输入是一个特殊的dll,本质就是一个dll,只是后最不同而已。
一个最简ime文件都必须两个函数
一个dllmain()
还有一个ImeInquire()
这两个是必须的
编写输入法主要文件
创建一个dll项目,解释都在注释中(注意项目为多字节字符集)dllmain.cpp
#include "stdafx.h"
#include "windows.h"
#include "imm.h"
#include "immdev.h"
#pragma comment(lib,"imm32.lib")
LPCSTR injectDllPaht = "C://expDll.dll"; //我们最终利用的Dll,写入自己的功能
void injectDLL();//定义函数,下面用
LRESULT WINAPI UIWndProc(HWND hUIWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{ return 0; }//窗口消息处理函数,可以不要
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)//主函数的标准格式
{
HINSTANCE hinstDLL = (HINSTANCE)hModule;//下面需要用这个句柄,格式强转以下
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{ //定义一个窗口类
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_IME;
wc.lpfnWndProc = UIWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 2 * sizeof(LONG);
wc.hInstance = hinstDLL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //IDC_ARROW
wc.hIcon = NULL;
wc.lpszMenuName = (LPTSTR)NULL;
wc.lpszClassName = TEXT("CInjWindow");//定义的窗口类的名字
wc.hbrBackground = NULL;
wc.hIconSm = NULL;
if (!RegisterClassEx((LPWNDCLASSEX)&wc))//注册这个窗口,IME必须要注册一个窗口才能安装
{
break;
}
injectDLL();//干事的func
break;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnregisterClass("CInjWindow", hinstDLL);//程序退出时注销窗口实例
break;
}
return TRUE;
}
void injectDLL()
{
WCHAR Mes[MAX_PATH];
//这里就可以写注入func,我这里就调用一个自己写的测试dll,每次加载的时候都会打印父窗口名称
HMODULE hMyDll = LoadLibrary(injectDllPaht);//因为现在已经在别的进程中,所以导入后的就成功注入想要的进程了
if (!hMyDll)
{
DWORD ERRCODE = GetLastError();
MessageBox(0, (LPCSTR)ERRCODE, 0, 0);
}
else
{
HMODULE hParentM = GetModuleHandle(0);
//FARPROC fRunFunc = GetProcAddress(hMyDll, "Run");
//fRunFunc();
}
}
BOOL WINAPI ImeInquire(LPIMEINFO lpImeInfo, LPTSTR lpszUIClass, LPCTSTR lpszOption)
{
//初始化ImeInquire
//这个函数是除了DllMain后第一个会被win32 调用的函数. 通过调用这个函数知道你的输入法有什么特性.
lpImeInfo->dwPrivateDataSize = 0;
lpImeInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | IME_PROP_UNICODE | IME_PROP_IGNORE_UPKEYS | IME_PROP_SPECIAL_UI;
lpImeInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_NOCONVERSION;
lpImeInfo->fdwSentenceCaps = 0;
lpImeInfo->fdwUICaps = UI_CAP_ROT90;
lpImeInfo->fdwSCSCaps = SCS_CAP_COMPSTR | SCS_CAP_MAKEREAD;
lpImeInfo->fdwSelectCaps = (DWORD)0;
lstrcpy(lpszUIClass, "CInjWindow");//注意这里,对ImeInquire赋予我们刚刚创建的类
return TRUE;
}
因为输入法需要图标,所以需要添加资源文件,右键dll项目添加
添加位图
要修改version值如下
然后生成就好了
真正需要注入的dll
其实干正事的过程也可以直接放到ime中,但是步方便管理,我这里写出来了
也是一个dll项目
因为我只是测试,所以就写的很简单,一个验证父进程函数名的就可以了。(游戏辅助代码就可以写在这)
dllmain.cpp如下
case DLL_PROCESS_ATTACH:
//获取当前程序名
GetModuleFileName(GetModuleHandle(0),lpFileName,sizeof(lpFileName));
//打印出来
MessageBox(0,lpFileName, 0, 0);
}
加载ime
把上面生成的dll改名为ime结尾,复制到windows32目录下
接下来创建一个控制台项目
如下
#include "stdafx.h"
#include "windows.h"
#include "imm.h"
#pragma comment(lib,"imm32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
if (argc<3)
{
MessageBox(0, "请注意参数 exp:exeName.exe imeName.ime Jerry", 0, 0);
return 0;
}
LPCSTR infecPath = argv[1];
LPCSTR infecName = argv[2];
PVOID m_retV;
//得到默认的输入法句柄并保存
::SystemParametersInfo(
SPI_GETDEFAULTINPUTLANG,
0,
&m_retV,
0);
//安装输入法
HKL m_hImeFile = ImmInstallIME(
infecPath,
infecName);
if (ImmIsIME(m_hImeFile))
{
//设置为默认输入法
SystemParametersInfo(
SPI_SETDEFAULTINPUTLANG,
0,
&m_hImeFile,
SPIF_SENDWININICHANGE);
MessageBox(0, "安装输入法成功", 0, 0);
}
else
{
MessageBox(0, "error 安装出错了", 0, 0);
}
}
把编译生成的exe文件也拷贝到windows32下
安装命令如下 exeName.exe imeName.ime Jerry
安装程序可以自由发挥,只要把ime文件安装到系统上就是了
最终效果
当你安装成功后,就会有弹窗提示,你打开任意一个程序,都会有弹窗提示这个程序的路径。这就说明已经注入成功了。
开机后在切换输入法时也会启动