[Delphi] Hooking van IE (windowHandle etc)

Pagina: 1
Acties:
  • 164 views sinds 30-01-2008
  • Reageer

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Hallodio

Ik heb nu een programma gemaakt dat Internet Explorer (of een ander programma) kan opstarten en deze onder controle heeft als het ware.
Als je dit geopende scherm wil sluiten of minimaliseren, dan verdwijnt hij naar de systray.

Ik krijg per opgestarte IE de ProcessId, ThreadId, ThreadHandle, Windowhandle en ProcessHandle.

Alleen werkt dit 'hooking' alleen voor de eerst geopende applicatie. De 2e wordt niet gehooked, dus kan zo worden gesloten. En dat is niet de bedoeling.
Ik denk dat in de capture.dll alle variablen in een array moeten staan zodat er meerdere apps gehooked kunnen worden, maar of dat ook echt zo is?

Ik heb de complete source geupload omdat ik niet weet welke code jullie nodig hebben.
Ik hoop dat jullie eruit kunnen komen.

http://xlerator.f2o.org/pubimg/hooking.rar

Start een IE door op Start New Instance te klikken, dan die gene in de ListView aanklikken en op Show Instance klikken.

Echt heel erg bedankt alvast!!!

Groetjes, Wim

[ Voor 6% gewijzigd door Guillome op 09-12-2003 23:21 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02-2025

SchizoDuckie

Kwaak

álles wat je kan bedenken dat te maken heeft met IE en delphi vind je op http://www.euromind.com/iedelphi :)

Snuffel daar eens rond zou ik zeggen. Er staan voor bijna alles wat je zoekt interfaces en sample codes :)

Stop uploading passwords to Github!


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Hele mooie site, bedankt :)
Maar het heeft niets met IExplorer te maken. Elk ander programma heeft het zelfde probleem.
Het heeft te maken met het hooken (capture.dll)

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Misschien dat je even moet gaan debuggen. Stuurt de functie NotifyObserver het wel naar de juiste window handle of wordt die functie uberhaupt nooit aangeroepen. Wordt de functie HookProc wel aangeroepen wanneer er vensters geopend worden? Wordt de DLL wel bij elk process ingeladen? Het debuggen zou je kunnen doen door log messages te sturen. Bijvoorbeeld met OutputDebugString en die dan op te vangen met bijvoorbeeld http://www.sysinternals.com/ntw2k/freeware/debugview.shtml

We adore chaos because we like to restore order - M.C. Escher


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ik zal er even naar kijken.
Maar ik moet wel zeggen dat de 1e gestartte app het prima doet he.
Die wordt wel gehooked

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Is er niemand die het weet?

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Jij zou toch debuggen? :) Als jij kan vertellen wat er precies niet werkt, kunnen wij er een oplossing voor bedenken.

We adore chaos because we like to restore order - M.C. Escher


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ok, ik ben al ietsje verder. Ten minste, met uitzoeken wáár de fout zit.
Hij kan maar 1 window 'observer'en.

code:
1
2
3
4
5
6
procedure TForm2.StartHooking;
begin
  if FWantClose or FWantStopHooking or (FSubClassedCount > 0) then Exit;
  SetObserver(Handle);
  SetHook;
end;


Als ik die FSubClassedCount uitschakel bij deze if, dan voert hij de 2 functies (Set..) ook de 2e keer uit, en dan hangt hij bij SetHook

En wel hier:
In de dll staat dit:
code:
1
2
3
4
5
6
7
8
9
procedure SetHook;
begin
  with GHookRecPtr^ do
  begin
    RWantProcessID := 0;
    RObservedWindow := 0;
    RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
  end;
end;

En dan hangt hij bij RHookID := SetWindowsHookEx

Ik hoop dat je hiermee iets kan?
Ik puzzel weer verder :) Maar ik vind het heel pittig.

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Kan je hier nu meer mee? Dit is mijn laatste kick, maar er moet toch wel iemand zijn die mij opweg kan helpen?
.oiyson had mij de vorige keer een heel end geholpen. Ben jij er nog? :)

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Postman
  • Registratie: Februari 2000
  • Laatst online: 01-05 13:23
Moet RHookID niet een unieke waarde zijn, en crasht hij daarom als je een tweede keer die functie wil uitvoeren??
Als je in dezelfde instantie werkt dan overschrijf je de oude id, en dus weet je programma niet meer welke bedoelt wordt. Misschien is een array een oplossing? Echter, ik weet niet zo heel veel van Delphi in het algemeen of jouw code in het bijzonder, dus vertrouw niet blind op me ;)

  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Je code kan ik niet meer downloaden :(

Gebruik je een 'system wide hook' ?

zo ja dan moet je zorgen dat de keyhook in shared memory zit.

Vb code van een system wide keyboard hook (ik weet dus niet of je uberhaupt gebruik maakt van API hooking).

PS TJclSwapFileMapping komt uit de Jedi JCL library

Delphi:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
library keyhook;

uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  JclFileUtils;

{$R *.RES}

type
  TSharedRec = record
    FKeyHook      : HHOOK;
    FNotifyWindow : HWND;
    FMsg          : UINT;
  end;

  PSharedRec = ^TSharedRec;

var
  GSharedRec   : PSharedRec;
  GFileMapping : TJclSwapFileMapping;
  GFileViewIdx : Integer;
  HookCreated  : Boolean;


function KeyboardProc(nCode : Integer; wParam : WPARAM; lParam : LPARAM) : LRESULT; stdcall;
begin
  if nCode < 0 then
  begin
    Result := CallNextHookEx(GSharedRec.FKeyHook, nCode, wParam, lParam);
    Exit;
  end;
  if nCode = HC_ACTION then
  begin
    SendNotifyMessage(GSharedRec.FNotifyWindow, GSharedRec.FMsg, wParam, lParam);
  end;
  Result := 0;
end;



function CreateHook(NotifyWindow : HWND; Msg : UINT) : Boolean; stdcall;
begin
  Result := True;

  if HookCreated then
    Exit;

  GSharedRec.FNotifyWindow := NotifyWindow;
  GSharedRec.FMsg := Msg;

  GSharedRec.FKeyHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0);

  if GSharedRec.FKeyHook <> 0 then
  begin
    HookCreated := True;
  end
  else
  begin
    MessageBox(0, 'hook = 0', 'error', MB_OK);
    HookCreated := False;
    Result := False;
  end;

end;


function UnHook : Boolean; stdcall;
begin
  if not HookCreated then
  begin
    Result := False;
    Exit;
  end;

  Result := UnHookWindowsHookEx(GSharedRec.FKeyHook);
  HookCreated := False;
end;

procedure DLLHandler(Reason: Integer);
begin
  case Reason of
    DLL_PROCESS_DETACH:
      begin
        UnHook;
        GFileMapping.Free;
      end;
  end; // end case
end;

exports
  CreateHook,
  UnHook;

begin
  try
    {disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications}
    DisableThreadLibraryCalls(HInstance);

    GFileMapping := TJclSwapFileMapping.Create('stigmergy_simple_keyhook',
                                               PAGE_READWRITE,
                                               SizeOf(TSharedRec),
                                               nil);

    GFileViewIdx := GFileMapping.Add(FILE_MAP_WRITE, SizeOf(TSharedRec), 0);

    GSharedRec := PSharedRec(GFileMapping.Views[GFileViewIdx].Memory);

    {initialize SharedRec for the first time}
    if not GFileMapping.Existed then
    begin
      GSharedRec.FKeyHook := 0;
      GSharedRec.FNotifyWindow := 0;
    end;

    DllProc := @DLLHandler;

  except
    on E : EJclFileMappingError do
    begin
      MessageBox(0, 'Create mapping error', 'error', MB_OK);
      Halt(1);
    end;
  end;
end.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Oh shit ja, de server was down en ik had er niet meer aan gedacht dat ik daar de source had opgezet. Hij staat nu op http://xlerator.f2o.org/pubimg/hooking.rar

Ik denk dat die variablen idd in een array moeten komen te staan. Ik zal eens kijken in hoeverre ik dat voorelkaar kan krijgen.
En ik ga nu even kijken naar dit voorbeeld hierboven.


