找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 4897|回复: 0

【C】Minecraft 1.8.7原版中文输入器(注入式)

[复制链接]
发表于 2015-7-31 00:51:54 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
这个东西的原理是在运行的时候,注入一段Shellcode到Minecraft游戏使用的LWJGL窗口(java.exe)拦截输入法打字的消息(WM_IME_CHAR)并将字符传递到剪贴板,然后发送Ctrl+V的模拟按键消息来让Minecraft游戏本身接收中文输入。用于按T键或/键聊天时输入中文。
Minecraft游戏在Win7上使用的Java库LWJGL对中文的输入存在问题:它会将WM_CHAR发送的大于0x7F的字符过滤掉导致游戏不接收中文输入。但是Minecraft聊天窗口接收Ctrl+C和Ctrl+V的复制粘贴操作。因此我写了这个玩意儿用于让Minecraft可以直接输入中文聊天。
不过这个东西我只完成了x86版。x64的Shellcode对CallWindowProcA的调用貌似会让Minecraft游戏退出(并且存一下档。这个存档的行为太可疑了!)但是如果是注入到自己进程创建的窗口的话似乎并没有什么问题。

这个程序目前只支持32位的Java的注入,不支持64位Java。

20150731004114.png

下载: MCIME.exe (12 KB, 下载次数: 15)

