unit rescanhelper; {$MODE Delphi} interface uses windows, LCLIntf, classes, symbolhandler, CEFuncProc,NewKernelHandler, maps, sysutils, syncobjs, pagemap, Sockets, CELazySocket, PointerscanNetworkCommands, zstream, commonTypeDefs; type TRescanHelper=class private pagemap: TPageMap; pagemapcs: TCriticalsection; memoryregion: TMemoryRegions; function BinSearchMemRegions(address: ptrUint): integer; procedure quicksortmemoryregions(lo,hi: integer); public function ispointer(address: ptrUint): boolean; function GetMemoryRegion(Address: ptruint): TMemoryRegion; function FindPage(index: ptruint): TPageInfo; function getMemoryRegions: TMemoryRegions; constructor create; destructor destroy; override; end; implementation uses ProcessHandlerUnit, Globals; function TRescanHelper.BinSearchMemRegions(address: ptrUint): integer; var First: Integer; Last: Integer; Found: Boolean; Pivot: integer; begin First := 0; //Sets the first item of the range Last := length(memoryregion)-1; //Sets the last item of the range Found := False; //Initializes the Found flag (Not found yet) Result := -1; //Initializes the Result while (First <= Last) and (not Found) do begin //Gets the middle of the selected range Pivot := (First + Last) div 2; //Compares the String in the middle with the searched one if (address >= memoryregion[Pivot].BaseAddress) and (address address then Last := Pivot - 1 //else select the second half else First := Pivot + 1; end; end; function TRescanHelper.ispointer(address: ptrUint): boolean; { Check the memoryregion array for this address. If it's in, return true } begin result:=BinSearchMemRegions(address)<>-1; end; function TRescanHelper.GetMemoryRegion(Address: ptruint): TMemoryRegion; var i: integer; begin i:=BinSearchMemRegions(address); if i<>-1 then result:=memoryregion[BinSearchMemRegions(address)] else result.BaseAddress:=0; end; function TRescanHelper.findPage(Index: ptrUint): TPageInfo; { will find the pageinfo. If not found, it will add it } var pi: TPageInfo; x: ptruint; r: PPageInfo; begin //the old method is faster, but has a small threading issue where adding new entries would lead to a memory leak if multiple threads added the same thing r:=pagemap.GetPageInfo(index); if r=nil then begin //not yet added, add it to the list pi.data:=nil; if ispointer(index shl 12) then begin //save the data {if socket>=0 then begin result:=DownloadPages(index shl 12); exit; end else } begin getmem(pi.data, 4096); if ReadProcessMemory(ProcessHandle, pointer(index shl 12), pi.data, 4096, x)=false then begin //unexpected failure reading the memory freemem(pi.data); pi.data:=nil; end; end; end; pagemapcs.enter; //adding on the other hand does require a lock, as it needs to fidn out where to add it, and what variables to initialize to what value (next/previous) r:=pagemap.GetPageInfo(index); if r=nil then begin //not yet added by another thread //add it pagemap.Add(index, pi.data); result:=pi; end else begin //another thread added it, abort if pi.data<>nil then freemem(pi.data); result:=r^; end; pagemapcs.Leave; end else //found: result:=r^; end; function TRescanHelper.getMemoryRegions: TMemoryRegions; begin result:=memoryregion; end; procedure TRescanHelper.quicksortmemoryregions(lo,hi: integer); var i,j: integer; x,h: TMemoryRegion; begin i:=lo; j:=hi; if hi<0 then exit; x:=memoryregion[(lo+hi) div 2]; repeat while (memoryregion[i].BaseAddressx.BaseAddress) do dec(j); if i<=j then begin h:=memoryregion[i]; memoryregion[i]:=memoryregion[j]; memoryregion[j]:=h; inc(i); dec(j); end; until i>j; if (lo0) and ((address+mbi.RegionSize)>address) do begin if (not symhandler.inSystemModule(ptrUint(mbi.baseAddress))) and (not (not scan_mem_private and (mbi._type=mem_private))) and (not (not scan_mem_image and (mbi._type=mem_image))) and (not (not scan_mem_mapped and ((mbi._type and mem_mapped)>0))) and (mbi.State=mem_commit) and ((mbi.Protect and page_guard)=0) and ((mbi.protect and page_noaccess)=0) then //look if it is commited begin if Skip_PAGE_NOCACHE then if (mbi.AllocationProtect and PAGE_NOCACHE)=PAGE_NOCACHE then begin address:=ptrUint(mbi.BaseAddress)+mbi.RegionSize; continue; end; setlength(memoryregion,length(memoryregion)+1); memoryregion[length(memoryregion)-1].BaseAddress:=ptrUint(mbi.baseaddress); //just remember this location memoryregion[length(memoryregion)-1].MemorySize:=mbi.RegionSize; end; address:=ptrUint(mbi.baseaddress)+mbi.RegionSize; end; //sort memoryregions from small to high quicksortmemoryregions(0,length(memoryregion)-1); end; destructor TRescanHelper.destroy; var i: integer; data: PByteArray; begin setlength(memoryregion,0); pagemapcs.free; pagemap.Free; inherited destroy; end; end.