Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Subclassing einer fremden Application, warum funzt das net ? (https://www.delphipraxis.net/11550-subclassing-einer-fremden-application-warum-funzt-das-net.html)

negaH 10. Nov 2003 22:56

Re: Subclassing einer fremden Application, warum funzt das n
 
Es ist eigentlich egal ob man MMF's nimmt oder nicht. Man könnte auch VirtualAllocEx() benutzten um einen Speicherbereich innerhalb eines anderen Processes zu injezieren. Man sollte nun zwei unterschiedliche Vorgehensweisen betrachten, abhängig ob Win9x oder Win2x.

Generell sähe es so aus:
1.) erzeuge einen Speicherbereich im Zielprozess
2.) initialisiere in diesem Speicher den Code + Datenstrukturen. In diesem Speicher liegt eine Threadfunktion und die WindowProc
3.) erzeuge einen Remote Thread, also einen Thread der im Zielprozess läuft. Unter Win2x gibts dafür CreateRemoteThread() unter Win9x kann man diese Funktion nachbauen.
4.) die Threadfunktion zeigt in unserem Speicherbereich

Nun ist es wichtig was die Threadfunktion überhaupt macht. Sie subclasses das betroffene Fensterhandle und setzt deren Fensterfunktion auf die Fensterfunktion in unserem Speicherbereich. Danach Terminiert sie den Thread.

Als Pseudocode sähe das so aus:

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd, Index): Pointer: stdcall;
    SetWindowLong: function(hWnd, Index, Pointer): Bool; stdcall;
    ExitThread: procedure(Return); stdcall;
    CallWndProc: function(Proc, hWnd, wParam, lParam): lResult; stdcall;
    VirtualFree: fucntion(Pointer): Integer; stdcall;
    WindowProc: array[0..0] of Byte; // hier wird MyWndProc rein kopiert
    ThreadCode: array[0..0] of Byte; // hier wird ThreadProc hineinkopiert
  end;

function MyWndProc(...): Integer; stdcall;
var
  Memory: PHookData;
begin
  asm
     CALL @@1
@@1: POP  EAX
     AND  EAX,$FFFFF000    // align
     MOV  Memory,EAX
  end;
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);

 // hier Memory freigeben, wichtig dabei das der aktuelle Code ja in diesem Memory^ liegt
 // wir müssen also die Reücksrungadresse aus dem Stack holen. Dann Memory auf den Stack pushen
 // danach Rücksrungadresse pushen und einem Jump nach VirtualFree() durchführen.
 // Somit kehrt VirtualFree NICHT in unseren nun freigegebene Memory zurück, sondern zum
 // Aufrufer von MyWndProc().
    asm
      POP EDX
      MOV EAX,Memory
      PUSH EAX
      PUSH EDX
      JMP [EAX].VirtualFree
    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, Wnd, Msg, wParam, lParam);
end;

function ThreadProc(Memory: PHookData): Dword; stdcall;
// wichtig !! keine Aufrufe von Funktionen und Daten die nicht Importe/Inhalte in Memory sind !!
begin
  Memory.SaveWindowProc := Memory.GetWindowLong(Memory.hWnd, gwl_WndProc);
  Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WindowProc);
  Memory.ExitThread(0);
end;
 
procedure Subclass(hWnd);
var
  Memory: PHookData;
  ProcSize: Integer;
  ThreadFunc: Pointer;
begin
  ProcSize := PChar(@Subclass) - PChar(@MyWndProc);

  Memory := VirtualAllocEx(..., SizeOf(THookData) + ProcSize); // align on Pageboundary needed !!
  Move(@MyWndProc, @Memory.WindowProc, ProcSize);
  Memory.hWnd := hWnd;
  Memory.GetWindowLong := GetProcAddress();
  Memory.SetWindowLong := GetProcAddress();
  Memory.ExitThread := GetProcAddress();
  Memory.CallWndProc := GetProcAddress();
  Memory.VirtualFree := GetProcAddress();
 
  ThreadFunc := PChar(Memory) + SizeOf(THookData) + PChar(@ThreadProc) - PChar(@MyWndProc);
 
  CreateRemoteThread(..., ThreadFunc, Memory, ...);
end;
WICHTIG ! dies niemals mit dem integrierten Debugger testen, da BorDbk Importe im Prozess wie GetProcAddress() selber umbiegt. Somit kann zB. GetProcAddress(, 'GetWindowLong') eine Adresse zurückgeben die in den BorDbk zeigt statt in's Kernel/GDI. Am besten eine eigene GetProcAddress() Funktion benutzen die ohne API auskommt !.

Jetzt mus man nur noch zum hWnd das Process Handle und Process ID rausbekommen.

Gruß Hagen

PS: Den Feinschliff müsst ihr selber rausfinden, da dieses Posting so ziemlich der direkte Weg ist für schlaue Jungs.

stoxx 11. Nov 2003 01:58

Re: Subclassing einer fremden Application, warum funzt das n
 
Hallo Hagen,

hab zwar noch nicht das Gefühl, dass ich das wirklich allein hinbekomme ;-) .. habe aber dennoch schonmal angefangen, Deinen Pseudocode umzuwandeln ;-)

Bis hierin bin ich gekommen, lässt sich aber nicht compilieren.

Bei dem Assembler Code sagt er mir in Zeile: JMP [EAX].VirtualFree
"Ungültige Kombination von Opcode und Operanden". ?

Hier der Quelltext:


Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  PHookData = ^THookData;
  THookData = packed record
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool; stdcall; // richtige Parameter ?
    WindowProc: array[0..0] of Byte; // hier wird MyWndProc rein kopiert
    ThreadCode: array[0..0] of Byte; // hier wird ThreadProc hineinkopiert
  end;



  TForm1 = class(TForm)
    Button1: TButton;
  private

  public

  end;



var
  Form1: TForm1;

implementation

{$R *.dfm}


function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
var
  Memory: PHookData;
begin
  asm
     CALL @@1 