以下是32位注入的Shellcode的源码。用nasm编译为win32格式。
  1. %define WM_IME_CHAR 0x0286
  2. %define WM_KEYDOWN 0x0100
  3. %define WM_KEYUP 0x0101
  4. %define WM_CHAR 0x0102
  5. %define WM_TIMER 0x0113

  6. %define GWLP_WNDPROC (-4)
  7. %define CF_TEXT 1
  8. %define LPTR 0x0040
  9. %define VK_CONTROL 0x11
  10. %define VK_V 0x56
  11. %define KEYEVENTF_KEYUP 0x0002
  12. %define USER_TIMER_MINIMUM 0x0000000A

  13. ;==============================================================================
  14. ;宏名:ProcBegin
  15. ;描述:用于每个过程的开头,建立栈帧,并使ebx指向指令起始地址
  16. ;------------------------------------------------------------------------------
  17. %macro ProcBegin 0-1
  18. push ebp;建立栈帧
  19. mov ebp,esp
  20. %if %0
  21. sub esp,(%1)*4;局部变量内存
  22. %endif
  23. push ebx;保存ebx
  24. call %%GetCurPos;取得指令原点
  25. %%GetCurPos:
  26. pop ebx
  27. sub ebx,%%GetCurPos-_InjectCode
  28. %endmacro

  29. ;==============================================================================
  30. ;宏名:ProcEnd
  31. ;描述:用于每个过程的结尾,恢复寄存器并返回,选择性清理栈内存
  32. ;------------------------------------------------------------------------------
  33. %macro ProcEnd 0-1
  34. pop ebx;恢复ebx
  35. mov esp,ebp
  36. pop ebp
  37. %if %0;返回
  38. ret %1
  39. %else
  40. ret
  41. %endif
  42. %endmacro

  43. ;==============================================================================
  44. ;宏名:Arg
  45. ;描述:用于过程中读取函数参数
  46. ;------------------------------------------------------------------------------
  47. %define Arg(x)        (ebp+8+(x)*4)

  48. ;==============================================================================
  49. ;宏名:Var
  50. ;描述:用于过程中读取变量
  51. ;------------------------------------------------------------------------------
  52. %define Var(x)        (ebp-4-(x)*4)

  53. ;==============================================================================
  54. ;宏名:Local
  55. ;描述:读取局部变量
  56. ;------------------------------------------------------------------------------
  57. %define Local(x)        [ebx+(x)-_InjectCode]

  58. global _InjectCode
  59. global _InjWndProc@16
  60. global _InjTimerProc@16
  61. global _SizeOfInjCode

  62. segment .data
  63. ;==============================================================================
  64. ;void InjectCode(HWND);
  65. ;------------------------------------------------------------------------------
  66. _InjectCode:
  67. ProcBegin

  68. lea eax,Local(KrnlDll)
  69. push eax
  70. call Local(_LoadLib)
  71. mov Local(.hKernel32),eax

  72. lea eax,Local(UserDll)
  73. push eax
  74. call Local(_LoadLib)
  75. mov Local(.hUser32),eax

  76. %macro LoadFunc 2
  77. lea eax,Local(%2_n)
  78. push eax
  79. push dword %1
  80. call Local(_GetProcAddr)
  81. mov Local(%2),eax
  82. %endmacro

  83. LoadFunc Local(.hUser32),        _GetWndLong
  84. LoadFunc Local(.hUser32),        _SetWndLong
  85. LoadFunc Local(.hUser32),        _Call_WndProc
  86. LoadFunc Local(.hUser32),        _OpenClp
  87. LoadFunc Local(.hUser32),        _EmptyClp
  88. LoadFunc Local(.hKernel32),        _LocAlloc
  89. LoadFunc Local(.hKernel32),        _LocFree
  90. LoadFunc Local(.hKernel32),        _LocLock
  91. LoadFunc Local(.hKernel32),        _LocUnlock
  92. LoadFunc Local(.hUser32),        _SetClpData
  93. LoadFunc Local(.hUser32),        _CloseClp
  94. LoadFunc Local(.hUser32),        _SendMsg
  95. LoadFunc Local(.hUser32),        _SetTmr
  96. LoadFunc Local(.hUser32),        _KillTmr

  97. %unmacro LoadFunc 2

  98. ;取得原始的WndProc
  99. push dword GWLP_WNDPROC
  100. push dword[Arg(0)]
  101. call Local(_GetWndLong)
  102. mov Local(_OrgWndProc),eax

  103. ;Hook掉
  104. lea eax,Local(_InjWndProc@16)
  105. push eax
  106. push dword GWLP_WNDPROC
  107. push dword[Arg(0)]
  108. call Local(_SetWndLong)

  109. ProcEnd

  110. .hUser32 dd 0
  111. .hKernel32 dd 0

  112. ;==============================================================================
  113. ;LRESULT CALLBACK InjWndProc(HWND,UINT,WPARAM,LPARAM);
  114. ;------------------------------------------------------------------------------
  115. _InjWndProc@16:
  116. ProcBegin

  117. ;处理WM_IME_CHAR消息
  118. cmp dword[Arg(1)],WM_IME_CHAR
  119. jnz .WndProcEnd

  120. ;将字符添加到缓冲区
  121. cmp dword Local(cbString),StringBufLen-2
  122. ja .WndProcEnd;保证不要超过缓冲区的大小

  123. ;在末尾追加字符
  124. lea eax,Local(StringBuf)
  125. add eax,Local(cbString)
  126. mov dx,[Arg(2)]
  127. xchg dl,dh
  128. or dl,dl
  129. jz .OneByte
  130. mov [eax],dl
  131. inc dword Local(cbString)
  132. inc eax
  133. .OneByte:
  134. mov [eax],dh
  135. inc dword Local(cbString)
  136. mov byte[eax+1],0

  137. ;添加一个定时器,用于复制字符到游戏中
  138. lea eax,Local(_InjTimerProc@16)
  139. push eax
  140. push USER_TIMER_MINIMUM
  141. push TimerID
  142. push dword[Arg(0)]
  143. call Local(_SetTmr)

  144. .WndProcEnd:
  145. ;通过调用CallWindowProc来调用旧的消息处理函数
  146. push dword[Arg(3)]
  147. push dword[Arg(2)]
  148. push dword[Arg(1)]
  149. push dword[Arg(0)]
  150. push dword Local(_OrgWndProc)
  151. call Local(_Call_WndProc)

  152. ProcEnd 16

  153. ;==============================================================================
  154. ;VOID CALLBACK InjTimerProc(HWND,UINT Msg,UINT_PTR idEvent,DWORD dwTime);
  155. ;------------------------------------------------------------------------------
  156. _InjTimerProc@16:
  157. ProcBegin 1

  158. cmp byte Local(CtrlVDown),0
  159. jz .CVNotDown
  160. dec byte Local(CtrlVDown)
  161. jnz .CVNotDown

  162. push 0xC02F0001;松开按键,扫描码0x2F,一次
  163. push VK_V
  164. push WM_KEYUP
  165. push dword[Arg(0)]
  166. push dword Local(_OrgWndProc)
  167. call Local(_Call_WndProc)

  168. push 0xC01D0001;松下按键,扫描码0x1D,一次
  169. push VK_CONTROL
  170. push WM_KEYUP
  171. push dword[Arg(0)]
  172. push dword Local(_OrgWndProc)
  173. call Local(_Call_WndProc)

  174. push TimerID
  175. push dword[Arg(0)]
  176. call Local(_KillTmr)

  177. .CVNotDown:
  178. ;判断是否输入了字符串
  179. cmp dword Local(cbString),0
  180. jz .TimerProcEnd

  181. ;打开剪贴板
  182. .OpenClp:
  183. push dword[Arg(0)]
  184. call Local(_OpenClp)
  185. or eax,eax
  186. jz .OpenClp
  187. call Local(_EmptyClp);清空剪贴板

  188. ;给剪贴板分配内存
  189. mov eax,Local(cbString)
  190. inc eax
  191. push eax
  192. push LPTR
  193. call Local(_LocAlloc)
  194. mov [Var(0)],eax

  195. ;锁定内存
  196. push eax
  197. call Local(_LocLock)

  198. ;写入字符数据
  199. push esi
  200. push edi
  201. lea esi,Local(StringBuf)
  202. mov edi,eax
  203. mov ecx,Local(cbString)
  204. rep movsb
  205. pop edi
  206. pop esi
  207. mov dword Local(cbString),0

  208. ;解锁内存
  209. push dword[Var(0)]
  210. call Local(_LocUnlock)

  211. ;设置剪贴板数据
  212. push dword[Var(0)]
  213. push dword CF_TEXT
  214. call Local(_SetClpData)

  215. ;关闭剪贴板
  216. call Local(_CloseClp)

  217. push 0x001D0001;按下按键,扫描码0x1D,一次
  218. push VK_CONTROL
  219. push WM_KEYDOWN
  220. push dword[Arg(0)]
  221. push dword Local(_OrgWndProc)
  222. call Local(_Call_WndProc)

  223. push 0x002F0001;按下按键,扫描码0x2F,一次
  224. push VK_V
  225. push WM_KEYDOWN
  226. push dword[Arg(0)]
  227. push dword Local(_OrgWndProc)
  228. call Local(_Call_WndProc)

  229. ;两个定时器周期后,松开按键
  230. mov byte Local(CtrlVDown),2

  231. .TimerProcEnd:
  232. ProcEnd 16

  233. ;==============================================================================
  234. ;全局变量区
  235. ;------------------------------------------------------------------------------
  236. _OrgWndProc dd 0                ;原先的WndProc

  237. ;定义Dll函数:制造一个变量,以及相应的字符串用于读取
  238. %macro DefDllFunc 2
  239. global %1
  240. %1 dd 0
  241. %1_n db %2,0
  242. %endmacro

  243. KrnlDll db "kernel32.dll",0
  244. UserDll db "user32.dll",0

  245. DefDllFunc _LoadLib,                "LoadLibraryA"
  246. DefDllFunc _GetProcAddr,        "GetProcAddress"
  247. DefDllFunc _GetWndLong,                "GetWindowLongA"
  248. DefDllFunc _SetWndLong,                "SetWindowLongA"
  249. DefDllFunc _Call_WndProc,        "CallWindowProcA"
  250. DefDllFunc _OpenClp,                "OpenClipboard"
  251. DefDllFunc _EmptyClp,                "EmptyClipboard"
  252. DefDllFunc _LocAlloc,                "LocalAlloc"
  253. DefDllFunc _LocFree,                "LocalFree"
  254. DefDllFunc _LocLock,                "LocalLock"
  255. DefDllFunc _LocUnlock,                "LocalUnlock"
  256. DefDllFunc _SetClpData,                "SetClipboardData"
  257. DefDllFunc _CloseClp,                "CloseClipboard"
  258. DefDllFunc _SendMsg,                "SendMessageA"
  259. DefDllFunc _SetTmr,                        "SetTimer"
  260. DefDllFunc _KillTmr,                "KillTimer"

  261. cbString dd 0                        ;字符串长度
  262. StringBufLen equ 1024
  263. StringBuf:                                ;字符串缓冲
  264. times StringBufLen db 0
  265. CtrlVDown db 0                        ;是否按下了Ctrl+V

  266. TimerID equ 0xAA55

  267. ;统计注入的字节数
  268. InjCodeLen equ $-_InjectCode
  269. _SizeOfInjCode dd InjCodeLen
