Entwickler-Ecke

Windows API - API Befehl zum Erstellen von Fenstern für Hook ?


F34r0fTh3D4rk - Sa 24.02.07 21:16
Titel: API Befehl zum Erstellen von Fenstern für Hook ?
hi, ich brauche in meinem programm einen hook, der erkennt, wann ein neues fenster / formular erstellt wird. welche prozedur hooke ich da am besten ? CreateWindowEx ?

weil irgendwie klappt das so net:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
library hook;

uses windows, uallHook, sysutils;

var
  oldCreateWindowEx,
  nextCreateWindowEx:
  function(dwExStyle: cardinal; lpClassName: PAnsiChar; lpWindowName: PAnsiChar;
           dwStyle: cardinal; x: integer; y: integer; nWidth: integer; nHeight: integer;
           hWndParent: HWND; hMenu: HMENU; hInstance: Cardinal; lpParam: Pointer): HWND; stdcall;

function myCreateWindowEx(dwExStyle: cardinal; lpClassName: PAnsiChar; lpWindowName: PAnsiChar;
           dwStyle: cardinal; x: integer; y: integer; nWidth: integer; nHeight: integer;
           hWndParent: HWND; hMenu: HMENU; hInstance: Cardinal; lpParam: Pointer): HWND; stdcall;
begin
  result := nextCreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
end;

var
  h: integer;
begin
  h :=  GetModuleHandle('user32.dll');
  if (h > 0then
  begin
    @oldCreateWindowEx := GetProcAddress(h, 'CreateWindowEx');
    if @oldCreateWindowEx <> nil then
      uallHook.HookCode(@oldCreateWindowEx, @myCreateWindowEx, @nextCreateWindowEx);
  end;
end.


Dieser Hook wird global injiziert.

mfg


evilsoft.de - So 04.03.07 13:16

in meiner user32.dlll befinden sich nur diese beiden functionen:
CreateWindowExA
CreateWindowExW

Edit: was genau klappt denn nicht?


uall@ogc - So 04.03.07 13:20

Vielleicht geht auch ein einfacher MessageHook, wenn du dann nach "WM_CREATE" schaust?


Billi Berserker - Mo 05.03.07 01:49

Am besten geht das ganze über Shell Hooks -> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/shellproc.asp
Da braucht man dann nur noc HSHELL_WINDOWCREATED und HSHELL_WINDOWDESTROYED auswerten und fertig :)
Wie jeder Hook der über SetWindowsHookEx gesetzt wird muß das ganze aus einer DLL Datei raus gemacht werden.


spawn89 - Do 22.01.09 00:24
Titel: Re: API Befehl zum Erstellen von Fenstern für Hook ?
Einen wundervollen guten Abend,

ich hab in etwa das gleiche Problem.
Nur das bei mir CreateWindowExW erfolgreich gehook´t wird und ich auch Code ausführen kann.
Das Problem liegt jetzt darin, dass sich das Programm immer aufhängt, wenn ich das "Orginal ungehook´te" CreateWindowExW mit den gleichen Parametern aufrufe. :shock:
Woran könnte das bitte liegen? :?

Auszug meines Codes:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
library hook;

// ... haufenweise Code ...

var
  nextCreateWindowExW: function(
    dwExStyle: Cardinal; lpClassName: PWideChar; lpWindowName: PWideChar; 
    dwStyle: Cardinal; X, Y, nWidth, nHeight: Integer; hWndParent: Cardinal; 
    hMenu: Cardinal; hInstance: Cardinal; lpParam: Pointer): Cardinal; stdcall;

// ... haufenweise Code ...

function myCreateWindowExW(dwExStyle: Cardinal; lpClassName: PWideChar;
  lpWindowName: PWideChar; dwStyle: Cardinal; X, Y, nWidth, nHeight: Integer;
  hWndParent: Cardinal; hMenu: Cardinal; hInstance: Cardinal; lpParam: Pointer): Cardinal; stdcall;
begin
  // Hier wird alles noch vorbildlich ausgeführt, wenn hier Code stünde.
  Result := nextCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
  // dieser, hier momentan nicht existierende, Code wird nicht mehr erreicht/ausgeführt.
end;

// ... haufenweise Code ...

Hier hab ich mal den Inhalt der Parameter geloggt:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
LogFile@InjectedDll

myCreateWindowExW Params:
dwExStyle: 0
lpClassName: ChatSkinWnd
lpWindowName: ChatSkinWnd
dwStyle: 2248146944
x: 531
y: 153
nWidth: 400
nHeight: 300
hWndParent: 0
hMenu: 0
hInstance: 4194304
lpParam: 0

Start creating Window with nextCreateWindowExW (@123731968)
// Result wurde schon gar nicht mehr geschrieben, dh er hängt in nextCreateWindowExW


Ich hoffe mir kann jemand helfen. :wink:

Spawn
(*Thread ausgrab*, ich wollte nicht gleich bei meinem erstem Post nen Thread erstellen) :wink2:


