![]() |
[Lib] Shellcode Forger für einfache Codeausführung in Fremdprozessen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
bei meinem letzten Projekt kam ich in die Verlegenheit Code in einem anderen Prozess ausführen zu müssen. Eine komplette DLL Injection wollte ich vermeiden, da die Codemenge in diesem Fall nur sehr gering war. Nun kann man natürlich einfach den Assembler Code einer kompletten Delphi Funktion injizieren und ausführen. Dies bringt allerdings einige Schwierigkeiten mit sich:
Um diesen Problemen entgegenzuwirken, habe ich eine Klasse geschrieben, welche Code erzeugen kann, der direkt in einem anderen Prozess ausführbar ist. Für den maximalen Komfort wird der Shellcode in einer Klasse gekapselt, die ihr von TBasicShellcode ableiten müsst. Alle Felder der Klasse werden zur Laufzeit im Fremdprozess verfügbar sein. Ebenfalls könnt ihr alle Klassenfunktionen für die Verwendung im Shellcode registrieren (nur VIRTUAL Methods) und so Unterfunktionen ganz intuitiv verwenden. Wenn der Shellcode externe API Imports benötigt, so reicht es einfach die jeweilige Funktion an ein beliebiges Feld der Klasse zu binden. Beispiel:
Delphi-Quellcode:
const
ID_WSTRING_INFO = $00000001; ID_WSTRING_INFO_TEXT = $00000002; ID_WSTRING_QUESTION = $00000003; ID_WSTRING_QUESTION_TEXT = $00000004; type TMyShellcode = class(TBasicShellcode) private FMessageTitle: PWideChar; FMessageText: PWideChar; FMessageFlags: DWord; private APIBeep: function(dwFreq, dwDuration: DWORD): BOOL; stdcall; APIMessageBoxW: function(hWnd: HWND; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall; private function ShowQuestion(Text, Title: PWideChar): Integer; virtual; procedure DoShowMessage; virtual; protected procedure RegisterImports(Forger: TBasicShellcodeForger); override; procedure RegisterMethods(Forger: TBasicShellcodeForger); override; procedure RegisterStrings(Forger: TBasicShellcodeForger); override; protected function Initialize({Param: Pointer}): DWord; override; function Finalize: DWord; override; end; { TMyShellcode } function TMyShellcode.ShowQuestion(Text, Title: PWideChar): Integer; begin Result := APIMessageBoxW(0, Text, Title, MB_ICONQUESTION or MB_YESNO); end; procedure EndOfTMyShellcodeShowQuestion; begin end; function TMyShellcode.Initialize({Param: Pointer}): DWord; begin APIBeep(1000, 200); FMessageText := FindWideString(ID_WSTRING_INFO_TEXT); FMessageTitle := FindWideString(ID_WSTRING_INFO); FMessageFlags := MB_ICONINFORMATION; DoShowMessage; Result := 0; end; procedure EndOfTMyShellcodeInitialize; begin end; procedure TMyShellcode.DoShowMessage; begin APIMessageBoxW(0, FMessageText, FMessageTitle, FMessageFlags); end; procedure EndOfTMyShellcodeDoShowMessage; begin end; function TMyShellcode.Finalize: DWord; begin APIBeep(500, 200); Result := ShowQuestion(FindWideString(ID_WSTRING_QUESTION_TEXT), FindWideString(ID_WSTRING_QUESTION)); end; procedure EndOfTMyShellcodeFinalize; begin end; procedure TMyShellcode.RegisterImports(Forger: TBasicShellcodeForger); begin inherited; RegisterImport(Forger, @@APIBeep, 'kernel32.dll', 'Beep'); RegisterImport(Forger, @@APIMessageBoxW, 'user32.dll', 'MessageBoxW'); end; procedure TMyShellcode.RegisterMethods(Forger: TBasicShellcodeForger); begin inherited; RegisterMethod(Forger, @TMyShellcode.Initialize, NativeUInt(@EndOfTMyShellcodeInitialize) - NativeUInt(@TMyShellcode.Initialize)); RegisterMethod(Forger, @TMyShellcode.Finalize, NativeUInt(@EndOfTMyShellcodeFinalize) - NativeUInt(@TMyShellcode.Finalize)); RegisterMethod(Forger, @TMyShellcode.ShowQuestion, NativeUInt(@EndOfTMyShellcodeShowQuestion) - NativeUInt(@TMyShellcode.ShowQuestion)); RegisterMethod(Forger, @TMyShellcode.DoShowMessage, NativeUInt(@EndOfTMyShellcodeDoShowMessage) - NativeUInt(@TMyShellcode.DoShowMessage)); end; procedure TMyShellcode.RegisterStrings(Forger: TBasicShellcodeForger); begin inherited; RegisterWideString(Forger, ID_WSTRING_INFO, 'Info'); RegisterWideString(Forger, ID_WSTRING_INFO_TEXT, 'Hello hello boys and girls!'); RegisterWideString(Forger, ID_WSTRING_QUESTION, 'Question'); RegisterWideString(Forger, ID_WSTRING_QUESTION_TEXT, 'Bye bye. What do you want me to return?'); end;
Delphi-Quellcode:
Feedback und Verbesserungsvorschläge erwünscht!
var
Forger: TBasicShellcodeForger; ProcessHandle, ThreadHandleA, ThreadHandleB: THandle; Shellcode: TMemoryStream; ShellcodeSize: DWord; BaseAddress, ProcEntryPoint, ProcDestructor: Pointer; BytesWritten: SIZE_T; TID, ExitCode: DWord; begin Forger := TBasicShellcodeForger.Create(TMyShellcode); try ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, false, {Process ID}); if (ProcessHandle <> 0) and (ProcessHandle <> INVALID_HANDLE_VALUE) then try ShellcodeSize := Forger.GetShellcodeSize; BaseAddress := VirtualAllocEx(ProcessHandle, nil, ShellcodeSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if Assigned(BaseAddress) then try Shellcode := TMemoryStream.Create; try Forger.GenerateShellcode(BaseAddress, Shellcode, ProcEntryPoint, ProcDestructor); if (WriteProcessMemory(ProcessHandle, BaseAddress, Shellcode.Memory, Shellcode.Size, BytesWritten)) and (BytesWritten = Shellcode.Size) then begin ThreadHandleA := CreateRemoteThread(ProcessHandle, nil, 0, ProcEntryPoint, BaseAddress, 0, TID); if (ThreadHandleA <> 0) and (ThreadHandleA <> INVALID_HANDLE_VALUE) then try WaitForSingleObject(ThreadHandleA, INFINITE); if GetExitCodeThread(ThreadHandleA, ExitCode) then begin MessageBox(0, PChar(Format('Shellcode initialize returned: %.8x.', [ExitCode])), 'Info', MB_ICONINFORMATION); end; finally CloseHandle(ThreadHandleA); end; ThreadHandleB := CreateRemoteThread(ProcessHandle, nil, 0, ProcDestructor, BaseAddress, 0, TID); if (ThreadHandleB <> 0) and (ThreadHandleB <> INVALID_HANDLE_VALUE) then try WaitForSingleObject(ThreadHandleB, INFINITE); if GetExitCodeThread(ThreadHandleB, ExitCode) then begin MessageBox(0, PChar(Format('Shellcode finalize returned: %.8x.', [ExitCode])), 'Info', MB_ICONINFORMATION); end; finally CloseHandle(ThreadHandleB); end; end; finally Shellcode.Free; end; finally VirtualFreeEx(ProcessHandle, BaseAddress, ShellcodeSize, MEM_RELEASE or MEM_FREE); end; finally CloseHandle(ProcessHandle); end; finally Forger.Free; end; end; Viele Grüße Zacherl |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:52 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