@@1: POP  EAX
     AND  EAX,$FFFFF000    // align
     MOV  Memory,EAX
  end;
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);

// hier Memory freigeben, wichtig dabei das der aktuelle Code ja in diesem Memory^ liegt
// wir müssen also die Reücksrungadresse aus dem Stack holen. Dann Memory auf den Stack pushen
// danach Rücksrungadresse pushen und einem Jump nach VirtualFree() durchführen.
// Somit kehrt VirtualFree NICHT in unseren nun freigegebene Memory zurück, sondern zum
// Aufrufer von MyWndProc().
    asm
      POP EDX
      MOV EAX,Memory
      PUSH EAX
      PUSH EDX
      JMP [EAX].VirtualFree
    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
end;




end.

negaH 11. Nov 2003 09:04

Re: Subclassing einer fremden Application, warum funzt das n
 
Delphi-Quellcode:
    asm
      JMP [EAX].THookData.VirtualFree
    end;
Wie gesagt, der Code lässt sich nicht so ohne weiteres direkt in Delphi umsetzen. Es gibt also noch ein paar Details zu beachten. Z.b. sind die Function Deklarationen der Windows API Funktionen nicht korrekt, sondern nur angedeutet.
Wichtig ist das VirtualAllocEx() einen an einer Speichergrenze von $1000 ausgerichteten Speicherbereich alloziert. Dies hat mehrere Gründe, der wichtigste ist aber wie im Assemblerpart von MyWndproc() am Anfang diese Speicheradresse ermittelt wird. Da alles dynamisch ist, auch für die Programmierung im Source, gibt es keine direkte und einfache Möglichkeit die korrekte Speicheradresse von Memory direkt der MyWndProc() zu übergeben. Diese Funktion muß also eine "Brute Force" Methode benutzen. Sie geht davon aus das Memory = $XXXXX000 ist.
Man könnte aber einen Dispatcher für MyWndProc() schreiben, d.h. eine kleine Assembler procedure vor MyWndProc() die einen zusätzlichen Parameter "Memory" in MyWndProc() einführt.

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    ... bla bla
    case Integer of
     0: (WindowProc: array[0..0] of Byte);
     1: (WindowProc_POP_EDX: Byte;
         WindowProc_PUSH_CONST: Byte;
         WindowProc_Memory: Pointer);
  end;

function MyWndProc(): lResult; stdcall; forward;

procedure MyWndProcDispatch;
asm
      POP EDX
      PUSH $12345678
      PUSH EDX
      JMP MyWndProc
end;

function MyWndProc(Wnd: hWnd,....,lParam: LParam; Memory: PHookData): lResult; stdcall
begin
end;

procedure SubClassWnd();
begin
  ... blabla
  Move(@MyWndProcDispatch, Memory^, CodeSize);
  Memory.WindowProc_Memory := Memory;
  ... blabla
  Memory...... := ......
end;
Nun muß man bei VirtualAllocEx() nicht mehr auf die Ausrichtung des Speicherbereiches achten, da gezielt ein neuer Parameter in MyWndProc() eingeführt wird der die Adresse von Memory enthält.
Obige Vorgehensweise ist notwendig da der Delphi Linker alle Prozeduren auf 4 Bytes Grenzen ausrichtet, also optimiert. Es können also zwischen den Proceduren MyWndProcDispatch() und MyWndProc() und ThreadFunc() und SubClassWnd() Bytes im Code stehen, die nur Fillerbytes sind.
Da MyWndProc() aber von dir beliebig erweitert werden kann und auch soll, können wir nicht direkt den Code vom MyWndproc() in Memory patchen. Denn je nach dem was für lokale Variablen du benutzt ändert sich auch der Code den der Compiler als Stackframe automatisch ohne deinen Einfluß ändert.

gruß Hagen

negaH 11. Nov 2003 09:21

Re: Subclassing einer fremden Application, warum funzt das n
 
Nachteile ? ja.

VirtualAllocEx() alloziert einen Speicher der sowohl im Zielprozess wie auch im eigenen Process zugänglich ist. Wenn die Speicheradresse von Memory im eigenen Prozess zB. $12345678 ist so heist dies NICHT zwangsläufig das diese Adresse auch im Zielprozess gleich $12345678 sein muß. Wir arbeiten ja in einem Protected Mode OS mit einem virtuellen Speichermanagement. Absolut transparent für uns könnte es also sein das Memory, obwohl es in beiden Prozesse zugreifbar ist, denoch an verschiedenen Adresse gemappt wird. Deshalb habe ich im ersten Posting den Trick mit dem ausgerichteten Speicher benutzt. Denn dadurch ermittelt der Code erst zur Laufzeit die korrekte und aktuell gültige Speicheradresse von Memory. Da Memory unseren Code enthält kann man zwangsläufig ausgehend vom gerade ausgeführten Code auf Memory zurückrechnen. Wir wissen aber nicht wie weit weg von der aktuellen Codeadresse der Anfang von Memory steht ! Deshalb ging mein Vorschlag von einem an einer Speichergrenze ausgerichteten Memory aus.

Generell sollte man bei solchen Tricks den sichersten Weg gehen und keinerlei Annahmen machen.

Gruß hagen

negaH 11. Nov 2003 09:35

Re: Subclassing einer fremden Application, warum funzt das n
 
Es gäbe aber einen sicheren Weg wenn man PHookData "umcodiert".

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    WindowProc: array[0..511] of Byte;
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool; stdcall;
  end;

function MyWndProc(hWnd: ... LParam, Memory): LResult; stdcall; forward;

procedure WndProcDispatcher;
asm
     CALL @@1
@@1: POP  EAX
     SUB  EAX,2    //  Opcode size für CALL @@1, somit EAX = Memory
     POP  EDX
     PUSH EAX
     PUSH EDX
     JMP  MyWndProc
end;

function MyWndProc(... Memory: PHookData): LResult; stdcall;
const
  MemorySize = SizeOf(THookData);