edit: Voor het gemak maar even de DLL code hierneer gezet:
code:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
library Capture;
uses
  Windows,
  CommCtrl,
  Messages,
  SysUtils;

{$R *.RES}

type
  PHookRec = ^THookRec;
  THookRec = record
    RObserver: THandle;
    RObservedWindow: THandle;   
    RHookID: HHOOK;
    RWantProcessID: DWORD;
  end;

const
  CM_NotifyObserver = WM_USER + 1;
  CM_NotifyObserverMsg = WM_USER + 2;
  WM_HCBT_MINMAX = WM_USER + 285;

  NO_BeginSubClassed = 0;
  NO_EndSubClassed = 1;
  NO_ProcessIDFound = 2;
  NO_ClosePrevented = 3;
  NO_StartProcess = 4;
  NO_EndProcess = 5;

var
  { Alle instanties van de dll die geinjecteerd worden in een window
    krijgen eigen instanties van de volgende vars: }

  { Pointer naar de data die alle dll instanties delen }
  GHookRecPtr: PHookRec = nil;
  { Handle naar de filemapping object }
  GMapObject: THandle = 0;
  { Pointer naar oude wndproc }
  GOldWndProc: Pointer = nil;
  { Handle naar Window die gesubclassed is }
  GHandle: THandle = 0;

procedure NotifyObserver(Msg, SubMsg: Integer);
begin
  PostMessage(GHookRecPtr.RObserver, CM_NotifyObserver, Msg, SubMsg);
end;

procedure UnSubClass {(Handle: HWnd)};
begin
  if (GOldWndProc <> nil) and (GHandle > 0) then
  begin
    SetWindowLongW(GHandle, GWL_WNDPROC, Longint(GOldWndProc));
    NotifyObserver(NO_EndSubClassed, LongInt(GHandle));
    GOldWndProc := nil;
    GHandle := 0;
  end;
end;

function WndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
var
  PID: DWORD;
begin
  with GHookRecPtr^ do
  begin
   // OutputDebugString(PChar(IntToStr(RObservedWindow)));
    if (RObservedWindow = 0) and (RWantProcessID > 0) then
    begin
      GetWindowThreadProcessId(Wnd, @PID);
      if PID <> RWantProcessID then
      begin
        Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
        UnSubClass {(Wnd)};
        Exit;
      end
      else
      begin
        //if (RObservedWindow = 0) Then
        RObservedWindow := Wnd;
        // else RObservedWindow2 := Wnd
        //NotifyObserver(NO_ProcessIDFound, LongInt(Wnd));
      end;
    end;

    case Msg of
      WM_NULL:
        if (WParam = $15) and (LParam = $15) then
        begin
          UnSubClass;     
          Result := 0;
          Exit;
        end;
      WM_SYSCOMMAND:
      Begin
        if (WParam = SC_CLOSE) or (WParam = 61539) then
        begin
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;    
        end else
        If (WParam = SC_MINIMIZE) Then
        Begin
        //  PostMessage(GHookRecPtr.RObserver, WM_HCBT_MINMAX, Wnd, lParam);
        End;
      End;
      WM_COMMAND:
        if (WParam = 40993) or (WParam = 106529) then
        begin
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;
        end;
    end;    
    Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
  end;
end;

procedure SubClass(Handle: Hwnd);
begin
  GHandle := Handle;
  GOldWndProc := Pointer(GetWindowLong(Handle, GWL_WNDPROC));
  SetWindowLongW(Handle, GWL_WNDPROC, Longint(@WndProc));
  NotifyObserver(NO_BeginSubClassed, LongInt(Handle));
end;

procedure SetObserver(Handle: HWnd);
begin
  GHookRecPtr.RObserver := Handle;
end;

function GetClassNameWnd(Wnd: HWND): string;
begin
  SetLength(Result, 80);
  SetLength(Result, GetClassName(Wnd, PChar(Result), Length(Result)));
end;

function HookProc(Code: Integer; WParam, LParam: Longint): Longint;
  stdcall;
var
  ExStyle: LongInt;
begin
  if (Code = HCBT_CREATEWND) and (GHookRecPtr.RObservedWindow = 0) Then
  //((GHookRecPtr.RObservedWindow = 0) or (GHookRecPtr.RObservedWindow2 = 0)) then
  begin
    ExStyle := GetWindowLong(WParam, GWL_EXSTYLE);
    if (ExStyle = 256) and (CompareText(GetClassNameWnd(WParam), 'ieframe') = 0)
      then
      begin
        SubClass(WParam);
//        OutputDebugString(PChar(IntToSTr(WParam)));
      End;
  end;
  Result := CallNextHookEx(GHookRecPtr.RHookID, Code, WParam, LParam)
end;

procedure SetWantProcessID(AProcessID: DWORD);
begin
  GHookRecPtr.RWantProcessID := AProcessID;
end;

procedure SetHook;
begin
  with GHookRecPtr^ do
  begin
    RWantProcessID := 0;
    RObservedWindow := 0;
    RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
  end;
end;

procedure UnSetHook;
begin
  UnHookWindowsHookEx(GHookRecPtr.RHookID);
end;

function getProcessID : Integer;
Begin
  Result := GHookRecPtr^.RWantProcessID;
End;

function getHandle : THandle;
Begin
  Result := GHookRecPtr^.RObservedWindow;
End;

exports
  SetHook,
  UnSetHook,
  SetObserver,
  getHandle,
  getProcessID,
  SetWantProcessID;

procedure EntryPointProc(Reason: Integer);
begin
  case reason of
    DLL_PROCESS_ATTACH:
      begin
        GMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
          SizeOf(THookRec), 'CaptureDesktopEvents');
        GHookRecPtr := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        NotifyObserver(NO_StartProcess, 0);
      end;
    DLL_PROCESS_DETACH:
      begin
        UnSubClass;
        NotifyObserver(NO_EndProcess, 0);
        try
          if GHookRecPtr <> nil then
            UnMapViewOfFile(GHookRecPtr);
          if GMapObject <> 0 then
            CloseHandle(GMapObject);
        except
        end;
      end;
  end;
end;

begin
  DllProc := @EntryPointProc;
  EntryPointProc(DLL_PROCESS_ATTACH);
end.

