![]() |
DLL Funktion Hook - Allgemeingültige Lösung / Codevorlage?
Hallo zusammen.
Ich habe mal endlich wieder mehr Zeit und mache mich mal wieder über ein paar alte Projekte her. Ich hatte mehrmals schon ansatzweise versucht, eine DLL Funktion zur Laufzeit zu überschreiben (gab hier sogar ein paar Themen dazu). * Zum einen hörte ich etwas von statischen und dynamischen DLLs (ich weiß, was das bedeutet) und dass man je nach dem unterschiedlich vorgehen muss. * Zum anderen fiel das Wort "Inline Hook" wenn ich eine Funktion einer DLL systemweit überschreiben möchte. Letzteres ergab bei mir eine schlechte Google Recherche, bei der ich nicht schlauer geworden bin: ![]() Es gibt also 4 Möglichkeiten: 1. Funktion einer statisch geladenen DLL für einen Prozess umbiegen 2. Funktion einer dynamisch geladenen DLL für einen Prozess umbiegen 3. Funktion einer statisch geladenen DLL systemweit umbiegen 4. Funktion einer dynamisch geladenen DLL systemweit umbiegen Wobei 3 und 4 eigentlich ein Punkt sind, denn wenn ich etwas systemweit umbiegen will, dann darf es im Endresultat keinen Unterschied machen, ob die DLL dynamisch oder statisch geladen ist. Nun meine Frage, damit ich endlich mal verstehe, wie so etwas funktioniert - kann mir jemand Codes zeigen, bei denen ganz einfach das Hooken einer Funktion mit diesen 4 Möglichkeiten gezeigt wird, sodass ich das korrekt nachvollziehen kann? Im Moment hätte ich nämlich folgenden Bedarf an Hooks: - Ich möchte versuchen, eine Funktion der system32.dll systemweit umzubiegen (Thread: Windows dazu bringen, dass Dateien sicher gelöscht werden) - Ich möchte versuchen, eine Funktion der winmm.dll für einen bestimmten Prozess umzubiegen, sodass ich alle ausgehenden MIDI-Kommandos mitschneiden kann. (Dynamisch/Statische DLL im Moment unbekannt) Ich hoffe, irgendwo da draußen gibt es so eine Art "Kochbuch", in dem eine Hook Lösung für Delphi so einfach dargestellt wird, dass man sie einfach auf die eigenen Wünsche adaptieren kann. Gruß blackdrake |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
Naja es kommt auch ncoh auf die Sicherheit an, dynamisch oder statisch geladene DLLs sind eigentelich wurscht, jedenfalls wenn man CodeOverwriting verwendet.
Für CodeOverwriting im User-Mode reicht es eigentlich für das systemweite hooking den hookcode in jeden Prozess zu laden. Für kommerzielle Programme solltest du mal ![]() ![]() Für sicherheitsrelevante Anwendungen, solltest du dann kernelhooking (Treiber, einfach mit c++, teilweise über das DDDK möglich) verwenden, da kannst du aber im Grunde nur die Systemfunktionen hooken. Leider aber nicht mehr einache userfunktionen aus dlls (geht zwar auch, indem man CodeOverwriting macht mit Systemcall und protecten durch hooken von VirtualProtect etc., würde ich dir aber nicht empfehlen). Also für den Anfang mal meien Collection anschaun, da sind hooks drin für z.B. opengl.glBegin usw. und ein testweiser Treiberhook aus Delphi (der vill auf 10% aller Systeme funzt und crahsen kann, also reines konzept zum testen). Für dich würde wohl madCodehook am besten sein (systemweit durch injecten in alle prozesse, mit codeoverwriting für statische und dynamisch geladene dlls) Bei madshi gibt es schöne Beschreibungen: ![]() Es gibt noch den "RelocationHooking, der bisl besser ist als Import+Export), hab ich damals eingebaut, glaub Madshi verwendet den mittlerweile auch. "Safe unhooking" ist meiner meinugn nach madshis Code nicht, jedenfalls hatten nildo und ich vor 2-3 jahren da mal etwas programmiert wo das Programm danach gecrashed ist. Aber madshis Codehook hat immerhin mehr checks damit nichts crashed. Einzige wo ich mich bisher immer mit mdashi in den haaren hatte war die sicherheit. Sein codehook wird z.b. bei asquared verwendet (malware check und instrusion dectection system). Man kann es einfach ausschalten indem man die DLL entläft (ist ja im eigene prozess und nicht im kernel). also ist das eigentlich für sicherheitsrelevante programme mist. |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
Hallo.
Vielen Dank für deine Antwort und die Links. Ich werde mich gleich mal an dem CodeOverwriting versuchen, um zu schauen, ob ich die Funktion der WinMM umbiegen kann. Ich melde mich wieder und teile mit, ob es funktioniert oder nicht. Leider scheint es keine allgemeingültige Lösung zu geben und es gibt auch scheinbar nicht nur 4 Fälle, so wie ich dachte, sondern viel mehr. Gruß blackdrake |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
jupp, das Einfachste wäre die DLL auszutauschen, bzw. dafür zu sorgen, daß eine eigene DLL, mit dem selben Namen, in den Suchpfaden vorher gefunden wird :nerd:
|
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
Hallo.
Irgendwie scheint das nicht ganz zu funktionieren. Ich habe jetzt folgenden Code:
Delphi-Quellcode:
In meiner überschriebenen Funktion wird ein writeln() ausgeführt. Kann es sein, dass midiOutOpne nicht systemweit überschrieben wird? Wie kann ich die Funktion für einen fremden Prozess überschreiben?
@origMessageBoxA := GetProcAddress(LoadLibrary('winmm.dll'),'midiOutOpen');
uallHook.HookCode(@origMessageBoxA,@callbackMessageBoxA,@newMessageBoxA); readln; uallHook.UnhookCode(@newMessageBoxA); // Edit Nochmal mit MessageBoxA mit den originalen Examples probiert. Ein anderer Prozess ruft MessageBoxA() auf. * uallHook.HookCode --> Kein Einfluss im Fremdprozess! * ualltableHook.HookApiJmp --> Kein Einfluss im Fremdprozess! * uallHook.HookApiIAT --> Kein Einfluss im Fremdprozess! * uallRelocHook.HookRelocationTable --> Kein Einfluss im Fremdprozess! (Jeweils zwei Tests gemacht: Fremdprozess läuft bereits und Fremdprozess wurde nach dem Hook gestartet) Was soll ich machen, damit der Fremdprozess sein Verhalten bezüglich der API Funktion ändert? // Edit 2 Ich habe mir auch mal das 1337 Example angeschaut und es hatte funktioniert. Jetzt habe ich es auf MessageBoxA umgestellt und es funktioniert nicht! Ich weiß nicht mehr, was ich machen soll. Hier der komplette Testfall! HOOK.DLL
Delphi-Quellcode:
EXEMAIN.EXE
library hook;
uses windows, sysutils, uallDisasm in '..\..\uallDisasm.pas', uallDisasmEx in '..\..\uallDisasmEx.pas', uallHook in '..\..\uallHook.pas', uallKernel in '..\..\uallKernel.pas', uallProcess in '..\..\uallProcess.pas', uallProtect in '..\..\uallProtect.pas', uallUtil in '..\..\uallUtil.pas'; var origMessageBoxA: function (hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall; newMessageBoxA: function (hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall; function callbackMessageBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall; begin Result := newMessageBoxA(hWnd,PChar(lpText+' [hooked]'),lpCaption,uType); end; procedure injectmain; var h: integer; begin h := GetModuleHandle('user32.dll'); if h > 0 then begin @origMessageBoxA := GetProcAddress(h,'MessageBoxA'); if @origMessageBoxA <> nil then uallHook.HookCode(@origMessageBoxA,@callbackMessageBoxA,@newMessageBoxA); end; end; procedure uninjectmain; begin uallHook.UnhookCode(@newMessageBoxA); 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.
Delphi-Quellcode:
TEST.EXE (Teil)
program exemain;
uses windows, tlhelp32, uallDisasm in '..\..\uallDisasm.pas', uallDisasmEx in '..\..\uallDisasmEx.pas', uallHook in '..\..\uallHook.pas', uallKernel in '..\..\uallKernel.pas', uallProcess in '..\..\uallProcess.pas', uallProtect in '..\..\uallProtect.pas', uallUtil in '..\..\uallUtil.pas'; const lh = '1337 hook'; begin if paramcount < 1 then MessageBox(0,'No Param, use PARAM -load / -unload to use 1337 hook',lh,0) else if uppercase(paramstr(1)) = uppercase('-load') then GlobalInjectLibrary(pchar(uallUtil.GetExeDirectory+'hook.dll')) else if uppercase(paramstr(1)) = uppercase('-unload') then GlobalUnloadLibrary(pchar('hook.dll')) else MessageBox(0,'Wrong Param, use PARAM -load / -unload to use 1337 hook',lh,0); end.
Delphi-Quellcode:
Ergebnis: Ich habe die Hook-DLL geladen (-load) und die Test.exe gestartet. Die erscheinende MessageBoxA hat nicht den erwarteten Zusatz " [hooked]". :|
procedure TForm1.Button1Click(Sender: TObject);
begin MessageBoxA(handle, 'X', 'Y', 0); end; Gruß blackdrake |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
erst die Test.exe starten dann den hook
was liefert denn HookCode zurück? Edit: Und welches BS verwendest du? Edit2: Hab deinen Code gerade getestet, bei mir funktioniert der einwandfrei. |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
Hallo.
Ich habe Win XP SP3. Ich habe alle möglichen Kombinationen probiert und kann versichern, dass MessageBoxA() partout nicht ging. Lediglich AudaCity zeigte ab und zu (!) bei dem "Möchten Sie speichern?" Dialog das [hooked]. Alle anderen Anwendungen waren nicht modifiziert. Keine Ahnung wieso! Aber: midiOutShortMsg() konnte ich wunderbar hooken und den MIDI-Verkehr mitschneiden (ich habe zuerst den obrigen Code verwendet, dann das Traffic-Demo abgewandelt, damit die Auswertung durch eine Host-Anwendung durchgeführt wird.) Jetzt habe ich noch ein Problem:
Delphi-Quellcode:
Alle Prozesse (auch die "neu hinzugekommenen") bekommen meine MIDI-Hook.DLL injeziert. Das Problem ist, dass nicht jede Anwendung winmm.dll eingebunden hat (bei WinAmp wird die winmm.dll beispielsweise erst eingebunden, wenn man eine MIDI öffnet und abspielt.) Bedeutet: Alle Prozesse, die die winmm.dll später einbinden, werden nicht mit aufgezeichnet, da die Bedingung "h > 0" nicht beim DLL-Init erfüllt war.
h := GetModuleHandle('winmm.dll');
if h > 0 then begin @origMessageBoxA := GetProcAddress(h,'midiOutShortMsg'); if @origMessageBoxA <> nil then uallHook.HookCode(@origMessageBoxA,@callbackMessageBoxA,@newMessageBoxA); end; Frage: (1) Was soll ich dagegen unternehmen? Soll ich vielleicht eine Endlosschleife in die DLL einfügen, sodass der Code ausgeführt wird, sobald "h > 0" wir? Folgefrage: (2) Wenn "h > 0" eingetreten ist, muss ich dann den HookCode() immer wieder durchführen (z.B. für den Fall dass die zu hook'ende DLL geladen und dann entladen und dann wieder geladen wurde? Und: (3) Ist es nicht fatal, wenn man eine DLL injeziert, die eine Endlosschleife beeinhaltet? Wenn jeder Prozess des Systems eine solche DLL injeziert bekommt, könnte die CPU-Auslastung ziemlich hoch werden, oder? Gruß blackdrake |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
zu 1 und 2:
eigentlich sollte es <> heißen
Delphi-Quellcode:
GetModuleHandle liefert das Handle der geladenen DLL
if h <> 0 then
oder 0, wenn diese nicht geladen ist. |
Re: DLL Funktion Hook - Allgemeingültige Lösung / Codevorlag
Wenn das Modul dynamisch geladen wird kannst du natürlich GetProcAddress hooken und ggf eine andere Addresse (z.B. eine Funktion von dir zurückgeben).
Bzw. du lädst die DLL selbst in dllmain und hookst dann direkt. (ist kein problem wenn dann das programm späternochmal die dll laden will) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz