DLL-Injection ohne Remote Thread

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

DLL-Injection ohne Remote Thread

Beitrag von Thorium »

Da es doch einige Programme (vorallem Spiele) gibt, die es erkennen wenn ein Thread per CreateRemoteThread erstellt wird, habe ich eine etwas kompliziertere Technik zur DLL-Injection in PB umgesetzt. Bei dieser Technik wird kein Thread erzeugt, sondern die Ausführung eines Threads des Zielprozesses auf eigenen Code umgebogen, der dann die DLL läd.

Wenn ihr das testen wollt mit einer DLL, welche eine MessageBox ausgibt, dann vergesst nicht folgende Zeile am Ende auszukommentieren:

Code: Alles auswählen

VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
Da der Zielprozess sonst nach dem schließen der MessageBox crasht, da der nachfolgende Code nichtmehr existiert.

Wenn die Injektion geklappt hat gibt die Prozedur 1 zurück andernfalls 0.

Code: Alles auswählen

;Written by Thorium
;PureBasic 4.02 Code

EnableExplicit

#THREAD_ALL_ACCESS = $1F03FF

Procedure.l InjectDLL(idTarget.l,FileName.s)
  Define.l FileNameLen,FileNameAddr,CodeAddr,BytesWritten,hKernel32,LoadLibraryAAddr,CodeBuffer,Position,idThread,hThread,hSnapshot,RetVal,LibKernel32,hTarget
  Define.CONTEXT ThreadContext
  Define.THREADENTRY32 ThreadInfo
  
  ;Zielprozess öffnen
  hTarget = OpenProcess_(#PROCESS_ALL_ACCESS,0,IdTarget)
  If hTarget = 0
    ProcedureReturn 0
  EndIf

  ;ID des Hauptthreads ermitteln
  ThreadInfo\dwSize = SizeOf(ThreadInfo)
  hSnapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,0)
  If hSnapshot <> 0
    RetVal = Thread32First_(hSnapshot,@ThreadInfo)
    If RetVal <> 0
      If ThreadInfo\th32OwnerProcessID = idTarget
        idThread = ThreadInfo\th32ThreadID
      Else
        Repeat
          RetVal = Thread32Next_(hSnapshot,@ThreadInfo)
          If RetVal = 0
            Break
          Else
            If ThreadInfo\th32OwnerProcessID = idTarget
              idThread = ThreadInfo\th32ThreadID
              Break
            EndIf
          EndIf
        Until RetVal = 0
      EndIf
      CloseHandle_(hSnapshot)
    EndIf
  EndIf
  If idThread = 0
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;Addresse von LoadLibraryA ermitteln
  hKernel32 = GetModuleHandle_("Kernel32.dll")
  If hKernel32 = 0
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  LoadLibraryAAddr = GetProcAddress_(hKernel32,"LoadLibraryA")
  If LoadLibraryAAddr = 0
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf

  ;Thread öffnen
  LibKernel32 = OpenLibrary(#PB_Any,"Kernel32.dll")
  hThread = CallFunction(LibKernel32,"OpenThread",#THREAD_ALL_ACCESS,0,idThread)
  If hThread = 0
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;Dateiname der DLL in den Zielprozess schreiben
  FileNameLen = Len(FileName) + 1
  FileNameAddr = VirtualAllocEx_(hTarget,0,FileNameLen,#MEM_COMMIT | #MEM_RESERVE,#PAGE_READWRITE)
  If FileNameAddr = 0
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  If WriteProcessMemory_(hTarget,FileNameAddr,FileName,FileNameLen,@BytesWritten) = 0
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  If BytesWritten <> FileNameLen
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;Speicher im Zielprozess für den Code allokieren
  CodeAddr = VirtualAllocEx_(hTarget,0,22,#MEM_COMMIT | #MEM_RESERVE,#PAGE_EXECUTE_READWRITE)
  If CodeAddr = 0
    CloseHandle_(hThread)
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;Speicher für die Codegenerierung allokieren
  CodeBuffer = AllocateMemory(22)
  
  ;Hauptthread anhalten
  If SuspendThread_(hThread) = -1
    CloseHandle_(hThread)
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
    FreeMemory(CodeBuffer)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;EIP-Register des Hauptthreads besorgen
  ThreadContext\ContextFlags = #CONTEXT_CONTROL
  If GetThreadContext_(hThread,@ThreadContext) = 0
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
    FreeMemory(CodeBuffer)
    ResumeThread_(hThread)
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;Code generieren
  PokeB(CodeBuffer,$68) ;push
  Position + 1
  PokeL(CodeBuffer + Position,ThreadContext\Eip)
  Position + 4
  PokeB(CodeBuffer + Position,$9C) ;pushfd
  Position + 1
  PokeB(CodeBuffer + Position,$60) ;pushad
  Position + 1
  PokeB(CodeBuffer + Position,$68) ;push
  Position + 1
  PokeL(CodeBuffer + Position,FileNameAddr)
  Position + 4
  PokeB(CodeBuffer + Position,$B8) ;mov eax,const
  Position + 1
  PokeL(CodeBuffer + Position,LoadLibraryAAddr)
  Position + 4
  PokeW(CodeBuffer + Position,$D0FF) ;call eax
  Position + 2
  PokeB(CodeBuffer + Position,$61) ;popad
  Position + 1
  PokeB(CodeBuffer + Position,$9D) ;popfd
  Position + 1
  PokeB(CodeBuffer + Position,$C3) ;ret
  
  ;Code in den Zielprozess schreiben
  If WriteProcessMemory_(hTarget,CodeAddr,CodeBuffer,22,@BytesWritten) = 0
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
    FreeMemory(CodeBuffer)
    ResumeThread_(hThread)
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  If BytesWritten <> 22
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
    FreeMemory(CodeBuffer)
    ResumeThread_(hThread)
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
  
  ;EIP-Register auf den Code setzen
  ThreadContext\Eip = CodeAddr
  ThreadContext\ContextFlags = #CONTEXT_CONTROL
  SetThreadContext_(hThread,@ThreadContext)

  ;Zielprozess weiterlaufen lassen
  ResumeThread_(hThread)
  
  ;Aufräumen
  Delay(1000)
  VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
  VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
  FreeMemory(CodeBuffer)
  CloseHandle_(hThread)
  CloseHandle_(hTarget)
  
  ProcedureReturn 1
EndProcedure
Zuletzt geändert von Thorium am 23.05.2007 15:11, insgesamt 1-mal geändert.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Rings
Beiträge: 977
Registriert: 29.08.2004 08:48

Beitrag von Rings »

hättest vielleicht ein paar Namen 'klarer' machen können:

Procedure.l InjectDLL(ProcessID,DLLFileName.s)
Rings hat geschrieben:ziert sich nich beim zitieren
Benutzeravatar
dige
Beiträge: 1235
Registriert: 08.09.2004 08:53

Beitrag von dige »

Ein Beispiel wie man das anwendet wäre auch nicht schlecht .. Danke! :D
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

dige hat geschrieben:Ein Beispiel wie man das anwendet wäre auch nicht schlecht .. Danke! :D
Hm, naja Beispiel.

Also idTarget ist PID also die ID des Zielprozesses.
FileName ist der Name der DLL, welche injiziert werden soll. Kann auch einen Pfad enthalten.
Stimmt Namen sind ein bissel blöd gewählt. :oops:

So richtig ein nützliches einfaches Beispiel kann ich hier garnicht bringen. Wenn du DLL-Injection brauchst, dann sollte das Aufrufen der Prozedur auch ohne Beispiel kein Problem darstellen. Wenn du nicht weisst wofür du DLL-Injection brauchen könntest, dann brauchst du es warscheinlich auch nicht. :wink:

Du kannst damit halt eine DLL in einen fremden Prozess einschleusen um deinen eigenen Code dort laufen zu lassen.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Waere es nicht besser das Modulehandle zurueck zu geben,
bzw ist es so ueberhaupt moeglich die DLL wieder zu entladen ?
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

edel hat geschrieben:Waere es nicht besser das Modulehandle zurueck zu geben,
bzw ist es so ueberhaupt moeglich die DLL wieder zu entladen ?
Naja gute Frage, das Handle befindet sich ja in dem Zielprozess. Man müsste mal schauen ob das ModuleHandle überhaupt übertragbar ist. Dann könnte man das Handle an den aufrufenden Prozess zurückgeben. Also so genau weis ich das jetzt nicht, müsste ich mich mal schlau machen. Ansonsten währe es natürlich interessant wenn sich die DLL selbst entladen könnte.

Edit: Dabei fällt mir ein, das Handle muss ja garnicht übertragbar sein. Man kann einfach Code in den Zielprozess injizieren, welcher das Handle nutzt um dort die DLL zu entladen. Das ist eine gute Idee, werde das demnächst mal umsetzen. :mrgreen:
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Wie sieht es denn mit GetExitCodeThread aus, aber der Thread wird ja hier nicht beendet oder ?
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

edel hat geschrieben:Wie sieht es denn mit GetExitCodeThread aus, aber der Thread wird ja hier nicht beendet oder ?
Naja der Thread ist ja hier ein bestehender Thread des Zielprozesses, dessen Ausführung nur kurzzeitig auf ein wenig eigenen Code umgeleitet wird. Der Thread läuft nach dem Laden der DLL so weiter wie vom Zielprozess beabsichtigt.

So oder so entläd das Beenden des Threads aber nicht die DLL.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Thorium hat geschrieben:So oder so entläd das Beenden des Threads aber nicht die DLL.
Nein , aber wenn man das Handle zur DLL kennt, koennte man es
ja (ueber den gleichen Weg) wieder mit FreeLibrary freigeben :?
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

edel hat geschrieben:
Thorium hat geschrieben:So oder so entläd das Beenden des Threads aber nicht die DLL.
Nein , aber wenn man das Handle zur DLL kennt, koennte man es
ja (ueber den gleichen Weg) wieder mit FreeLibrary freigeben :?
Jep, hab ich ja auch geschrieben.
Siehe das Edit in meinem vorletzten Post. ^^
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten