Just example, I spent a lot of time to figure it out. I hope it will be useful for someone.
function process_vm_readv (PID: pid_t;local_iov: piovec;liovcnt: ulong;remote_iov: piovec;riovcnt: ulong; flags: ulong):ssize_t;cdecl; external clib name 'process_vm_readv';
function process_vm_writev (PID: pid_t;local_iov: piovec;liovcnt: ulong;remote_iov: piovec;riovcnt: ulong; flags: ulong):ssize_t;cdecl; external clib name 'process_vm_writev';
function TLinuxMemoryScanner.Attach: boolean;
var
Status: longint = 0;
begin
if PTrace(PTRACE_ATTACH, pid_t(PID), nil, 0) = -1 then
begin
result:=false;
raise Exception.Create(Format(ErrFailedToAttach,[PID]));
end;
if (WaitPid(PID,@status,0) = -1) or not WIFSTOPPED(status) then
begin
result:=false;
raise Exception.Create(ErrSigStopWaiting);
end;
result:=true;
end;
function TLinuxMemoryScanner.Detach: boolean;
begin
result:= ptrace(PTRACE_DETACH, pid, nil, nil) > -1;
end;
{$IFDEF OLDKERNEL}
function TLinuxMemoryScanner.GetValue(Address: integer; ValueSize: integer;
Value: Pointer): boolean;
var
i: integer;
x:longint=0;
begin
if not Attach then
begin
result:=false;
exit;
end;
i:=0;
while i <= ValueSize do
begin
x := ptrace(PTRACE_PEEKDATA, PID, Address + i, nil);
PByteArray(Value)^[i]:=x;
inc(i);
end;
detach();
result:=true;
end;
function TLinuxMemoryScanner.SetValue(Address: integer; ValueSize: integer;
Value: Pointer): boolean;
var
i: integer;
x:longint=0;
begin
if not Attach then
begin
result:=false;
exit;
end;
for i:= 0 to ValueSize - 1 do
begin
x := ptrace(PTRACE_POKEDATA, PID, Address + i, PByteArray(Value)^[i]);
if errno <> 0 then
begin
Detach;
result:=false;
end;
end;
detach();
result:=true;
end;
{$ELSE}
function TLinuxMemoryScanner.GetValue(Address: integer; ValueSize: integer;
Value: Pointer): boolean;
var
local,remote: array [0..0] of iovec;
NRead: longint = 0;
begin
result:=false;
Local[0].iov_len:=ValueSize;
Local[0].iov_base:=Value;
Remote[0].iov_base:=Pointer(Address);
Remote[0].iov_len:=Valuesize;
Nread:=process_vm_readv(PID,@local[0],1,@remote[0],1,0);
if not Nread <> ValueSize then
result:=true;
end;
function TLinuxMemoryScanner.SetValue(Address: integer; ValueSize: integer;
Value: Pointer): boolean;
var
local,remote: array [0..0] of iovec;
NWritten: longint = 0;
begin
result:=false;
Local[0].iov_len:=ValueSize;
Local[0].iov_base:=Value;
Remote[0].iov_base:=Pointer(Address);
Remote[0].iov_len:=Valuesize;
NWritten:=process_vm_writev(PID,@local[0],1,@remote[0],1,0);
if not NWritten <> ValueSize then
result:=true;
end;
{$ENDIF}
Tested on Ubuntu, works fine:)