复制代码
以下为注入器的源码(C语言)的源码(注意是控制台程序。)
你只需要把其中的重点代码抽出来用就行了。可以写成Dll。
  1. #include<Windows.h>
  2. #include<stdio.h>
  3. #include<conio.h>
  4. #include<process.h>

  5. HWND g_hWnd=NULL;

  6. extern DWORD InjectCode(LPVOID);
  7. extern DWORD SizeOfInjCode;
  8. extern void*LoadLib;
  9. extern void*GetProcAddr;

  10. //=============================================================================
  11. //函数:PrintLE
  12. //描述:打印GetLastError的字符串信息。
  13. //-----------------------------------------------------------------------------
  14. void PrintLE()
  15. {
  16.         LPVOID lpMsgBuf;
  17.         DWORD dwLastErr;
  18.         FormatMessageA
  19.         (
  20.                 FORMAT_MESSAGE_ALLOCATE_BUFFER | //返回一个已分配的内存
  21.                 FORMAT_MESSAGE_FROM_SYSTEM |  //系统消息
  22.                 FORMAT_MESSAGE_IGNORE_INSERTS, //无视插入信息
  23.                 NULL,
  24.                 dwLastErr=GetLastError(),
  25.                 0, //默认语言
  26.                 (LPSTR)&lpMsgBuf,
  27.                 0,
  28.                 NULL
  29.         );
  30.         fprintf(stderr,"GetLastError()==%d,%s\n",dwLastErr,lpMsgBuf);
  31.         LocalFree(lpMsgBuf);
  32. }

  33. //=============================================================================
  34. //函数:SetPrivilege
  35. //描述:提权,使自己拥有注射指令到别的进程的权限。
  36. //-----------------------------------------------------------------------------
  37. BOOL SetPrivilege()
  38. {
  39.         HANDLE hToken=INVALID_HANDLE_VALUE;
  40.         TOKEN_PRIVILEGES tkp;
  41.         LUID SEDebugNameValue;

  42.         if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
  43.         {
  44.                 PrintLE();
  45.                 return FALSE;
  46.         }

  47.         if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&SEDebugNameValue))
  48.         {
  49.                 PrintLE();
  50.                 CloseHandle(hToken);
  51.                 return FALSE;
  52.         }

  53.         tkp.PrivilegeCount = 1;
  54.         tkp.Privileges[0].Luid=SEDebugNameValue;
  55.         tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

  56.         if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
  57.         {
  58.                 PrintLE();
  59.                 CloseHandle(hToken);
  60.                 return FALSE;
  61.         }

  62.         CloseHandle(hToken);
  63.         return TRUE;
  64. }

  65. //=============================================================================
  66. //函数:InjectToProcess
  67. //描述:注射到指定窗口句柄所在的进程。
  68. //-----------------------------------------------------------------------------
  69. BOOL InjectToProcess(HWND hWnd)
  70. {
  71.         HANDLE hProc=INVALID_HANDLE_VALUE,hRemoteProc=INVALID_HANDLE_VALUE;
  72.         HMODULE hKernel32=NULL;
  73.         SIZE_T cbWrite;
  74.         void*pMemAddr=NULL;
  75. #        ifdef _DEBUG
  76.         DWORD dwProcID=GetCurrentProcessId();
  77.         DWORD dwOldProtect;
  78. #        else
  79.         DWORD dwProcID;
  80. #        endif

  81.         hKernel32=LoadLibrary(TEXT("kernel32.dll"));
  82.         if(!hKernel32)
  83.         {
  84.                 fputs("Could not load library.\n",stderr);
  85.                 PrintLE();
  86.                 return FALSE;
  87.         }
  88.        
  89.         //写入API地址到要注射的代码中
  90.         LoadLib=                GetProcAddress(hKernel32,        "LoadLibraryA");
  91.         GetProcAddr=        GetProcAddress(hKernel32,        "GetProcAddress");

  92.         FreeLibrary(hKernel32);hKernel32=NULL;

  93.         //Debug编译的代码并没有注入的行为,主要用于调试。
  94. #        ifdef _DEBUG
  95.         VirtualProtectEx(GetCurrentProcess(),InjectCode,SizeOfInjCode,PAGE_EXECUTE_READWRITE,&dwOldProtect);
  96.         InjectCode(hWnd);
  97.         return TRUE;
  98. #        endif

  99.         //取得进程ID
  100.         GetWindowThreadProcessId(hWnd,&dwProcID);
  101.         if(!dwProcID)
  102.         {
  103.                 fputs("Could not get process Id.\n",stderr);
  104.                 PrintLE();
  105.                 return FALSE;
  106.         }
  107.         fprintf(stderr,"Process Id = %u\n",dwProcID);
  108.        
  109.         //打开进程
  110.         hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcID);
  111.         if(!hProc||hProc==INVALID_HANDLE_VALUE)
  112.         {
  113.                 fputs("Open process failed.\n",stderr);
  114.                 PrintLE();
  115.                 return FALSE;
  116.         }

  117.         //远程分配内存
  118.         pMemAddr=VirtualAllocEx(hProc,NULL,SizeOfInjCode,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  119.         if(!pMemAddr)
  120.         {
  121.                 fputs("Could not allocate remote memory.\n",stderr);
  122.                 PrintLE();
  123.                 goto FailRet;
  124.         }

  125.         //注入代码
  126.         if(!WriteProcessMemory(hProc,pMemAddr,InjectCode,SizeOfInjCode,&cbWrite))
  127.         {
  128.                 fputs("Could not write data to remote memory.\n",stderr);
  129.                 PrintLE();
  130.                 goto FailRet;
  131.         }
  132.        
  133.         //创建远程线程
  134.         hRemoteProc=CreateRemoteThread(hProc,NULL,0,(LPTHREAD_START_ROUTINE)pMemAddr,hWnd,0,NULL);
  135.         if(!hRemoteProc||hRemoteProc==INVALID_HANDLE_VALUE)
  136.         {
  137.                 fputs("Could not create remote thread.\n",stderr);
  138.                 PrintLE();
  139.                 goto FailRet;
  140.         }

  141.         CloseHandle(hRemoteProc);
  142.         CloseHandle(hProc);
  143.         return TRUE;
  144. FailRet:
  145.         if(hKernel32)
  146.                 FreeLibrary(hKernel32);
  147.         if(hProc&&hProc!=INVALID_HANDLE_VALUE)
  148.                 CloseHandle(hProc);
  149.         if(hRemoteProc&&hRemoteProc!=INVALID_HANDLE_VALUE)
  150.                 CloseHandle(hRemoteProc);
  151.         return FALSE;
  152. }

  153. //=============================================================================
  154. //函数:MatchWindow
  155. //描述:判断窗口是不是指定的窗口类
  156. //-----------------------------------------------------------------------------
  157. BOOL MatchWindow(HWND hWnd,LPCTSTR szClassName)
  158. {
  159.         TCHAR*szClass;
  160.         int nClass,nNewClass;
  161.         int cbClass;

  162.         nClass=lstrlen(szClassName);
  163.         nNewClass=nClass+2;
  164.         cbClass=nNewClass*sizeof(TCHAR);
  165.         szClass=(TCHAR*)malloc(cbClass);
  166.         if(!szClass)return FALSE;
  167.         memset(szClass,0,cbClass);

  168.         if(GetClassName(hWnd,szClass,nNewClass)==nClass)
  169.         {
  170.                 if(!lstrcmp(szClass,szClassName))
  171.                 {
  172.                         free(szClass);
  173.                         return TRUE;
  174.                 }
  175.         }

  176.         free(szClass);
  177.         return FALSE;
  178. }

  179. //=============================================================================
  180. //函数:EnumWindowsProc
  181. //描述:枚举窗口的回调函数。
  182. //-----------------------------------------------------------------------------
  183. BOOL CALLBACK EnumWindowsProc(HWND hWnd,LPARAM lParam)
  184. {
  185.         TCHAR szClass[7]={0};

  186.         if(MatchWindow(hWnd,TEXT("LWJGL")))
  187.         {
  188.                 printf("0x%08X\n",hWnd);
  189.                 InjectToProcess(hWnd);
  190.         }
  191.        
  192.         return TRUE;
  193. }

  194. //Debug编译时创建窗口的一系列操作
  195. #ifdef DEBUG
  196. //=============================================================================
  197. //函数:WndProc
  198. //描述:自己的窗口的消息处理函数
  199. //-----------------------------------------------------------------------------
  200. LRESULT CALLBACK WndProc(HWND hWnd,UINT Msg,WPARAM wp,LPARAM lp)
  201. {
  202.         switch(Msg)
  203.         {
  204.         default:
  205.                 return DefWindowProc(hWnd,Msg,wp,lp);
  206.         case WM_DESTROY:
  207.                 PostQuitMessage(0);
  208.                 break;
  209.         }
  210.         return 0;
  211. }

  212. //=============================================================================
  213. //函数:CreateWnd
  214. //描述:创建并显示自己的窗口
  215. //-----------------------------------------------------------------------------
  216. HWND CreateWnd()
  217. {
  218.         HINSTANCE hInst=GetModuleHandle(NULL);
  219.         WNDCLASSEX WCEx={sizeof(WNDCLASSEX),0,WndProc,0,0,hInst,NULL,LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW)),(HBRUSH)COLOR_BTNFACE,NULL,TEXT("mcime"),NULL};//窗口类
  220.         HWND hWnd=CreateWindowEx(0,MAKEINTATOM(RegisterClassEx(&WCEx)),TEXT("mcime"),WS_OVERLAPPEDWINDOW,
  221.                 CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL);//窗口句柄
  222.         ShowWindow(hWnd,SW_SHOW);
  223.         UpdateWindow(hWnd);
  224.         return hWnd;
  225. }

  226. //=============================================================================
  227. //函数:RunWnd
  228. //描述:线程函数,用于处理所有的窗口消息。
  229. //-----------------------------------------------------------------------------
  230. void RunWnd(void*p)
  231. {
  232.         MSG msg;

  233.         g_hWnd=CreateWnd();
  234.         if(!g_hWnd)
  235.                 return;

  236.         while(GetMessage(&msg,NULL,0,0))//消息循环
  237.         {
  238.                 TranslateMessage(&msg);
  239.                 DispatchMessage(&msg);
  240.         }
  241. }
  242. #endif

  243. int main(int argc,char**argv)
  244. {
  245.         //先提权
  246.         if(!SetPrivilege())
  247.         {
  248.                 fputs("Take privilege failed.(%u)\n",stderr);
  249.                 return 1;
  250.         }
  251. #        ifdef _DEBUG
  252.         //创建线程用于显示窗口
  253.         _beginthread(RunWnd,0,NULL);

  254.         //等窗口创建好
  255.         while(!g_hWnd)
  256.                 Sleep(1);

  257.         //注入到窗口
  258.         InjectToProcess(g_hWnd);
  259. #        else
  260.         EnumWindows(EnumWindowsProc,0);
  261. #        endif

  262.         //暂停一下以便于看到错误信息。
  263.         _getch();
  264.         return 0;
  265. }