SAiBOT - Do 22.01.09 02:59
Titel: Re: API Befehl zum Erstellen von Fenstern für Hook ?
Erstmal :welcome:,
Du hättest ruhig einen neuen Thread eröffnen können finde ich :P

Also die Parameter sehen richtig aus..., ich vermute du hast uns die falschen Codestellen gepostet.

Schick mal den gesamten Code, der etwas mit dem Hook zu tun hat!


spawn89 - Do 22.01.09 11:18

Danke schonmal für die Antwort.
Hier der komplette Code der etwas mit dem CreateWindowExW-hook zu tun hat:

Form um die Dll zu injecten (HookUallTestFrm):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
unit HookUallTestFrm;

interface

uses
  Windows, SysUtils, Forms, Dialogs, StdCtrls, Controls, Classes, uallHook;

type
  THookUallTestForm = class(TForm)
    btInjectInTarget: TButton;
    btUnInject: TButton;
    edPID: TEdit;
    procedure btInjectInTargetClick(Sender: TObject);
    procedure btUnInjectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
  var
    DllPath: String;
    procedure ShowSuccess(const Success: Boolean);
  public
  end;

var
  HookUallTestForm: THookUallTestForm;

implementation

{$R *.dfm}

const
  cTargetApp = 'Xfire.exe';
  cDllName = 'InjectedDll.Dll';

procedure THookUallTestForm.FormCreate(Sender: TObject);
begin
  DllPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+cDllName;
end;

procedure THookUallTestForm.ShowSuccess(const Success: Boolean);
begin
  if Success then
    ShowMessage('Erfolgreich ausgeführt!')
  else
    ShowMessage('Fehlgeschlagen!')
end;

procedure THookUallTestForm.btInjectInTargetClick(Sender: TObject);
var
  PID: Cardinal;
begin
  ShowSuccess(
    TryStrToInt(edPID.Text, Integer(PID)) and
    FileExists(DllPath) and
    uallHook.InjectLibrary(PID, PChar(DllPath))
  );
end;

procedure THookUallTestForm.btUnInjectClick(Sender: TObject);
var
  PID: Cardinal;
begin      
  ShowSuccess(
    TryStrToInt(edPID.Text, Integer(PID)) and
    FileExists(DllPath) and
    UnloadLibrary(PID, PChar(DllPath))
  );
end;

end.


Auszuführende Dll (InjectedDll):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
library InjectedDll;

uses 
  uallHook, SysUtils, Windows, Dialogs, Controls;

var
  oldCreateWindowExW, nextCreateWindowExW:
    function(dwExStyle: Cardinal; lpClassName, lpWindowName: PWideChar; dwStyle: Cardinal; X, Y, nWidth,
             nHeight: Integer; hWndParent, hMenu, hInstance: Cardinal; lpParam: Pointer): Cardinal; stdcall;

{$R *.res}

procedure AddLogEntry(const Log: Stringconst CR: Boolean=true); 
const
  cDllLogTextFile = 'C:\DllLogFile.txt';
var
  hFile: TextFile;
