在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 {=============================================} {=============的到进程的ID=====================} {=============================================} function TReadMemory.GetProcessInfo: TList; var ProcessInfoList : TList; ProcessInfo : PProcessInfo; hSnapShot : THandle; mProcessEntry32 : TProcessEntry32; bFound : Boolean; begin ProcessInfoList:=TList.Create; ProcessInfoList.Clear; hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); mProcessEntry32.dwSize := Sizeof(mProcessEntry32); bFound := Process32First(hSnapShot, mProcessEntry32); while bFound do begin New(ProcessInfo); ProcessInfo.ProcessExe := mProcessEntry32.szExeFile; ProcessInfo.ProcessId := mProcessEntry32.th32ProcessID; ProcessInfoList.Add(ProcessInfo); bFound := Process32Next(hSnapShot, mProcessEntry32); end; Result := ProcessInfoList; end;
这里用到 1:CreateToolhelp32Snapshot()创建系统快照句柄(hSnapShot是我们声明用来保存 创建的快照句柄) 2:Process32First、Process32Next是用来枚举进程 {=============================================} {=============内存查找=========================} {=============================================} function TReadMemoryFrm.StartSearch: Boolean; var ProcHandle:Integer; begin Result:=False; ReadMemoryProgress.Position:=0; if Not CheckInput then Exit;
if File>begin PParameter.FirstSearch:=False; PParameter.Data:=StrToInt(EdtSearchData.Text); end else begin //------------------------------第一次搜索 PParameter.FirstSearch:=True; if PParameter.ProcessHandle>0 then CloseHandle(PParameter.ProcessHandle); ProcHandle:=OpenProcess(PROCESS_ALL_ACCESS,false,StrToInt(EdtProcID.Text)); if ProcHandle>0 then begin PParameter.Data:=StrToInt(EdtSearchData.Text); Case DataType.ItemIndex of 0:PParameter.DataType:=1; 1:PParameter.DataType:=2; 2:PParameter.DataType:=4; end; end else Exit; FileName:=TabSheet1.Caption; PParameter.ProcessHandle:=ProcHandle; end;
分析内存块 //----------------------------------------------------分析内存块 function TReadMemoryThread.GetMemoryRegion: Boolean; var TempStartAddress : DWord; TempEndAddress : DWord; I,J,k : Integer; NewMemoryRegions : array [0..40000] of TmemoryRegion; begin Result:=False; MemoryRegionsIndex := 0; TempStartAddress := 1*1024*1024; TempEndAddress := 2*1024*1024; TempEndAddress := TempEndAddress*1024; While (VirtualQueryEx(PParameter.ProcessHandle, pointer(TempStartAddress), MBI, sizeof(MBI))>0) and (TempStartAddressbegin if (MBI.State=MEM_COMMIT) then begin if (MBI.Protect=PAGE_READWRITE) or (MBI.Protect=PAGE_WRITECOPY) or (MBI.Protect=PAGE_EXECUTE_READWRITE) or (MBI.Protect=PAGE_EXECUTE_WRITECOPY) then begin PMemoryRegion[MemoryRegionsIndex].BaseAddress:=Dword(MBI.BaseAddress); PMemoryRegion[MemoryRegionsIndex].MemorySize:=MBI.RegionSize; Inc(MemoryRegionsIndex); end; end; TempStartAddress:=Dword(MBI.BaseAddress)+MBI.RegionSize; end; if MemoryRegionsIndex=0 then Exit; //---------------------------------------------判断内存块是否过大 J:=0; for i:=0 to MemoryRegionsIndex-1 do begin if PMemoryRegion[i].MemorySize>$FFFF then begin for K:=0 to PMemoryRegion[i].MemorySize div $FFFF do begin if K=PMemoryRegion[i].MemorySize div $FFFF+1 then begin NewMemoryRegions[j].BaseAddress:=PMemoryRegion[i].BaseAddress+K*$FFFF; NewMemoryRegions[j].MemorySize:=PMemoryRegion[i].MemorySize Mod $FFFF; end else begin NewMemoryRegions[j].BaseAddress:=PMemoryRegion[i].BaseAddress+K*$FFFF; NewMemoryRegions[j].MemorySize:=$FFFF; end; Inc(J); end; end else begin NewMemoryRegions[j].BaseAddress:=PMemoryRegion[i].BaseAddress; NewMemoryRegions[j].MemorySize:=PMemoryRegion[i].MemorySize; Inc(J); end; end; //---------------------------------------------------数据转换 MemoryRegionsIndex:=j; for i:=0 to MemoryRegionsIndex-1 do begin PMemoryRegion[i].MemorySize:=NewMemoryRegions[i].MemorySize; PMemoryRegion[i].BaseAddress:=NewMemoryRegions[i].BaseAddress; end; Result:=True; end; 1:查找的内存大小 TempStartAddress := 1*1024*1024; TempEndAddress := 2*1024*1024; TempEndAddress := TempEndAddress*1024;
返回值: 函数写入lpBuffer的字节数,如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失败。 http://www.vckbase.com/vckbase/function/viewfunc.asp?id=139 讲了这个API的详细信息 {=============================================} {=============开始查找=========================} {=============================================} procedure TReadMemoryThread.Execute; var //StopAddr,StartAddr:Dword; BeginTime,EndTime:String; I:Integer; begin inherited; while Not Terminated do begin AddrCount := 0; if PParameter.FirstSearch then begin if Not GetMemoryRegion then Exit; GetMaxMemoryRange; GetMinMemoryRange; SendMessage(APPHandle,WM_READMEMORY,RM_MAXPROGRESS,MemoryRegionsIndex); BeginTime:=FloatToStr(CPUTimeCounterQPC); for I:=0 to MemoryRegionsIndex-1 do begin FirstCheckMemory(PMemoryRegion[i].BaseAddress,PMemoryRegion[i].MemorySize); end; EndTime:=FloatToStr(CPUTimeCounterQPC); SendMessage(APPHandle, WM_READMEMORY, RM_USETIME, StrToInt(Copy(EndTime,1,Pos('.',EndTime)-1))-StrToInt(Copy(BeginTime,1,Pos('.',BeginTime)-1))); SendMessage(APPHandle,WM_READMEMORY,RM_ADDRCOUNT,AddrCount); SendMessage(APPHandle,WM_READMEMORY,RM_FINISH,RM_FINISH); end else begin SendMessage(APPHandle,WM_READMEMORY,RM_MAXPROGRESS,100); BeginTime:=FloatToStr(CPUTimeCounterQPC); for i:=0 to High(PSearchAgain) do begin SecondCheckMemory(PSearchAgain[i].DataAddr); end; EndTime:=FloatToStr(CPUTimeCounterQPC); SendMessage(APPHandle, WM_READMEMORY, RM_USETIME, StrToInt(Copy(EndTime,1,Pos('.',EndTime)-1))-StrToInt(Copy(BeginTime,1,Pos('.',BeginTime)-1))); SendMessage(APPHandle,WM_READMEMORY,RM_ADDRCOUNT,AddrCount); SendMessage(APPHandle,WM_READMEMORY,RM_FINISH,RM_FINISH); end; Suspend; end; end;