nie wiem czy ten kod ci pomoże, na forme tylko 3 guziki jak widać.
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Green: TButton;
Red: TButton;
procedure CallModifiedCode(Sender: TObject);
procedure ModifyCode(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{$O-} //make sure nop's don't get optimized out of the compiled exe
procedure TForm1.CallModifiedCode(Sender: TObject);
var b : boolean;
frmColour : TColor;
label 1;
begin
frmColour := clGreen;
b := true;
{ Nastepna linia zostanie zmodyfikowana w pamieci.
Komentarze pokazuja jak wyglada kod asemblera i jego
Heksadecymalna reprezentacja.
Mozesz ustawic breakpoint na nastepna linie i otworzyc Delphi CPU view,
aby zobaczyc zmiane.
}
if b then goto 1; // "jnz SOME_ADDRESS" "$75 SOME_ADDRESS"
{
Zmodyfikujemy powyzsza linie na:
"jz SOME_ADDRESS" "$74 SOME_ADDRESS" co oznacza:
if NOT(b) then goto 1;
}
{ Nastepujacy kod asemblera nie robi nic (nop = no operation).
Jest to poprostu uzyte jako znacznik, aby znalezc pozycje
skoku powyzej w pamieci
}
asm
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90
end;
frmColour := clRed;
1:
Form1.Color := frmColour;
end;
procedure TForm1.ModifyCode(Sender: TObject);
const BUFFMAX=65536;
type TBytes6=Array[0..5] of byte;
TMemblock=array[0..BUFFMAX-1] of byte;
Function ReadBufferFromMemory(ad, size:integer; var MB:TMemBlock):cardinal;
var cnt:cardinal;
begin
ReadProcessMemory(Getcurrentprocess, pointer(ad), @MB[0], size, cnt);
// otrzymana ilosc bajtow odczytanych
ReadBufferFromMemory := cnt;
End;
procedure WriteByteToMemory(ad:cardinal;rt:byte);
var cnt:cardinal;
oldprotect:dword;
begin
//upewniamy sie,ze mamy dostep do adresu
VirtualProtect(pointer(ad),sizeof(rt),PAGE_EXECUTE_READWRITE,@oldprotect);
WriteProcessMemory(Getcurrentprocess, pointer(ad), @rt, sizeof(rt), cnt);
//przywracamy poprzednia ochrone dostepu
VirtualProtect(pointer(ad),sizeof(rt),oldprotect,@oldprotect);
End;
var st : TBytes6;
rt : Byte;
stcount : word;
BytesRead : cardinal;
sad,ead,ad : cardinal;
x,y,z : cardinal;
found : boolean;
MemBlock : TMemBlock;
begin
{definiujemy co ma znalezione - w tym wypadku blok instrukcji
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90}
st[0]:=$90; // nop
st[1]:=$90;
st[2]:=$90;
st[3]:=$90;
st[4]:=$90;
st[5]:=$90;
stCount:=6;
{zmienniamy instrukcje w zaleznosci ktory przycisk zostal wcisniety}
if (sender = red) then rt := $74 // asm: jz
else rt := $75; // asm: jnz
//zakres adresu, ktory ma byc przeszukany
sad := ($00400000);
ead := ($7fffffff);
//aktualny adres
ad := sad;
found := false;
repeat
// odczyta jeden blok o dlugosci BUFFMAX od aktualnego adresu ad
BytesRead := ReadBufferFromMemory(ad, BUFFMAX, MemBlock);
//zadnych bajtow odczytanych;wynosimy sie
if BytesRead = 0 then break;
// upewniamy sie, ze nie ominelismy nieczego gdy mamy dwa bloki pamieci;
If BytesRead = BUFFMAX Then BytesRead := BytesRead-stCount;
// przeszukujemy Blok Pamieci
For x := 0 To BytesRead-1 do
begin
found := true;
// sprawdzamy czy znaleziono
For y := 0 To stCount-1 do
If MemBlock[x+y] <> st[y] then
begin
found := false;
break;
end;
If found Then
begin
// to co znalezlismy zaczyna sie od ad+x+y-stcount
z := ad+x+y-stcount;
// kod, ktory chcemy zamienic zaczyna sie 2 bajty wczwsniej
//Zamiana kodu
WriteByteToMemory(z-2,rt);
break; // Koniec poszukiwan
end;
end;
ad := ad+BytesRead;
until (ad >= ead) or found;
end;
end.