begin
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, Msg, wParam, lParam);
    asm
       MOV EAX,Memory
       POP EDX
       PUSH EAX
       PUSH MemorySize
       PUSH 0
       PUSH EDX
       JMP [EAX].THookData.VirtualFree
    end;
  end .....
end;

procedure SubClassWnd;
begin
...
  Memory := VirtualAllocEx(..., SizeOf(THookData), ...);
  Move(@WndProcDispatcher, Memory^, CodeSize);
...
end;
Nun ist es so das der Code für WndProcDispatcher + MyWndproc + ThreadFunc gleich am Anfang von Memory gespeichert wird. Da wir aber nicht die exakte Codegröße für diese Funktionen kennen reservieren wir 512 Bytes dafür. Es kann nun passieren das der Code größer als 512 Bytes wird und dies ist gefährlich. Dafür können wird auf einfache Weise die Adresse für Memory in WndProcDispatcher dynamisch an Hand der Adresse des ausgeführten Codes ermitteln.

Gruß Hagen

stoxx 11. Nov 2003 12:45

Re: Subclassing einer fremden Application, warum funzt das n
 
der WndProcDispatcher braucht doch sicherlich dieselben Parameter, wie MyWndProc oder ?

function WndProcDispatcher (hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;


der Aufruf mit Setwindowlong sähe dann so aus ?

Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WndProcDispatcher); ?


oder ist das falsch ?

negaH 11. Nov 2003 16:27

Re: Subclassing einer fremden Application, warum funzt das n
 
Zitat:

der WndProcDispatcher braucht doch sicherlich dieselben Parameter, wie MyWndProc oder ?
Nein, auf gar keinen Fall. Er hat zwar diese Aufrufparamter aber du solltest sie NICHT deklarieren. Es ist dann nämlich durchaus möglich das der Compiler einen Stackframe, auch für den Assemblercode, anlegt. Da wir im Assemblerpart direkt den Stack manipulieren würde dies zu Abstürtzen führen. Also: WindowProcDispatcher so lassen wie er ist.

Zitat:

function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM; Memory: PHookData): lResult; stdcall;
Ist richtig, da unser WindowProcDispatcher() ja den letzten Parameter Memory in die Parameterlist hinzufügt.

Zitat:

Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WndProcDispatcher); ?
Richtig. Oder besser,

Delphi-Quellcode:
Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, Memory);
da im letzten meiner Beispiele der Dispatcher am Anfang von Memory steht.

Gruß Hagen

stoxx 12. Nov 2003 03:18

Re: Subclassing einer fremden Application, warum funzt das n
 
Hallo Hagen,

ich komme hier echt nicht weiter.
Mein Problem ist, dass ich noch nie irgendwas in Assembler programmiert habe.
Auch habe ich von Befehlen wie : VirtualAllocEx heute das erste mal gehört, und habe weder mit diesen Funktionen gearbeitet, noch wüsste ich sie einzusetzen.
Geschweige denn, die richtigen Parameter zu verwenden.
Ehrlich gesagt bin ich nicht davon überzeugt, dass man mit meinem Wissen aus Deinen Hinweisen einen funktionierenden Code schreiben kann.

Um noch ehrlicher zu sein, ich bekomms alleine nicht hin und bräuchte die fertige Lösung.
... also im Moment bin ich am Ende mit meinem Latein :gruebel:


Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  PHookData = ^THookData;
  THookData = packed record
    WindowProc: array[0..511] of Byte;
    ThreadCode: array[0..511] of Byte;

   
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM;  
      lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool;  
      stdcall;

  end;



  TForm1 = class(TForm)
    Button1: TButton;
  private

  public

  end;



var
  Form1: TForm1;

implementation

{$R *.dfm}


function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): LResult; stdcall; forward;

////////////////////////////////////////////////////////////////////////////////

procedure WndProcDispatcher;
asm
     CALL @@1 
@@1: POP  EAX
     SUB  EAX,2    //  Opcode size für CALL @@1, somit EAX = Memory
     POP  EDX
     PUSH EAX
     PUSH EDX
     JMP  MyWndProc
end;

/////////////////////////////////////////////////////////////////////////////////

function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
const
  MemorySize = SizeOf(THookData );
var
  Memory: PHookData;
begin

  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
    asm
      MOV EAX,Memory
       POP EDX
       PUSH EAX
       PUSH MemorySize
       PUSH 0
       PUSH EDX
       JMP [EAX].THookData.VirtualFree

    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
end;

/////////////////////////////////////////////////////////////////////////////////

function ThreadProc(Memory: PHookData): Dword; stdcall;
begin
  Memory.SaveWindowProc := Pointer ( Memory.GetWindowLong(Memory.hWnd, gwl_WndProc) );
  Memory.SetWindowLong(Memory.hWnd, gwl_WndProc, Memory.WndProcDispatcher);
  Memory.ExitThread(0);
end;

/////////////////////////////////////////////////////////////////////////////////

procedure SubClassWnd(hWnd);
var
  Memory: PHookData;
  ProcSize: Integer;
  ThreadFunc: Pointer;

begin
  ProcSize := PChar(@Subclass) - PChar(@MyWndProc);
  Memory := VirtualAllocEx(..., SizeOf(THookData), ...);
  Move(@WndProcDispatcher, Memory^, ProcSize);
  Memory.hWnd := hWnd;

   ???

end;


end.

DaFox 13. Nov 2003 00:22

Re: Subclassing einer fremden Application, warum funzt das n
 
Hagen,

darf ich mal ganz frech fragen, ob Du selbst auf diese Methode gekommen bist oder ob Du von Jeffrey Richter inspiriert wurdest? Richter erklärt nämlich in seinem Buch genau die gleiche Methode! Rein theoretisch natürlich und er schließt diesen Ausflug in die Theorie auch mit "Leider habe ich dazu aber kein Beispiel" :wink:
Wenn es auf Deinem Mist gewachsen ist und Du also den gleichen Einfall wie er hattest, solltest Du dich mal daran machen ein Buch zu schreiben! :-D

Gruß,
Markus

negaH 13. Nov 2003 00:51

Re: Subclassing einer fremden Application, warum funzt das n
 
Ich hatte mit Luckie schon das Vergnügen über Richter zu diskutieren. Und ich habe von ihm gehört, kenne aber keines seiner Bücher. Warum auch ? Die Ideen und angedeuteten Umsetzungen findest du überall im WEB. Auch ich werde hier NUR andeuten und nur die richtige Richtung wie es funktionieren wird, aufzeigen. Warum ? Man muß sich selber reinpfriemeln und kann eigentlich NUR dadurch auch alles selber kapieren und verstehen lernen. Eine Presentation der fertigen Lösung ist also falsch. Grundsätzlich ist es doch so, ohne arrogant erscheinen zu wollen, "ich weiß wie es geht und habe es gecodet" das reicht mir eigentlich.

Appropo Bücher schreiben:
1.) als Geschichtenerzähler tauge ich nichts, und meine Ausdruckweise
2.) während ein Buchautor Zeit verschwendet um nach Informationen zu suchen, seine Sätze gut zu formulieren und noch Grafiken beipackt, sitze ich am Rechner und erweitere mein Wissen.
3.) Buchautoren schreiben also gute Bücher, und sie sind sehr wertvoll um sich in eine Materie einzuarbeiten. Will man mehr, dann gibt es keine Lehrer mehr die einem was beibringen können, und man muß mehr Wissen als der Buchautor erlangen.
4.) Wissen in der Programmierung ist eine Kombination aus theoretischem Wissen und praktischer Umsetzung. Ich halte Programmieren für ein Handwerk und die vielen unfähigen Dr. Informatiker der Universitäten beweisen dies leider immer wieder. (autsch)
Ähnliches trifft auf Buchautoren zu, wir als Leser verlangen das Unmögliche von ihnen: sehr breites Informationsfeld mit bis ins kleinste beschriebenen Details und fertigen hocheffizienten Beispielen. Dies kann ein Buch der Programmierung heutzutage nicht mehr liefern.

Gruß Hagen

Luckie 13. Nov 2003 01:07

Re: Subclassing einer fremden Application, warum funzt das n
 
[OFFTOPIC]
Leider bleibt dadurch Zugang zu deinem Wissen der Masse verwehrt. Obwohl du dir redliche Mühe gibst, es hier im Forum unterzubringen.

negaH 13. Nov 2003 03:09

Re: Subclassing einer fremden Application, warum funzt das n
 
@Luckie, dies ist im grunde richtig und in dieser Beziehung bin ich vielleicht ein bischen egoistisch. Es kostet aber wie du selber weist sehr viel Zeit in solchen Foren wie hier ausführliche Antworten zu geben. Nebenbei habe ich noch Geld zu verdienen und das als Freelancer, eine fucking Palm Anwendung mal endlich netzerkfähig zu bekommen, mich demzufolge mit INDY rumzuärgern, mein DEC fertig zu machen, bei der Primzahl Competition in den Borland Newsgroup weiter zu machen usw. usw. und meine Freudin samt zwei Katzen wollen auch noch Zeit.

Back zum Thema: ich hatte jetzt mal meine Datenbank nach meinen Sourcen zum Thema durchsucht. Leider finde ich den Mist nicht. Das heist also wenn ich die Zeit finde versuche ich obigen Draft mal fertig zu machen. Sehr viel fehlt ja nicht mehr, und ich dachte das vielleicht Nico, Luckie oder Assarbad noch ihren Beitrag leisten würden :-)

Gruß Hagen

negaH 13. Nov 2003 03:12

Re: Subclassing einer fremden Application, warum funzt das n
 
Übrigens, schau mal auf die Uhrzeit der Postings ! das sagt alles.

Gruß Hagen

Phoenix 13. Nov 2003 07:40

Re: Subclassing einer fremden Application, warum funzt das n
 
[Ganz Offtopic]

Ich habe jetzt einfach mal interessehalber den Thread gelesen, bin am Ende der Seite 3 auch auf die Idee gekommen Hagen zu fragen, ob er darüber mal nicht ein Buch screiben wollte und hab dann seine Antwort auf meinen Zuvorkommer gelesen :)

Ich muss da wirklich sagen: Schade. :cry:

@Hagen: Wo hast Du den ganzen Kram gelernt? Ich meine, ich fühle mich in Datenbankapplikationen wie der Fisch der im Wasser, aber diese tiefsten Assembler-Riffe in den Du rumschwimmst... da hakts bei mir leider komplett aus.

Hast Du uns denn wenigstens Buchtipps? ;-)

Grüßle,

Sebastian <-- der gerade merkt das er noch gewaltigen Nachholbedarf hat

stoxx 13. Nov 2003 12:25

Re: Subclassing einer fremden Application, warum funzt das n
 
Zitat:

Zitat von negaH
@Luckie, dies ist im grunde richtig und in dieser Beziehung bin ich vielleicht ein bischen egoistisch. Es kostet aber wie du selber weist sehr viel Zeit in solchen Foren wie hier ausführliche Antworten zu geben. Nebenbei habe ich noch Geld zu verdienen und das als Freelancer, eine fucking Palm Anwendung mal endlich netzerkfähig zu bekommen, mich demzufolge mit INDY rumzuärgern, mein DEC fertig zu machen, bei der Primzahl Competition in den Borland Newsgroup weiter zu machen usw. usw. und meine Freudin samt zwei Katzen wollen auch noch Zeit.

Back zum Thema: ich hatte jetzt mal meine Datenbank nach meinen Sourcen zum Thema durchsucht. Leider finde ich den Mist nicht. Das heist also wenn ich die Zeit finde versuche ich obigen Draft mal fertig zu machen. Sehr viel fehlt ja nicht mehr, und ich dachte das vielleicht Nico, Luckie oder Assarbad noch ihren Beitrag leisten würden :-)