[ Voor 90% gewijzigd door Guillome op 09-12-2003 23:22 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Weet je zeker dat het hooken mis gaat? of gaat het hooken wel goed maar 'de rest' niet?

In Platform SDK staat bij CBTProc :
[in] Specifies a code that the hook procedure uses to determine how to process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx.
Ik jouw code zie ik niet dat je checked op nCode < 0 en dat onmiddelijk CallNextHookEx aan roept. Ik weet niet wat de consequentie is van het altijd (zoals jij doet) aanroepen van CallNextHookEx maar je zou kunnen kijken of dat wat uit maakt. Het is ook aan te raden om DisableThreadLibraryCalls(HInstance) in je dll entry proc te zetten vanwege een bug in Delphi.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Als ik er dit van maak:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function HookProc(Code: Integer; WParam, LParam: Longint): Longint;
  stdcall;
var
  ExStyle: LongInt;
begin
  if (Code = HCBT_CREATEWND) and (GHookRecPtr.RObservedWindow = 0) Then
  //((GHookRecPtr.RObservedWindow = 0) or (GHookRecPtr.RObservedWindow2 = 0)) then
  begin
    ExStyle := GetWindowLong(WParam, GWL_EXSTYLE);
    if (ExStyle = 256) and (CompareText(GetClassNameWnd(WParam), 'ieframe') = 0)
      then
      begin
        SubClass(WParam);
//        OutputDebugString(PChar(IntToSTr(WParam)));
      End;
  end;
  if (code < 0) then Result := CallNextHookEx(GHookRecPtr.RHookID, Code, WParam, LParam)
end;

Dan hangt de computer helemaal.

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Zowiezo moet Result := 0 als code >= 0. Zou kunnen dat ie nu willekeurige data returned (weet niet of dat de oorzaak is van het hangen)
The value returned by the hook procedure determines whether the system allows or prevents one of these operations. For operations corresponding to the following CBT hook codes, the return value must be 0 to allow the operation, or 1 to prevent it:

HCBT_ACTIVATE
HCBT_CREATEWND
HCBT_DESTROYWND
HCBT_MINMAX
HCBT_MOVESIZE
HCBT_SETFOCUS
HCBT_SYSCOMMAND

[ Voor 60% gewijzigd door martijn_brinkers op 11-12-2003 14:48 ]


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ik ben al een heel stuk verder, gelukkig :D

Alleen nu is er iets anders vaags. Ik laat eerst de code even zien:

code:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
library Capture;
uses
  Windows,
  CommCtrl,
  Messages,
  SysUtils;

{$R *.RES}

type
  PHookRec = ^THookRec;
  THookRec = record
    RObserver: THandle;
    RObservedWindow: THandle;   
    RHookID: HHOOK;
    WHandle: HWND;
    RWantProcessID: DWORD;
  end;

const
  CM_NotifyObserver = WM_USER + 1;
  CM_NotifyObserverMsg = WM_USER + 2;
  WM_HCBT_MINMAX = WM_USER + 285;

  NO_BeginSubClassed = 0;
  NO_EndSubClassed = 1;
  NO_ProcessIDFound = 2;
  NO_ClosePrevented = 3;
  NO_StartProcess = 4;
  NO_EndProcess = 5;
  TotalInstances = 3;

var
  { Alle instanties van de dll die geinjecteerd worden in een window
    krijgen eigen instanties van de volgende vars: }

  { Pointer naar de data die alle dll instanties delen }
  GHookRecPtr: array[0..3] of PHookRec;
  { Handle naar de filemapping object }
  GMapObject: THandle = 0;
  { Pointer naar oude wndproc }
  GOldWndProc: Pointer = nil;
  { Handle naar Window die gesubclassed is }
  GHandle: THandle = 0;
  { Laatst gebruikte Instance }
  LastUsed : Integer;

procedure NotifyObserver(Msg, SubMsg: Integer);
begin
  PostMessage(GHookRecPtr[LastUsed].RObserver, CM_NotifyObserver, Msg, SubMsg);
end;

procedure UnSubClass {(Handle: HWnd)};
begin
  if (GOldWndProc <> nil) and (GHandle > 0) then
  begin
    SetWindowLongW(GHandle, GWL_WNDPROC, Longint(GOldWndProc));
    NotifyObserver(NO_EndSubClassed, LongInt(GHandle));
    GOldWndProc := nil;
    GHandle := 0;
  end;
end;

function getLastUsed : Integer;
Begin
  Result := LastUsed;
End;

function WndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
var
  ID, PID: DWORD;
begin
  For ID := 0 to TotalInstances do
  Begin
    If GHookRecPtr[ID].WHandle = Wnd Then
    Begin
      LastUsed := ID;
      Break;
    End;
  End;
  with GHookRecPtr[LastUsed]^ do
  begin
    OutputDebugString(PChar(IntToStr(LastUsed)));
    if (RObservedWindow = 0) and (RWantProcessID > 0) then
    begin
      GetWindowThreadProcessId(Wnd, @PID);
      if PID <> RWantProcessID then
      begin
        Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
        UnSubClass {(Wnd)};
        Exit;
      end
      else
      begin
        RObservedWindow := Wnd;
        NotifyObserver(NO_ProcessIDFound, LongInt(Wnd));
      end;
    end;   
    
    //OutputDebugString(PChar(IntToStr(LastUsed)));
    case Msg of
      WM_NULL:
        if (WParam = $15) and (LParam = $15) then
        begin
          UnSubClass;     
          Result := 0;
          Exit;
        end;
      WM_SYSCOMMAND:
      Begin
        if (WParam = SC_CLOSE) or (WParam = 61539) then
        begin
          //OutputDebugString(PChar(IntToStr(LastUsed)));
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;    
        end else
        If (WParam = SC_MINIMIZE) Then
        Begin
        //  PostMessage(GHookRecPtr.RObserver, WM_HCBT_MINMAX, Wnd, lParam);
        End;
      End;
      WM_COMMAND:
        if (WParam = 40993) or (WParam = 106529) then
        begin
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;
        end;
    end;    
    Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
  end;
end;

procedure SubClass(Handle: Hwnd);
begin
  GHandle := Handle;
  GOldWndProc := Pointer(GetWindowLong(Handle, GWL_WNDPROC));
  SetWindowLongW(Handle, GWL_WNDPROC, Longint(@WndProc));
  NotifyObserver(NO_BeginSubClassed, LongInt(Handle));
end;

procedure SetObserver(Handle: HWnd);
begin
  GHookRecPtr[LastUsed].RObserver := Handle;
end;

function GetClassNameWnd(Wnd: HWND): string;
begin
  SetLength(Result, 80);
  SetLength(Result, GetClassName(Wnd, PChar(Result), Length(Result)));
end;

function HookProc(Code: Integer; WParam, LParam: Longint): Longint;
  stdcall;
var
  ExStyle: LongInt;
begin
  if (Code = HCBT_CREATEWND) and (GHookRecPtr[LastUsed].RObservedWindow = 0) Then
  begin
    ExStyle := GetWindowLong(WParam, GWL_EXSTYLE);
    if (ExStyle = 256) and (CompareText(GetClassNameWnd(WParam), 'ieframe') = 0)
      then
      begin
        SubClass(WParam);
        GHookRecPtr[LastUsed].WHandle := WParam;
      End;
  end;
  if (code <= 0) then Result := CallNextHookEx(GHookRecPtr[LastUsed].RHookID, Code, WParam, LParam) else result := 0;
end;

procedure SetWantProcessID(ID: Integer; AProcessID: DWORD);
begin
  GHookRecPtr[ID].RWantProcessID := AProcessID;
end;

procedure SetHook;
Var ID : Integer;
begin
  for ID := 0 to TotalInstances do
  Begin
    if GHookRecPtr[ID].RHookID = 0 Then
    Begin
      LastUsed := ID;
      break;
    End;
  End;
  with GHookRecPtr[LastUsed]^ do
  begin
    RWantProcessID := 0;
    RObservedWindow := 0;
    RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
  end;
end;

procedure UnSetHook;
begin
  UnHookWindowsHookEx(GHookRecPtr[LastUsed].RHookID);
end;

function getProcessID : Integer;
Begin
  Result := GHookRecPtr[LastUsed]^.RWantProcessID;
End;

function getHandle(ID: Integer) : THandle;
Begin
  Result := GHookRecPtr[ID]^.RObservedWindow;
End;

exports
  SetHook,
  UnSetHook,
  SetObserver,
  getHandle,
  getLastUsed,
  getProcessID,
  SetWantProcessID;

procedure EntryPointProc(Reason: Integer);
begin
  case reason of
    DLL_PROCESS_ATTACH:
      begin
        GMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
          SizeOf(THookRec), 'CaptureDesktopEvents');
        GHookRecPtr[0] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        GHookRecPtr[1] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0); 
        GHookRecPtr[2] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        GHookRecPtr[3] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        NotifyObserver(NO_StartProcess, 0);
      end;
    DLL_PROCESS_DETACH:
      begin
        UnSubClass;
        NotifyObserver(NO_EndProcess, 0);
        try
          if GHookRecPtr[0] <> nil then
            UnMapViewOfFile(GHookRecPtr[0]);
          if GHookRecPtr[1] <> nil then
            UnMapViewOfFile(GHookRecPtr[1]);  
          if GHookRecPtr[2] <> nil then
            UnMapViewOfFile(GHookRecPtr[2]);
          if GHookRecPtr[3] <> nil then
            UnMapViewOfFile(GHookRecPtr[3]);
          if GMapObject <> 0 then
            CloseHandle(GMapObject);
        except
        end;
      end;
  end;
end;

begin
  DllProc := @EntryPointProc;
  EntryPointProc(DLL_PROCESS_ATTACH);
  DisableThreadLibraryCalls(HInstance);
end.


Je zit dat ik nu de GHookRecPtr in een array heb staan, dus kunnen er meerdere instances worden geobserveerd. Opzich wil dit al goed maar...

In de functie SetHook:
RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
Bij deze regel, regel 192, zet hij niet alleen de RHookID van de
with GHookRecPtr[LastUsed]^ do
Op de resultwaarde, maar van alle array-items zet hij de HookID op die waarde. Waardoor het allemaal fout gaat.
Hoe kan dat?? Dat hij meteen alles veranderd?

