簡單的內存監視實現


簡單的內存監視實現

 

前言:

 

  前段時間學習了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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM