Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Undokumentierter Sendmessage-Befehl (https://www.delphipraxis.net/162760-undokumentierter-sendmessage-befehl.html)

PinkFloydFan 5. Sep 2011 07:22

AW: Undokumentierter Sendmessage-Befehl
 
Guten Morgen DeddyH!

Static Labels sind auf keinen Fall. :cry:
Mit z.B. Winspy erhalte ich keine Handles. Einzig für ein TPanel,
welches die übergeordnete Komponente dieser 14 Labels darstellt.

Vielleicht gibts über das TPanel nen Ansatz??

Hab mal spasseshalber einen Memory-Dump dieses Programms erzeugt. Die Captions dieser Label sind da schon enthalten, aber immer an anderen Offsets. ( Und auch die vorherigen Captions.. also fast schon wie ne History..)
Irgendwo muss Windows ja mitgeteilt werden, welcher Text wo zu malen ist..

Morphie 5. Sep 2011 07:47

AW: Undokumentierter Sendmessage-Befehl
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von PinkFloydFan (Beitrag 1121698)
Ich habe auch die Vorschläge in http://www.delphipraxis.net/86561-zu...wendung-2.html durchprobiert, was ja an sich auch funktioniert. Nur kenne ich die Namen der Labels nicht. Label1, Label2 usw sinds jedenfalls nicht. Die können ja jeden X-beliebigen Namen haben, zB LblIrgendwas oder ArtikelNrLabel oder sonst was...

An die Namen kommst du z.B. ganz leicht mittels ResHacker ran.

DeddyH 5. Sep 2011 07:52

AW: Undokumentierter Sendmessage-Befehl
 
Aber wie kommt man von außen an die Beschriftung? WM_GETTEXT usw. scheiden ja mangels Fensterhandle aus.

PinkFloydFan 5. Sep 2011 08:02

AW: Undokumentierter Sendmessage-Befehl
 
Moin Morphie!

jo!! Das sieht gut aus!! Werde ich dann gleich versuchen, wenn ich in der Maloche bin..

Melde mich wenn ich ein Ergebnis habe..


@DeddyH:

so kommt man dran: (Source von Sirius, Link weiter oben)

Delphi-Quellcode:
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.
Natürlich muss dieser Source noch entsprechend aufbereitet werden und einige Sachen entfallen, aber das Prinzip funktioniert..

Morphie 5. Sep 2011 08:12

AW: Undokumentierter Sendmessage-Befehl
 
das hier sollte wohl auch schon reichen:
Delphi-Quellcode:
function GetLabelText(ParentHandle: HWND; LabelName: string): string;
var
  pi, p, pm: ppointer;
  a: integer;
  obj: tPersistent;
  myhandle: hwnd;
begin
  Result := '';
  myhandle := ParentHandle;
  p := pointer(getwindowlong(myhandle, gwl_wndproc) + 9);
  pm := p;
  pm := pointer(integer(pm^) + 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
    obj := tPersistent(pi^);
    if obj is TLabel then
    begin
      if (TLabel(obj).Name = LabelName) then
      begin
        Result := TLabel(obj).Caption;
        break;
      end;
    end;
  end;
end;
ParentHandle = Handle der Form, auf der sich das Label befindet
LabelName = Name des Label-Controls

PinkFloydFan 5. Sep 2011 08:16

AW: Undokumentierter Sendmessage-Befehl
 
Nu wirds aber richtig interessant!!

Werde ich gleich mal antesten!!

Sollte es doch noch eine Lösung geben?? :thumb: *freu*

PinkFloydFan 5. Sep 2011 08:28

AW: Undokumentierter Sendmessage-Befehl
 
@Morphie:

Danke für deinen Vorschlag!!
Liest sich soweit gut, aaaber:

hier bekomme ich eine Zugriffsverletzung:

Delphi-Quellcode:
pm := pointer(integer(pm^) + 16);



"Lesen von Adresse 00000009"

Dieser Code scheint nur bei der eigenen Anwendung zu funktionieren.
Sobald man das Handle einer fremden Anwendung angibt, erhält man die Zugriffs-Verletzung

Edit: Ers ma Kaffee zubereiten...

Morphie 5. Sep 2011 08:30

AW: Undokumentierter Sendmessage-Befehl
 
vergiss es doch wieder mit meiner Lösung ;-) Klappt doch nicht so wunderbar, wie ich gedacht habe

himitsu 5. Sep 2011 22:46

AW: Undokumentierter Sendmessage-Befehl
 
Liste der Anhänge anzeigen (Anzahl: 2)
Eigentlich wäre es besser, wenn ihr das Programm neu erstellt.



Wie/warum konnte da jemand eigentlich einfach so alle Quellen zerstören?
(keine Backups :zwinker: )

Es ist eigentlich nicht möglich vorgesehn, Komponenten von extern auszulesen.
und ja, eigentlich gibt es da so Wege, aber die sind kein Zuckerschlecken, da man die RTTI manuell auslesen und die Komponenten/Property/Speicherzuriffe ebenfalls alle manuell zurückverfolgen muß (also alles, was einem die ganzen VCL-Klassen sonst abnehmen).
Auch ist HInstance noch hardgecodet, was natürlich bei allen "verschobenen" Programmen zwangläufig darin enden muß, daß dort nichts gefunden wird.

Was mich aber grade sehr überrascht hat ist, daß Skype (für Windows) wohl doch immernoch in Delphi geschrieben ist. :shock:
Code:
$0340F180 TLoginForm:LoginForm
   $0693A490 TLoginControl:{NoName}
      $06943890 TAccessibleComboBox:{NoName}
      $0694B460 TAccessibleEdit:{NoName}


$06B6A630 TZapMainForm:ZapMainForm
   $034DF180 THomeForm:{NoName}
      $06B7A490 TCanvasNavigationPanel:{NoName}
      $06B7B250 THomeBackground:{NoName}
         $06B8B460 TWebAppBrowser:{NoName}
            $06B7B5C0 TWebAppErrorPanel:{NoName}
               $06B8B740 TButton:{NoName}
            $034DF600 TWebBrowserEx:{NoName}
   $06B58200 TPanelButtons:PanelButtons
   $06B79360 TZapCommunicator:Com
   $06B796D0 TMyselfControl:{NoName}
   $06B5F5C0 TConversationsControl:{NoName}
      $06B8ABC0 TAccessibleEdit:{NoName}
      $06B8AEA0 TScrollBar:{NoName}
   $06B79A40 TEmptyCanvas:{NoName}
   $06B79DB0 TSkypeSplitter:{NoName}
   $06B5F980 TDCEmbedBanner:{NoName}
   $06B5FD40 TChromeMenu:ChromeToolbar
      $06B83890 TToolButton:{NoName}
      $06B83A70 TToolButton:{NoName}
      $06B83C50 TToolButton:{NoName}
      $06B83E30 TToolButton:{NoName}
      $06B84010 TToolButton:{NoName}
      $06B841F0 TToolButton:{NoName}
      $06B843D0 TToolButton:{NoName}
      $06B845B0 TToolButton:{NoName}
      $06B84790 TToolButton:{NoName}
   {Fehler}
Das Programm ist in D2010 geschrieben und nutzt die 2010er-RTTI, also mit anderen Delphi-Version könnte es Probleme geben, vorallem mit TControl.Name, da dieses natürlich als Unicode ausgelesen wird.
Außerdem kann es auch zu unstimmigkeiten kommen, da ja die Fremd-Objetke mit der eigenen RTTI interpretiert werden, anstatt mit der Fremden (läßt sich bestimmt auch noch irgendwie lösen).
TControl.ClassName hat Emba allerdings halbwegs abwärtskompatibel gelassen, bzw. sie haben es sich leicht gemacht und die RTTI eigentlich in ANSI (UTF-8) belassen. :stupid:

Für D2010\XE\XE2 könnte man sowas also vermutlich relativ "leicht" ausbauen, aber darunter wird es echt frickelig.

gekkorist 5. Sep 2011 23:36

AW: Undokumentierter Sendmessage-Befehl
 
Kann mir nicht so richtig vorstellen das man es nicht mit Readprocessmemory auslesen kann.
Hattest ja schon geschrieben das du ein mem dump gemacht hattest und sich die Adressen verschieben, aber das ist so gut wie normal. Irgendwann kommt man aber an die Adresse wo die Werte Statisch stehen.. ist aber ebend bissel Arbeit.
Ein starkes Tool um Adressen von "multi level pointers" zu finden könnt ich die Cheatengine empfehlen, wo man sich aber auch erst reinfitzen muss.

gutes Gelingen in deinem Projekt


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:52 Uhr.
Seite 2 von 4     12 34      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz