307 lines
6.8 KiB
ObjectPascal
Executable File
307 lines
6.8 KiB
ObjectPascal
Executable File
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 then exit;
|
|
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<nSize do
|
|
begin
|
|
if (nsize-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 then exit(False);
|
|
|
|
if ptrUint(lpbaseaddress)+s>(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<nSize do
|
|
begin
|
|
if (nsize-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)<filebaseaddress then
|
|
begin
|
|
lpbuffer.AllocationBase:=pointer(0);
|
|
lpbuffer.AllocationProtect:=0;
|
|
lpbuffer.State:=MEM_FREE;
|
|
lpbuffer.protect:=PAGE_NOACCESS;
|
|
lpbuffer._Type:=0;
|
|
lpbuffer.RegionSize:=filebaseaddress-ptruint(lpBuffer.BaseAddress);
|
|
result:=dwlength;
|
|
end
|
|
else
|
|
begin
|
|
filesize:=filedata.Size; // getfilesize(hprocess,@ignore);
|
|
lpbuffer.AllocationBase:=pointer(filebaseaddress);
|
|
lpbuffer.AllocationProtect:=PAGE_EXECUTE_READWRITE;
|
|
lpbuffer.RegionSize:=filesize-ptruint(lpBuffer.BaseAddress-lpbuffer.AllocationBase);
|
|
if (lpbuffer.RegionSize mod 4096)>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.
|
|
|
|
|
|
|
|
|
|
|
|
|