zoukankan      html  css  js  c++  java
  • 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 %s
    ", 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 << "
    ";
    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 <<"               "<< "
    ";
    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转载过来这篇文章。
     
    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表,因为很多程序都会循环去看又没有被改回来,又会被修改回去。
  • 相关阅读:
    javaDoc 注释规范
    [阿里云] 如何 开放云主机 非80 端口?
    [Go] 跨平台文件系统监控工具 fsnotify 应用举例
    如何利用 jQuery 修改 css 中带有 !important 的样式属性?
    code.google.com/p/log4go 下载失败
    [Go] ok 判断 汇总
    [Go] 编码规范
    《Go语言实战》摘录:7.3 并发模式
    《Go语言实战》摘录:7.2 并发模式
    《Go语言实战》摘录:7.1 并发模式
  • 原文地址:https://www.cnblogs.com/MiraculousB/p/12763103.html
Copyright © 2011-2022 走看看