Autor Beitrag
dummzeuch
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 593
Erhaltene Danke: 5


Delphi 5 ent, Delphi 6 bis Delphi XE8 pro
BeitragVerfasst: So 16.03.08 18:18 
Hi,

ich versuche mit der uallcollection einen Hook auf die API Funktion GetFileAttributesA zu setzen. Leider funktioniert das nicht. Es wird zwar meine Funktion aufgerufen und ausgefuehrt, jedoch bekomme ich beim Aufruf der Original-Funktion eine Access-Violation:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
  // Installieren des Hooks:
  p4 := GetProcAddress(GetModuleHandle(kernel32), 'GetFileAttributesA');
  if p4 <> nil then begin
    @GetFileAttributesARec.old := p4;
    if uallHook.HookCode(@GetFileAttributesARec.old, @MyGetFileAttributesA, @GetFileAttributesARec.next) then begin
      LogLine('Hook for GetFileAttributesA installed');
    end else
      LogLine('Failed to hook GetFileAttributesA');
  end;

  // meine Hook-Funktion:
function MyGetFileAttributesA(lpFileName: PAnsiChar): DWORD; stdcall;
begin
  Result := GetFileAttributesARec.next(lpFileName);
end;


Natuerlich soll die Hook-Funktion mal etwas mehr machen, als nur die Original-Funktion aufrufen, aber schon dieser einfache Code fuehrt zu dem Fehler. Andere
Funktionen lassen sich ohne Probleme hooken.

Im Debugger sieht der Aufruf ganz OK aus:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
01F8FD30 55               push ebp
01F8FD31 8BEC             mov ebp,esp
01F8FD33 8B4508           mov eax,[ebp+$08]
01F8FD36 50               push eax
01F8FD37 FF1528A7F901     call dword ptr [$01f9a728]
01F8FD3D 5D               pop ebp
01F8FD3E C20400           ret $0004


Allerdings finde ich den aufgerufenen Code irgendwie seltsam:

ausblenden Quelltext
1:
2:
3:
4:
021E0000 FF742404         push dword ptr [esp+$04]
021E0004 E885200100       call $021f208e
021E0009 685474587C       push $7c587454
021E000E C3               ret


Meine Assembler-Kenntnisse reichen nicht wirklich aus, um zu verstehen, was hier passiert. Die beiden letzen Befehle legen wohl eine neue Ruecksprungadresse auf den Stack und rufen sie auf, vermutlich ist das der Aufruf fuer die Originalfunktion. Aber so weit kommt es gar nicht erst, schon der zweite Befehl landet in der Pampa: $021f208e ist ein nicht initialisierter Speicherbereich.

Mache ich was falsch? Wieso funktioniert es mit anderen API-Funktionen (z.B. FindFirstFileA) aber nicht mit FileGetAttributesA?

twm
dummzeuch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 593
Erhaltene Danke: 5


Delphi 5 ent, Delphi 6 bis Delphi XE8 pro
BeitragVerfasst: So 16.03.08 18:58 
user profile icondummzeuch hat folgendes geschrieben:

ausblenden Quelltext
1:
2:
3:
4:
021E0000 FF742404         push dword ptr [esp+$04]
021E0004 E885200100       call $021f208e
021E0009 685474587C       push $7c587454
021E000E C3               ret



Ok, ich mache nichts falsch, es liegt wohl daran, dass der Befehl
ausblenden Quelltext
1:
021E0004 E885200100       call $021f208e					

aus dem Original-Code von FileGetAttributesA kopiert wird, aber leider ein relativer Aufruf ist, sprich, wenn man ihn woandershin kopiert, springt er an die falsche Stelle. Im Original sieht er naemlich so aus:
ausblenden Quelltext
1:
7C58744F E885200100       call $7c5994d9					

uallHook.HookCode erkennt das Problem anscheinend nicht.

So weit, so schlecht.

Was kann ich nun dagegen tun?

twm
dummzeuch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 593
Erhaltene Danke: 5


Delphi 5 ent, Delphi 6 bis Delphi XE8 pro
BeitragVerfasst: So 16.03.08 20:05 
OK, fuer alle, die evtl. mal dasselbe Problem haben:

uall collection kann auch auf andere Weise APIs hooken, naemlich via der Import Address Table (IAT). Das ist, wenn es funktioniert, auch einfacher, da kein Code kopiert werden muss sondern nur ein Pointer umgesetzt wird:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
  if uallHook.HookApiIAT(kernel32, 'GetFileAttributesA', @MyGetFileAttributesA, p4) then begin
    @GetFileAttributesARec.old := p4;
    @GetFileAttributesARec.next := p4;
  end;


In meinem Fall hat's geklappt.

twm
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Di 25.03.08 12:01 
Hi Thomas,
mit dem IAT Hook werden jedoch nicht alle Aufrufe der API abgefangen, sondern nur alle statischen (logisch: da nur diese in der IAT stehen). Der Codehook, wenn er denn funktioniert, fängt jedoch alle ab.

Über Vor- und Nachteile kann man sich hier informieren: help.madshi.net/ApiHookingMethods.htm
Madshi bietet selbst (leider nur kommerziell, früher gabs auch eine freie Version) ebenfalls eine weitaus ausgereiftere Version zum API hooken an.

Eine von mir erweiterte Version des IAT Hooks wäre der Relcoation hook, der die Relocation Section der PE Datei nach JMP [ADDR] durchsucht und diese auch noch mithookt. Dann können einige dynamisch geladenen Funktionen zusätzlich zum IAT gehookt werden.

PUSH ADDR, RET ist auch eine von mir eingeführte Art des JUMPs. Dieser Jump ist genau wie ein relativer Jump nur 6Bytes groß, hat aber den Vorteil, dass man diesen widerum einfach durch Codekopieren hooken kann. So kann man die selbe API mehrmals hooken ohne den relativen Code anzupassen.

Das relative Adressen angepasst werden müsste noch implementiert werden. Da hast du richtig gesehen, dass es noch nicht in der derzeitigen Version implementiert wird. Alternativ kannst du die WideChar API hooken, da sowieso jeder Call der A in den Aufruf der W Version endet. Und dort sollte (hoffentlich) kein relativer Call am Anfang der Funktion sein.

_________________
wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 25.03.08 23:51 
Ich hab mal im Bugtracker nen Report eingetragen, um das Problem im Auge zu behalten. Die Bugmeldung gibt's unter bugs.omorphia.de/view.php?id=220.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.