![]() |
Inject DLL from Memory
Hallo liebe Community,
ich suche ein Äquivalent zu der "StealthInject" Lib (C++) für Delphi. Sie bietet die Möglichkeit eine DLL (in einem Stream,Buffer,String) direkt aus dem Memory heraus in einen fremden Prozess zu injecten - ohne Umweg über die Festplatte. Alternativ würde mir auch eine Beschreibung oder ein Pseudocode, wie man so etwas selber macht, sehr helfen. Danke im Vorraus Megamorph |
Re: Inject DLL from Memory
In meiner uallCollection gibts da so eine funktion (jedenfalls ein InjectMe, und ich bin mir sicher, dass ich da auch mal so eine funktion zum injecten geschrieben habe. Wenn ich mich nicht irre kannst du LoadLibraryX oder so verwenden die lädt eine DLL in den Speicher, verwendet aber CreateFileA um die Dll zu laden und reserveirt selbst Speicher. Dieses kannst du dann ja weglassen)
Einfach googlen :) |
Re: Inject DLL from Memory
Hey,
danke für den Tipp. Die Funktion InjectMe entsprach nicht ganz meiner Vorstellung. Ich möchte schon eine DLL injecten und keine EXE. Jedoch habe ich einen Code in Anlehnung an die InjectLibrary geschrieben, welcher jedoch noch nicht ganz funktioniert. Es wäre nett, wenn ihr mal einen Blick darüber werft, danke. (-;
Delphi-Quellcode:
Anmerkung:
procedure TForm1.Timer1Timer(Sender: TObject);
var BytesWritten, Process, Thread, ThreadId: cardinal; load_lib_param, body: pointer; DLL: pchar; szDll: string; dllptr : pointer; PID: cardinal; begin if GetWindowThreadProcessID(FindWindow(nil,pchar('Unbenannt - Paint')),nil) = 0 then exit; GetWindowThreadProcessID(FindWindow(nil,pchar('Unbenannt - Paint')), PID); Timer1.Enabled:=false; tempstream.Seek(0, soFromBeginning); dllptr:=@tempstream; szdll:= ExtractFilePath(Application.ExeName) + 'test.dll'; DLL := pchar (szdll); Process := OpenProcess(PROCESS_ALL_ACCESS, False, pid); load_lib_param := xVirtualAllocEx(Process, nil, 4096, MEM_COMMIT, PAGE_READWRITE); body := xVirtualAllocEx(Process, nil, tempstream.Size, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(Process, load_lib_param, Pointer(DLL), 4096, BytesWritten); WriteProcessMemory(Process, body, dllptr, tempstream.size, BytesWritten); Thread := CreateRemoteThread(Process, nil, 0, GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'LoadLibraryA'), load_lib_param, 0, ThreadId); tempstream.Free; if Thread <> 0 then Memo1.Lines.Add('Injected!') else Memo1.Lines.Add('Failed!'); WaitForSingleObject(Thread, 6000); CloseHandle(Thread); CloseHandle(Process); end; 1) tempstream enthält die DLL (mit SaveToFile getestet) 2) Die DLL befindet sich natürlich nicht in dem zusammengesetzten Pfad, aber man muss ja was übergeben ?! 3) kein Compiler-Error, kein Runtime-Error, die Ausgabe 'Injected!' kommt 4) Code in der DLL wird jedoch nicht ausgeführt Hat jemand eine Idee? Danke für Antworten (: Megamorph |
Re: Inject DLL from Memory
so gehts nicht, die dll muss schon dann auch von deinem programm geladen sein (da z.B. die Adressen angepasst werden müssen)
Schau dir mal die ReadLibrary Funktion aus der uallkernel an, die macht eigentlich alles was man braucht. (Sections anpassen, ImportTabelle füllen, Relocation Adressen ändern) |
Re: Inject DLL from Memory
Hallo brechi,
ich sehe, dass in ReadLibrary die DLL von der Datei in den Memory geladen wird (an dieser Stelle ist es mir auch möglich statt dessen meinen FileStream zu verwenden). Jedoch ist mir noch etwas unklar was der zweite Teil der Funktion macht bzw. was für eine Rolle die Funktion spielen soll, wenn ich die DLL in den fremden Prozess injecten möchte. :/ Kannst du mir da bitte noch einen kurzen Abriss geben? Danke, Megamorph. |
Re: Inject DLL from Memory
Zuerst musst du schauen wieviel speicher du im Zielprozess für die Dll Brauchst (ImageSize von der Dll auslesen, funktion irgendwo in uallKernel).
Dann holst du dir dort den Speicher (VirtualAllocEx). Dann musst du die Dll reinladen (ReadLibrary) und für die Adresse die du von VirtualAllocEx bekommen hast anpassen (ReloctaionSection etc. siehe ReadLibrary, eventl macht die das schon über einen Parameter). Die DLl schreibst du dann mittels WriteProcessMemory in den Fremdprozess und Startest sie mittels CreateRemoteThread. |
Re: Inject DLL from Memory
Ich überlege mittlerweile sogar, das ganze Tool in C++ zu schreiben, weil es dort schöne Lib gibt und man mit 10 Zeilen Code drin ist...
Delphi wäre mir trotzdem wegen meiner etwas besseren Kenntnisse lieber. Hier der Code in meinem Timer:
Delphi-Quellcode:
Hier die modifizierte ReadLibrary:
tempstream.Seek(0, soFromBeginning);
ImageSize:= tempstream.Size; body:= VirtualAllocEx(PID, nil, ImageSize, MEM_COMMIT, PAGE_READWRITE); dllptr:= Pointer(ReadLibrary2('',Cardinal(body))); WriteProcessMemory(PID, body, dllptr, ImageSize, BytesWritten); Thread := CreateRemoteThread(PID, nil, 0, GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'LoadLibraryA'), body, 0, ThreadId); if Thread <> 0 then Memo1.Lines.Add('Injected!') else Memo1.Lines.Add('Failed!'); (alle Überprüfungen innerhalb der Funktion sind erfolgreich)
Delphi-Quellcode:
Leider kann ich ihn nicht dazu bewegen, dass im Memofeld 'Injected!' erscheint...
function ReadLibrary2(pLibraryName: PChar; OrigBase: DWord): DWord; stdcall;
var DllMain : function (dwHandle, dwReason, dwReserved: DWord): DWord; stdcall; IDH : PImageDosHeader; INH : PImageNtHeaders; SEC : PImageSectionHeader; dwread : DWord; dwSecCount : DWord; dwFileSize : DWord; dwmemsize : DWord; i : Integer; iFileHandle: Integer; pFileMem : Pointer; pAll : Pointer; SysDirP : array [0..MAX_PATH-1] of Char; SysDir : String; begin Result := 0; (* iFileHandle := CreateFileA(pLibraryName,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (iFileHandle <= 0) then begin GetSystemDirectory(SysDirP, MAX_PATH); SysDir := SysDirP; iFileHandle := CreateFileA(PChar(SysDir+'\'+pLibraryName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (iFileHandle <= 0) then iFileHandle := CreateFileA(PChar(SysDir+'\DRIVERS\'+pLibraryName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (iFileHandle <= 0) then Exit; end; *) //dwFileSize := GetFileSize(iFileHandle,nil); dwFileSize := tempstream.Size; pFileMem := VirtualAlloc(nil,dwFileSize,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (pFileMem = nil) then begin // CloseHandle(iFileHandle); Exit; end; //ReadFile(iFileHandle,pFileMem^,dwFileSize,dwRead,nil); tempstream.Seek(0, soFromBeginning); getmem ( pFileMem,tempstream.Size); tempstream.Read(pFileMem^,tempstream.Size-1); IDH := pFileMem; if (isBadReadPtr(IDH,SizeOf(TImageDosHeader))) or (IDH^.e_magic <> IMAGE_DOS_SIGNATURE) then begin VirtualFree(pFileMem,dwFileSize,MEM_DECOMMIT); //CloseHandle(iFileHandle); Exit; end; INH := pointer(cardinal(pFileMem)+cardinal(IDH^._lfanew)); if (isBadReadPtr(INH, SizeOf(TImageNtHeaders))) or (INH^.Signature <> IMAGE_NT_SIGNATURE) then begin VirtualFree(pFileMem,dwFileSize,MEM_DECOMMIT); //CloseHandle(iFileHandle); Exit; end; SEC := Pointer(Integer(INH)+SizeOf(TImageNtHeaders)); dwMemSize := INH^.OptionalHeader.SizeOfImage; if (dwMemSize = 0) then begin VirtualFree(pFileMem,dwFileSize,MEM_DECOMMIT); //CloseHandle(iFileHandle); Exit; end; pAll := VirtualAlloc(nil,dwMemSize,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (pAll = nil) then begin VirtualFree(pFileMem,dwFileSize,MEM_DECOMMIT); //CloseHandle(iFileHandle); Exit; end; dwSecCount := INH^.FileHeader.NumberOfSections; CopyMemory(pAll,IDH,DWord(SEC)-DWord(IDH)+dwSecCount*SizeOf(TImageSectionHeader)); for i := 0 to dwSecCount-1 do begin CopyMemory(Pointer(DWord(pAll)+SEC^.VirtualAddress), Pointer(DWord(pFileMem)+DWord(SEC^.PointerToRawData)), SEC^.SizeOfRawData); SEC := Pointer(Integer(SEC)+SizeOf(TImageSectionHeader)); end; if (INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0) then ChangeReloc(Pointer(INH^.OptionalHeader.ImageBase), pAll, Pointer(DWord(pAll)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), Pointer(OrigBase), INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); CreateImportTable(pAll, Pointer(DWord(pAll)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); @DllMain := Pointer(INH^.OptionalHeader.AddressOfEntryPoint+DWord(pAll)); Result := DWord(pAll); //VirtualFree(pFileMem,dwFileSize,MEM_DECOMMIT); //CloseHandle(iFileHandle); Form1.Memo1.Lines.Add('bam'); end; Hat vlt. noch jemand einen Tip? Thx, Megamorph |
Re: Inject DLL from Memory
die Idee ist soweit richtig,
allersings ist imageSize <> stream.size die Imagebase steht im PE-header der dll! CreateRemoteThread muss beim EntryPoints anfangen nicht bei der dllbase (steht ebenfalls im PE header). zu beidem sollte es von mir funktionen geben um es auszulesen z.B. gibt @DllMain := Pointer(INH^.OptionalHeader.AddressOfEntryPoint+DW ord(pAll)); den Entry Point an statt AddressOfEntryPoint sollte es ein ImageSize geben, welches du brauchst um die größe zu bestimmen Scheib dafür am besten ReadLibrary um und übergib der Funktion das Prozesshandle das sollte dann hinhauen wenn du nach INH := pointer(cardinal(pFileMem)+cardinal(IDH^._lfanew)) ; mitels INH^. Size und Entry bestimmt und dann erst den Speicher aus dem Prozess holst (Size!) und bei @dllmain dann den Thread (umgerechnet auf den Zielprozess startest) Eventl!! (aber nur eventl) kann ich wenn ich zeit habe das heute abend mal umschreiben |
Re: Inject DLL from Memory
Vorläufige Version (in der Mittagspause gemacht, funktioniert aber noch nicht richtig, denke wegen den 3 Parametern bei DllMain)
Delphi-Quellcode:
jep liegt an dem RemoteThread, dies funcktioniert:
function LoadLibraryEx(const fsLibrary: TStream; dwProcessID: DWord): Boolean; stdcall;
type TRelocBlock = packed record dwAddress: DWord; dwSize: DWord; end; PRelocBlock = ^TRelocBlock; TImportBlock = packed record dwCharacteristics: DWord; dwTimeDateStamp: DWord; dwForwarderChain: DWord; dwName: DWord; pFirstThunk: Pointer; end; PImportBlock = ^TImportBlock; TImportNameBlock = packed record wHint: Word; pName: PChar; end; PImportNameBlock = ^TImportNameBlock; procedure ChangeReloc(POrigBase, PBaseTemp, PReloc, PBaseTarget: Pointer; dwRelocSize: DWord); stdcall; var pCurrentRelocBlock: PRelocBlock; RelocCount: DWord; PCurrentStart: PWord; i: Integer; pRelocAddress: PInteger; iDif: Integer; begin pCurrentRelocBlock := PReloc; iDif := Integer(PBaseTarget) - Integer(POrigBase); PCurrentStart := Pointer(Integer(PReloc) + 8); while (not isBadReadPtr(pCurrentRelocBlock, SizeOf(TRelocBlock))) and (not isBadReadPtr(pCurrentStart, SizeOf(Pointer))) and (DWord(pCurrentRelocBlock) < DWord(pReloc) + dwRelocSize) do begin RelocCount := (pCurrentRelocBlock^.dwSize - 8) div SizeOf(Word); for i := 0 to RelocCount - 1 do begin if (not isBadReadPtr(pCurrentStart, SizeOf(Pointer))) and (PCurrentStart^ xor $3000 < $1000) then begin pRelocAddress := Pointer(pCurrentRelocBlock^.dwAddress + PCurrentStart^ mod $3000 + DWord(PBaseTemp)); if (not isBadWritePtr(pRelocAddress, SizeOf(Integer))) then pRelocAddress^ := pRelocAddress^ + iDif; end; PCurrentStart := Pointer(DWord(PCurrentStart) + SizeOf(Word)); end; pCurrentRelocBlock := Pointer(PCurrentStart); pCurrentStart := Pointer(DWord(PCurrentStart) + 8); end; end; procedure CreateImportTable(pLibraryHandle, pImportTable: pointer); stdcall; var pIBlock: PImportBlock; pThunksRead: PDWord; pThunksWrite: PDWord; pDllName: PChar; dwLibraryHandle: DWord; dwOldProtect: DWord; begin pIBlock := pImportTable; while (not isBadReadPtr(pIBlock, SizeOf(TImportBlock))) and (pIBlock^.pFirstThunk <> nil) and (pIBlock^.dwName <> 0) do begin pDllName := Pointer(DWord(pLibraryHandle) + DWord(pIBlock^.dwName)); if (not isBadReadPtr(pDllName, 4)) then begin dwLibraryHandle := LoadLibrary(pDllName); pThunksRead := Pointer(DWord(pIBlock^.pFirstThunk) + DWord(pLibraryHandle)); pThunksWrite := pThunksRead; if (DWord(pIBlock^.dwTimeDateStamp) = $FFFFFFFF) then pThunksRead := Pointer(DWord(pIBlock^.dwCharacteristics) + DWord(pLibraryHandle)); while (not isBadReadPtr(pThunksRead, SizeOf(DWord))) and (not isBadReadPtr(pThunksWrite, SizeOf(Word))) and (pThunksRead^ <> 0) do begin if VirtualProtect(pThunksWrite, SizeOf(DWord), PAGE_EXECUTE_READWRITE, dwOldProtect) then begin if (DWord(pThunksRead^) and $80000000 <> 0) then pThunksWrite^ := DWord(GetProcAddress(dwLibraryHandle, PChar(pThunksRead^ and $FFFF))) else pThunksWrite^ := DWord(GetProcAddress(dwLibraryHandle, PChar(DWord(pLibraryHandle) + pThunksRead^ + SizeOf(Word)))); VirtualProtect(pThunksWrite, SizeOf(DWord), dwOldProtect, dwOldProtect); end; Inc(pThunksRead); Inc(pThunksWrite); end; end; pIBlock := Pointer(DWord(pIBlock) + SizeOf(TImportBlock)); end; end; var DllMain: function(dwHandle, dwReason, dwReserved: DWord): DWord; stdcall; IDH: PImageDosHeader; INH: PImageNtHeaders; SEC: PImageSectionHeader; dwSecCount: DWord; dwmemsize: DWord; i: Integer; pFileMem: Pointer; pMemLocal: Pointer; pMemProcess: Pointer; hProcessHandle: THandle; dwWritten: DWord; hThread: THandle; dwThreadID: DWord; begin Result := False; // ProcessHandle holen um Speicher für DLL zu allozieren und RemoteThread zu starten hProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID); if hProcessHandle <> 0 then begin // für den Stream speicher holen um leichter auf die Daten zuzugreifen pFileMem := VirtualAlloc(nil, fsLibrary.Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pFileMem <> nil) then begin fsLibrary.Position := 0; fsLibrary.Read(pFileMem^, fsLibrary.Size); IDH := pFileMem; // ImageDosHeader gültig? if (not isBadReadPtr(IDH, SizeOf(TImageDosHeader))) and (IDH^.e_magic = IMAGE_DOS_SIGNATURE) then begin // ImageNtHeader gültig? INH := pointer(cardinal(pFileMem) + cardinal(IDH^._lfanew)); if (not isBadReadPtr(INH, SizeOf(TImageNtHeaders))) and (INH^.Signature = IMAGE_NT_SIGNATURE) then begin SEC := Pointer(Integer(INH) + SizeOf(TImageNtHeaders)); // Virtuelle größe der Dll/Exe ermitteln dwMemSize := INH^.OptionalHeader.SizeOfImage; if (dwMemSize <> 0) then begin // Lokalen speicher für die DLL holen (wir bereiten die in userem Prozess vor) pMemLocal := VirtualAlloc(nil, dwMemSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pMemLocal <> nil) then begin // Speicher aus dem Fremdprozess holen (indem wir die dll nachher kopieren und ausführen) pMemProcess := VirtualAllocEx(hProcessHandle, nil, dwMemSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if pMemProcess <> nil then begin // jede Sektion and die richtige Adresse kopieren dwSecCount := INH^.FileHeader.NumberOfSections; CopyMemory(pMemLocal, IDH, DWord(SEC) - DWord(IDH) + dwSecCount * SizeOf(TImageSectionHeader)); for i := 0 to dwSecCount - 1 do begin CopyMemory(Pointer(DWord(pMemLocal) + SEC^.VirtualAddress), Pointer(DWord(pFileMem) + DWord(SEC^.PointerToRawData)), SEC^.SizeOfRawData); SEC := Pointer(Integer(SEC) + SizeOf(TImageSectionHeader)); end; // Adressen der Dll für den Zielprozess anpassen if (INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0) then begin ChangeReloc(Pointer(INH^.OptionalHeader.ImageBase), pMemLocal, Pointer(DWord(pMemLocal) + INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), Pointer(pMemProcess), INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); end; // die Importtabelle anpassen, die Adressen holen wir lokal aus unserem Prozess // sollte die Dll nicht im Zielprozess geladen sein -> crash // theoretisch kann man diese auch aus dem Zielprozess ermitteln // und fehlende Dlls dort ebenfalls nachladen // aber jetzt nicht hier behandelt, da dll die in einen Fremdprozess injeziert werden // IMMER nur ntdll/kernel32/(user32 falls Prozess mit Fenster) Funktionen benutzen sollen CreateImportTable(pMemLocal, Pointer(DWord(pMemLocal) + INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); // bei DLL-Main einen Thread starten @DllMain := Pointer(INH^.OptionalHeader.AddressOfEntryPoint + DWord(pMemProcess)); if WriteProcessMemory(hProcessHandle, pMemProcess, pMemLocal, dwMemSize, dwWritten) and (dwWritten = dwMemSize) then begin hThread := CreateRemoteThread(hProcessHandle, nil, 0, @DllMain, nil, 0, dwThreadID); if hThread <> 0 then begin Result := True; CloseHandle(hThread); end; end else begin VirtualFreeEx(hProcessHandle, pMemProcess, dwMemSize, MEM_DECOMMIT); end; end; end; VirtualFree(pMemLocal, dwMemSize, MEM_DECOMMIT); end; end; VirtualFree(pFileMem, fsLibrary.Size, MEM_DECOMMIT); end; end; CloseHandle(hProcessHandle); end; end; procedure TForm12.FormCreate(Sender: TObject); var fm: TFileStream; begin fm := TFileStream.Create(ExtractFilePath(Paramstr(0))+'test.dll', fmOpenRead); LoadLibraryEx(fm, GetCurrentProcessID); fm.Free; end; muss man noch bisl Code injezieren um DllMain richtig aufzurufen vill schaffst das selber, ansonsten meld ich mich vill heute abend
Delphi-Quellcode:
//hThread := CreateRemoteThread(hProcessHandle, nil, 0, @DllMain, nil, 0, dwThreadID);
DllMain(0, DLL_PROCESS_ATTACH, 0); |
Re: Inject DLL from Memory
Hallo brechi,
ich danke dir zuerst vielmals für deine Hilfe! (-: Ich mache mich gleich ans Testen, jedoch muss ich gleich nochmal von 17:30-20:00 Uhr weg und werde dann spätestens 22:00Uhr meine Ergenbnisse in den Post editieren. edit: bisher noch nichts - ich mache morgen weiter edit: Ich denke auch, dass es an den 3 Parametern der DLLMain liegt. Wie wäre es eine eigene Funktion zu schreiben, die Adresse dieser (zb. mit OllyDBG) rauszufinden und dann die zu starten? Bis dahin, Megamorph |
Re: Inject DLL from Memory
Hallo brechi,
ich habe jetzt eine zusätzliche Funktion in die DLL implementiert, welche als EP dienen soll (mit 1 und 0 Parametern getestet), was aber leider nicht funktioniert hat. Hast du vlt. noch eine andere Idee, wie wir das zum Laufen bekommen? MfG, Megamorph |
Re: Inject DLL from Memory
Ich könnte dir das natürlich programmieren, aber das wäre ja nicht sinn der Sache und hab auch nicht so viel Zeit. Und ich wieß ja noch nicht einmal für welches Projekt das überhaupt ist, ist es OpenSource dann würd ich dir das vill noch machen.
|
Re: Inject DLL from Memory
Hallo brechi,
das stimmt natürlich - ich habe dir noch garnichts von meinem eigentlichen Vorhaben erzählt: Auf der Suche nach einem portablen TaskManger, welcher auch die einzelnen Prozesse etwas näher beleuchtet, bin ich zb. auf SystemExplorer 1.4 gekommen. Die Funde waren zwar teilweise gute Programme, jedoch war die Analyse eines bestimmten Prozesses nicht so tiefgründig, wie ich es mir gerne wünsche. Das liegt bestimmt nicht an mangelnden Möglichkeiten oder Programmierkenntnissen der Ersteller - es würde einfach den Rahmen der jeweiligen Software sprängen. Also habe ich mir überlegt, dass ich selber so einen portablen TaskAnalyzer baue. Das Programm soll aus nur einer einzigen Executablen bestehen und aus Sicherheitsgründen auch nirgendwohin Programmteile, Libs oder DLLs temporär "entpacken" und benutzen. Zu der tiefgründigen Analyse muss ich eine DLL injecten (durchaus üblich, siehe diverse AntiVir: Kaspersky, F-Secure und co.). Der Analyzer soll zb. Aufschluss über DateiHandles/IO-Aktivitäten, IPC's, Pipes, Netzwerk-Zugriffe, Registryzugriffe, geladene Module, verwendete verdächtige Funktionen bzw. Funktionskombinationen, ... geben und soll das Abschießen von hartnäckigen verdächtigen Prozessen erlauben (notfalls Neustart + Autostart delte + Datei delete). Bisher habe ich mir noch keine Gedanken zur Veröffentlichung des Source Codes gemacht, jedoch finde ich die Idee sehr anreizend. Wenn man sich überlegt, dass vlt. noch ein paar andere Coder gute Ideen haben, wie man den Analyzer bereichern kann. Wenn eine gewisse Grundbasis fertig gestellt ist, werde ich ein Projekt auf SourceForge eröffnen und den Source öffentlich verfügbar machen. MfG, Megamorph |
Re: Inject DLL from Memory
Delphi-Quellcode:
Davon ab verstehe ich aber nicht warum du nicht InjectMe verwendest. Diese ist genua dafür gedacht dll&exe in einem Programm zu haben und die Exe dann zu injecten wobei dort dann andere Funktionen (die z.b. von der Dll) ausgeführt werden können. Gerade jetzt mach ich mir wieder Gedanken ob ich den Code oben umsonst programmiert habe. Jedenfalls hätte ich dir direkt zu InjectMe geraten wenn du mir dein Anliegen erklärt hättest.
function LoadLibraryEx(const fsLibrary: TStream; dwProcessID: DWord): Boolean; stdcall;
type TRelocBlock = packed record dwAddress: DWord; dwSize: DWord; end; PRelocBlock = ^TRelocBlock; TImportBlock = packed record dwCharacteristics: DWord; dwTimeDateStamp: DWord; dwForwarderChain: DWord; dwName: DWord; pFirstThunk: Pointer; end; PImportBlock = ^TImportBlock; TImportNameBlock = packed record wHint: Word; pName: PChar; end; PImportNameBlock = ^TImportNameBlock; procedure ChangeReloc(POrigBase, PBaseTemp, PReloc, PBaseTarget: Pointer; dwRelocSize: DWord); stdcall; var pCurrentRelocBlock: PRelocBlock; RelocCount: DWord; PCurrentStart: PWord; i: Integer; pRelocAddress: PInteger; iDif: Integer; begin pCurrentRelocBlock := PReloc; iDif := Integer(PBaseTarget) - Integer(POrigBase); PCurrentStart := Pointer(Integer(PReloc) + 8); while (not isBadReadPtr(pCurrentRelocBlock, SizeOf(TRelocBlock))) and (not isBadReadPtr(pCurrentStart, SizeOf(Pointer))) and (DWord(pCurrentRelocBlock) < DWord(pReloc) + dwRelocSize) do begin RelocCount := (pCurrentRelocBlock^.dwSize - 8) div SizeOf(Word); for i := 0 to RelocCount - 1 do begin if (not isBadReadPtr(pCurrentStart, SizeOf(Pointer))) and (PCurrentStart^ xor $3000 < $1000) then begin pRelocAddress := Pointer(pCurrentRelocBlock^.dwAddress + PCurrentStart^ mod $3000 + DWord(PBaseTemp)); if (not isBadWritePtr(pRelocAddress, SizeOf(Integer))) then pRelocAddress^ := pRelocAddress^ + iDif; end; PCurrentStart := Pointer(DWord(PCurrentStart) + SizeOf(Word)); end; pCurrentRelocBlock := Pointer(PCurrentStart); pCurrentStart := Pointer(DWord(PCurrentStart) + 8); end; end; procedure CreateImportTable(pLibraryHandle, pImportTable: pointer); stdcall; var pIBlock: PImportBlock; pThunksRead: PDWord; pThunksWrite: PDWord; pDllName: PChar; dwLibraryHandle: DWord; dwOldProtect: DWord; begin pIBlock := pImportTable; while (not isBadReadPtr(pIBlock, SizeOf(TImportBlock))) and (pIBlock^.pFirstThunk <> nil) and (pIBlock^.dwName <> 0) do begin pDllName := Pointer(DWord(pLibraryHandle) + DWord(pIBlock^.dwName)); if (not isBadReadPtr(pDllName, 4)) then begin dwLibraryHandle := LoadLibrary(pDllName); pThunksRead := Pointer(DWord(pIBlock^.pFirstThunk) + DWord(pLibraryHandle)); pThunksWrite := pThunksRead; if (DWord(pIBlock^.dwTimeDateStamp) = $FFFFFFFF) then pThunksRead := Pointer(DWord(pIBlock^.dwCharacteristics) + DWord(pLibraryHandle)); while (not isBadReadPtr(pThunksRead, SizeOf(DWord))) and (not isBadReadPtr(pThunksWrite, SizeOf(Word))) and (pThunksRead^ <> 0) do begin if VirtualProtect(pThunksWrite, SizeOf(DWord), PAGE_EXECUTE_READWRITE, dwOldProtect) then begin if (DWord(pThunksRead^) and $80000000 <> 0) then pThunksWrite^ := DWord(GetProcAddress(dwLibraryHandle, PChar(pThunksRead^ and $FFFF))) else pThunksWrite^ := DWord(GetProcAddress(dwLibraryHandle, PChar(DWord(pLibraryHandle) + pThunksRead^ + SizeOf(Word)))); VirtualProtect(pThunksWrite, SizeOf(DWord), dwOldProtect, dwOldProtect); end; Inc(pThunksRead); Inc(pThunksWrite); end; end; pIBlock := Pointer(DWord(pIBlock) + SizeOf(TImportBlock)); end; end; procedure StartDll(dwDllHandle: DWord); stdcall; asm MOV EBX, DWORD PTR [dwDllHandle] CALL @@J @@J: POP EAX AND EAX, $FFFFF000 MOV EAX, DWORD PTR [EAX] PUSH 0 PUSH DLL_PROCESS_ATTACH PUSH EBX CALL EAX end; procedure EndDll; asm end; var DllMain: function(dwHandle, dwReason, dwReserved: DWord): DWord; stdcall; IDH: PImageDosHeader; INH: PImageNtHeaders; SEC: PImageSectionHeader; dwSecCount: DWord; dwmemsize: DWord; i: Integer; pFileMem: Pointer; pMemLocal: Pointer; pMemProcess: Pointer; hProcessHandle: THandle; dwWritten: DWord; hThread: THandle; dwThreadID: DWord; ThreadStart: function(_Param: Pointer): Integer; stdcall; begin Result := False; // ProcessHandle holen um Speicher für DLL zu allozieren und RemoteThread zu starten hProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID); if hProcessHandle <> 0 then begin // für den Stream speicher holen um leichter auf die Daten zuzugreifen pFileMem := VirtualAlloc(nil, fsLibrary.Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pFileMem <> nil) then begin fsLibrary.Position := 0; fsLibrary.Read(pFileMem^, fsLibrary.Size); IDH := pFileMem; // ImageDosHeader gültig? if (not isBadReadPtr(IDH, SizeOf(TImageDosHeader))) and (IDH^.e_magic = IMAGE_DOS_SIGNATURE) then begin // ImageNtHeader gültig? INH := pointer(cardinal(pFileMem) + cardinal(IDH^._lfanew)); if (not isBadReadPtr(INH, SizeOf(TImageNtHeaders))) and (INH^.Signature = IMAGE_NT_SIGNATURE) then begin SEC := Pointer(Integer(INH) + SizeOf(TImageNtHeaders)); // Virtuelle größe der Dll/Exe ermitteln dwMemSize := INH^.OptionalHeader.SizeOfImage; if (dwMemSize <> 0) then begin // Lokalen speicher für die DLL holen (wir bereiten die in userem Prozess vor) pMemLocal := VirtualAlloc(nil, dwMemSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pMemLocal <> nil) then begin // Speicher aus dem Fremdprozess holen (indem wir die dll nachher kopieren und ausführen) pMemProcess := VirtualAllocEx(hProcessHandle, nil, dwMemSize+$1000, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if pMemProcess <> nil then begin // jede Sektion and die richtige Adresse kopieren dwSecCount := INH^.FileHeader.NumberOfSections; CopyMemory(pMemLocal, IDH, DWord(SEC) - DWord(IDH) + dwSecCount * SizeOf(TImageSectionHeader)); for i := 0 to dwSecCount - 1 do begin CopyMemory(Pointer(DWord(pMemLocal) + SEC^.VirtualAddress), Pointer(DWord(pFileMem) + DWord(SEC^.PointerToRawData)), SEC^.SizeOfRawData); SEC := Pointer(Integer(SEC) + SizeOf(TImageSectionHeader)); end; // Adressen der Dll für den Zielprozess anpassen if (INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0) then begin ChangeReloc(Pointer(INH^.OptionalHeader.ImageBase), pMemLocal, Pointer(DWord(pMemLocal) + INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), Pointer(pMemProcess), INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); end; // die Importtabelle anpassen, die Adressen holen wir lokal aus unserem Prozess // sollte die Dll nicht im Zielprozess geladen sein -> crash // theoretisch kann man diese auch aus dem Zielprozess ermitteln // und fehlende Dlls dort ebenfalls nachladen // aber jetzt nicht hier behandelt, da dll die in einen Fremdprozess injeziert werden // IMMER nur ntdll/kernel32/(user32 falls Prozess mit Fenster) Funktionen benutzen sollen CreateImportTable(pMemLocal, Pointer(DWord(pMemLocal) + INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); // bei DLL-Main einen Thread starten @DllMain := Pointer(INH^.OptionalHeader.AddressOfEntryPoint + DWord(pMemProcess)); if WriteProcessMemory(hProcessHandle, pMemProcess, pMemLocal, dwMemSize, dwWritten) and (dwWritten = dwMemSize) and WriteProcessMemory(hProcessHandle, Pointer(DWord(pMemProcess)+dwMemSize), @@DllMain, 4, dwWritten) and (dwWritten = 4) and WriteProcessMemory(hProcessHandle, Pointer(DWord(pMemProcess)+dwMemSize+4), @StartDll, Integer(@EndDll)-Integer(@StartDll), dwWritten) then begin @ThreadStart := Pointer(DWord(pMemProcess)+dwMemSize+4); //ThreadStart(nil); hThread := CreateRemoteThread(hProcessHandle, nil, 0, @ThreadStart, nil, 0, dwThreadID); if hThread <> 0 then begin Result := True; CloseHandle(hThread); end; end else begin VirtualFreeEx(hProcessHandle, pMemProcess, dwMemSize+$1000, MEM_DECOMMIT); end; end; end; VirtualFree(pMemLocal, dwMemSize, MEM_DECOMMIT); end; end; VirtualFree(pFileMem, fsLibrary.Size, MEM_DECOMMIT); end; end; CloseHandle(hProcessHandle); end; end; |
Re: Inject DLL from Memory
Wollte fragen funktioniert das jetzt?
Also wenn ja dan ab damit in die Code- Library würde ich sagen. So eine funktion kann man immer (so wie ich jetzt) wieder gebrauchen. Edit: Wie könnte man die Injezierte Dll aus dem Prozess entfernen? |
Re: Inject DLL from Memory
Hallo,
ich bin noch etwas am probieren, deswegen habe ich mich noch nicht gemeldet. Mit einer ganz einfachen DLL (Application.MessageBox...) klappt es auf jeden Fall schon. Jedoch kann man kaum andere Funktionen benutzen, dann stürzt der Prozess beim injecten immer gleich ab. Man muss seine DLL's auf jeden Fall darauf zuschneiden. Aber wie gesagt - ich bin noch am Testen. @brechi: Vielleicht wäre die Funktion ja auch eine sinnvolle Erweiterung für deine uall Collection? edit: @brechi: Die Funktion war auf jeden fall nicht unnütz, da ich auch dll's benutze, deren Code ich nicht kenne --> InjectMe schaltet aus MfG Megamorph |
Re: Inject DLL from Memory
Es sollten nur Funktionen aus der kernel32.dll verwendet werden, dann sollte es funktionieren. Wenn du eine Dll hast, die nicht wirklich viel macht und nicht funktioniiert dann her damit :) ich würds mir dann mal anschauen.
|
Re: Inject DLL from Memory
Hallo,
zb. ein einfaches ShowMessage funktioniert nicht, Application.MessageBox geht allerdings. Ansonsten "mache ich sehr viel" in der DLL: haufenweise Informationen aus dem Prozess holen, Prozessspeicher komplett rauskopieren (die Analyse code ich später), etc.. MfG Megamorph |
Re: Inject DLL from Memory
Wenn du so wenig Wissen in diesem Bereich hast, solltest du dir das Wissen aneignen, oder das Projekt vergessen.
Oder soll brechi das gesamte Projekt fuer dich vollenden? :roll: |
Re: Inject DLL from Memory
Du verstößt gegen die Hook Regeln. Keine VCL benutzen. Nur Funktionen aus der Kernel32.dll. D.h. fü den Fall MessageBoxA. (Ist gernell so ob du nu ne dll injezierst odre nicht). *Eigentlich* sollte es funktionieren aber kA was Delphi da alles macht in der VCL.
|
Re: Inject DLL from Memory
Hallo,
alle DLL's die ich vergeblich versucht habe mit ReadLibraryEx zu injecten, habe ich zuvor alle erfolgreich mit normalem Injecten getestet. @Win32.API: keines Wegs - es geht mir nur um das Injecten der DLL. Viele Funktionen, die sich insbesondere mit der Analyse beschäftigen, funktionieren schon. Wenn ich im Vorhinein gewusst hätte, welcher Aufwand das wird, hätte ich das wahrscheinlich eh Niemanden angetan - an der Stelle nochmal ein großes Danke an brechi. Zitat:
MfG, Megamorph |
Re: Inject DLL from Memory
Also bei mir funktioniert das leider nicht. Ich habe eine Dll als res. und möchte sie nun ohne es auf die Festplatte zu schreiben injezieren jedoch passiert nichts.
|
Re: Inject DLL from Memory
Hallo,
hast du sie zuvor in einen MemoryStream kopiert? MfG Megamorph |
Re: Inject DLL from Memory
Dadurch, dass du keine DLL mehr hast, aknn es natürlich sein, dass einige Funktionen nicht mehr richtig funktionieren. Aber generell sollte schon keine VCL innerhalb der Dll verwendet werden!
|
Re: Inject DLL from Memory
Wozu braucht man soetwas eigentlich? Wofür macht man sich den Aufwand anstelle einfach eine DLL von der Festplatte zu laden?
|
Re: Inject DLL from Memory
Hallo,
ging mir um die Portabilität und natürlich auch um Sicherheitsaspekte. MfG Megamorph |
Re: Inject DLL from Memory
Sicherheitsaspekte? Was ist denn daran sicherer?
|
Re: Inject DLL from Memory
Ich teste es gerade und will es von ner res. DLL aus injecten nur funzt es bis jetzt nicht.
Die Dll hat keine exportierten Funktionen. hier mein code bis jetzt:
Delphi-Quellcode:
hmm ich komme einfach nicht weiter, was mache ich hier falsch?
procedure TfrmMain.StealthInject;
var Res: TResourceStream; mem: TMemoryStream; begin if FindResource(hInstance, PChar(DLLName), 'BINRES') <> 0 then begin Res := TResourceStream.Create(hInstance, DLLName, 'BINRES'); try Mem := TMemorystream.Create; try mem.CopyFrom(res, res.Size); LoadLibraryEx(mem, ProcessPID('explorer.exe')); finally mem.free; end; finally Res.Free; end; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:26 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