Post by Skybuck FlyingOk, do you have some delphi code to get me started and try modifieing some
simple delphi console programs ? ;)
You'll be building a DLL which will contain the patching and hooking
code, and you'll want an .exe which will start up the target application
and inject your DLL into it. The meat of the .exe code is something like
this:
var
StartUpInfo: TStartUpInfo;
ProcInfo: Process_Information;
errno: integer;
msg: pchar;
begin
FillChar(StartUpInfo, SizeOf(StartUpInfo), 0);
StartUpInfo.cb := SizeOf(StartUpInfo);
if not CreateProcessex(nil,
'C:\targetapp.exe',
nil, nil, False, 0, nil, nil,
StartUpInfo, ProcInfo, 'c:\mydll.dll') then begin
ErrNo := GetLastError;
Msg := AllocMem(4096);
try
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, ErrNo,
0, Msg, 4096, nil);
showmessage('Create Process Error #' + IntToStr(ErrNo) + ': ' +
string(Msg));
finally
FreeMem(Msg);
end;
end;
h := procinfo.hprocess;
end;
Your DLL's main procedure (begin...end.) will be executed when the
application starts (You can immediately create and show forms,
everything!). The way I like to add code to already existing code
depends on the target application. Do you want to tack code onto the
beginning or end of a C++ object's methods, or add code to the middle of
an existing code block?
If trying to add code to the middle of an existing code block, you can
use something like this (Untested: Had to rip out of my application):
var patches: tobjectlist;
const retn = $C3;
nop = $90;
ipush = $68;
iret = $C3;
icall = $E8;
ipusheax = $50;
type
thookprocedure = procedure(injectpoint: pointer; eax, ecx, edx, esi:
longword);
tjumpstruct = packed record
push1: byte;
oldaddress: pointer;
push2: byte;
newaddress: pointer;
ret: byte;
end;
TPatch = class
public
oldaddress, newaddress: pointer;
handler: thookprocedure;
buf: string;
restorepoint: pointer;
restorebuf: string;
procedure patch; virtual;
procedure patchrestorer; virtual;
procedure backup; virtual;
procedure restore; virtual;
procedure restorerestorepoint; virtual;
end;
procedure patchgeneric(injectpoint, restorepoint: pointer; handler:
thookprocedure);
implementation
procedure dohook(esi, edx, ecx: longword; ainjection: pointer; eax:
longword); stdcall;
var t1: integer;
myfunc: thookprocedure;
begin
for t1 := 0 to patches.count - 1 do
if tpatch(patches[t1]).oldaddress = ainjection then begin
myfunc := tpatch(patches[t1]).handler;
myfunc(ainjection, eax, ecx, edx, esi); // call registered handler
tpatch(patches[t1]).restore; // return the original code at
injection site
tpatch(patches[t1]).patchrestorer; // install the restorer hook
exit;
end;
showmessage('Hook not found!');
end;
procedure dorestore(ainjection: pointer);
var t1: integer;
begin
for t1 := 0 to patches.count - 1 do
if tpatch(patches[t1]).restorepoint = ainjection then begin
tpatch(patches[t1]).restorerestorepoint; // return original
code at restore point
tpatch(patches[t1]).patch; // install injection hook
exit;
end;
end;
procedure resmain;
asm
pushad
mov eax,[esp+$20] // injection point address
call dorestore
popad
ret
end;
procedure injmain;
asm
pushad
push eax
mov eax,[esp+$24] // injection point address
push eax
push ecx
push edx
push esi
call dohook
popad
ret
end;
procedure tpatch.patch;
var
oldprotect: cardinal;
j: tjumpstruct;
jumplength: integer;
begin
j.push1 := ipush;
j.oldaddress := oldaddress;
j.push2 := ipush;
j.newaddress := newaddress;
j.ret := iret;
jumplength := sizeof(j);
VirtualProtect(oldaddress, jumplength, PAGE_EXECUTE_READWRITE,
oldprotect);
Move(j, oldaddress^, sizeof(j));
end;
procedure tpatch.patchrestorer;
var
oldprotect: cardinal;
j: tjumpstruct;
jumplength: integer;
begin
j.push1 := ipush;
j.oldaddress := restorepoint;
j.push2 := ipush;
j.newaddress := @resmain;
j.ret := iret;
jumplength := sizeof(j);
VirtualProtect(restorepoint, jumplength, PAGE_EXECUTE_READWRITE,
oldprotect);
Move(j, restorepoint^, sizeof(j));
end;
procedure tpatch.backup;
var jumplength: integer;
begin
jumplength := sizeof(tjumpstruct);
setlength(buf, jumplength);
move(oldaddress^, buf[1], jumplength);
setlength(restorebuf, jumplength);
move(restorepoint^, restorebuf[1], jumplength);
end;
procedure tpatch.restore;
begin
move(buf[1], oldaddress^, length(buf)); // move old code back
end;
procedure tpatch.restorerestorepoint;
begin
move(restorebuf[1], restorepoint^, length(restorebuf)); // move old
code back
end;
procedure patchgeneric(injectpoint, restorepoint: pointer; handler:
thookprocedure);
var patch: tpatch;
begin
patch := tpatch.Create;
patch.oldaddress := injectpoint;
patch.newaddress := @injmain;
patch.restorepoint := restorepoint;
patch.handler := handler;
patches.add(patch);
patch.backup;
patch.patch;
end;
Usage: This patching method requires the address of the site where you
want to inject your code ("Injectpoint") and a restore point at least 11
bytes later on in the routine ("Restorepoint"). Your handler will be
called with the contents of some registers.
Algorithm: The code writes some code at the injectpoint which calls
"Injmain", this routine calls your handler, copies the code that used to
be at the injection site back, then returns control back to the target
application. When the target appication reaches the restorepoint, it
reinstalls the new code at the injectpoint and returns the original code
back to the restorepoint. Complex, but it works. Who knows what will
happen if your procedure is recursive :). I shudder to consider what
might happen if the target application is multithreaded.
If you are patching a C++ object's method, then you can do a much
cleaner version which allows you to access and modifiy all of the
parameters of the method and allows you to allow or deny the original
method running.
You should add exception handlers to the procedures I've posted so that
Delphi exceptions don't filter through to the host application: They
don't like that :).
Post by Skybuck FlyingFor example... I need to copy a buffer from an application into a new buffer
so that I can modify it and later pass it back replacing the original buffer
etc...
What sort of buffer?
Post by Skybuck Flyingdb 10000
Or do I have to allocate memory somehow ? ;)
Depends on what you are talking about and what your target is.
Cheers,
Nicholas Sherlock