c++hook内联汇编模板

c++hook内联汇编模板

  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] == '')
 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 != ''; 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 %sn", 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 }

View Code

实际操作时对写内存函数有疑问,jmp的机器码和跳转的地址不一致。从https://blog.csdn.net/chenchong_219/article/details/17973935转载过来这篇文章。
总结就是E9跳转的是相对地址,不是绝对地址,并且该相对地址不包含当前指令的长度。
要跳转的地址=偏移+5+当前E9指令的内存地址。
也就是说,当偏移为0时(E9 00000000),就会跳转到该E9指令的下一个位置。
比如 010073B4     - E9 00000000
那么他就会跳到 010073B9 这个地址
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
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表,因为很多程序都会循环去看又没有被改回来,又会被修改回去。

原文链接: https://www.cnblogs.com/MiraculousB/p/12763103.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    c++hook内联汇编模板

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/343930

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午2:22
下一篇 2023年3月2日 上午2:22

相关推荐