日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

Windows2000下用戶模式的內(nèi)存掃描( 二 )


(Committed) 。一個(gè)未用的頁面是指該頁面未被保留或是提交,對(duì)一個(gè)進(jìn)
程來講一個(gè)未用的頁面是不可訪問的,訪問這樣的頁面將導(dǎo)致訪問違例 。
進(jìn)程可以要求系統(tǒng)保留一些頁面以備后用,系統(tǒng)返回一段保留的地址給進(jìn)
程,但是這些地址同樣是不可訪問的,進(jìn)程若想使用這段地址空間,使用
必須先提交 。只有一個(gè)提交的頁面才是一個(gè)真正可以訪問的頁面 。不過你
提交了一個(gè)頁面,系統(tǒng)并不會(huì)馬上分配物理頁面,只有在該頁面第一次被
訪問到時(shí),系統(tǒng)才會(huì)分配頁面并初始化 。另外,這三個(gè)狀態(tài)的兩兩之間都
是可以相互轉(zhuǎn)化的 。相關(guān)的API函數(shù)有 VirtualAlloc 、 VirtualAllocEx 、
VirtualFree 、 VirtualFreeEx 等 .
這樣我們的工作已大大減少了,只需要掃描那些提交的頁面就好了 。接下來要做的就
是得到一個(gè)進(jìn)程的已提交的頁面范圍 。這就要用到另外兩個(gè) API函數(shù)VirtualQuery和
VirtualQueryEx 。兩個(gè)函數(shù)的功能相似,不同就是VirtualQuery只是查詢本進(jìn)程而
VirtualQueryEx可以查詢指定進(jìn)程的內(nèi)存空間信息,后者正是我們所需要的,函數(shù)原
型如下:
DWord VirtualQueryEx(
HANDLE hProcess , // handle to process LPCVOID lpAddress , // address of region PMEMORY_BASIC_INFORMATION lpBuffer , // information buffer SIZE_T dwLength // size of buffer ); 第一個(gè)參數(shù)是進(jìn)程的句柄;第二個(gè)參數(shù)是內(nèi)存地址指針;第三個(gè)參數(shù)是指向 MEMORY_BASIC_INFORMATION 結(jié)構(gòu)的指針,用于返回內(nèi)存空間的信息;第四個(gè)參數(shù)是 lpBuffer 的長度 。再來看一下結(jié)構(gòu) MEMORY_BASIC_INFORMATION 的聲明: typedef struct _MEMORY_BASIC_INFORMATION { PVOID BaseAddress ; PVOID AllocationBase ; DWORD AllocationProtect ; SIZE_T RegionSize ; DWORD State ; DWORD Protect ; DWORD Type ; } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 第一個(gè)參數(shù)是查詢內(nèi)存塊的基地址;第二個(gè)參數(shù)指的是用VirtualAlloc分配該內(nèi)存時(shí)實(shí)際分配的基地址,可以小于 BaseAddress,也就是說 BaseAddress 一定包含在 AllocationBase 分配的范圍內(nèi);第三個(gè)參數(shù)指的是分 配該頁面時(shí),頁面的一些屬性,如 PAGE_READWRITE、PAGE_EXECUTE 等(其它屬性 可參考 Platform SDK );第四 個(gè)參數(shù)指的是從 BaseAddress 開始,具有相同屬性的頁面的大小 。第五參數(shù)指的是頁面的狀態(tài),有三種可能值: MEM_COMMIT、MEM_FREE 和 MEM_RESERVE,這個(gè)參數(shù)對(duì)我們來說是最重要的了,從中我們便可知指定內(nèi)存頁面的狀態(tài)了; 第六個(gè)參數(shù)指的是頁面的屬性,其可能的取值與 AllocationProtect 相同;最后一個(gè)參數(shù)指明了該內(nèi)存塊的類型,有三種可能值: MEM_IMAGE 、 MEM_MAPPED 和 MEM_PRIVATE。這樣我們就可得到進(jìn)程中需要掃描的地址范圍了 。到這里剩下的問題就是要讀取指定的進(jìn)程的指定的地地址空間的內(nèi)容了 。這里要用到的是用于調(diào)試程序和錯(cuò)誤處理( Debugging and Error Handling )的 API函數(shù) 。在“ Platform SDK: Debugging and Error Handling” 章節(jié)中,介紹了一部分與程序調(diào)試和錯(cuò)誤處理相關(guān)的 API函數(shù),有許多是很有用,例如我們下面用到的 ReadProcessMemory 和 WriteProcessMemory,它們?cè)腿缦拢?BOOL ReadProcessMemory( HANDLE hProcess , // handle to the process LPCVOID lpBaseAddress , // base of memory area LPVOID lpBuffer , // data buffer SIZE_T nSize , // number of bytes to read SIZE_T * lpNumberOfBytesRead // number of bytes read ); BOOL WriteProcessMemory( HANDLE hProcess , // handle to process LPVOID lpBaseAddress , // base of memory area LPCVOID lpBuffer , // data buffer SIZE_T nSize , // count of bytes to write SIZE_T * lpNumberOfBytesWritten// count of bytes written ); 參數(shù)很簡(jiǎn)單從它們的名字都可以猜出其意義了,這里就不多做說明了 。要說明的是 要對(duì)一個(gè)進(jìn)程進(jìn)行 ReadProcessMemory操作,當(dāng)前進(jìn)程對(duì)要讀的進(jìn)程必須有PROCESS_VM_READ訪問權(quán) 。要對(duì)一個(gè)進(jìn)程進(jìn)行WriteProcessMemory操作,當(dāng)前進(jìn)程對(duì)要寫的進(jìn)程必須有PROCESS_VM_WRITE 和PROCESS_VM_OPERATION訪問權(quán) 。要獲得一個(gè)進(jìn)程的句柄和對(duì)這個(gè)進(jìn)程的一些控制權(quán)可以使用API函數(shù)OpenProcess得到,其使用不做詳細(xì)說明了,只給出其原型: HANDLE OpenProcess( DWORD dwDesiredAccess , // access flag BOOL bInheritHandle , // handle inheritance option DWORD dwProcessId // process identifIEr ); 這樣對(duì)一個(gè)進(jìn)程的用戶地址空間內(nèi)存掃描的流程基本就闡述清楚了 。

推薦閱讀