unit U_getImage;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
const mymsg=WM_User+1;
type TSearchtype=(sClassName,sName,sCaption);
type PMemory=^TMemory;
TMemory=packed
record
Thread:
array[0..1023]
of char;
Postmessage:
function(wnd:hwnd;msg,wparam,lparam:cardinal):bool;
stdcall;
exitthread:
procedure(exitcode:integer);
stdcall;
getwindowlong:
function(wnd:hwnd;
index:integer):cardinal;
stdcall;
watchwnd:hwnd;
backwnd:hwnd;
backmsg:integer;
count:integer;
SearchType:TSearchtype;
vgl:
array[0..31]
of char;
vgllength:integer;
end;
type
TForm1 =
class(TForm)
Image1: TImage;
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Label1: TLabel;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure GetMyMsg(
var msg:TMessage);
message mymsg;
procedure GetMyCaption(
var msg:TMessage);
message mymsg+1;
procedure Button3Click(Sender: TObject);
private
{ Private-Deklarationen }
myhandle:hwnd;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function injectThread(memory:Pmemory):integer;
stdcall;
{Diese Funktion landet nachher in einem fremden Process.
Deswegen dürfen hier keine Funktionen von Delphi benutzt werden
(inkl. Stringoperationen, VCL, etc.).}
var pi,p,pm:ppointer;
i,a:integer;
c:pchar;
left,top,width,height:smallint;
same:boolean;
wparam,lparam:cardinal;
begin
wparam:=0;
lparam:=0;
p:=pointer(memory^.getwindowlong(memory^.watchwnd,gwl_wndproc)+9);
pm:=pointer(integer(p^)+16);
for a:=0
to pinteger(integer(pm^)+8)^-1
do begin //von 0 bis componentcount
p:=pointer(integer(pm^)+4);
p:=pointer(integer(p^)+4*a);
pi:=p;
//pi^ ist Zeiger auf ein Objekt
if memory^.SearchType=sClassname
then begin
p:=p^;
p:=pointer(integer(p^)-44);
end else
p:=pointer(integer(p^)+8);
p:=p^;
c:=pchar(p);
if (pbyte(p)^=memory^.vgllength)
or(memory^.SearchType
in[sName,sCaption])
then begin
if memory^.SearchType=sClassName
then inc(c);
same:=false;
for i:=1
to memory^.vgllength
do begin
if memory^.vgl[i-1]<>c^
then break;
same:=i=memory^.vgllength;
inc(c);
end;
if same
then begin
dec(memory^.count);
if (memory^.count=0)
or(memory^.SearchType
in [sName,sCaption])
then begin
if memory^.SearchType=sCaption
then begin
p:=pointer(integer(pi^)+$64);
wparam:=cardinal(p^);
c:=pchar(p^);
while c^<>#0
do begin
inc(c);
inc(lparam);
end;
inc(memory^.backmsg);
end else begin
left:=pinteger(integer(pi^)+$40)^;
top:=pinteger(integer(pi^)+$44)^;
width:=pinteger(integer(pi^)+$48)^;
height:=pinteger(integer(pi^)+$4C)^;
//4 Zahlen in 2*32Bit kopieren
wparam:=left*65536+top;
lparam:=width*65536+height;
end;
break;
end;
end;
end;
end;
//Ergebnis Nach Hause senden
memory^.Postmessage(memory^.backwnd,memory^.backmsg,wparam,lparam);
result:=0;
//Thread beenden
memory^.exitthread(0);
end;
procedure endpoint;
//ohne Funktion nur zum finden des Address-endes von injcetThread
asm
nop
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;
procedure TForm1.Button1Click(Sender: TObject);
var mem:TMemory;
lib:THandle;
size:integer;
process:cardinal;
processid:cardinal;
procmem:PMemory;
tmp:cardinal;
threadID:cardinal;
thread:THandle;
begin
memo1.clear;
myhandle:=findwindow(
nil,'
PImage');
//Beispielprogramm finden
if myhandle=0
then exit;
//mem ist der Record der nachher in den anderen Process kopiert wird
mem.backwnd:=self.Handle;
//Handle, damit wir Nachrichten zurückschicken können
mem.backmsg:=mymsg;
//Message-Nr., damit wir unsere Message wiederfinden
mem.watchwnd:=myhandle;
//Das Handle für getwindowlong
mem.count:=6;
//welches TControl (=mem.vgl)? (nur für Searchtype=sClassName)
mem.vgl:='
Label2';
//der Vergleichsstring <-------------------------------------------------------------------------------------------- HIER
mem.vgllength:=6;
//Länge des Vergleichsstrings
mem.SearchType:=sCaption;
//vgl vergleichen mit Classname oder Name oder Caption zurücksenden
//kopieren der funktion injectthread in den Record
size:=integer(@endpoint)-integer(@injectThread);
move(injectthread,mem.thread,size);
//EinsprungAdresse von 3 WinAPI-funktionen, die nacher benötigt werden
//Die Adressen sind in jedem Process gleich
lib:=getmodulehandle('
user32.dll');
mem.Postmessage:=getprocaddress(lib,'
PostMessageA');
mem.getwindowlong:=getprocaddress(lib,'
GetWindowLongA');
lib:=getmodulehandle('
kernel32.dll');
mem.exitthread:=getprocaddress(lib,'
ExitThread');
//Thread-Record in anderen Process kopieren und mem.Thread starten
getwindowthreadprocessid(myhandle,@processid);
process:=openprocess(PROCESS_ALL_ACCESS,false,processid);
//Speicher reservieren
procmem:=virtualallocex(process,
nil,sizeof(Tmemory),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
//Kopieren
writeprocessmemory(process,procmem,@mem,sizeof(TMemory),tmp);
//Starten
thread:=createremotethread(process,
nil,0,@procmem.thread,procmem,0,threadid);
//Warten bis injectthread beendet ist
waitforsingleobject(thread,infinite);
//Speicher wieder freigeben
closehandle(thread);
virtualfreeex(process,procmem,0,mem_decommit);
closehandle(process);
end;
procedure TForm1.GetMyMsg(
var msg:TMessage);
begin
memo1.Lines.add(inttostr(msg.WParamlo));
memo1.Lines.add(inttostr(msg.WParamhi));
memo1.Lines.add(inttostr(msg.lParamlo));
memo1.Lines.add(inttostr(msg.lParamhi));
end;
procedure TForm1.GetMyCaption(
var msg:TMessage);
var process,processID,tmp:cardinal;
s:
string;
begin
if myhandle=0
then exit;
//in msg.wparam steht der Pointer auf das TLabel.caption im anderen Process
//in msg.lparam die Länge des TCaption
getwindowthreadprocessid(myhandle,@processid);
process:=openprocess(PROCESS_VM_READ,false,processid);
setlength(s,msg.LParam);
readprocessmemory(process,pointer(msg.wparam),@s[1],msg.lparam,tmp);
closehandle(process);
memo1.Lines.add(s);
end;
end.