Gruß Hagen


Hallo Hagen,

Dein Standpunkt ist nachvollziehbar.

Mit dem Satz: " .. und ich dachte das vielleicht Nico, Luckie oder Assarbad noch ihren Beitrag leisten würden :-)"

verrätst Du eigentlich ganz deutlich, dass Du Dir bewusst bist, dass der Otto Normal Programmierer mit Deiner Erklärung allein nix anfangen kann. Und ich glaub, Du weißt, dass ich Recht hab :-)

Aber wer hat schon das Wissen eines Nicos oder eines Assarbads ? Ich glaube, wenn man nicht gerade seit seinem 10. Lebensjahr in Assembler programmiert, ist dieser Status sehr schwer zu erreichen.

Ich habs auch mal mit den inject DLL´s programmiert. Das hab ich sogar hinbekommen, da ein Poster ja mal Links dazu gepostet hat. Aber Pustekuchen, funktioniert nicht. Da steht man wie ein Schwein vorm Uhrwerk, weil man nicht mal weiß, was mit dem Quelltext der Inject DLL überhaupt gemacht wird, kann also ergo auch nichts dran ändern.

Bleibt mein letzte Hoffnung bei Assarbad oder Nico. :spin:

negaH 13. Nov 2003 14:21

Re: Subclassing einer fremden Application, warum funzt das n
 
Zitat:

@Hagen: Wo hast Du den ganzen Kram gelernt? Ich meine, ich fühle mich in Datenbankapplikationen wie der Fisch der im Wasser, aber diese tiefsten Assembler-Riffe in den Du rumschwimmst... da hakts bei mir leider komplett aus.

Hast Du uns denn wenigstens Buchtipps?
Leider habe ich keine Buchtipps, weil ich eben schon seit Jahren keine Bücher übers OS usw lese.
Vor Jahren fand ich das Buch "Das MS-DOS Programmierhandbuch" von Günter Born im Markt&Technik Verlag wichtig. Ich liebe reine Nachschlagewerke die nur die API's erklären oder Formeln erklären. Ich habe auch noch so'n fetten Wälzer über VGA Karten Peogrammierung. Na und dann noch die vielen Bücher über die Programmierung und dem Selberbauen vom 8080 (im Osten U880) Rechnern. Mit dem Selberbauen und programmieren eines eigenen U880 Rechner habe ich übrigens angefangen (vor ca. 15 Jahren).

Die einzigsten Bücher die ich in letzter Zeit gekauft habe, und auch wirklich benötigte, sind meistens mathematischer Natur. "Arithmetics" von D.Knuth, "A Course in Computational Algebraic Number Theory" von Henri Cohen, "Einführung in die Kryptographie" von Johannes Buchman, "Applied Cryptography" von Menezes, van Oorschot, Vanstone, "Genetische Algortihmen und Evolutionsstrategien" von Schönberg,Heinzman,Feddersen naja usw. usw.
D.h. meistens benötige ich Informationen über Algorithmen oder bestimmten Theorien und Techniken.

Ich habe eigentlich nur Cobol, PL4 und ein bischen PASCAL in der Schule gelernt. Allerdings PASCAL und Assembler habe ich schon vor der Lehre beherrscht. Das meiste und allerwichtigste habe ich in einer Informatik AG gelernt. Zu Ostzeiten gab es "Pionierhäuser" und die GST "Gesellschaft für Sport und Technik". Das waren staatlich finanzierte Häuser in denen ehrenamtliche und interessierte Leute den Kindern was beibringen wollten, zwanglos, alles freiwillig und ohne politische Hintergedanken. Eben Privatinitiativen und kostenlos. Nun, ich war in verschiedenen solcher AG's, Holzschnitzen, kreative Tonarbeiten (Töpfern :), Flugmodellbau, Elektonik. Die Elektonik AG entwickelte sich mit der Zeit zu einer Informatik AG. Also sofort nachdem die technischen Möglichkeiten gegeben waren bauten wir unsere ersten Computer selber. Diese wurden natürlich auch selber programmiert, sogar einen eigenen BASIC Interpreter musste man selber entwickeln. Bei solchen Bedingungen mit einem "Lehrer" der selber fit und enormen Spaß an der Sache hat, kann man sich sehr gut vorstellen wie effizient und leicht man lernen kann.

Dies war auch mein Vorteil verglichen zu heutigen Generationen. Damals waren Computer eine einfache Sache und sehr leicht verständlich. Die Jungen von heute haben es da ungleich schwerer. Alleine die bescheuerten, stänig neuen Werbe-Fachbegriffe, müssen bei Anfängern absolute Verwirrung erzeugen.

Zitat:

Ich habs auch mal mit den inject DLL´s programmiert. Das hab ich sogar hinbekommen, da ein Poster ja mal Links dazu gepostet hat. Aber Pustekuchen, funktioniert nicht. Da steht man wie ein Schwein vorm Uhrwerk, weil man nicht mal weiß, was mit dem Quelltext der Inject DLL überhaupt gemacht wird, kann also ergo auch nichts dran ändern.
Egal ob Inject DLL's oder Inject Threads, die logische Vorgehensweise bleibt die gleiche.
Ausgehend vom nötigen Source-Overhead sind Inject DLL's komplizierter. Dafür funktioniert der gleiche Code unter alle OS Versionen.

Wie gesagt, ich hoffe nächste Woche finde ich die Zeit, und kann obigen Draft besser ausarbeiten. Bis zum Sonntag habe ich erstmal einen Geschäftstermin und somit keine Zeit weiter.

Gruß Hagen

stoxx 13. Nov 2003 15:00

Re: Subclassing einer fremden Application, warum funzt das n
 
