![]() |
x64 main-thread hook mittels dll
Hallo,
ich versuche zur Zeit den main-thread einer Anwendung zu hooken. Hierfür injecte ich die Dll ganz normal über CreateRemoteThread und rufe eine exportierte Funktion meiner Dll als Einstieg auf. Die Dll versucht dann in den main-thread zu gelangen. Das funktioniert soweit auch, aber ab und an friert die Anwendung einfach ein, obwohl an der dll selber nichts verändert wurde. Ich vermute das es Probleme mit dem Stack gibt. Um in den main-thread zu gelangen verwende ich zunächst folgende 2 Funktionen, letztere ist sicher nicht perfekt vermute hier aber nicht den Fehler:
Code:
Direkt nach dem injizieren wird mittels der beiden Funktionen dann folgender Assembler Code aufgerufen:
function GetMainThreadId: Cardinal;
var ThreadEntry: THREADENTRY32; hThreadSnapShot: THandle; dwProcessId: Cardinal; begin result := 0; dwProcessId := GetCurrentProcessId(); ThreadEntry.dwSize := SizeOf(THREADENTRY32); hThreadSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID); if (Thread32First(hThreadSnapShot, ThreadEntry)) then begin repeat if (ThreadEntry.th32OwnerProcessID = dwProcessID) then begin CloseHandle(hThreadSnapShot); result := ThreadEntry.th32ThreadID; exit; end; until Thread32Next(hThreadSnapshot, ThreadEntry) = false; CloseHandle(hThreadSnapShot); end; end; function HookThread(pFunction: Pointer; var OldEIP: NativeUInt): Boolean; var hThread: THandle; dwMainThreadId: Cardinal; ctx: TContext; const THREAD_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $3FF; begin dwMainThreadId := GetMainThreadId(); if (dwMainThreadId = 0) then exit(false); hThread := OpenThread(THREAD_ALL_ACCESS, false, dwMainThreadId); if (hThread = 0) then exit(false); if (SuspendThread(hThread) = Cardinal(-1)) then begin CloseHandle(hThread); exit(false); end; ctx.ContextFlags := CONTEXT_CONTROL; if not (GetThreadContext(hThread, ctx)) then begin ResumeThread(hThread); CloseHandle(hThread); exit(false); end; OldEIP := ctx.Rip; ctx.Rip := NativeUInt(pFunction); if (SetThreadContext(hThread, ctx)) then begin ResumeThread(hThread); CloseHandle(hThread); result := true; end else result := false; end;
Delphi-Quellcode:
Load Funktion:
procedure AsmLoader; assembler;
asm sub RSP, 8h push RAX push RBX push RCX push RDX push RDI push RSI push RSP push RBP push R8 push R9 push R10 push R11 push R12 push R13 push R14 push R15 mov RAX, _rip mov [RSP+128], RAX call _Load pop R15 pop R14 pop R13 pop R12 pop R11 pop R10 pop R9 pop R8 pop RBP pop RSP pop RSI pop RDI pop RDX pop RCX pop RBX pop RAX end;
Delphi-Quellcode:
_rip ist ein NativeUint.
procedure _Load;
begin // sobald hier etwas aufgerufen wird kann es krachen GetCurrentThreadId(); end; // Exported function procedure Load(pArgs: Pointer); begin if not (HookThread(@AsmLoader, _rip)) then ExitProcessMessage('Basic init failed'); end; Den Assembler Code um die Register zu sichern und anschließend meine Funktion aufzurufen habe ich aus einem C++ Forum, der andere Part stammt von mir. Ich bin bei x64 komplett neu, wäre nett wenn da mal jemand nachschauen könnte ob das alles so korrekt ist, und mir ggf. noch mitteilen kann wieso weshalb warum ;) Es frieren übrigens alle Anwendungen ab und zu ein welche ich als Ziel benutze, kann auch das Notepad sein. Grüße |
AW: x64 main-thread hook mittels dll
Darf man fragen, was du genau vor hast?
Unter x64 werden alleine schon von der calling-convention her nicht nur die GP-Register verwendet, sondern auch XMM, etc. Diese musst du ebenfalls saven und wieder restoren. Und das (R)/(E)FLAGS Register würde ich mir ebenfalls sichern, sofern du nicht 100%-ig garantieren kannst, dass deine aufgerufene Funktion die Flags nicht affektiert. |
AW: x64 main-thread hook mittels dll
Die Register und Flags sind zwar ein Problem, aber ein lösbares ... besonders wenn man sich mal anguckt was getThreadContext sichert ;)
Das kompliziertere Problem ist, dass du das Programm irgendwo unterbrichst. Wenn der gerade an einer Datenstruktur rummanipuliert und deine injizierte Funktion diese auch benutzt, kann es krachen. Ähnliches Problem wie mit Unix-Signal-Handlern. |
AW: x64 main-thread hook mittels dll
Bist du dir denn sicher, dass GetMainThreadId dir auch immer den Mainthread zurückgibt?
Du gehst ja davon aus, dass der erste Thread der für den Prozess gefunden wird der Mainthread ist. Ist das irgendwo dokumentiert? Kann mir vorstellen, dass du manchmal einfach im falschen Thread landest. |
AW: x64 main-thread hook mittels dll
Zitat:
@Clowdy: Mit ![]() |
AW: x64 main-thread hook mittels dll
Hallo hallo! Danke für die doch zahlreichen Antworten. :)
Zitat:
Rufe ich in der _Load Funktion SetTimer() auf - was nicht mein Ziel ist, führen meine Aufrufe in der Callback Funktion in keinen Fall mehr zu einem Freeze. Rufe ich ich die gleichen Funktionen direkt in _Load auf, stürzt mir die Anwendung ab. Ich gehe also davon aus das nur der Assembler Code mit der Stack-Sicherung das Problem ist. Die ThreadId habe ich mit Breakpoints ohne das meine Dll injiziert ist noch einmal verifiziert. Der Aufruf erfolgt ausnahmslos vom ersten erstellten Thread. Ich bin aber wahrlich noch kein Meister mit WinDbg. Die Funktionen, oder eher ein Teil davon meiner Ziel-Anwendung sind nicht Thread sicher, daher der Umweg. Zitat:
Zitat:
Zitat:
Habt mir schon mal sehr weitergeholfen. |
AW: x64 main-thread hook mittels dll
Hallo nochmal,
da durchaus der ein oder andere durch Google auf den Beitrag hier stoßen dürfte und die Resultate zu Thread Hijacking unter x64 ziemlich dürftig sind, möchte ich hier noch einmal den korrigierten Code posten. Ich habe den Code jetzt seit einer Woche ohne Probleme bei mir im Einsatz, möglich das er noch immer Fehler enthält, dafür übernehme ich keine Gewähr. :p Hinzu kamen einige Probleme bei den Parametern einiger Funktionen bei der Anwendung für die ich meine DLL nutze, aber das dürfte eher uninteressant sein. edit: Mit QueueUserAPC habe ich mich ebenfalls intensiv beschäftigt, scheidet hier aber leider aus da der Thread sich in einer Schleife befindet und nie in einem alertable state ist, das wäre also nur eine Lösung gewesen wenn ich direkt beim Start der Anwendung injiziere.
Delphi-Quellcode:
procedure AsmLoader; assembler;
asm push [_rip] pushfq push RAX push RBX push RCX push RDX push RDI push RSI push RSP push RBP push R8 push R9 push R10 push R11 push R12 push R13 push R14 push R15 call _Load pop R15 pop R14 pop R13 pop R12 pop R11 pop R10 pop R9 pop R8 pop RBP pop RSP pop RSI pop RDI pop RDX pop RCX pop RBX pop RAX popfq end; |
AW: x64 main-thread hook mittels dll
Der Vollsrändigkeit halber solltest du aber auf jeden Fall noch den State der XMM Register XMM0-XMM15 sichern. YMM, ZMM und die AVX512 Erweiterung mit X/Y/ZMM16-31 kann man denke ich außer Acht lassen, aber einige XMM Register werden für die Standard 64-Bit CallingConvention verwendet. Die würde ich deshalb auf jeden Fall noch sichern.
|
AW: x64 main-thread hook mittels dll
Da muss ich mich tatsächlich selber noch einmal schlau machen, pushen geht ja nicht einfach so.
Ist bisher auch in keines der Beispiele die ich gefunden habe behandelt worden, allgemein unterscheiden sich die Lösungsansätze hier und da. Ist aber ein guter Einwand. :wink: Meinen aktuellen Lösungseinsatz habe ich übrigens von hier: ![]() |
AW: x64 main-thread hook mittels dll
Die AVX Register kannst du so pushen:
![]() Um ganz generisch zu sein, könntest du auch noch den FPU State sichern. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:14 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