1. 程式人生 > >DLL獲取自己的模組控制代碼的方法

DLL獲取自己的模組控制代碼的方法

 這幾天看了一下window核心程式設計,第22章有一個例子使用遠端呼叫注入Dll的。其中注入Dll的時候載入dll的程序呼叫VirtualQuery查詢程序虛擬空間得到程序載入的所有模組路徑。

但是,查詢程式碼很奇怪,於是翻看文件,VirtualQuery說明中沒有說到過任何與dll有關的話題,但作者又如何肯定可以讀出dll的資訊呢?看來值得深入研究一下。

首先看一下程式碼:

  1. #include <Windows.h>
  2. #include <fstream>
  3. #include <tchar.h>
  4. int WINAPI DllMain(HINSTANCE hDllHandle, 
    DWORD dwReason, LPVOID lpReserved)
  5. {
  6. if (dwReason == DLL_PROCESS_ATTACH)
  7.     {
  8.         std::wfstream file;
  9.         file.open(_T("D://SeeIn.txt"), std::ios_base::out);
  10. if (!file)
  11.         {
  12. return FALSE;
  13.         }
  14.         MEMORY_BASIC_INFORMATION memory;
  15.         memset(&memory, 0, sizeof(memory));
  16. DWORD
     pFind = NULL;
  17. while(VirtualQuery((LPVOID)pFind, &memory, sizeof(memory)) == sizeof(memory))
  18.         {
  19. if (memory.State == MEM_FREE)
  20.             {
  21.                 memory.AllocationBase = memory.BaseAddress;
  22.             }
  23. if (memory.BaseAddress == hDllHandle ||
  24.                 memory.AllocationBase != memory.BaseAddress ||
  25.                 memory.AllocationBase == 0)
  26.             {
  27.                 pFind += memory.RegionSize;
  28.                 memset(&memory, 0, sizeof(memory));
  29. continue;
  30.             }
  31. else
  32.             {
  33. TCHAR szName[MAX_PATH] = {0};
  34. if (0 != GetModuleFileName((HMODULE)memory.AllocationBase, szName, sizeof(szName) / sizeof(TCHAR)))
  35.                 {
  36.                     file.write(szName, sizeof(szName));
  37. //file.write(_T("/r/n"), sizeof(_T("/r/n")));
  38.                     file.clear();
  39.                 }
  40.             }
  41.             pFind += memory.RegionSize;
  42.             memset(&memory, 0, sizeof(memory));
  43.         }
  44.         file.close();
  45.     }
  46. return TRUE;
  47. }

其中可以看出,AllocationBase == BaseAddress的時候,這個頁是一個dll模組載入進來的時候分配的,檢視文件,對於AllocationBase 是這麼說的:

A pointer to the base address of a range of pages allocated by the VirtualAlloc function. The page pointed to by the BaseAddress member is contained within this allocation range.

翻譯:一個指向一系列範圍內的頁的基地址的指標,這些頁是通過VirtualAlloc 函式分配的。被BaseAddress 成員指向的頁被包含在這個分配範圍內。

通過程式碼和文件,看一看出,AllocationBase 是頁的基地址,BaseAddress 也是頁的基地址,唯一不同的是,BaseAddressVirtualAlloc 分配記憶體後第一頁的地址,AllocationBase 是每一頁的地址。

比如假設windows為每一塊由VirtualAlloc 分配的記憶體準備了若干頁:p1,p2,p3,p4,……那麼,BaseAddress 就是p1的基地址,而AllocationBase 就分別是p1,p2,p3,p4,……的基地址。

當然,要想獲得每一個頁的AllocationBase ,那就必須不斷的呼叫VirtualQuery遍歷這些頁。

還有一個重要的地方,從這個程式看出,程序載入dll記憶體空間是由VirtualAlloc 分配的。

綜上,當AllocationBase == BaseAddress的時候,AllocationBase 就是模組在程序記憶體中的起始地址,即HMODULE。

至此,VirtualQuery應該是比較明瞭了。

通俗說VirtualQuery的功能就是:以頁為單位,遍歷程序虛擬空間。

一點理解,高手路過請指正!