Entwickler-Ecke
Windows API - HookCode FileGetAttributesA
dummzeuch - So 16.03.08 18:18
Titel: HookCode FileGetAttributesA
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:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| 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;
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:
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:
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 - So 16.03.08 18:58
Titel: Re: HookCode FileGetAttributesA
dummzeuch hat folgendes geschrieben: |
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
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:
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 - So 16.03.08 20:05
Titel: Re: HookCode FileGetAttributesA
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:
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 - 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:
http://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.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!