Ik heb dus GHookRecPtr[0] tm GHookRecPtr[3] maar hij past meteen alle RHookID`s aan.

Ook als ik dit heb:
GHookRecPtr[0].RHookID := 10;
wordt GHookRecPtr[1].RHookID ook 10, en 2 en 3 ook

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Dat komt omdat je MapViewOfFile met dezelfde GMapObject handle gebruikt. Logisch dat GHookRecPtr[0], GHookRecPtr[1] en GHookRecPtr[3] dan naar exact dezelfde record verwijzen. Je zou verschillende File mappings kunnen maken ( dus 3 keer CreateFileMapping ) maar mooier is het om THookRec aan te passen dat ie arrays gaat bevatten. Dan hoef je maar een keer CreateFileMapping en MapViewOfFile aan te roepen.

code:
1
2
3
4
5
6
        GMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
          SizeOf(THookRec), 'CaptureDesktopEvents');
        GHookRecPtr[0] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        GHookRecPtr[1] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0); 
        GHookRecPtr[2] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        GHookRecPtr[3] := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);


even uit de losse pols (dus niet getest)


code:
1
2
3
4
5
6
7
8
9
10
  TPartHookRec = record
    RObserver: THandle;
    RObservedWindow: THandle;   
    RHookID: HHOOK;
    RWantProcessID: DWORD;
  end;

  THookRec = record
    Hooks : array[0..2] of TPartHookRec
  end;

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Heej dat was een hele goeie tip :)
Maar still met probleempjes :)
Ik heb het nu zo aangepast dus:
code:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
library Capture;
uses
  Windows,
  CommCtrl,
  Messages,
  SysUtils;

{$R *.RES}

type
  PHookRec = ^THookRec;
  TPartHookRec = record
    RObserver: THandle;
    RObservedWindow: THandle;
    RHookID: HHOOK;
    WHandle: HWND;
    RWantProcessID: DWORD;
  end;
  THookRec = record
    Hooks : Array[0..1] of TPartHookRec;
  end;

const
  CM_NotifyObserver = WM_USER + 1;
  CM_NotifyObserverMsg = WM_USER + 2;
  WM_HCBT_MINMAX = WM_USER + 285;

  NO_BeginSubClassed = 0;
  NO_EndSubClassed = 1;
  NO_ProcessIDFound = 2;
  NO_ClosePrevented = 3;
  NO_StartProcess = 4;
  NO_EndProcess = 5;
  TotalInstances = 2;

var
  { Alle instanties van de dll die geinjecteerd worden in een window
    krijgen eigen instanties van de volgende vars: }

  { Pointer naar de data die alle dll instanties delen }
  GHookRecPtr: PHookRec;
  { Handle naar de filemapping object }
  GMapObject: THandle = 0;
  { Pointer naar oude wndproc }
  GOldWndProc: Pointer = nil;
  { Handle naar Window die gesubclassed is }
  GHandle: THandle = 0;
  { Laatst gebruikte Instance }
  LastUsed : Integer;

procedure NotifyObserver(Msg, SubMsg: Integer);
begin
  PostMessage(GHookRecPtr.Hooks[0].RObserver, CM_NotifyObserver, Msg, SubMsg);
end;

procedure UnSubClass {(Handle: HWnd)};
begin
  if (GOldWndProc <> nil) and (GHandle > 0) then
  begin
    SetWindowLongW(GHandle, GWL_WNDPROC, Longint(GOldWndProc));
    NotifyObserver(NO_EndSubClassed, LongInt(GHandle));
    GOldWndProc := nil;
    GHandle := 0;
  end;
end;

function getLastUsed : Integer;
Begin
  Result := LastUsed;
End;    
         
Function getSetLastUsed(Wnd: HWND): Word;
Var ID: Word;
Begin
  For ID := 0 to TotalInstances - 1 do
  Begin
    If GHookRecPtr.Hooks[ID].WHandle = Wnd Then
    Begin
      Result := ID;
//      OutputDebugString(PChar('SET LastUsed to: ' + IntToStr(ID)));
      Break;
    End;
  End;
End;

function WndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
var
  PID: DWORD;
  LocalLastUsed: Word;
begin
  LocalLastUsed := getSetLastUsed(Wnd);
  with GHookRecPtr^.Hooks[LocalLastUsed] do
  begin
    //OutputDebugString(PChar(IntToStr(LastUsed)));
    if (RObservedWindow = 0) and (RWantProcessID > 0) then
    begin
      GetWindowThreadProcessId(Wnd, @PID);
      if PID <> RWantProcessID then
      begin
        Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
        UnSubClass {(Wnd)};
        Exit;
      end
      else
      begin
        RObservedWindow := Wnd;
        NotifyObserver(NO_ProcessIDFound, LongInt(Wnd));
      end;
    end;   
    
    //OutputDebugString(PChar(IntToStr(LastUsed)));
    case Msg of
      WM_NULL:
        if (WParam = $15) and (LParam = $15) then
        begin
          UnSubClass;     
          Result := 0;
          Exit;
        end;
      WM_SYSCOMMAND:
      Begin
        if (WParam = SC_CLOSE) or (WParam = 61539) then
        begin
          //OutputDebugString(PChar(IntToStr(LastUsed)));
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;    
        end else
        If (WParam = SC_MINIMIZE) Then
        Begin
        //  PostMessage(GHookRecPtr.RObserver, WM_HCBT_MINMAX, Wnd, lParam);
        End;
      End;
      WM_COMMAND:
        if (WParam = 40993) or (WParam = 106529) then
        begin
          NotifyObserver(NO_ClosePrevented, LongInt(Msg));
          Result := 0;  
          Exit;
        end;
    end;    
    Result := CallWindowProcW(GOldWndProc, Wnd, Msg, WParam, LParam);
  end;
end;

procedure SubClass(Handle: Hwnd);
begin     
  GHandle := Handle;
  GOldWndProc := Pointer(GetWindowLong(Handle, GWL_WNDPROC));
  SetWindowLongW(Handle, GWL_WNDPROC, Longint(@WndProc));
  NotifyObserver(NO_BeginSubClassed, LongInt(Handle));
end;

procedure SetObserver(Handle: HWnd);
begin
  GHookRecPtr.Hooks[LastUsed].RObserver := Handle;
end;

function GetClassNameWnd(Wnd: HWND): string;
begin
  SetLength(Result, 80);
  SetLength(Result, GetClassName(Wnd, PChar(Result), Length(Result)));
end;

function HookProc(Code: Integer; WParam, LParam: Longint): Longint;
  stdcall;
var
  ExStyle: LongInt;
Begin
  OutputDebugString(PChar(IntToStr(LastUsed) + ' - ' + 
    IntToStr(GHookRecPtr.Hooks[LastUsed].RObservedWindow) + ' - ' + 
   IntToStr(Code)));
  if (Code = HCBT_CREATEWND) and (GHookRecPtr.Hooks[LastUsed].RObservedWindow = 0) Then
  begin
    ExStyle := GetWindowLong(WParam, GWL_EXSTYLE);
    if (ExStyle = 256) and (CompareText(GetClassNameWnd(WParam), 'ieframe') = 0) then
    begin
      SubClass(WParam);
      GHookRecPtr.Hooks[LastUsed].WHandle := WParam;
      Result := 0;
      Exit;
//      OutputDebugString(PChar(IntToStr(GHookRecPtr.Hooks[LastUsed].WHandle)));
    End;
  end;
  if (code <= 0) then 
    Result := CallNextHookEx(GHookRecPtr.Hooks[LastUsed].RHookID, Code, WParam, LParam) 
      else result := 0;
end;

procedure SetHook;
Var ID : Integer;
begin
  for ID := 0 to TotalInstances do
  Begin
    if GHookRecPtr.Hooks[ID].RHookID = 0 Then
    Begin
      LastUsed := ID;
      break;
    End;
  End;
  with GHookRecPtr^.Hooks[LastUsed] do
  begin
    OutputDebugString(PChar('SetHook: ' + IntToStr(LastUsed)));
    RWantProcessID := 0;
    RObservedWindow := 0;
    RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
  End;
end;    

procedure SetWantProcessID(ID: Integer; AProcessID: DWORD);
begin
  GHookRecPtr.Hooks[ID].RWantProcessID := AProcessID;
end;

procedure UnSetHook;
begin
  UnHookWindowsHookEx(GHookRecPtr.Hooks[LastUsed].RHookID);
end;

function getProcessID : Integer;
Begin
  Result := GHookRecPtr^.Hooks[LastUsed].RWantProcessID;
End;

function getHandle(ID: Integer) : THandle;
Begin
  Result := GHookRecPtr^.Hooks[ID].RObservedWindow;
End;

exports
  SetHook,
  UnSetHook,
  SetObserver,
  getHandle,
  getLastUsed,
  getProcessID,
  SetWantProcessID;

procedure EntryPointProc(Reason: Integer);
begin
  case reason of
    DLL_PROCESS_ATTACH:
      begin
        GMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
          SizeOf(THookRec), 'CaptureDesktopEvents');
        GHookRecPtr := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        NotifyObserver(NO_StartProcess, 0);
      end;
    DLL_PROCESS_DETACH:
      begin
        UnSubClass;
        NotifyObserver(NO_EndProcess, 0);
        try
          if GHookRecPtr <> nil then
            UnMapViewOfFile(GHookRecPtr);
          if GMapObject <> 0 then
            CloseHandle(GMapObject);
        except
        end;
      end;
  end;
end;

begin
  DllProc := @EntryPointProc;
  EntryPointProc(DLL_PROCESS_ATTACH);
  DisableThreadLibraryCalls(HInstance);
end.


Ik heb de functie getSetLastUsed die de variabele lastUsed op de waarde zet die hij moet hebben.
Dat doet hij aan de hand van de window handle, die ook opgeslagen zit in het Hook record. Op die manier gebruikt hij het goede array element.
Maar hij doet iets niet goed.
Als ik kijk met OutPutDebugString dan blijft hij lastUsed op 0 zetten als de 'code' in de HookProc 3 is (Code = HCBT_CREATEWND).
Dus dan wordt hij niet nog een keer gehooked. Heel raar, maar hij blijft die lastUsed op 0 zetten. Als hij wel op 1 wordt gezet is dus de Code <> HVBT_CREATEWND, dus wordt hij ook niet gehooked. Ik hoop dat jullie het snappen. Hier een screenshot:

logfile
De waardes zijn: lastUsed - GHookRecPtr.Hooks[LastUsed].RObservedWindow) - IntToStr(Code)));
op regel 170 - 172

Daar ze je (op regel 2) dat die goed is: 0 - 0 - 3 (lastUsed op 0, ObservedWindow op 0 en Code = 3)
Maar vanaf SetHook: 1 gaat het mis. Daar zou het 1 - 0 - 3 moeten zijn, maar omdat hij daar lastUsed op 0 heeft staan, krijgt hij ook de verkeerde ObservedWindow, maar ik krijg de lastUsed dan dus niet goed.
Terwijl hij in setHook zeker wel op 1 wordt gezet. Je ziet ook dat hij verderop wel op 1 komt te staan.
Ik weet dat die 2 procedures (Hookproc en winproc) constant doorlopen, maar als de 2e window gemaakt wordt, dan moet hij toch zien dat hij het 2e record van het array moet pakken omdat daar de windowhandle het zelfde is? (getSetLastUsed)

[ Voor 19% gewijzigd door Guillome op 13-12-2003 14:35 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
-

[ Voor 100% gewijzigd door Guillome op 13-12-2003 14:35 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ik denk dat het komt omdat de HookProc de variable LastUsed niet elke keer opnieuw uitleest, maar cached oid. Kan dat? En zo ja, hoe kan ik dat aanpassen?
Op de een of andere manier wordt de variabele te laat op 1 gezet. Komt dat omdat deze hook door blijft gaan met zijn 1e aanroep zeg maar?[/quote]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Ik heb niet uitgebreid naar je prog gekeken dus ik weet niet wat er mis is. Het is wel zo dat LastUsed voor elke dll instantie (dus voor elk prog waar de dll is geinjecteerd) een eigen geheugen locatie gebruikt. Maw de LastUsed var is niet ge-shared. Ik weet ook niet of dat jouw bedoeling is maar zo ja dan zou dat de verklaring kunnen zijn dat hij niet veranderd.

een ander mogelijk probleem (hoewel dat in jouw geval niet op treedt) is

code:
1
RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);


Als SetWindowsHookEx failed dat returned hij 0. Je controleerd daar niet op. Sterker, je gebruikt dat later om te zien of die ID al in gebruik is

code:
1
if GHookRecPtr.Hooks[ID].RHookID = 0 Then


Als nou SetWindowsHookEx 0 returned dan blijft hij zeg maar altijd dezlfde ID gebruiken en zal nooit 'verder' komen

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Dank je wel :)
Hoe kan ik dan die variable geshared maken?

En over je 2e punt:
Ik controleer dat hiermee toch?

code:
1
2
3
if (code <= 0) then 
    Result := CallNextHookEx(GHookRecPtr.Hooks[LastUsed].RHookID, Code, WParam, LParam) 
      else result := 0;


En moet ik ipv
code:
1
if GHookRecPtr.Hooks[ID].RHookID = 0 Then

Dit gebruiken?
code:
1
if GHookRecPtr.Hooks[ID].RObservedWindow = 0 Then

Of iets dergelijks?

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Hoe kan ik dan die variable geshared maken?
Door hem een member te maken van THookRec. Doordat je gebruik maakt van een memory mapped file is de instantie van THookRec geshared tussen applicaties. Ik weet dus niet of dat jouw bedoeling is omdat je hem nl expliciet niet in THookRec had gezet.

code:
1
2
3
4
 THookRec = record
    Hooks : Array[0..1] of TPartHookRec;
    LastUsed : Integer;
  end;


Nu is LastUsed een member van THookRec en zal elke applicatie die jouw dll geinjecteerd heeft gekregen dezelfde waarde gebruiken. Waar je wel op moet letten is dat omdat je een shared memory blok gebruikt je problemen gaat krijgen met multiple threads. Je hoort dus eigenlijk de access naar het shared memory te 'beveiligen' met een Mutex.
En over je 2e punt:
Ik controleer dat hiermee toch?
Wat ik bedoel is het volgende. In onderstaande code (uit SetHook) kijk je niet of SetWindowsHookEx 0 returned. 0 betekend dat het mis is gegaan.

code:
1
2
3
4
5
6
7
  with GHookRecPtr^.Hooks[LastUsed] do
  begin
    OutputDebugString(PChar('SetHook: ' + IntToStr(LastUsed)));
    RWantProcessID := 0;
    RObservedWindow := 0;
    RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);
  End;


echter in dezelfe routine ( SetHook) doe je

code:
1
2
3
4
5
6
7
8
  for ID := 0 to TotalInstances do
  Begin
    if GHookRecPtr.Hooks[ID].RHookID = 0 Then
    Begin
      LastUsed := ID;
      break;
    End;
  End;


Je kijkt dus of er 0 in staat. Zo ja dan gebruik je hem. Echter als SetWindowsHookEx mis gaat is het altijd 0. Op zich hoeft dat niet erg te zijn want hij blijft dan steeds dezelde gebruiken. Het is echter beter om te controleren of SetWindowsHookEx 0 returned zodat je weet dat er wat mis gaat. Wat ik al zei is dat het niet verkeerd is wat je doet. Het is alleen handiger om te zien dat SetWindowsHookEx fout gaat.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Echt zo ontzettend bedankt TijnFLip, en alle anderen die geholpen hebben uiteraard!!!
Hij werkt nu prima :)
Inderdaad door LastUsed in de GHookRecPtr te zetten. Nu wertk hij prima.

Maar aangezien ik niet veel thuis ben (was ;)) in dll`s en geheugen-perikkelen snap ik dit ook nog niet:
Waar je wel op moet letten is dat omdat je een shared memory blok gebruikt je problemen gaat krijgen met multiple threads. Je hoort dus eigenlijk de access naar het shared memory te 'beveiligen' met een Mutex.
Wat voor soort problemen? Wanneer heb ik multiple threads? En wat is een mutex?

Echt enorm bedantk alvast!!! Superb!

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Omdat je mbv een memorymapped file geheugen shared tussen verschillende processen (en dus verschillende threads) moet je zorgen dat er geen 'gekke' dingen gebeuren als meerdere threads tegelijkertijd je shared geheugen gaan aanspreken. Mbv een mutex kan je ervoor zorgen dat er maar een thread tegelijkertijd iets kan uitvoeren (een criticalsection is iets vergelijkbaars echter is deze niet shared tussen applicaties en dus niet bruikbaar in jouw geval). Het gaat iets te ver om hier de ins-and-outs van multithreading uit te leggen dus moet je maar even zoeken op het net.

intro threads en Delphi (aanrader)

http://www.pergolesi.demon.co.uk/prog/threads/ToC.html

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Die site ga ik zeker doornemen, erg bedankt voor al je hulp! :)
Nu nog 1 klein vraagje, maar ik zie zelf de oplossing niet.

Ik heb nu ook een scherm gemaakt waarin je alle geopende internet explorer vensters ziet, met de windowhandle. (dus niet alleen de door-mijn-app-geopende-ievensters, maar ook die al open waren etc)
En nu wil ik dat ik zo`n al-geopende-Internet explorere kan laten 'observeren' door mijn programma. Maar ik zie niet echt hoe de dll de net-geopende (door mijn prog) IE pakt.
Is het de HInstance in
code:
1
RHookID := SetWindowsHookEx(WH_CBT, @HookProc, HInstance, 0);

in setHook die het hem doet? En dat dat dus niet kan met een IE die door de gebruiker zelf gestart is?

[ Voor 30% gewijzigd door Guillome op 14-12-2003 23:24 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Het komt omdat GetWindowLong niet werkt. Dat kan ik niet met een buitenstaand window doen, wel met een door-dit-programma-gestartte-IE. De windowhanlde klopt wel (showwindows, getwindowText werkt wel), maar ik krijg 0 terug bij
code:
1
GetWindowLong(hWnd, GWL_WNDPROC)


Hoe kan dat? Geen enkele GetWindow___ (functie werkt (getwindowlong, getwindowstyle etc)
Hoe kan dat? GetLastError geeft 5. Ik kan daar de betekenis niet van vinden, omdat er in windows.pas alleen foutnummers van 1400 tot 1420 ofzo staan.
Ik had eerst 1400, en dat is het verkeerde windowhandle, en dat klopte wel. Maar nu die goed is gezet geeft hij 5, en doet het nog steeds niet.
Mijn IE-list code:
code:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
unit IEList;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ImgList, ExtCtrls;

type
  TfIEList = class(TForm)
    Button1: TButton;
    IExplorers: TListView;
    ImageList1: TImageList;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure getList;
    procedure IExplorersDblClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fIEList: TfIEList;

implementation

uses capture2;

{$R *.DFM}

procedure SubClass(Handle: Hwnd); external 'Capture.dll';
procedure SetHook; external 'Capture.dll';
procedure makeObserverable(ProcessId: Integer; Handle: HWND); external 'Capture.dll';

Function EnumWindProc(hWnd: Thandle; lParam: LPARAM): BOOL; stdcall;

  function ItemExists(hWnd: Integer): Boolean;
  var Item : TListItem;
  Begin
    Result := false;
    Item := fIEList.IExplorers.Items[0];
    While Item <> nil do
    Begin
      If Item.SubItems[0] = IntToStr(hWnd) Then
      Begin
        Result := True;
        Exit;
      End;
      Item := fIEList.IExplorers.GetNextItem(Item, sdAll, [isNone]);
    End;
  End;

var s: array[byte] of Char;
    s2: string;
    Item: TListItem; 
    ProcessId: Integer;
begin
  GetWindowText(hWnd, @s, 255);
  s2 := s;
  If (pos(' - Microsoft Internet Explorer', s2) > 0) and (not ItemExists(hWnd)) Then
  Begin
    Item := fIEList.IExplorers.Items.Add();
    SetLength(s2, Length(s2) - 30);
    Item.Caption := s2;
    Item.SubItems.Add(IntToStr(hWnd));
    GetWindowThreadProcessId(hWnd, @ProcessId);
    Item.SubItems.Add(IntToStr(ProcessId));
  End;
  Result := True;
end;

Procedure TfIEList.getList;
var Item : TListItem;
    ItemIndex: Word;
    s: array[byte] of Char;
    s2: string;
    ProcessId: Integer;
Begin
  Item := fIEList.IExplorers.Items[0];
  While Item <> nil do
  Begin
    ProcessId := GetWindowThreadProcessId(StrToInt(Item.SubItems[0]), nil);
    If (ProcessId = 0) Then
    Begin
      ItemIndex := Item.Index;
      Item.Delete;
      Item := fIEList.IExplorers.Items[ItemIndex];
    End else
    Begin
      GetWindowText(StrToInt(Item.SubItems[0]), @s, 255);
      s2 := s;
      SetLength(s2, Length(s2) - 30);
      If (Item.Caption <> s2) then Item.Caption := s2;
    End;
    Item := fIEList.IExplorers.GetNextItem(Item, sdAll, [isNone]);
  End;
  EnumWindows(@EnumWindProc, 0);
End;

procedure TfIEList.Timer1Timer(Sender: TObject);
begin
  getList;
end;

procedure TfIEList.FormCreate(Sender: TObject);
begin
  getList;
end;

procedure TfIEList.IExplorersDblClick(Sender: TObject);
Var Style: Integer;
begin
  If IExplorers.Selected = nil Then Exit;
  //ShowMessage(IntToStr(GetWindowLong(StrToInt(IExplorers.Selected.SubItems[0]), GWL_STYLE)));
  Style := GetWindowLong(StrToInt(IExplorers.Selected.SubItems[0]), GWL_STYLE);
  If (Style = 114229248) or (Style = 919535616) or (Style = 651100160) Then
    ShowWindow(StrToInt(IExplorers.Selected.SubItems[0]), SW_SHOWNORMAL or SW_RESTORE);
  SetForegroundWindow(StrToInt(IExplorers.Selected.SubItems[0]));
end;

procedure TfIEList.Button1Click(Sender: TObject);
var wHandle: Integer;
    s: array[byte] of char;
begin
  wHandle := StrToInt(IExplorers.Selected.SubItems[0]);
  GetWindowText(wHandle, @s, 255);
  ShowMessage(IntToStr(GetWindowLong(FindWindow('ieframe', nil), GWL_WNDPROC)));
  ShowMessage(IntToStr(GetWindowLong(wHandle, GWL_WNDPROC)));
  makeObserverable(StrToInt(IExplorers.Selected.SubItems[1]), StrToInt(IExplorers.Selected.SubItems[0]));
end;

end.


Wat zie ik over het hoofd?
Hier de files incl .exe:
http://xlerator.beefhole.nl/webstuff/hooking.rar

[ Voor 8% gewijzigd door Guillome op 15-12-2003 00:52 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
volgens mij werkt GetWindowLong niet tussen processen. Dwz dat je niet vanuit een ander proces mbv de window handle GetWindowLong kan aanroepen.

  • Jester
  • Registratie: September 2000
  • Laatst online: 05:28
Ik wil deze ook in de gaten houden! (ben met soortgelijk probleem bezig)

- hardware always changes.. -


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Dus is het niet mogelijk de getWindowLong van een ander window te krijgen?
En dus de wndProc?

Blah
Ik zie dat het wel zou moeten kunnen met CreateRemoteThread, maar ik snap nix van hoe ik een functie in die thread kan zetten.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TfIEList.Button1Click(Sender: TObject);
var wHandle, pId: Integer;
    InitDataAddr, WriteAddr: Pointer;
    TheadID: DWord;
//    s: array[byte] of char;
begin
  wHandle := StrToInt(IExplorers.Selected.SubItems[0]);
  pId := StrToInt(IExplorers.Selected.SubItems[1]);
  OpenProcess(PROCESS_CREATE_THREAD, false, pId);
  CreateRemoteThread(pId, nil, 0, WriteAddr, InitDataAddr, 0, TheadID);
//  SendMessage(wHandle, WM_GETICON
//  GetWindowText(wHandle, @s, 255);
  //ShowMessage(IntToStr(GetWindowLong(FindWindow('ieframe', nil), GWL_WNDPROC)));
//  ShowMessage(IntToStr(GetWindowLong(wHandle, GWL_WNDPROC)));
  makeObserverable(StrToInt(IExplorers.Selected.SubItems[1]), StrToInt(IExplorers.Selected.SubItems[0]));
end;

Maar nu? Ik heb op google gezocht, op GoT en op Pascal gebruikers groep. Maar geen resultaat :S

edit2: en uiteraard de help

[ Voor 88% gewijzigd door Guillome op 15-12-2003 22:23 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Het probleem is volgens mij dat GetWindowLong(wHandle, GWL_WNDPROC) een adres terug geeft. Echter in jouw geval zou het dan moeten gaan om een adres in een ander proces. Dat gaat dus niet omdat het geheugen tussen processen gescheiden is. Je zou dus het subclassen moeten laten doen in de DLL en niet vanuit een extern programma. Je moet er dus voor zorgen dat als jouw dll in het process wordt geinjecteerd hij ook gelijk 'sub-classed'.

Een voorbeeld van CreateRemoteThread staat op:

http://www.codeproject.com/system/hooksys.asp

Nadeel is wel dat het alleen werkt onder WINNT, 2K (XP denk ik ook)

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Okeej, hoe moet ik nu verder? Ik heb dit, en dit gaat zonder foutmelding:
code:
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
procedure TfIEList.Button1Click(Sender: TObject);
var wHandle, pId: Integer;
    pfnLoadLibrary: Pointer;
    ThreadID, Tmp, dllModule: DWord;
    Process: THandle;
    dllpath: array[0..255] of Char;
begin
  wHandle := StrToInt(IExplorers.Selected.SubItems[0]);
  pId := StrToInt(IExplorers.Selected.SubItems[1]);
  dllpath := 'D:\\Data\\DELPHI\\testshellcatch3\\capture.dll';
  OpenProcess(PROCESS_ALL_ACCESS, false, pId);

  pfnLoadLibrary := VirtualAllocEx(pId, nil, sizeof(dllpath), MEM_COMMIT, PAGE_READWRITE);
  WriteProcessMemory(pId, pfnLoadLibrary, @dllpath, sizeof(dllpath), Tmp);
  Process := CreateRemoteThread(Process, nil, 0, GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryA'),
  pfnLoadLibrary, 0, ThreadID);
  WaitForSingleObject(Process, INFINITE);
  GetExitCodeThread(Process, dllModule);
  CloseHandle(Process);
  VirtualFreeEx(Process, pfnLoadLibrary, sizeof(dllpath), MEM_RELEASE);
//  SendMessage(wHandle, WM_GETICON
//  GetWindowText(wHandle, @s, 255);
  //ShowMessage(IntToStr(GetWindowLong(FindWindow('ieframe', nil), GWL_WNDPROC)));
 // ShowMessage(IntToStr(GetWindowLong(wHandle, GWL_WNDPROC)));
  ShowMessage(IntToStr(ThreadID));
  makeObserverable(StrToInt(IExplorers.Selected.SubItems[1]), StrToInt(IExplorers.Selected.SubItems[0]));
end;


Maar ik kan nergens vinden hoe ik nu een functie kan starten in de ge-attachte dll

[ Voor 156% gewijzigd door Guillome op 16-12-2003 17:13 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Is dit soms wat ik moet inbouwen bij mij?
Voordat ik uren ermee bezig ben lijkt het me handig om te vragen of dit is wat het doet. Het kwam van een duitse site :P
http://www.delphipraxis.net/topic13066,45.html
code:
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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;

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Kikker
Ik kom er zelf echt niet meer uit hoor :/
:)

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Een andere mogelijkheid zou kunnen zijn om gebruik te maken van madCodeHook. Dat is een een van de beste code-hook libraries die er is en is speciaal voor delphi. Voor niet commerciele toepassingen is hij gratis. Probeer het daar eens mee. Is erg goed en heel geavanceerd.

http://www.madshi.net

Nou kan het zijn dat je zelf alle code-hooking wil doen (ik weet niet precies wat je doel is) maar zoals je hebt ondervonden is dat vrij lastig. Als ik nog tijd heb zal ik nog even naar je probleem kijken hoewel het vrij lastige materie is en ik niet heel veel tijd heb (sterker ik ga dinsdag op vakantie :) )

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Nou veel plezier met je vakantie in ieder geval :D
En mijn doel? Ik wil dit programma werkend hebben omdat ik het zelf wil gebruiken, en ook op internet wil verspreiden als Freeware, net als HandyFTP (zie sig voor website) en RegRunner.
Ik ben zo`n iemand die al zijn code het liefst zelf maakt. Ik heb bijna alles wat ik gemaakt heb zelf geschreven. Maar zoals dit.... dit is voor mij op dit moment nog niet te doen, dus ik zal kijken naar die pagina. Heel erg bedankt alvast en ik hoop dat je me straks verder kan helpen :)
Maar eerst veel plezier dindsdag!

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ik heb nu dit, maar hoe moet ik nu een functie starten uit de geinjecteerde DLL?
Zo werkt hij nog steeds niet:
code:
1
2
3
4
5
6
7
8
9
10
procedure TfIEList.Button1Click(Sender: TObject);
var t: procedure;
begin
  If (IExplorers.Selected = nil) Then Exit;
  InjectLibrary(StrToInt(IExplorers.Selected.SubItems[1]), 'capture.dll', 7000);
  @t := GetProcAddress(GetModuleHandle('capture.dll'), 'makeObservable');
  t;
  //makeObservable(StrToInt(IExplorers.Selected.SubItems[1]), StrToInt(IExplorers.Selected.SubItems[0]));
  UninjectLibrary(StrToInt(IExplorers.Selected.SubItems[1]), 'capture.dll', 7000);
