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:
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;
Direkt nach dem injizieren wird mittels der beiden Funktionen dann folgender Assembler Code aufgerufen:
Delphi-Quellcode:
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;
Load Funktion:
Delphi-Quellcode:
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;
_rip ist ein NativeUint.
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