unit Filehandler; {$MODE Delphi} { implement replaced handlers for ReadProcessMemory and WriteProcessMemory so it reads/writes to the file instead } interface uses {$ifdef darwin} macport, {$endif} {$ifdef windows} jwawindows, windows, {$endif} LCLIntf, syncobjs, sysutils, Classes; function ReadProcessMemoryFile(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: ptruint): BOOL; stdcall; function WriteProcessMemoryFile(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: ptruint): BOOL; stdcall; function VirtualQueryExFile(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD): DWORD; stdcall; procedure CommitChanges(fn: string=''); var filename: string; filedata: TMemorystream; filebaseaddress: ptruint; //filehandle: thandle; bigendianfileaccess: boolean=false; blockfilehandlerpopup: boolean=false; implementation uses dialogs, controls; procedure CommitChanges(fn: string=''); begin if filedata<>nil then begin if fn='' then fn:=filename; filedata.SaveToFile(fn); end; end; var filecs: tcriticalsection; //only 1 filehandle, so make sure rpm does not change the filepointer while another is still reading it function ReadProcessMemoryFile(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: ptruint): BOOL; stdcall; var filesize,ignore:dword; i: integer; b: pdword; t: dword; ba: ptruint; s: integer; begin //ignore hprocess if filedata=nil then begin exit(false); lpNumberOfBytesRead:=0; end; {$ifdef windows} if hprocess=GetCurrentProcess then exit(windows.ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead)); {$endif} result:=false; ba:=ptruint(lpBaseAddress); inc(ba,ptruint(filedata.Memory)); dec(ba,filebaseaddress); filesize:=filedata.Size; if ptruint(lpbaseaddress)=filebaseaddress+filesize then exit; s:=nsize; if ptrUint(lpbaseaddress)+s>=filebaseaddress+filesize then begin ZeroMemory(lpBuffer, nsize); dec(s, ((ptrUint(lpbaseaddress)+s)-(filebaseaddress+filesize))); end; if s<=0 then exit; nsize:=s; CopyMemory(lpbuffer,pointer(ba),nsize); lpNumberOfBytesRead:=nsize; result:=true; {$ifndef CPUAARCH64} if bigendianfileaccess then begin i:=0; while i=4 then begin b:=@PByteArray(lpBuffer)[i]; t:=b^; {$ifdef cpu64} asm push rax xor rax,rax mov eax,t bswap eax mov t,eax pop rax end; {$else} asm push eax xor eax,eax mov eax,t bswap eax mov t,eax pop eax end; {$endif} b^:=t; end; inc(i, 4); end; end; {$endif} end; function WriteProcessMemoryFile(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: ptruint): BOOL; stdcall; var filesize,ignore:dword; i,o: integer; b: pdword; t: dword; ba: ptruint; s: integer; begin //ignore hprocess {$ifdef windows} if hprocess=GetCurrentProcess then exit(windows.WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten)); {$endif} if filedata=nil then begin exit(false); lpNumberOfBytesWritten:=0; end; result:=false; ba:=ptruint(lpBaseAddress); inc(ba,ptruint(filedata.Memory)); dec(ba,filebaseaddress); filesize:=filedata.Size; s:=nsize; if ptrUint(lpbaseaddress)(filebaseaddress+filesize) then begin if (MainThreadID=GetCurrentThreadId) and (not blockfilehandlerpopup) then begin i:=ptrUint(lpbaseaddress-filebaseaddress)+s; if MessageDlg('Change the file size to '+inttostr(i)+' bytes?',mtConfirmation,[mbyes,mbno],0)=mryes then begin filedata.SetSize(i); ZeroMemory(pointer(ptruint(filedata.Memory)+filesize), i-filesize); filesize:=filedata.size; end else dec(s, ((ptrUint(lpbaseaddress)+s)-filesize)); end else dec(s, ((ptrUint(lpbaseaddress)+s)-filesize)); end; if s<=0 then exit; nsize:=s; CopyMemory(pointer(ba),lpbuffer,nsize); lpNumberOfBytesWritten:=nsize; result:=true; {$ifndef CPUAARCH64} if bigendianfileaccess then begin i:=0; while i=4 then begin b:=@PByteArray(lpBuffer)[i]; t:=b^; {$ifdef cpu64} asm push rax xor rax,rax mov eax,t bswap eax mov t,eax pop rax end; {$else} asm push eax xor eax,eax mov eax,t bswap eax mov t,eax pop eax end; {$endif} b^:=t; end; inc(i, 4); end; end; {$endif} end; function VirtualQueryExFile(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD): DWORD; stdcall; var ignore: dword; filesize: ptrUint; begin lpBuffer.BaseAddress:=pointer((ptrUint(lpAddress) div $1000)*$1000); if ptruint(lpAddress)0 then lpbuffer.RegionSize:=lpbuffer.RegionSize+($1000-lpbuffer.RegionSize mod $1000); lpbuffer.State:=mem_commit; lpbuffer.Protect:=PAGE_EXECUTE_READWRITE; lpbuffer._Type:=MEM_PRIVATE; if (ptrUint(lpAddress)>filesize+filebaseaddress) //bigger than the file then begin zeromemory(@lpbuffer,dwlength); result:=0 end else result:=dwlength; end; end; initialization filecs:=tcriticalsection.create; finalization filecs.free; end.