end;


dll:
code:
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
...
...
...
function makeObservable(pId, wHandle: Integer): Boolean;
Begin
  OutputDebugString(PChar('asd' + IntTostr(GetWindowLong(wHandle, GWL_WNDPROC))));
End;

exports
  makeObservable,
  ..,
  ..;

procedure EntryPointProc(Reason: Integer);
begin
  case reason of
    DLL_PROCESS_ATTACH:
      begin
        GMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
          SizeOf(THookRec), 'CaptureDesktopEvents');
        GHookRecPtr := MapViewOfFile(GMapObject, FILE_MAP_WRITE, 0, 0, 0);
        NotifyObserver(NO_StartProcess, 0);
      end;
    DLL_PROCESS_DETACH:
      begin
        UnSubClass;
        NotifyObserver(NO_EndProcess, 0);
        try
          if GHookRecPtr <> nil then
            UnMapViewOfFile(GHookRecPtr);
          if GMapObject <> 0 then
            CloseHandle(GMapObject);
        except
        end;
      end;
  end;
end;

begin
  DllProc := @EntryPointProc;
  EntryPointProc(DLL_PROCESS_ATTACH);
  DisableThreadLibraryCalls(HInstance);
end.

[ Voor 4% gewijzigd door Guillome op 22-12-2003 00:41 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Het probleem dat je moet oplossen is 'hoe doe ik de subclassing in de hook dll en niet in mn applicatie?'

Je moet nl subclassen in je hook dll omdat winproc adres etc. alleen maar valide is in het process dat je wil hooken. Nou zijn er verschillende manieren voor om dat voor elkaar te krijgen. Een daarvan is dat je de subclassing doet in je hookproc als je ziet dat je nog niet hebt gesubclassed (volgens mij doe je dat in je hook dll). Wat ik niet zo goed snap is wat je wil met makeObserverable. Daarin roep je nl weer SubClass aan. Het probleem hiermee is dat subclass dan wordt aangeroepen in de context van jouw applicatie en niet van IE. Je moet er dus op de een of andere manier voor zorgen dat je kan communiceren met de dll instanties die geinjecteerd zijn in de verschillende processen zodat je per dll kan 'vertellen' wat er moet gebeuren. Je moet onthouden dat het injecteren van een dll in een ander process ervoor zorgt dat er ook daadwerkelijk verschillende instanties zijn van de hook dll.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Het subclassen gebeurt al in mijn dll hoor.
Ik roep in mijn app "setHook" aan in de dll, en vanuit daar wordt er ge-setWindowHook-t, en gesubclassed.

Alleen als ik nu injectLibrary doe, dan wil die makeObservable nog niet.
Er staat nu alleen nog maar een regel getWindowLong in om te kijken of hij dat pakt. Zo ja, dan wil de rest ook wel. Maar hij blijft `m uitvoeren vanuit mijn eigen app, dus returnt getWindowLong altijd 0

Met MakeObservable wil ik een bestaande IE venster ook gesubclassed krijgen.

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Je moet er dus voor zorgen dat je makeObservable in de context van het gehookte process doet. Een mogelijke oplossing is de volgende. Je zou mbv RegisterWindowMessage een unique message kunnen registeren, noem deze bijv. MakeObservableMessage. De message identifier zou je dan in de shared map kunnen zetten (zodat alle dll instanties ze kunnen lezen). Omdat je in de IE processen een specifieke window hebt gesubclassed kan je dus alle messages onderscheppen. Je kan dus nu vanuit je applicatie een MakeObservableMessage sturen naar de window handle die je al had gesubclassed. Je onderschept die message en je kan je actie uitvoeren. Je kan etv. ook nog met die message wat parameters doorsturen. Heb je hier iets aan?

  • Guillome
  • Registratie: Januari 2001
  • Niet online
MakeObservableMessage sturen naar de window handle die je al had gesubclassed
Maar het gaat om de vensters die (nog) niet gesubclassed zijn he?
Of bedoel jij dat getWindowLong op deze manier (vanuit de overige IE processen) wel werkt?

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
dan snap ik het niet. Waarom zijn die nog niet gesubclassed? Ik d8 nl dat je de dll injecteerd in alle processen en dat tijdens het injecteren je subclassed? waarschijnlijk heb ik het mis.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ja :)
Ik kan met mijn programma IE instancies opstarten (createProcess), en met die vensters kan ik met getWindowLong de wndProc opvragen, en vervangen met SetWindowLong.
Alleen, vensters die ik niet geopend heb met mijn programma, maar die opgestart zijn door de gebruiker zelf, daarvan kan ik de wndProc niet opvragen met getWindowLong.
Vandaar dat mijn DLL dan geinjecteerd moet worden in dat IExplorer venster, en dan subclassen.
Maar ik weet niet ik een functie moet starten van de geinjecteerde dll, of wat de dll doet als hij geinjecteerd wordt.

Hier m`n programmatje tot nu toe, dan heb je misschien even een iets helderder beeld :)
http://xlerator.beefhole.nl/webstuff/IE starter.rar
Start een IE in het menu (IE venster openen), en dan in het menu op de naam klikken.

