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

    前言 处理一对多关系,有两种方式 (1)创建关系表,将对应关系保存在物理表中. (2)表中添加一个字段,将多关系的值以特殊符号隔开进行保存. 本例使用的就是,以逗号隔开(InterestID='1,2 ...

  2. MethodHandleVS反射

    Method Handle与反射 如无特殊说明,本文所有代码均基于JDK1.8.0_221 Method Handle入门 反射我们都知道,为我们提供了运行时对类的成员方法访问的手段,极大地提高了Ja ...

  3. Redis 设计与实现 5:压缩列表

    压缩列表是 ZSET.HASH和 LIST 类型的其中一种编码的底层实现,是由一系列特殊编码的连续内存块组成的顺序型数据结构,其目的是节省内存. ziplist 的结构 外层结构 下图展示了压缩列表的 ...

  4. qt界面设计

    需求 需要不同界面同样的位置有上下的公共部分 分解 在WPF中我亦接触到需要这样做的程序.在wpf中我将上下公共部分作为界面基类,其它界面都继承这个基类.我用qt准备定义一个stackedpanel, ...

  5. java.lang.NoSuchMethodError的解决办法

    开发一个知识图谱在线服务(基于springcloud+vue)构建中医理论的知识图谱构建帕金森的知识图谱提供免费的知识图谱服务,希望能为朋友们的生活.学习.工作提供帮助(敬请期待)PS:关注后,点击头 ...

  6. (数据科学学习手札101)funcy:Python中的函数式编程百宝箱

    本文示例文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们在使用Python完成日常任务时,经常会遇到 ...

  7. Ubuntu+KVM显卡透传

    好久没有更新微博了,最近有点忙,大家见谅啊!今天带来的是我前段时间做的东西,也就是在 Ubuntu下做KVM虚拟机显科透传.(最近人有点懒,其实有几次是有时间更新的,但是就是懒得动,唉!得保持清醒不能 ...

  8. js表单简单验证(手机号邮箱)

    1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncod ...

  9. Linux服务器上搭建测试环境(war包+tomcat)

    悟空CRM项目环境部署(Java war项目) 在/root目录下创建一个文件夹(名字自取). ls命令查看一下是否创建成功,看到了新建的文件夹说明创建成功. tomcat和war包的准备:可以使用X ...

  10. MobPush厂商通道排查

    开启log 一.添加开启log代码 有AndroidManifest.xml的 //在AndroidManifest.xml的application标签中添加 <meta-data androi ...