1. 1 #include "Windows.h"
  2. 2 #include "tlhelp32.h"
  3. 3 #include "String.h"
  4. 4 #include "Shlwapi.h"
  5. 5 #include "iostream"
  6. 6 #include "map"
  7. 7 using namespace std;
  8. 8
  9. 9 HANDLE hProcess;
  10. 10 LPVOID lp_address;
  11. 11 LPVOID lp_ret_value_address;
  12. 12 DWORD lp_ret_jmp, calladd;
  13. 13 DWORD lp_to_jmp;
  14. 14
  15. 15 template <typename T>
  16. 16 T Read(LPVOID Address)
  17. 17 {
  18. 18 T Data;
  19. 19 ReadProcessMemory(hProcess, (LPVOID)Address, &Data, sizeof(T), nullptr);
  20. 20 return Data;
  21. 21 }
  22. 22
  23. 23 uintptr_t FindPattern(uintptr_t start, uintptr_t length, const unsigned char* pattern, const char* mask)
  24. 24 {
  25. 25 size_t pos = 0;
  26. 26 auto maskLength = strlen(mask) - 1;
  27. 27
  28. 28 auto startAdress = start;
  29. 29 for (auto it = startAdress; it < startAdress + length; ++it)
  30. 30 {
  31. 31 if (Read<unsigned char>(LPVOID(it)) == pattern[pos] || mask[pos] == '?')
  32. 32 {
  33. 33 if (mask[pos + 1] == '\0')
  34. 34 return it - maskLength;
  35. 35
  36. 36 pos++;
  37. 37 }
  38. 38 else pos = 0;
  39. 39 }
  40. 40 return 0;
  41. 41 }
  42. 42
  43. 43 //读内存4字节整数型
  44. 44 DWORD _ReadMemeryInt(HANDLE hGameHandle, DWORD _address)
  45. 45 {
  46. 46 DWORD buffer;
  47. 47 ReadProcessMemory(hGameHandle, LPCVOID(_address), &buffer, sizeof(buffer), NULL);
  48. 48 return buffer;
  49. 49 }
  50. 50
  51. 51 //读内存小数型
  52. 52 FLOAT _ReadMemeryFloat(HANDLE hGameHandle, DWORD _address)
  53. 53 {
  54. 54 FLOAT buffer;
  55. 55 ReadProcessMemory(hGameHandle, LPCVOID(_address), &buffer, sizeof(buffer), NULL);
  56. 56 return buffer;
  57. 57 }
  58. 58
  59. 59 //读内存文本型
  60. 60 char* _ReadMemeryString(HANDLE hGameHandle, DWORD _address)
  61. 61 {
  62. 62 char read[256];
  63. 63 char* pa;
  64. 64
  65. 65 pa = read;
  66. 66
  67. 67 ReadProcessMemory(hGameHandle, LPCVOID(_address), read, sizeof(read), NULL);
  68. 68
  69. 69 for (pa; *pa != '\0'; pa++)
  70. 70 {
  71. 71 return pa;
  72. 72 }
  73. 73
  74. 74 }
  75. 75
  76. 76 //写内存整数型
  77. 77 BOOL WriteMemeryInt(HANDLE hGameHandle, DWORD _address, DWORD Data)
  78. 78 {
  79. 79 return WriteProcessMemory(hGameHandle, LPVOID(_address), &Data, sizeof(Data), NULL);
  80. 80 }
  81. 81
  82. 82 //写内存小数型
  83. 83 BOOL WriteMemeryFloat(HANDLE hGameHandle, DWORD _address, FLOAT Data)
  84. 84 {
  85. 85 return WriteProcessMemory(hGameHandle, LPVOID(_address), &Data, sizeof(Data), NULL);
  86. 86 }
  87. 87
  88. 88 //写内存字节数组
  89. 89 BOOL WriteMemeryBytes(HANDLE hGameHandle, DWORD _address, BYTE Data[], SIZE_T Bytes)
  90. 90 {
  91. 91 return WriteProcessMemory(hGameHandle, LPVOID(_address), Data, Bytes, NULL);
  92. 92 }
  93. 93
  94. 94
  95. 95
  96. 96 //特征码寻址
  97. 97 uintptr_t FindPattern(HMODULE hModule, const unsigned char* pattern, const char* mask)
  98. 98 {
  99. 99 IMAGE_DOS_HEADER DOSHeader = Read<IMAGE_DOS_HEADER>(hModule);
  100. 100 IMAGE_NT_HEADERS NTHeaders = Read<IMAGE_NT_HEADERS>(LPVOID(uintptr_t(hModule) + DOSHeader.e_lfanew));
  101. 101
  102. 102 return FindPattern(
  103. 103 reinterpret_cast<uintptr_t>(hModule) + NTHeaders.OptionalHeader.BaseOfCode,
  104. 104 reinterpret_cast<uintptr_t>(hModule) + NTHeaders.OptionalHeader.SizeOfCode, pattern, mask);
  105. 105 }
  106. 106
  107. 107 HMODULE GetProcessModuleHandleByName(DWORD pid, LPCSTR ModuleName)
  108. 108 {
  109. 109 MODULEENTRY32 ModuleInfo;
  110. 110 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
  111. 111 if (!hSnapshot)
  112. 112 {
  113. 113 return 0;
  114. 114 }
  115. 115 ZeroMemory(&ModuleInfo, sizeof(MODULEENTRY32));
  116. 116 ModuleInfo.dwSize = sizeof(MODULEENTRY32);
  117. 117 if (!Module32First(hSnapshot, &ModuleInfo))
  118. 118 {
  119. 119 return 0;
  120. 120 }
  121. 121 do
  122. 122 {
  123. 123 if (!lstrcmpi(ModuleInfo.szModule, ModuleName))
  124. 124 {
  125. 125 CloseHandle(hSnapshot);
  126. 126 return ModuleInfo.hModule;
  127. 127 }
  128. 128 } while (Module32Next(hSnapshot, &ModuleInfo));
  129. 129 CloseHandle(hSnapshot);
  130. 130 return 0;
  131. 131 }
  132. 132
  133. 133 DWORD GetProcessIDByName(const char* pName)
  134. 134 {
  135. 135 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  136. 136 if (INVALID_HANDLE_VALUE == hSnapshot) {
  137. 137 return NULL;
  138. 138 }
  139. 139 PROCESSENTRY32 pe = { sizeof(pe) };
  140. 140 for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
  141. 141 if (strcmp(pe.szExeFile, pName) == 0) {
  142. 142 CloseHandle(hSnapshot);
  143. 143 return pe.th32ProcessID;
  144. 144 }
  145. 145 //printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
  146. 146 }
  147. 147 CloseHandle(hSnapshot);
  148. 148 return 0;
  149. 149 }
  150. 150
  151. 151
  152. 152 //内联汇编被写入
  153. 153 inline __declspec(naked) void ret_hook()
  154. 154 {
  155. 155 __asm
  156. 156 {
  157. 157 Pushfd
  158. 158 Pushad
  159. 159 add esi, 0xC
  160. 160 push esi
  161. 161 mov dword ptr[esi], edx
  162. 162 mov eax ,0xCF7000
  163. 163 mov [eax], esi
  164. 164 sub esi, 0xC
  165. 165 pop esi
  166. 166 popad
  167. 167 popfd
  168. 168 mov dword ptr[esi + 0xC], edx
  169. 169 }
  170. 170 }
  171. 171
  172. 172
  173. 173 int main()
  174. 174 {
  175. 175 SetConsoleTitleA("过考试");
  176. 176
  177. 177 DWORD OldProtect = NULL;
  178. 178 int Pid = GetProcessIDByName("qwq.exe");
  179. 179 hProcess = INVALID_HANDLE_VALUE;
  180. 180 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);//游戏进程句柄
  181. 181
  182. 182 cout << "进程ID:" << Pid << endl << "进程句柄:" << hProcess << endl;
  183. 183
  184. 184 HMODULE hbcryptPrimitives = GetProcessModuleHandleByName(Pid, "qwq.exe");
  185. 185 lp_ret_jmp = (DWORD)hbcryptPrimitives + 0x74c93;
  186. 186 lp_to_jmp = (DWORD)hbcryptPrimitives + 0x74c8b;
  187. 187 calladd = (DWORD)hbcryptPrimitives + 0x742a0;
  188. 188
  189. 189 lp_address = VirtualAllocEx(hProcess, NULL, 128, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  190. 190 cout << lp_address << endl;
  191. 191
  192. 192 SIZE_T num_byte;
  193. 193 SIZE_T *p = &num_byte;
  194. 194
  195. 195 WriteProcessMemory(hProcess, lp_address, ret_hook, 50, p);
  196. 196
  197. 197
  198. 198 BYTE call_e8 = { 0xe8 };
  199. 199 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x18), (LPVOID)&call_e8, 1, NULL);
  200. 200 int rec_call = (int)calladd - ((DWORD)lp_address + 0x18) - 5;
  201. 201 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x19), (LPVOID)&rec_call, 4, NULL);
  202. 202
  203. 203 BYTE jmp_e9 = { 0xe9 };
  204. 204 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address+0x19+4), (LPVOID)&jmp_e9, 1, NULL);
  205. 205 int jmp_ret = (int)lp_ret_jmp - ((DWORD)lp_address + 0x19 + 4) - 5;
  206. 206 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x19 + 5), (LPVOID)&jmp_ret, 4, NULL);
  207. 207
  208. 208 WriteProcessMemory(hProcess, (LPVOID)(DWORD)lp_to_jmp, (LPVOID)&jmp_e9, 1, NULL);
  209. 209 int jmp_to = (int)lp_address - (DWORD)lp_to_jmp -5;
  210. 210 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_to_jmp + 1), (LPVOID)&jmp_to, 4, NULL);
  211. 211
  212. 212
  213. 213 BYTE nop_90 = { 0x90 };
  214. 214 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_to_jmp +5), (LPVOID)&nop_90, 1, NULL);
  215. 215 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_to_jmp + 6), (LPVOID)&nop_90, 1, NULL);
  216. 216 WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_to_jmp + 7), (LPVOID)&nop_90, 1, NULL);
  217. 217
  218. 218 DWORD tmpadd_mon = _ReadMemeryInt(hProcess, 0xCF7000);
  219. 219 double add_data_mon = _ReadMemeryFloat(hProcess, tmpadd_mon);
  220. 220 //cout << "对象地址:" << hex << tmpadd_mon << " " << "对象坐标:" << add_data_mon << "\r";
  221. 221
  222. 222 std::map<DWORD, DWORD> mymap;
  223. 223
  224. 224
  225. 225 int t = 100000;
  226. 226 while (t--)
  227. 227 {
  228. 228 DWORD tmpadd = _ReadMemeryInt(hProcess, 0xCF7000);
  229. 229 double add_data = _ReadMemeryFloat(hProcess, tmpadd);
  230. 230 std::map<DWORD, DWORD>::iterator it;
  231. 231 it = mymap.find(tmpadd);
  232. 232 if(it==mymap.end())
  233. 233 {
  234. 234 cout << "怪物地址:" << hex << tmpadd << endl;
  235. 235 }
  236. 236 mymap[tmpadd] = tmpadd;
  237. 237 }
  238. 238 cout << "GO" << endl;
  239. 239 while (1)
  240. 240 {
  241. 241 DWORD tmpadd = _ReadMemeryInt(hProcess, 0xCF7000);
  242. 242 float add_data = _ReadMemeryFloat(hProcess, tmpadd);
  243. 243 std::map<DWORD, DWORD>::iterator qwq;
  244. 244 qwq = mymap.find(tmpadd);
  245. 245 //cout << hex << tmpadd << endl;
  246. 246 if (qwq == mymap.end())
  247. 247 {
  248. 248 cout << "人物地址:" << hex << tmpadd << " " << "人物坐标:" << add_data <<" "<< "\r";
  249. 249 }
  250. 250 }
  251. 251
  252. 252 //while (1)
  253. 253 //{
  254. 254 // for (std::map<char, int>::iterator it = mymap.begin(); it != mymap.end(); it++)
  255. 255 // {
  256. 256 // double add_data = _ReadMemeryFloat(hProcess, (DWORD)(it->second));
  257. 257 // cout << "对象地址:" << hex << (DWORD)(it->second) << " " << "对象坐标:" << add_data << endl;
  258. 258 // }
  259. 259 // system("cls");
  260. 260 //}
  261. 261
  262. 262
  263. 263
  264. 264 ////cout << "分配的写入hook的地址:" << lp_address << hex << endl;
  265. 265
  266. 266 ////bcryptPrimitives.dll+24AFF - CC - int 3
  267. 267
  268. 268 //HMODULE hbcryptPrimitives = GetProcessModuleHandleByName(Pid, "qwq.exe");
  269. 269
  270. 270
  271. 271 ////这边自己搞检测地址
  272. 272 //lp_ret_jmp = (DWORD)hbcryptPrimitives + 0x74C93;
  273. 273 //lp_to_jmp = (DWORD)hbcryptPrimitives + 0x74C8B;
  274. 274 //calladd = (DWORD)hbcryptPrimitives + 0x742A0;
  275. 275 ////cout << "跳回的地址计算:" << lp_ret_jmp << endl;
  276. 276
  277. 277
  278. 278 ///*写ret hook*/
  279. 279 //if (WriteProcessMemory(hProcess, lp_address, ret_hook, 50, NULL) != 0) {
  280. 280 // cout << "写入成功!" << endl;
  281. 281 // cout << lp_address << endl;
  282. 282
  283. 283
  284. 284 // BYTE jmp_e9 = { 0xe9 };
  285. 285 // WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x7), (LPVOID)&jmp_e9, 1, NULL);
  286. 286 // int jmp_ret = (int)lp_ret_jmp - ((DWORD)lp_address + 0x7) - 5;
  287. 287 // WriteProcessMemory(hProcess, (LPVOID)((DWORD)lp_address + 0x8), (LPVOID)&jmp_ret, 4, NULL);
  288. 288
  289. 289
  290. 290 // //to hook
  291. 291
  292. 292 // BYTE jmp_to_e9 = { 0xe9 };
  293. 293 // WriteProcessMemory(hProcess, (LPVOID)lp_to_jmp, (LPVOID)&jmp_to_e9, 1, NULL);
  294. 294 // int jmp_to_hook = (int)lp_address;
  295. 295 // WriteProcessMemory(hProcess, (LPVOID)(lp_to_jmp + 0x1), (LPVOID)&jmp_to_hook, 4, NULL);
  296. 296
  297. 297
  298. 298
  299. 299 //}
  300. 300 ///*ret jmp*/
  301. 301
  302. 302 //
  303. 303
  304. 304 getchar();
  305. 305 return 0;
  306. 306 }
实际操作时对写内存函数有疑问,jmp的机器码和跳转的地址不一致。从https://blog.csdn.net/chenchong_219/article/details/17973935转载过来这篇文章。
 
od随便打开一个记事本,汇编几条jmp指令,可以看到如下

地址           HEX              反汇编

010073B4     - E9 7B9E8787      JMP 88881234
010073B9     - E9 769E8787      JMP 88881234
010073BE     - E9 719E8787      JMP 88881234
010073C3     - E9 6C9E8787      JMP 88881234
010073C8     - E9 679E8787      JMP 88881234
010073CD     - E9 629E8787      JMP 88881234
010073D2     - E9 5D9E8787      JMP 88881234
010073D7     - E9 589E8787      JMP 88881234
010073DC     - E9 539E8787      JMP 88881234
010073E1     - E9 4E9E8787      JMP 88881234
010073E6     - E9 499E8787      JMP 88881234
可以看到同样的汇编指令,在不同的地址上的机器码不一样。
有啥关系呢?看第一条:88881234-010073b4=87879e80
这个值跟E9后面的那个值差了5(E9后面那个值要反过来看,因为X86是大端模式)
 
同样这个规律也使用与后面几条。
 
为什么呢?
下面摘录一个网上的
 
直接的jmp分3种 
Short Jump(短跳转)机器码 EB rel8 
只能跳转到256字节的范围内 
Near Jump(近跳转)机器码 E9 rel16/32 
可跳至同一个段的范围内的地址 
Far Jump(远跳转)机器码EA ptr 16:16/32 
可跳至任意地址,使用48位/32位全指针 
要注意的是,短跳转和近跳转指令中包含的操作数都是相对于(E)IP的偏移,而远跳转指令中包含的是目标的绝对地址,所以短/近跳转会出现跳至同一目标的指令机器码不同,不仅会不同,而且应该不同。而远跳转中包含的是绝对地址,因此转移到同一地址的指令机器码相同 
下面的指令是这样计算偏移的. 
004A2FCE    ^ E9 072BFEFF   jmp     00485ADA 
                 ======== 
485ADA-4A2FCE=  FFFE2B0C  这里只是指向当前指令的IP处,实际计算跳转地址要去 
掉当前指令的长度,当前的跳转指令需要5个字节,FFFE2B0C-5=FFFE2B07
 
我们一般就用E9了,所以计算公式就是 要跳转的地址-指令所在的位置-5=机器码
当然 如果我们要在内存中写的话,肯定是写机器码的。也就是也E9 机器码。
 
 
结合上面的博文,可以在被HOOK的地址出写入JMP指令跳回到原来的地方,
被HOOK的地址-原来地址-5 = 机器码(这个就是要写入到 被HOOK地址的地方)
为什么不直接修改SSDT表,因为很多程序都会循环去看又没有被改回来,又会被修改回去。

c++hook内联汇编模板的更多相关文章

  1. 最牛X的GCC 内联汇编

    导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 ...

  2. Linux 中 x86 的内联汇编

    工程中需要用到内联汇编,找到一篇不错的文章,趁机学习下. 原文地址:http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/ 如果 ...

  3. GCC内联汇编入门

    原文为GCC-Inline-Assembly-HOWTO,在google上可以找到原文,欢迎指出翻译错误. 中文版说明 由于译者水平有限,故译文出错之处,还请见谅.C语言的关键字不译,一些单词或词组( ...

  4. [翻译] GCC 内联汇编 HOWTO

    目录 GCC 内联汇编 HOWTO 原文链接与说明 1. 简介 1.1 版权许可 1.2 反馈校正 1.3 致谢 2. 概览 3. GCC 汇编语法 4. 基本内联 5. 扩展汇编 5.1 汇编程序模 ...

  5. Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)【转】

    转自:http://www.linuxidc.com/Linux/2013-06/85221p3.htm 阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入 ...

  6. GCC 内联汇编(GCC内嵌ARM汇编规则)

    转:http://smileleeboo.howbbs.com/posts/list/3127/81062.html 更多文档参见:http://pan.baidu.com/s/1eQ7nd8Q 有时 ...

  7. 汇编语言---GCC内联汇编

    转:http://www.cnblogs.com/taek/archive/2012/02/05/2338838.html GCC支持在C/C++代码中嵌入汇编代码,这些代码被称作是"GCC ...

  8. x86平台转x64平台关于内联汇编不再支持的解决

    x86平台转x64平台关于内联汇编不再支持的解决     2011/08/25   把自己碰到的问题以及解决方法给记录下来,留着备用!   工具:VS2005  编译器:cl.exe(X86 C/C+ ...

  9. GNU C 内联汇编介绍

    GNU C 内联汇编介绍 简介 1.很早之前就听说 C 语言能够直接内嵌汇编指令.但是之前始终没有去详细了解过.最近由于某种需求,看到了相关的 C 语言代码.也就自然去简单的学习了一下如何在 C 代码 ...

随机推荐

  1. 30G 上亿数据的超大文件,如何快速导入生产环境?

    Hello,大家好,我是楼下小黑哥~ 如果给你一个包含一亿行数据的超大文件,让你在一周之内将数据转化导入生产数据库,你会如何操作? 上面的问题其实是小黑哥前段时间接到一个真实的业务需求,将一个老系统历 ...

  2. C#WebApi 接口增加备注和测试 默认api文档

    1:配置 接口注释. (1)配置生成xml的路径.我们在项目上面点右键→属性→生成标签页配置xml的路径. (2)在xml的读取路径:在Areas\HelpPage\App_Start\HelpPag ...

  3. 【进程/作业管理】篇章一:Linux进程及其管理(系统监控类工具)----glances、dstat

    glances   dstat   glances命令详解 相对于htop工具的使用,这里介绍一下glances工具的使用,我个人是比较喜欢这款工具的,主要就是由于glances这款工具可以将系统状态 ...

  4. matplotlib学习日记(十)-划分画布的主要函数

    (1)函数subplot()绘制网格区域中的几何形状相同的子区布局 import matplotlib.pyplot as plt import numpy as np '''函数subplot的介绍 ...

  5. 4.mysql profile的使用方法

    profile的使用 1.作用 使用profile可以对某一条sql性能进行分析 2.语法 mysql> show variables like '%profil%'; +----------- ...

  6. CentOS7离线安装mysql5.6

    下载mysql5.6,系统选择redhat,版本选择RHEL7,下载RPM Bundle后得到一个tar文件.这里得到文件MySQL-5.6.44-1.el7.x86_64.rpm-bundle.ta ...

  7. idea 中在src/main/java中的xml扫描不到问题

    <build> <!-- start idea 默认 不加载 java下的配置文件 --> <resources> <resource> <dir ...

  8. 【Java并发编程】阿里最喜欢问的几道线程池的面试题?

    引言 上一篇文章我们有介绍过线程池的一个基本执行流程<[Java并发编程]面试必备之线程池>以及它的7个核心参数,以及每个参数的作用.以及如何去使用线程池 还留了几个小问题..建议看这篇文 ...

  9. maven中pom的结构介绍

    1.自己的坐标 groupId-->artifactId-->version> ` 2.打包方式 jar war pom packaging-->jar/war/pom 3. ...

  10. Codefroces 1328E Tree Querie(dfs序)

    Codefroces 1328E Tree Querie 题目 给出一棵1为根,n个节点的树,每次询问\(k_i\) 个节点,问是否存在这样一条路径: 从根出发,且每个节点在这条路径上或者距离路径的距 ...