复制代码
另外附上x64的Shellcode。这个会让Minecraft退出,原因不明。
  1. %define WM_IME_CHAR 0x0286
  2. %define WM_KEYDOWN 0x0100
  3. %define WM_KEYUP 0x0101
  4. %define WM_CHAR 0x0102
  5. %define WM_TIMER 0x0113

  6. %define STD_ERROR_HANDLE 0xFFFFFFF4

  7. %define GWLP_WNDPROC (-4)
  8. %define GCL_WNDPROC (-24)
  9. %define CF_TEXT 1
  10. %define LPTR 0x0040
  11. %define VK_CONTROL 0x11
  12. %define VK_V 0x56
  13. %define KEYEVENTF_KEYUP 0x0002
  14. %define USER_TIMER_MINIMUM 0x0000000A

  15. ;==============================================================================
  16. ;宏名:ProcBegin
  17. ;描述:用于每个过程的开头,建立栈帧,并使ebx指向指令起始地址
  18. ;------------------------------------------------------------------------------
  19. %macro ProcBegin 0-1
  20. push rbp;建立栈帧
  21. mov rbp,rsp

  22. ;如果有参数
  23. ;参数的作用:指定当前过程中调用的所有子过程中最大参数个数
  24. %if %0
  25. %if (%1)!=0
  26.         %define LocalVarsMem
  27.         %assign LocalVarsMem (((((%1)+1)/2)*16)+8);参数个数16字节对齐,外加8字节
  28.         sub rsp,LocalVarsMem;分配局部变量内存
  29. %endif
  30. %endif

  31. push rbx;保存rbx
  32. call %%GetCurPos;取得指令原点
  33. %%GetCurPos:
  34. pop rbx
  35. sub rbx,%%GetCurPos-InjectCode
  36. %endmacro

  37. ;==============================================================================
  38. ;宏名:ProcEnd
  39. ;描述:用于每个过程的结尾,恢复寄存器并返回,选择性清理栈内存
  40. ;------------------------------------------------------------------------------
  41. %macro ProcEnd 0-1
  42. .EndOfProc:
  43. %ifdef LocalVarsMem
  44.         %if LocalVarsMem;释放局部变量内存
  45.                 add rsp,LocalVarsMem
  46.         %endif
  47.         %undef LocalVarsMem
  48. %endif
  49. pop rbx;恢复ebx
  50. mov rsp,rbp
  51. pop rbp
  52. ret
  53. %endmacro

  54. ;==============================================================================
  55. ;宏名:Arg
  56. ;描述:用于过程中读取函数参数
  57. ;------------------------------------------------------------------------------
  58. %define Arg(x)                (rbp+16+(x)*8)

  59. ;==============================================================================
  60. ;宏名:Var
  61. ;描述:用于过程中读取变量
  62. ;------------------------------------------------------------------------------
  63. %define Var(x)                (rbp-8-(x)*8)

  64. ;==============================================================================
  65. ;宏名:Param
  66. ;描述:用于设置函数的参数
  67. ;------------------------------------------------------------------------------
  68. %define Param(x)        (rsp+(x)*8)

  69. ;==============================================================================
  70. ;宏名:Local
  71. ;描述:读取局部变量
  72. ;------------------------------------------------------------------------------
  73. %define Local(x)        [rbx+(x)-InjectCode]

  74. global InjectCode
  75. global InjWndProc
  76. global InjTimerProc
  77. global SizeOfInjCode

  78. segment .data
  79. ;==============================================================================
  80. ;void InjectCode(HWND);
  81. ;------------------------------------------------------------------------------
  82. InjectCode:
  83. ProcBegin 4;过程中调用的函数参数个数最大4个

  84. mov [Arg(0)],rcx

  85. lea rcx,Local(KrnlDll)
  86. call Local(LoadLib)
  87. mov Local(.hKernel32),rax

  88. lea rcx,Local(UserDll)
  89. call Local(LoadLib)
  90. mov Local(.hUser32),rax

  91. %macro LoadFunc 2
  92. lea rdx,Local(%2_n)
  93. mov rcx,%1
  94. call Local(GetProcAddr)
  95. mov Local(%2),rax
  96. %endmacro

  97. LoadFunc Local(.hUser32),        GetWndLong
  98. LoadFunc Local(.hUser32),        SetWndLong
  99. LoadFunc Local(.hUser32),        Call_WndProc
  100. LoadFunc Local(.hUser32),        DefWndProc
  101. LoadFunc Local(.hUser32),        OpenClp
  102. LoadFunc Local(.hUser32),        EmptyClp
  103. LoadFunc Local(.hKernel32),        LocAlloc
  104. LoadFunc Local(.hKernel32),        LocFree
  105. LoadFunc Local(.hKernel32),        LocLock
  106. LoadFunc Local(.hKernel32),        LocUnlock
  107. LoadFunc Local(.hUser32),        SetClpData
  108. LoadFunc Local(.hUser32),        CloseClp
  109. LoadFunc Local(.hUser32),        SendMsg
  110. LoadFunc Local(.hUser32),        SetTmr
  111. LoadFunc Local(.hUser32),        KillTmr

  112. %unmacro LoadFunc 2

  113. ;取得原始的WndProc
  114. mov rdx,GWLP_WNDPROC
  115. mov rcx,[Arg(0)]
  116. call Local(GetWndLong)
  117. mov Local(OrgWndProc),rax

  118. ;Hook掉
  119. lea r8,Local(InjWndProc)
  120. mov rdx,GWLP_WNDPROC
  121. mov rcx,[Arg(0)]
  122. call Local(SetWndLong)

  123. ProcEnd

  124. .hUser32 dq 0
  125. .hKernel32 dq 0

  126. ;==============================================================================
  127. ;LRESULT CALLBACK InjWndProc(HWND,UINT,WPARAM,LPARAM);
  128. ;------------------------------------------------------------------------------
  129. InjWndProc:
  130. ProcBegin 5;过程中调用的函数参数个数最大5个

  131. mov[Arg(0)],rcx
  132. mov[Arg(1)],rdx
  133. mov[Arg(2)],r8
  134. mov[Arg(3)],r9

  135. ;处理WM_IME_CHAR消息
  136. cmp edx,WM_IME_CHAR
  137. jnz .WndProcEnd

  138. ;将字符添加到缓冲区
  139. cmp qword Local(cbString),StringBufLen-1
  140. ja .WndProcEnd;保证不要超过缓冲区的大小

  141. ;在末尾追加字符
  142. lea rax,Local(StringBuf)
  143. add rax,Local(cbString)
  144. mov dx,r8w
  145. xchg dl,dh
  146. or dl,dl
  147. jz .OneByte
  148. mov [rax],dl
  149. inc qword Local(cbString)
  150. inc rax
  151. .OneByte:
  152. mov [rax],dh
  153. inc qword Local(cbString)

  154. ;添加一个定时器,用于复制字符到游戏中
  155. lea r9,Local(InjTimerProc)
  156. mov r8,USER_TIMER_MINIMUM
  157. mov rdx,TimerID
  158. mov rcx,[Arg(0)]
  159. call Local(SetTmr)
  160. jmp .DefProc

  161. .WndProcEnd:
  162. ;通过调用CallWindowProc来调用旧的消息处理函数

  163. mov rax,[Arg(3)]
  164. mov [Param(4)],rax;第五个参数入栈
  165. mov r9,[Arg(2)]
  166. mov r8,[Arg(1)]
  167. mov rdx,[Arg(0)]
  168. mov rcx,Local(OrgWndProc)
  169. call Local(Call_WndProc)

  170. jmp .EndOfProc

  171. .DefProc:
  172. call Local(DefWndProc)
  173. ProcEnd

  174. ;==============================================================================
  175. ;VOID CALLBACK InjTimerProc(HWND,UINT Msg,UINT_PTR idEvent,DWORD dwTime);
  176. ;------------------------------------------------------------------------------
  177. InjTimerProc:
  178. ProcBegin 5;过程中调用的函数参数个数最大5个

  179. mov[Arg(0)],rcx
  180. mov[Arg(1)],rdx

  181. cmp byte Local(CtrlVDown),0
  182. jz .CtrlVUp
  183. dec byte Local(CtrlVDown)
  184. jnz .CtrlVUp

  185. mov dword[Param(4)],0xC02F0001
  186. mov r9,VK_V
  187. mov r8,WM_KEYUP
  188. mov rdx,[Arg(0)]
  189. mov rcx,Local(OrgWndProc)
  190. call Local(Call_WndProc)

  191. ;发送Ctrl+V的松开
  192. mov dword[Param(4)],0xC01D0001
  193. mov r9,VK_CONTROL
  194. mov r8,WM_KEYUP
  195. mov rdx,[Arg(0)]
  196. mov rcx,Local(OrgWndProc)
  197. call Local(Call_WndProc)

  198. mov rdx,TimerID
  199. mov rcx,[Arg(0)]
  200. call Local(KillTmr)

  201. .CtrlVUp:
  202. ;判断是否输入了字符串
  203. cmp qword Local(cbString),0
  204. jz .TimerProcEnd

  205. ;打开剪贴板
  206. .OpenClp:
  207. mov rcx,[Arg(0)]
  208. call Local(OpenClp)
  209. or rax,rax
  210. jz .OpenClp

  211. call Local(EmptyClp);清空剪贴板

  212. ;给剪贴板分配内存
  213. mov rdx,Local(cbString)
  214. inc rdx
  215. mov rcx,LPTR
  216. call Local(LocAlloc)
  217. mov[Arg(2)],rax;用参数2的位置(没用)来存储内存句柄

  218. ;锁定内存
  219. mov rcx,rax
  220. call Local(LocLock)

  221. ;写入字符数据
  222. push rsi
  223. push rdi
  224. lea rsi,Local(StringBuf)
  225. mov rdi,rax
  226. mov rcx,Local(cbString)
  227. rep movsb
  228. pop rdi
  229. pop rsi
  230. mov qword Local(cbString),0

  231. ;解锁内存
  232. mov rcx,[Arg(2)]
  233. call Local(LocUnlock)

  234. ;设置剪贴板数据
  235. mov rdx,[Arg(2)]
  236. mov rcx,CF_TEXT
  237. call Local(SetClpData)

  238. ;关闭剪贴板
  239. call Local(CloseClp)

  240. ;发送Ctrl+V的按键信息
  241. mov dword[Param(4)],0x001D0001
  242. mov r9,VK_CONTROL
  243. mov r8,WM_KEYDOWN
  244. mov rdx,[Arg(0)]
  245. mov rcx,Local(OrgWndProc)
  246. call Local(Call_WndProc)

  247. mov dword[Param(4)],0x002F0001
  248. mov r9,VK_V
  249. mov r8,WM_KEYDOWN
  250. mov rdx,[Arg(0)]
  251. mov rcx,Local(OrgWndProc)
  252. call Local(Call_WndProc)

  253. ;已按下这个键
  254. mov byte Local(CtrlVDown),2;键盘反应时间

  255. .TimerProcEnd:
  256. ProcEnd 16

  257. ;==============================================================================
  258. ;全局变量区
  259. ;------------------------------------------------------------------------------
  260. OrgWndProc                dq 0                ;原先的WndProc

  261. ;定义Dll函数:制造一个变量,以及相应的字符串用于读取
  262. %macro DefDllFunc 2
  263. global %1
  264. %1 dq 0
  265. %1_n db %2,0
  266. %endmacro

  267. KrnlDll db "kernel32.dll",0
  268. UserDll db "user32.dll",0
  269. hStdErr dq 0
  270. StrLen dq 0

  271. DefDllFunc LoadLib,                "LoadLibraryA"
  272. DefDllFunc GetProcAddr,        "GetProcAddress"
  273. DefDllFunc GetWndLong,        "GetWindowLongPtrA"
  274. DefDllFunc SetWndLong,        "SetWindowLongPtrA"
  275. DefDllFunc Call_WndProc,"CallWindowProcA"
  276. DefDllFunc DefWndProc,        "DefWindowProcA"
  277. DefDllFunc OpenClp,                "OpenClipboard"
  278. DefDllFunc EmptyClp,        "EmptyClipboard"
  279. DefDllFunc LocAlloc,        "LocalAlloc"
  280. DefDllFunc LocFree,                "LocalFree"
  281. DefDllFunc LocLock,                "LocalLock"
  282. DefDllFunc LocUnlock,        "LocalUnlock"
  283. DefDllFunc SetClpData,        "SetClipboardData"
  284. DefDllFunc CloseClp,        "CloseClipboard"
  285. DefDllFunc SendMsg,                "SendMessageA"
  286. DefDllFunc SetTmr,                "SetTimer"
  287. DefDllFunc KillTmr,                "KillTimer"

  288. cbString                dq 0        ;字符串长度
  289. StringBufLen equ 1024
  290. StringBuf:                                ;字符串缓冲
  291. times StringBufLen db 0
  292. CtrlVDown db 0                        ;是否按下了Ctrl+V

  293. TimerID equ 0xAA55

  294. ;统计注入的字节数
  295. InjCodeLen equ $-InjectCode
  296. SizeOfInjCode dq InjCodeLen
复制代码
全部源码: MCIME.7z (12 KB, 下载次数: 0, 售价: 1 个宅币)

本帖被以下淘专辑推荐:

回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-24 10:19 , Processed in 0.038684 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表