Code:
Allerdings PASCAL und Assembler habe ich schon vor der Lehre beherrscht. Das meiste und allerwichtigste habe ich in einer Informatik AG gelernt. Zu Ostzeiten gab es "Pionierhäuser" und die GST "Gesellschaft für Sport und Technik". Das waren staatlich finanzierte Häuser in denen ehrenamtliche und interessierte Leute den Kindern was beibringen wollten, zwanglos, alles freiwillig und ohne politische Hintergedanken. Eben Privatinitiativen und kostenlos..

Dazu fällt mir eine Fernsehsendung ein, in der Finnland erwähnt wurde, als einer der obersten Plätze in der Pisa Studie.

"Seit den 60-er Jahren bereisten nämlich zahlreiche Kommissionen aus dem Norden die DDR, um deren Schulwesen zu studieren. Überzeugt davon, dass der pädagogischen Ansatz zu guten Ergebnissen führen kann, wurde die finnische Schule u.a. nach DDR-Vorbild aufgebaut."

http://www.mdr.de/umschau/909860.html

Code:
Wie gesagt, ich hoffe nächste Woche finde ich die Zeit, und kann obigen Draft besser ausarbeiten. Bis zum Sonntag habe ich erstmal einen Geschäftstermin und somit keine Zeit weiter.

Danke ! :-)





.

negaH 14. Nov 2003 04:35

Re: Subclassing einer fremden Application, warum funzt das n
 
Keine Garantien meinerseits, bei mir funktionierts prächtig.

Gruß Hagen

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    WndProc: array[0..255] of Byte;
    ThreadProc: array[0..255] of Byte;
    GetWindowLong: function(Wnd: hWnd; Index: Integer): Pointer; stdcall;
    SetWindowLong: function(Wnd: hWnd; Index: Integer; Value: Pointer): Pointer; stdcall;
    ExitThread: procedure(ExitCode: DWord); stdcall;
    CallWindowProc: function(PrevFunc: Pointer; Wnd: hWnd; Msg,wParam,lParam: Integer): Integer; stdcall;
    VirtualFree: function(Address: Pointer; Size,FreeType: DWord): Bool; stdcall;
    MessageBox: function(Wnd: hWnd; Text,Caption: PChar; Flag: DWord): Integer; stdcall;
    SaveWindowProc: Pointer;
    Wnd: hWnd;
    MsgText,MsgTitle: array[0..127] of Char;
  end;


function GetProcAddr(Module: hModule; Name: PChar): Pointer;
asm
        XOR  ECX,ECX                // except frame
        PUSH OFFSET @@6
        PUSH DWord Ptr FS:[ECX]
        MOV  FS:[ECX],ESP
        PUSH EBP
        PUSH EBX
        MOV  EBP,EDX
        AND  EAX,not 3
        PUSH EDI
        MOV  EDX,[EAX + 03Ch]
        PUSH ESI
        TEST EBP,EBP
        JZ   @@5
        CMP  Word Ptr [EAX + EDX],'EP'
        MOV  EDX,[EAX + EDX + 078h]
        JNZ  @@5
        ADD  EDX,EAX
        TEST EBP,0FFFF0000h
        MOV  EBX,EAX
        JZ   @@3                         // import by ordinal ??
        MOV  EAX,[EDX + 018h]
        MOV  ECX,[EDX + 020h]
        NOT  EAX
@@1:   INC  EAX
        MOV  ESI,EBP
        JZ   @@4
        MOV  EDI,[EBX + ECX]
        ADD  ECX,4
        ADD  EDI,EBX
@@2:   CMPSB
        JNE  @@1
        CMP  Byte Ptr [ESI - 1],0
        JNE  @@2
        ADD  EAX,[EDX + 018h]
        MOV  ECX,[EDX + 024h]
        ADD  ECX,EBX
        MOVZX EBP,Word Ptr [ECX + EAX * 2]
        INC  EBP
@@3:   MOV  ECX,[EDX + 01Ch]
        DEC  EBP
        ADD  ECX,EBX
        MOV  EAX,[ECX + EBP * 4]
        ADD  EAX,EBX
@@4:   POP  ESI
        POP  EDI
        POP  EBX
        POP  EBP
        POP  DWord Ptr FS:[0]
        POP  ECX
        RET
@@5:   XOR  EAX,EAX
        JMP  @@4
@@6:   MOV  EAX,[ESP + 00Ch]                // except handler
        PUSH OFFSET @@5
        POP  DWord Ptr [EAX + 0B8h]
        SUB  EAX,EAX
end;

function MyWndProc(Memory: PHookData; Wnd: hWnd; Msg,wParam,lParam: Integer): Integer; stdcall; forward;

procedure WndProcDispatcher;
asm
     CALL @@1
@@1: POP  EAX
     SUB  EAX,5
     POP  EDX
     PUSH EAX
     PUSH EDX
     JMP  MyWndProc
end;

function MyWndProc(Memory: PHookData; Wnd: hWnd; Msg,wParam,lParam: Integer): Integer; stdcall;
const
  MemorySize = SizeOf(THookData);
begin
  if Msg = wm_Destroy then
  begin
    Result := Memory.CallWindowProc(Memory.SaveWindowProc, Wnd, Msg, wParam, lParam);
    asm
      MOV EAX,Memory

      POP EBX               // Delphi push it
      POP EBP               // Delphi stackframe
      POP EDX               // Return address caller

      POP ECX               // 5 paramters Memory,Wnd,Msg,wParam,lParam
      POP ECX
      POP ECX
      POP ECX
      POP ECX

      PUSH EAX               // VirtualFree() params
      PUSH MemorySize
      PUSH 0
      PUSH EDX               // VirtualFree() returns back to our caller
      JMP [EAX].THookData.VirtualFree
    end;
  end else
    if (Msg = wm_Close) or (Msg = wm_Quit) then
    begin
      Result := 0;
      Memory.MessageBox(0, Memory.MsgText, Memory.MsgTitle, 0);
    end else
      Result := Memory.CallWindowProc(Memory.SaveWindowProc, Wnd, Msg, wParam, lParam);
end;

