當前位置:編程學習大全網 - 編程語言 - 怎麽用vb讀取到內存的所有信息

怎麽用vb讀取到內存的所有信息

在WIN32中,每個應用程序都可“看見”4GB的線性地址空間,其中最開始的4MB和最後的2GB由操作系統保留,剩下不足2GB的空間用於應用程序私有空間。具體分配如下:0xFFFFFFFF-0xC0000000的1GB用於VxD、存儲器管理和文件系統;0xBFFFFFFF-0x80000000的1GB用於***享的WIN32 DLL、存儲器映射文件和***享存儲區;0x7FFFFFFF-0x00400000為每個進程的WIN32專用地址;0x003FFFFF-0x00001000為MS-DOS 和 WIN16應用程序;0x00000FFF-0x00000000為防止使用空指針的4,096字節。以上都是指邏輯地址,也就是虛擬內存。

虛擬內存通常是由固定大小的塊來實現的,在WIN32中這些塊稱為“頁”,每頁大小為4,096字節。在Intel CPU結構中,通過在壹個控制寄存器中設置壹位來啟用分頁。啟用分頁時CPU並不能直接訪問內存,對每個地址要經過壹個映射進程,通過壹系列稱作“頁表”的查找表把虛擬內存地址映射成實際內存地址。通過使用硬件地址映射和頁表WIN32可使虛擬內存即有好的性能而且還提供保護。利用處理器的頁映射能力,操作系統為每個進程提供獨立的從邏輯地址到物理地址的映射,使每個進程的地址空間對另壹個進程完全不可見。WIN32中也提供了壹些訪問進程內存空間的函數,但使用時要謹慎,壹不小心就有可能破壞被訪問的進程。本文介紹如何讀另壹個進程的內存,寫內存與之相似,完善壹下妳也可以做個 FPE 之類的內存修改工具。好吧,先準備好編程利器Delphi 和 參考手冊 MSDN ,Now begin!

ReadProcessMemory 讀另壹個進程的內存,原形如下:

BOOL ReadProcessMemory(

HANDLE hProcess, // 被讀取進程的句柄;

LPCVOID lpBaseAddress, // 讀的起始地址;

LPVOID lpBuffer, // 存放讀取數據緩沖區;

DWORD nSize, // 壹次讀取的字節數;

LPDWORD lpNumberOfBytesRead // 實際讀取的字節數;

);

hProcess 進程句柄可由OpenProcess 函數得到,原形如下:

HANDLE OpenProcess(

DWORD dwDesiredAccess, // 訪問標誌;

BOOL bInheritHandle, // 繼承標誌;

DWORD dwProcessId // 進程ID;

);

當然,用完別忘了用 CloseHandle 關閉打開的句柄。讀另壹個進程的內存 dwDesiredAccess 須指定為 PROCESS_VM_READ ,寫另壹個進程的內存 dwDesiredAccess 須指定為 PROCESS_VM_WRITE ,繼承標誌無所謂,進程ID可由 Process32First 和 Process32Next 得到,這兩個函數可以枚舉出所有開啟的進程,這樣進程的信息也就得到了。 Process32First 和 Process32Next是由 TLHelp32 單元提供的,需在 uses 裏加上TLHelp32。ToolsHelp32 封裝了壹些訪問堆、線程、進程等的函數,只適用於Win9x,原形如下:

BOOL WINAPI Process32First(

HANDLE hSnapshot //

由 CreateToolhelp32Snapshot 返回

的系統快照句柄;

LPPROCESSENTRY32 lppe // 指向壹個 PROCESSENTRY32 結構;

);

BOOL WINAPI Process32Next(

HANDLE hSnapshot // 由 CreateToolhelp32Snapshot 返回

的系統快照句柄;

LPPROCESSENTRY32 lppe // 指向壹個 PROCESSENTRY32 結構;

);

hSnapshot 由 CreateToolhelp32Snapshot 返回的系統快照句柄;

CreateToolhelp32Snapshot 原形如下:

HANDLE WINAPI CreateToolhelp32Snapshot(

DWORD dwFlags, // 快照標誌;

DWORD th32ProcessID // 進程ID;

);

現在需要的是進程的信息,所以將 dwFlags

指定為 TH32CS_SNAPPROCESS,

th32ProcessID 忽略;PROCESSENTRY32 結構如下:

typedef struct tagPROCESSENTRY32 {

DWORD dwSize; // 結構大小;

DWORD cntUsage; // 此進程的引用計數;

DWORD th32ProcessID; // 進程ID;

DWORD th32DefaultHeapID; // 進程默認堆ID;

DWORD th32ModuleID; // 進程模塊ID;

DWORD cntThreads; // 此進程開啟的線程計數;

DWORD th32ParentProcessID;// 父進程ID;

LONG pcPriClassBase; // 線程優先權;

DWORD dwFlags; // 保留;

char szExeFile[MAX_PATH]; // 進程全名;

} PROCESSENTRY32;

至此,所用到的主要函數已介紹完,實現讀內存只要從下到上依次調用上述函數即可,具體參見原代碼:

procedure TForm1.Button1Click(Sender: TObject);

var

FSnapshotHandle:THandle;

FProcessEntry32:TProcessEntry32;

Ret : BOOL;

ProcessID : integer;

ProcessHndle : THandle;

lpBuffer:pByte;

nSize: DWORD;

lpNumberOfBytesRead: DWORD;

i:integer;

s:string;

begin

FSnapshotHandle:=CreateToolhelp32Snapshot(

TH32CS_SNAPPROCESS,0);

//創建系統快照

FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);

//先初始化 FProcessEntry32 的大小

Ret:=Process32First(FSnapshotHandle,FProcessEntry32);

while Ret do

begin

s:=ExtractFileName(FProcessEntry32.szExeFile);

if s='KERNEL32.DLL' then

begin

ProcessID:=FProcessEntry32.th32ProcessID;

s:=';

break;

end;

Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);

end;

//循環枚舉出系統開啟的所有進程,找出“Kernel32.dll”

CloseHandle(FSnapshotHandle);

Memo1.Lines.Clear ;

memo1.lines.add('Process ID '+IntToHex(

FProcessEntry32.th32ProcessID,8));

memo1.lines.Add('File name '+FProcessEntry32.szExeFile);

////輸出進程的壹些信息

nSize:=4;

lpBuffer:=AllocMem(nSize);

ProcessHndle:=OpenProcess(PROCESS_VM_READ,false,ProcessID);

memo1.Lines.Add ('Process Handle '+intTohex(ProcessHndle,8));

for i:=$00800001 to $0080005f do

begin

ReadProcessMemory(

ProcessHndle,

Pointer(i),

lpBuffer,

nSize,

lpNumberOfBytesRead

);

s:=s+intTohex(lpBuffer^,2)+' ';

//讀取內容

if (i mod 16) =0 then

begin

Memo1.Lines.Add(s);

s:=';

end;

//格式化輸出

end;

FreeMem(lpBuffer,nSize);

CloseHandle(ProcessHndle);

//關閉句柄,釋放內存

end;

  • 上一篇:nlp的理解六層次
  • 下一篇:CMD發送收購德爾福
  • copyright 2024編程學習大全網