begin
  AssignFile(hFile, cDllLogTextFile);
  try
    if FileExists(cDllLogTextFile) then
      Append(hFile)
    else
      Rewrite(hFile);

    if CR then
      Writeln(hFile, Log+#13#10)
    else
      Writeln(hFile, Log);

    CloseFile(hFile);
  except
    CloseFile(hFile);
  end;
end;

function myCreateWindowExW(dwExStyle: Cardinal;
  lpClassName, lpWindowName: PWideChar; dwStyle: Cardinal; X, Y, nWidth,
  nHeight: Integer; hWndParent, hMenu, hInstance: Cardinal; lpParam: Pointer): Cardinal; stdcall;
begin
  AddLogEntry('myCreateWindowExW Params:' + #13#10 +
    'dwExStyle: ' + IntToStr(dwExStyle) + #13#10 +
    'lpClassName: ' + String(lpClassName) + #13#10 +
    'lpWindowName: ' + String(lpWindowName) + #13#10 +
    'dwStyle: ' + IntToStr(dwStyle) + #13#10 +
    'x: ' + IntToStr(x) + #13#10 +
    'y: ' + IntToStr(y) + #13#10 +
    'nWidth: ' + IntToStr(nWidth) + #13#10 +
    'nHeight: ' + IntToStr(nHeight) + #13#10 +
    'hWndParent: ' + IntToStr(hWndParent) + #13#10 +
    'hMenu: ' + IntToStr(hMenu) + #13#10 +
    'hInstance: ' + IntToStr(hInstance) + #13#10 +
    'lpParam: ' + IntToStr(Cardinal(lpParam))
  );
  if MessageDlg('Soll das Fenster erstellt werden?',  mtInformation, [mbYes, mbNo], 0) = mrYes then
  begin
    AddLogEntry('Start creating Window with nextCreateWindowExW (@'+
      IntToStr(Cardinal(@nextCreateWindowExW))+')'); // Wird noch aufgerufen

    Result := nextCreateWindowExW( // Hier hängt das targetProg
      dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight,
      hWndParent, hMenu, hInstance, lpParam);
      
    AddLogEntry('Result: '+ IntToStr(Result)); // Wird schon gar nicht mehr aufgerufen
  end
  else
    Result := 0;
end;

procedure InjectMain;
var
  h: Integer;
begin
  h := GetModuleHandle(user32);
  if h > 0 then
  begin
    @oldCreateWindowExW := GetProcAddress(h, 'CreateWindowExW');
    if @oldCreateWindowExW = nil then
      AddLogEntry('GetProcAddress failed (=0)')
    else
      if HookCode(@oldCreateWindowExW, @myCreateWindowExW, @nextCreateWindowExW) then
        AddLogEntry('Code injected')
      else
        AddLogEntry('HookCode failed')
  end
  else
    AddLogEntry('GetModuleHandle failed (=0)')
end;

procedure UninjectMain;
begin 
  if UnhookCode(@nextCreateWindowExW) then
    AddLogEntry('Code unhooked');
end;

procedure DllMain(dwReason: Integer); 
begin 
  case dwReason of 
    DLL_PROCESS_ATTACH : 
      InjectMain;
    DLL_PROCESS_DETACH : 
      UninjectMain;
  end;
end

begin
  DllProc := @DllMain;
  DLLMain(1); 
end.


Also Fehlerquellen die ich ausschließen kann:
- PID ist die richtige.
- Hook wird injeziert und ausgeführt. (AbfrageBox erscheint im richtigem Programm zur richtigen Zeit)

Kann es eventuell daran liegen, dass das Zielprogramm nicht in Delphi geschrieben wurde?


SAiBOT - Do 22.01.09 14:27

Ich habe deinen Code mal überflogen, sieht alles richtig aus...wobei:
Message-Dialoge machen sich nie gut in einer Hook Prozedur!

Ob es in deinem fall nun an xFire liegt lässt sich ganz leicht herausfinden:
Erstelle ein eigenes kleines Programm was die Funktion aufruft und installiere deinen Hook.

In welcher Sprache das programm gecodet wurde ist egal!

Probieren kannst du es auch (wie user profile iconBilli Berserker schon sagte) mit SetWindowsHookEx(WH_SHELL) (ShellHooks).

MfG


spawn89 - Do 22.01.09 16:09

Und ich dachte immer ich käme am nonVcl vorbei. :?
Gut, ich hab mal selbst ein Opferprogramm mit CreateWindowExW gebastelt und siehe da, alles funktioniert wunderbar. :shock:

Leider habe/bekomme ich kein xFire hier auf der Arbeit, so das ich das erst heute Abend wieder testen kann.
Evtl. hab ich gestern Abend doch irgendwo Mist gebaut und den MsgDlg pack ich dann wieder raus und füg nur nen log bei Fehler/Erfolg hinzu.

user profile iconSAiBOT hat folgendes geschrieben Zum zitierten Posting springen:
Probieren kannst du es auch (wie user profile iconBilli Berserker schon sagte) mit SetWindowsHookEx(WH_SHELL) (ShellHooks).

Naja, das mach ich als Notlösung bzw nachdem mein Code funktioniert.
Ich sitz da etwas paranoid hinter, wenn mein Code nicht funktioniert. :wink:

Vielen Dank für die Tipps!

Edit:
@Boldar: Thx, darüber habe ich gar nicht mehr nachgedacht. :)
(Ist momentan eh nur zu testzwecken drin)


Boldar - Do 22.01.09 16:13

noch einen Tipp: ich glaube es wäre besser, ddas öffnen der Logdatei am anfang zu machen und nicht jedesmal neu, das könnte die Performance runterziehen. Unter initialization kann man die öffnen und unter finalization schließen...


spawn89 - Do 22.01.09 19:53

Hmm also nochmal getestet und raus kam, dass er sich genau hierbei aufhängt:

Delphi-Quelltext
1:
Result := nextCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);                    

Dann "freezet" XFire (also "Keine Rückmeldung") und nach ziemlich genau 10 Sekunden poppt nen Dialog auf mit einer XFire Exception, in der ich gefrag werde, ob ich diese hochladen würde.
U.a. steht da folgendes drinne:

Quelltext
1:
2:
3:
4:
<Exception Code="C0000005" Address="785E19B1"></Exception>
...
<Module Section="0001" Offset="0005E067" FileName="C:\Delphi\Projekte\Tests\HookUallTest - XFire\InjectedDll.Dll"/
....

Und weiterhin steht da noch anscheinend eine ganze Menge über meine Dll.

Jetzt wieder eine Frage: *sry*
Kann ein Prozess herausfinden ob eine Prozedur/Funktion gehooket ist bzw. anderer Code ausgeführt wird?

Weil irgendwie hab ich den Verdacht, XFire gaukelt mir die Exception vor und will irgendwas über meine Dll erfahren. :nixweiss:
Und ich würde auch gerne so "Sicherheitsmechanismen" in meine Programme einbauen. :lol:

Ich hoffe ich geh euch nicht zu sehr auf den Wecker. *duck*