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. 解决[BScroll warn]: Can not resolve the wrapper DOM. Vue better-scroll

    在开发项目过程中,使用better-scroll插件中遇到了滚动一次重复提示相同错误 [BScroll warn]: Can not resolve the wrapper DOM. Vue bett ...

  2. 将notepad++关联到右键菜单

    Step1: 新建txt文本, 将以下内容复制到文本中: Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT*\Shell\NotePad+ ...

  3. 《改善python程序的91个建议》读书笔记

    推荐 <改善Pthon程序的91个建议>是从基本原则.惯用方法.语法.库.设计模式.内部机制.开发工具和性能优化8个方面深入探讨编写高质量python代码的技巧.禁忌和最佳实践. 读书就如 ...

  4. 读取平台管理员xlsx文件

    package com.cn.peitest.excel; import java.io.File; import java.io.FileInputStream; import java.io.Fi ...

  5. 内部类和Lambda

    1.1 内部类的基本使用 在一个类中定义一个类.举例:在一个类A的内部定义一个类B,类B就被称为内部类 内部类定义格式 格式&举例: /* 格式:    class 外部类名{   修饰符 c ...

  6. 「每日一题」面试官问你对Promise的理解?可能是需要你能手动实现各个特性

    关注「松宝写代码」,精选好文,每日一题 加入我们一起学习,day day up 作者:saucxs | songEagle 来源:原创 一.前言 2020.12.23日刚立的flag,每日一题,题目类 ...

  7. 如何把 Next.js 项目部署到服务器?

    Next.js 是什么? Next.js 是一个用于 生产环境的 React 框架.Next.js 为您提供生产环境所需的所有功能以及最佳的开发体验:包括静态及服务器端融合渲染. 支持 TypeScr ...

  8. 嵌入式LInux-让开发板访问外网-ping bad address baidu.com

    我的嵌入式设备已经接入网络.能够ping局域网ip.可是为了实现能够ping通外网.比如 ping baidu.com 还是不行的. 当运行ping baidu.com这个命令时,提示 ping ba ...

  9. MyBatis-Plus 多表联查+分页

    在写东西的过程中,多表联查和分页功能必不可少.当然,crud也很重要 但是又不想写代码和xml. 通过苦苦的查找.发现MyBatis-Plus一款国产的框架.优化了许多操作 本次主要记录一下,多表联查 ...

  10. excel字符串拼接

    函数:CONCATENATE() 参数可以是文本值.数字或单元格引用. 文本值和数字使用双引号括住,单元格引用直接使用.例如 =CONCATENATE("abc",A2),设A2为 ...