DLL-Injection ohne Remote Thread
Verfasst: 22.05.2007 23:39
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:
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.
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)
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