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. C#中RDLC控制某列的显示隐藏

    使用 1.添加参数IsEnable(用于控制显示或隐藏)2.在RDLC页面,需要控制的列上,右键,列的可见性...,基于表达式隐藏或显示3.输入 IIF(Parameters!IsEnable.Val ...

  2. 在 xunit 测试项目中使用依赖注入

    在 xunit 测试项目中使用依赖注入 Intro 之前写过几篇 xunit 依赖注入的文章,今天这篇文章将结合我在 .NET Conf 上的分享,更加系统的分享一下在测试中的应用案例. 之所以想分享 ...

  3. SQL Server中datetimeset转换datetime类型问题浅析

    在SQL Server中,数据类型datetimeoffset转换为datetime类型或datetime2类型时需要特别注意,有可能一不小心你可能会碰到下面这种情况.下面我们构造一个简单案例,模拟一 ...

  4. Error:java: JDK isn't specified for module 'xxx'异常的解决方法

    问题描述 博主启动的项目的时候出现了一个这样的异常 解决方法 打开左上角这个Project Structure

  5. 后台查询出来的list结果 在后台查询字典表切换 某些字段的内容

    list=listEFormat(list, "Class_type", "611");//list查询数据库得到的结果Class_type /** * @Ti ...

  6. easyui中连接按钮样式

    方法1. <a href="otherpage.php" class="easyui-linkbutton" data-options="ico ...

  7. Spring Cloud Hystrix应用篇(十一)

    一.背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务.如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商 ...

  8. 自动化运维工具-Ansible之5-流程控制

    自动化运维工具-Ansible之5-流程控制 目录 自动化运维工具-Ansible之5-流程控制 playbook条件语句 单条件 多条件 多条件运算 示例 playbook循环语句 with_ite ...

  9. Date、SimpleDateFormat以及Calendar

    Date类 毫秒值 java.util.Date:表示日期和时间的类 类Date表示特定的瞬间,精确到毫秒 日期转毫秒,号秒转日期 中国属于东八区,会把事件增加8个小时 1天 = 4 * 60 * 6 ...

  10. uni-app阻止事件向父级冒泡

    在官网找到的就只有这个方法,但是我放在app项目里并不支持,所以就想到vue的阻止事件冒泡的方法,现在分享,免得大家踩坑     <view class="parent" @ ...