[ Voor 22% gewijzigd door Guillome op 22-12-2003 16:13 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Ik zie twee 'problemen' met jouw code. Als er al IE windows open zijn voordat je jouw programma opstart dan wordt jouw dll (nog) niet geinjecteerd in de al bestaande IE processen (kan je zien mbv attach process in delphi en dan show modules). Echter wanneer je dan een window opent in het al bestaande IE process (bijv. Tools->Internet Options) dan wordt de dll wel geinjecteerd. De rede hiervan is dat de WH_CBT hook pas iets doet wanneer er iets gebeurd met windows (kan ook zijn dat minimize van het IE window al voldoende is). Echter als dan de dll is geinjecteerd dan lijkt het nog niks te doen. Ik weet niet wat er dan precies mis gaat want op zich denk ik wel dat je de window dan al wel hebt ge-subclassed. Je zou kunnen kijken of je met DebugOutputMessage kan zien of hij ge-subclassed is.
Als je nou IE opstart nadat je jouw programma (Starter) hebt gestart dan zie je wel dat je dll is geinjecteerd. Maar ook nu kan ik het IE window nog closen. Of je window is niet ge-subclassed of er gaat was mis in je HookProc.
Het 1e probleem kan je oplossen door gebruik te maken van een andere manier van Hooken. Bijv. door de Madshi library of door WH_GETMESSAGE hook want elke app heeft in iedergeval een message queue.

PS. Om te zien of jouw dll is geinjecteerd kan je gebruik maken van 'attach process' in Delphi. Je kiest dan IExplorer.exe en attach. Je kan nu mbv vies->debug windows->modules alle dll's zien die in het process zijn geladen. Nadeel is dat als je je app in delphi dan closed je ook de attached proc closed.

  • Guillome
  • Registratie: Januari 2001
  • Niet online
TijnFLiP schreef op 22 december 2003 @ 17:25:
Ik zie twee 'problemen' met jouw code. Als er al IE windows open zijn voordat je jouw programma opstart dan wordt jouw dll (nog) niet geinjecteerd in de al bestaande IE processen (kan je zien mbv attach process in delphi en dan show modules).
Klopt, dit staat ook niet in de code ;) Hij doet alleen dingen met IE vensters die hij zelf opstart. Pas als je in -IE venster lijst- op button1 klikt (staat op invisible in die online versie), dán moet ie de dll injecteren in de geselecteerde IE venster.
Echter wanneer je dan een window opent in het al bestaande IE process (bijv. Tools->Internet Options) dan wordt de dll wel geinjecteerd. De rede hiervan is dat de WH_CBT hook pas iets doet wanneer er iets gebeurd met windows (kan ook zijn dat minimize van het IE window al voldoende is).
Dat komt zeker omdat de vensters die het progje zelf opent, bezig is met starten, en daardoor de hookproc aanroept? Want dat werkt allemaal wel gewoon goed.
Hij start eerst het hooken, daarna start hij IE pas op.
Echter als dan de dll is geinjecteerd dan lijkt het nog niks te doen. Ik weet niet wat er dan precies mis gaat want op zich denk ik wel dat je de window dan al wel hebt ge-subclassed. Je zou kunnen kijken of je met DebugOutputMessage kan zien of hij ge-subclassed is.
Het subclassen bij al bestaande IE vensters gaat niet omdat hij de wndProc niet kan getten en setten met get/setWindowLong.
Als je nou IE opstart nadat je jouw programma (Starter) hebt gestart dan zie je wel dat je dll is geinjecteerd. Maar ook nu kan ik het IE window nog closen. Of je window is niet ge-subclassed of er gaat was mis in je HookProc.
Het 1e probleem kan je oplossen door gebruik te maken van een andere manier van Hooken. Bijv. door de Madshi library of door WH_GETMESSAGE hook want elke app heeft in iedergeval een message queue.