function ThreadProc(Memory: PHookData): DWord; stdcall;
const
  MemorySize = SizeOf(THookData);
begin
  Memory.SaveWindowProc := Memory.GetWindowLong(Memory.Wnd, gwl_WndProc);
  if Memory.SaveWindowProc <> nil then // hier eventuell Param für ExitThread setzen
    Memory.SetWindowLong(Memory.Wnd, gwl_WndProc, Memory);
  Memory.ExitThread(0);
end;

procedure SubClass(Wnd: hWnd);
var
  CodeSize: Integer;
  Process: THandle;
  ProcessID: DWord;
  Thread: THandle;
  ThreadID: DWord;
  Memory: PHookData;
  DLL: hModule;
  Temp: THookData;
  Bytes: DWord;
begin
  if not IsWindow(Wnd) then Exit;
  GetWindowThreadProcessID(Wnd, @ProcessID);
  if ProcessID = 0 then Exit;

  Process := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_CREATE_THREAD, False, ProcessID);
  if Process <> 0 then
  begin
    Memory := VirtualAllocEx(Process, nil, SizeOf(THookData), MEM_COMMIT, PAGE_READWRITE);
    if Memory <> nil then
    begin
      CodeSize := PChar(@ThreadProc) - PChar(@WndProcDispatcher);
      Move(WndProcDispatcher, Temp.WndProc, CodeSize);
      CodeSize := PChar(@SubClass) - PChar(@ThreadProc);
      Move(ThreadProc, Temp.ThreadProc, CodeSize);

      DLL := GetModuleHandle('user32.dll');
      Temp.GetWindowLong := GetProcAddr(DLL, 'GetWindowLongA');
      Temp.SetWindowLong := GetProcAddr(DLL, 'SetWindowLongA');
      Temp.CallWindowProc := GetProcAddr(DLL, 'CallWindowProcA');
      Temp.MessageBox := GetProcAddr(DLL, 'MessageBoxA');
      DLL := GetModuleHandle('kernel32.dll');
      Temp.ExitThread := GetProcAddr(DLL, 'ExitThread');
      Temp.VirtualFree := GetProcAddr(DLL, 'VirtualFree');
      Temp.Wnd := Wnd;
      Temp.MsgText := 'Want close';
      Temp.MsgTitle := 'Test';

      if WriteProcessMemory(Process, Memory, @Temp, SizeOf(THookData), Bytes) then
      begin
        Thread := CreateRemoteThread(Process, nil, 0, @Memory.ThreadProc, Memory, 0, ThreadID);
        if Thread <> 0 then
        begin
          WaitForSingleObject(Thread, INFINITE);
     // hier eventuell ExitCode vom Thread auswerten
          MessageBox(Application.Handle, 'Hooked successfull', 'SubClass()', 0);
 
          CloseHandle(Thread);
        end;
      end else
      begin
        VirtualFreeEx(Process, Memory, SizeOf(THookData), 0);
      end;
    end;
    CloseHandle(Process);
  end;
end;

procedure TestSubClass;

  function MyEnum(Wnd: hWnd; Return: PInteger): Bool; stdcall;
  var
    ClassName: String;
    ProcessID: DWord;
  begin
    Result := True;
    SetLength(ClassName, MAX_PATH);
    SetLength(ClassName, GetClassname(Wnd, PChar(ClassName), Length(ClassName)));
    if ClassName = 'TConsoleMainForm' then
    begin
      GetWindowThreadProcessID(Wnd, @ProcessID);
      if GetCurrentProcessID <> ProcessID then
      begin
        Return^ := Wnd;
        Result := False;
      end;
    end;
  end;

var
  Wnd: Integer;
begin
  Wnd := 0;
  EnumWindows(@MyEnum, Integer(@Wnd));
  SubClass(Wnd);
end;

stoxx 14. Nov 2003 12:47

Re: Subclassing einer fremden Application, warum funzt das n
 
wow .. hihi .. Danke !
sieht zumdindest so aus, als hätte ich das nie im Leben selber hinbekommen !
Und funktioniert. Was nun auch immer der Assembercode macht, es wird mir zumindest noch lange verborgen bleiben ...

Ist jetzt Unsubclass genauso kompliziert ? :-) :-)

stoxx 15. Nov 2003 15:58

Re: Subclassing einer fremden Application, warum funzt das n
 
Hallo Hagen,

das mit dem Unsubclass klappt noch nicht so recht.
Da kommt eine heftige Fehlermeldung und das betreffende Programm rauscht gleich ganz ab.
ich hab die Adresse von memory in einer globalen Variablen m_memory gespeichert.
Ist das falsch ?
Kommt man auch ohne diese globale Variable aus ?
Also kann man die Adrese von memory auch nur mit Hilfe von hWnd des Fensters ermitteln ?

Hier mal die Anfänge des Codes .....

Code:
////////////////////////////////////////////////////////////////////////////////

function ThreadProcunsub(Memory: PHookData): DWord; stdcall;
const
  MemorySize = SizeOf(THookData);
begin
  if Memory.SaveWindowProc <> nil then
   Memory.SetWindowLong(memory.wnd, gwl_WndProc,Memory.saveWindowProc);
  Memory.ExitThread(0);
end;

//////////////////////////////////////////////////////////////////////////////////


procedure UnSubClass(Wnd : hWnd);
var
   ProcessID: DWord;
   Process: THandle;
   Thread: THandle;
   ThreadID: DWord;
   Memory: PHookData;
begin
  memory := m_memory;
  if not IsWindow(Wnd) then Exit;
  GetWindowThreadProcessID(Wnd, @ProcessID);
  if ProcessID = 0 then Exit;

  Process := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_CREATE_THREAD, False, ProcessID);

  Thread := CreateRemoteThread(Process, nil, 0, @Memory.ThreadProcunsub, Memory, 0, ThreadID);
        if Thread <> 0 then
        begin
          WaitForSingleObject(Thread, INFINITE);
     // hier eventuell ExitCode vom Thread auswerten
        //  MessageBox(Application.Handle, 'Hooked successfull', 'SubClass()', 0);

          CloseHandle(Thread);
        end;

