zoukankan      html  css  js  c++  java
  • 简单的内存监视实现

    简单的内存监视实现

    前言:

      前段时间学习了API HOOK,对这技术也略知一二,决定利用这技术实现个小功能。

    以前有用过某工具,可以偷取别人外挂的功能地址,当时想想觉得挺不可思议的,如今了解API HOOK后,觉得这功能也就那样。

    废话不多说,进入正题。

    一、    HOOK WriteProcessMemory

    首先看看WriteProcessMemory()原型:

    BOOL WriteProcessMemory(
      HANDLEhProcess,               // handle to process
      LPVOIDlpBaseAddress,          // base of memory area
      LPVOIDlpBuffer,               // data buffer
      DWORDnSize,                   // number of bytes to write
      LPDWORDlpNumberOfBytesWritten // number of bytes written
    );

    如何实现呢?其实很简单,我们只需是获取hProcess/ lpBaseAddress/ nSize/ lpBuffer这四个参数。

    我们定义一个结构体:

    复制代码
    typedef struct HookData
    
         {
    
             HANDLE hProcess,               // handle to process
    
             LPVOID lpBaseAddress,          // base of memory area
    
             LPVOID lpBuffer,               // data buffer
    
             DWORD nSize,                   // number of bytes to write
    
     
    
         }HookData,*pHookData;
    复制代码

    并定义一个全局变量HookData g_hookdata;

    在我们自己的函数体里保存四个参数,然后返回原函数:

    复制代码
    BOOL MyWriteProcessMemory(
    
                                HANDLE hProcess,               // handle to process
    
                                LPVOID lpBaseAddress,          // base of memory area
    
                                LPVOID lpBuffer,               // data buffer
    
                                DWORD nSize,                   // number of bytes to write
    
                                LPDWORD lpNumberOfBytesWritten // number of bytes written
    
                                )
    
    {
    
         g_hookdata.hProcess = hProcess;
    
         g_hookdata.lpBaseAddress = lpBaseAddress;
    
         g_hookdata.lpBuffer = lpBuffer;
    
         g_hookdata.nSize =nSize;
    
         return WriteProcessMemory(hProcess,lpBaseAddress,lpBuffer,nSize,lpNumberOfBytesWritten);
    
    }
    复制代码

    获取这四个参数后,如何将这些数据取出来,我这里抛砖引玉,用一种笨方法,把数据以文件方式保存,然后外部程序读取:

    复制代码
    BOOL SaveHookData(HANDLE hpro,pHookData phd)
    
    {
    
         if (g_hookdata.hProcess != hpro)//判断是否对目标进程HOOK成功
    
             return FALSE;
    
     
    
         FILE *fp = fopen("hookdata","r+");
    
         if (!fp)
    
             return FALSE;      //打开文件失败
    
     
    
         if (!fwrite(phd,sizeof(HookData),sizeof(phd),fp))
    
         {
    
             fclose(fp);
    
             return FALSE;
    
         }
    
         fclose(fp);
    
         return TRUE;
    
    }
    
     
    
    BOOL TakeHookData(pHookData phd)
    
    {
    
         FILE *fp = fopen("c:\hookdata","r+");
    
         if (!fp)
    
             return FALSE;      //打开文件失败
    
     
    
         if (!fread(phd,sizeof(HookData),1,fp))
    
         {
    
             fclose(fp);
    
             return FALSE;
    
         }
    
         fclose(fp);
    
         return TRUE;
    
    }
    复制代码

    二、HOOK ReadProcessMemory

             ReadProcessMemory()原型:

    BOOL ReadProcessMemory(

      HANDLE hProcess,             // handle to the process

      LPCVOID lpBaseAddress,       // base of memory area

      LPVOID lpBuffer,             // data buffer

      DWORD nSize,                 // number of bytes to read

      LPDWORD lpNumberOfBytesRead  // number of bytes read

    );

      同HOOK WriteProcessMemory()类似,需要获取 hProcess/ lpBaseAddress/ nSize/ lpBuffer这四个参数,不过有一点不同,ReadProcessMemory()的lpBuffer参数不是在一开始就有数据。我们先看看ReadProcessMemory 的反汇编代码:

    复制代码
    751A9982 >    8BFF          mov     edi, edi                                    ; 
    
    751A9984   .  55            push    ebp
    
    751A9985   .  8BEC          mov     ebp, esp
    
    751A9987   .  8D45 14       lea     eax, dword ptr [ebp+14]
    
    751A998A   . 50            push    eax                                         ;
    
    751A998B   .  FF75 14       push    dword ptr [ebp+14]                          ;  地址
    
    751A998E   .  FF75 10       push    dword ptr [ebp+10]                          ;  data buffer
    
    751A9991   .  FF75 0C       push    dword ptr [ebp+C]                           ;  nSize
    
    751A9994   .  FF75 08       push    dword ptr [ebp+8]                           ; 
    
    751A9997   .  FF15 B4111A75 call    dword ptr [<&ntdll.NtReadVirtualMemory>]    ;  ntdll.ZwReadVirtualMemory
    
    751A999D   .  8B4D 18       mov     ecx, dword ptr [ebp+18]
    
    751A99A0   .  85C9          test    ecx, ecx
    
    751A99A2   .  75 0F         jnz     short 751A99B3
    
    751A99A4   >  85C0          test    eax, eax
    
    751A99A6   .  0F8C 789E0100 jl      751C3824
    
    751A99AC   .  33C0          xor     eax, eax
    
    751A99AE   .  40            inc     eax
    
    751A99AF   >  5D            pop     ebp
    
    751A99B0   .  C2 1400       retn    14
    
    751A99B3   >  8B55 14       mov     edx, dword ptr [ebp+14]                     ;  LPCVOID lpBaseAddress,       // base of memory area
    
    751A99B6   .  8911          mov     dword ptr [ecx], edx                        ;  lpBuffer,             // data buffer
    
    751A99B8   .^ EB EA         jmp     short 751A99A4
    
     
    复制代码

      我们可以得出当程序执行到751A99B3才开始读取lpBaseAddress的值到lpBuffer,所以如果HOOK函数头,那么截取到的内容肯定为空。

    那到底如何实现呢?其实有个很取巧的方法,我们同样HOOK函数头,截取lpBaseAddress参数后再自己手动将该地址的内容读取出来,用memcpy()函数就能实现。

    实现方法与上面的HOOK WriteProcessMemory类似,没必要重复写了。

    三、总结

      相信看完篇文章,你可以揭开“偷取外挂功能地址”的神秘面纱。由于本人也是菜鸟,只能完成这些,代码没有经过测试,有什么地方有错误,可以给我留言,大家一起探讨,大神们看完可以指点指点。

      本文所实现的方法对做了反监视、非远程内存读写式外挂无效,对于后者,只要弄清楚外挂的实现方式,理论上按照本方法,HOOK关键函数,是可以完成的。

    JJHUANG

    2013/8/28

     
     
     
  • 相关阅读:
    哈希表--扩展数组
    哈希表效率
    P=(1+1/(1-L))/2
    函数推进
    简单函数2
    简单函数
    getting data from the keybroad
    nutch-2.2.1 hadoop-1.2.1 hbase-0.92.1 集群部署(实用)
    hbase zookeeper独立搭建
    Orchard 介绍
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3288396.html
Copyright © 2011-2022 走看看