PS. Om te zien of jouw dll is geinjecteerd kan je gebruik maken van 'attach process' in Delphi. Je kiest dan IExplorer.exe en attach. Je kan nu mbv vies->debug windows->modules alle dll's zien die in het process zijn geladen. Nadeel is dat als je je app in delphi dan closed je ook de attached proc closed.
[/quote]

Ik zie dat hij 'UNKNOWN MODULE' heeft geadd, als ik `m attach aan een bestaande IExplorer venster. Klopt dat wel?

Even voor de duidelijkheid wat er gedaan moet worden:
Normaal gesproken gaat het als volgd:
StartHook -> Start IE -> Subclassen -> SetWantProcessID (aangeven welk venster).

Omdat je de rechten hebt om de wndProc te benaderen met get/setWindowLong bij een process dat door je eigen app is gestart, werkt dit allemaal prima.

Maar die rechten heb je niet bij een venster dat al geopend is, dus moet ik de dll injecteren in dat proces.
Maar wat ik nu niet snap is hoe ik dan SetHook kan aanroepen in de DLL.
Als test gebruikte ik hiervoor makeObservable, maar uiteindelijk moet dat setHook zijn.

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ik wil even zeggen dat ik mijn code vrij wil geven aan iemand die er verder aan wil werken. Ik kom er niet meer uit.
Ik dacht dat ik `m nu helemaal af had (nog steeds met dit laatste probleem overigens), maar nu werkt hij niet goed meer.
Het loskoppelen gaat niet goed bij meerdere vensters, en hij is gewoon niet stabiel.
Dit was toch wat te hoog gegrepen. Dus voor de liefhebbers, zeg het maar :)


edit
Hij werkt nu 100% goed :D Joehoe!!!! De aanhouder wint!! :D:D:D::D:D:D:D:DD

[ Voor 13% gewijzigd door Guillome op 04-02-2004 21:08 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router

Pagina: 1