end; // von Unsubclass

negaH 17. Nov 2003 10:23

Re: Subclassing einer fremden Application, warum funzt das n
 
Tja, das entfernen eines Subclassing ist nicht so einfach wie man denkt.
Zb. du hast mit obiger Methode ge-subclassed, und in gwl_WndProc steht unsere Windowproc drinnen. Nun Subclassed ein anderes Modul ebenfalls, dann gibt es keine Möglichkeit die eigene Subclass wieder zu entfernen. Denn dein Modul + das andere Modul + Windows selber kennen kein gemeinsammes Protokoll das es ermöglicht geordnet die Subclassings zu entfernen. Da ja nun dein Subclassing im Kontext des Window-Processes läuft wäre es am einfachsten, 1. einfach ein Flag Active in die HookData Struktur einzubauen. Statt also das Subclassing zu deinstallieren wird es nur deaktiviert. 2. ist es für die Kommunikation mit deinem Hook besser eine globale Windowsbotschaft mit RegisterWindowMessage() zu benutzen. Dein Hook reagiert auf diese Botschaft, und in wParam,lParam der Message können Steuerkommandos untergebracht werden. Über dieses Verfahren könntest du auch das Subclassing terminieren. Dabei hast du mehrere Dinge zu beachten. 1.) NIEMALS im Code der in PHookData kopiert wird auf irgendwelche Globale Variablen, Importe etc zugreifen. ALLES an daten und Zugriff MUSS in PHookData stehen. Informiere dich mal was es heist Protected Mode OS, Module und Prozesse und Mapping der Daten-/Codesegmente von Modulen in Prozessen. Dies MUSST du begriffen haben, dann weisst du auch warum Dein Zugriff auf eine globale Variable absolut falsch sein muss. Nungut, desweiteren ist ds Entfernen des Hooks möglich wenn mit GetWindowLong(gwl_WndProc) unsere Addresse auf unsere WndProc = Memory zurückgegeben wird. Sollte dies nicht der Fall sein kann NICHT deinstalliert werden. Ich würde sowieso nur eine Deaktivierung des Hooks benutzen. Angenommen GetWindowLong(gwl_WndProc) = Memory, dann könnte man deinstallieren, mit SetWindowLong(Memory.SaveWindowProc). Das Problem entsteht nun dabei WIE wir unseren Memory mit VirtualFree() freigeben müssen. 1.) ExitThread() ist absolut FALSCH, denn eine Windowsproc läuft nicht in dem Thread den wie benutzten um den Hook zu installieren. Mit ExitThread() beendest du meistens den Main-Thread des Ziel-Prozesses dem das Fenster gehört. 2.) Da unser Deinstallations-Code selber in Memory steht, also innerhalb von Memory ausgeführt wird kann man nicht einfach so VirtualFree(Eigerner_Code_In_Memory) aufrufen, logisch ok !? Denn nach dem VirtualFree() müssen wir Code ausführen der zum Aufrufer zurückkehrt, also mindestens ein RET und eventuell noch einige POP's. Deshalb nutzt man einen Trick. Man legt alle notwendigen Daten auf den Stack des aktuellen Threads, mit PUSH's und springt am Ende mit einem JMP Memory.VirtualFree zu VirtualFree() um das aktuelle "Codesegment" freizugeben. VirtualFree() würde nach Beendigung nur noch auf den Stack des Threads zugreifen und kann so gezielt und geordnet zum Aufrufer der Fensterprocedure zurückkehren.

Also nochmal in kurz die beste Vorgehensweise:
1.) mit RegisterWindowMessage() eine Steuermessage erzeugen
2.) in MyWndProc() diese Steuermessage abfangen und den entsprechende Kommandos reinbauen
3.) Kommando "IsInstalled" um ein Fenster auf unseren Hook zu checken
4.) Kommando "Deaktivate" um unseren wm_Close Hook zu deaktivieren
5.) Kommando "Aktivate" um wm_Close Hook zu aktivieren
6.) Kommand "Deinstall" um das Subclassing zu entfernen. Dabei solltest mit GetWindowLong(gwl_WndProc) == Memory überprüfen, wenn ja dann SetWindowLong(gwl_WndProc, memory) aufrufen, und danach EXAKT den ASM-Code der jetzt in wm_Destroy steht aufrufen.

Gruß Hagen

negaH 17. Nov 2003 10:30

Re: Subclassing einer fremden Application, warum funzt das n
 
Statt mit RegisterWindowMessage() zu arbeiten, kann man auch wm_CopyData benutzen. Das hat einen entscheidenden Vorteil, nämlich das Windows darauf achtet das die Speicherdaten in wm_CopyData von einem Prozess zum anderen zugreifbar sind. Der Nachteil dabei ist es WIE wir sicherstellen können das unser Hook erkennen kann das eine wm_CopyData Botschaft für uns ist, und andere wm_CopyData Handler NICHT unsere Botschaft fälschlicherweise abarbeiten (zb. wenn ein Fenster nicht mit unserem Hook versehen wurde). Ich würde deshalb mit RegisterWindowMessage() arbeiten, und eventuelle Daten per wm_CopyData versenden NACHDEM überprüft wurde ob das Zielfenster unseren Hook installiert hat.

Eventuell baue ich obigen Code noch dementsprechend um (wenn ich Zeit finde).

Gruß Hagen

Metal_Snake2 5. Sep 2008 18:10

Re: Subclassing einer fremden Application, warum funzt das n
 
Sry das ich das Thema wieder ausgrabe aber ich krieg einfach nicht die Unsubclass Methode hin.

@negaH: Wärst du bitte bitte so nett und würdest die Unsubclass Methode Implementieren.

Das wäre echt Super, dann könnte man auch den Code hier gleich in die Code- Library posten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:20 Uhr.
Seite 2 von 2     12   

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