转贴: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; ///////////////////////////////////////////////////////////编写16位程序访问指定内存的值的函数:{Access Memory for win31&win95} {must compile with delphi1.0---16bit App} {no VXD or DLL need} {pure native source code here,all include} {Writen by Xueyu,LEE} const fMemoryMapped:boolean=false; var fSelector :word; fBaseAddr :LongInt; fMemoryPointer :Pointer; fMemorySize :Word;function MapPhysMemory(PhAddr:LongInt; Size:Word):Pointer; {input: } { phAddr: physics Address} { Size : Alloc Size(bytes)} {output:} { Result: pointer to the physics memory} {example:} { access the address 0:$123} { ptr:=MapPhysMemory($123,1)} begin Result:=fMemoryPointer; if fMemoryMapped then UnmapPhysMemory; fMemorySize:=Size; fBaseAddr:=PhAddr; fMemoryMapped:=TRUE; fSelector:=AllocSelector(DSeg); SetSelectorBase(fSelector,PhAddr); SetSelectorLimit(fSelector,Size); fMemoryPointer:=Ptr(fSelector,0); Result:=fMemoryPointer; end;procedure UnmapPhysMemory; begin if fMemoryMapped then FreeSelector(fSelector); fSelector:=0; fMemoryMapped:=FALSE; fBaseAddr:=0; fMemoryPointer:=NIL; fMemorySize:=0; end; ///////////////////////////////////////////BOOL DebugActiveProcess(DWORD dwProcessId); //将dwProceeeID进程设置为被当前进程调试BOOL ReadProcessMemory( HANDLE hProcess, // handle of the process whose memory is read LPCVOID lpBaseAddress, // address to start reading LPVOID lpBuffer, // address of buffer to place read data DWORD nSize, // number of bytes to read LPDWORD lpNumberOfBytesRead // address of number of bytes read ); BOOL WriteProcessMemory( HANDLE hProcess, // handle to process whose memory is written to LPVOID lpBaseAddress, // address to start writing to LPVOID lpBuffer, // pointer to buffer to write data to DWORD nSize, // number of bytes to write LPDWORD lpNumberOfBytesWritten // actual number of bytes written );
谢谢提醒,我在VB中时没这么麻烦的,请看看我哪写错了m:longint; d:pointer; a:pointer; begin m:=getmodulehandle('user32.dll'); d:=getprocaddress(m,'MessageBoxA'); readprocessmemory(m,d,a,1,0); end;这个完全是照VB搬的~~编译出错[错误] Unit1.pas(35): Types of actual and formal var parameters must be identical [致命错误] Project1.dpr(5): Could not compile used unit 'Unit1.pas'
用法为
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;
///////////////////////////////////////////////////////////编写16位程序访问指定内存的值的函数:{Access Memory for win31&win95}
{must compile with delphi1.0---16bit App}
{no VXD or DLL need}
{pure native source code here,all include}
{Writen by Xueyu,LEE}
const fMemoryMapped:boolean=false;
var fSelector :word;
fBaseAddr :LongInt;
fMemoryPointer :Pointer;
fMemorySize :Word;function MapPhysMemory(PhAddr:LongInt; Size:Word):Pointer;
{input: }
{ phAddr: physics Address}
{ Size : Alloc Size(bytes)}
{output:}
{ Result: pointer to the physics memory}
{example:}
{ access the address 0:$123}
{ ptr:=MapPhysMemory($123,1)}
begin
Result:=fMemoryPointer;
if fMemoryMapped then UnmapPhysMemory;
fMemorySize:=Size;
fBaseAddr:=PhAddr;
fMemoryMapped:=TRUE;
fSelector:=AllocSelector(DSeg);
SetSelectorBase(fSelector,PhAddr);
SetSelectorLimit(fSelector,Size);
fMemoryPointer:=Ptr(fSelector,0);
Result:=fMemoryPointer;
end;procedure UnmapPhysMemory;
begin
if fMemoryMapped then FreeSelector(fSelector);
fSelector:=0;
fMemoryMapped:=FALSE;
fBaseAddr:=0;
fMemoryPointer:=NIL;
fMemorySize:=0;
end;
///////////////////////////////////////////BOOL DebugActiveProcess(DWORD dwProcessId); //将dwProceeeID进程设置为被当前进程调试BOOL ReadProcessMemory(
HANDLE hProcess, // handle of the process whose memory is read
LPCVOID lpBaseAddress, // address to start reading
LPVOID lpBuffer, // address of buffer to place read data
DWORD nSize, // number of bytes to read
LPDWORD lpNumberOfBytesRead // address of number of bytes read
); BOOL WriteProcessMemory(
HANDLE hProcess, // handle to process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // pointer to buffer to write data to
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
d:pointer;
a:pointer;
begin
m:=getmodulehandle('user32.dll');
d:=getprocaddress(m,'MessageBoxA');
readprocessmemory(m,d,a,1,0);
end;这个完全是照VB搬的~~编译出错[错误] Unit1.pas(35): Types of actual and formal var parameters must be identical
[致命错误] Project1.dpr(5): Could not compile used unit 'Unit1.pas'