Einzelnen Beitrag anzeigen

Clowdy

Registriert seit: 1. Mai 2016
4 Beiträge
 
#1

x64 main-thread hook mittels dll

  Alt 1. Mai 2016, 18:49
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
  Mit Zitat antworten Zitat