![]() |
Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP)
Hey,
ich muss die Adresse einer Funktion in meiner eigenen EXE herausfinden ohne den @ Operator zu verwenden. Wie kann ich sowas realisieren? Kann ich irgendwie mit Assembler tricksen, sodass ich die betreffende Funktion aufrufe und in dieser irgendwie CS:IP ermittele? Gruß |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Hoppla, wozu brauchst du das denn? Und inwiefern kannst du die Funktion verändern?
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Ich kann in die Funktion alles reinschreiben was ich möchte. In dem speziellen Szenario, welches ich habe, funktioniert der @ Operator im Bezug auf Funktionsadressen unter Vista nicht korrekt.
CreateThread mit @ThreadProc als dritten Parameter schlägt fehlt. GetLastError liefert mir ERROR_BAD_EXE_FORMAT. Daher suche ich nun nach Alternativen .. sowas wie @Array[0] hingegen z.b. unter Verwendung von CopyMemory funktioniert allerdings wunderbar .. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
:gruebel:
Und was hat das mit Vista zu tun? Das @ wird vom Compiler umgesetzt. Er weis ja, an welche Stelle er die Funktion geschrieben hat. Was machst du genau? Der üblich Weg innerhalb der Funktion ist so:
Delphi-Quellcode:
..aber das passt nicht ganz zu dem beschriebenen Problem :wiejetzt: .
function xyz
asm call @@n //dadurch landet die Rücksprungadresse auf dem Stack (diese zeigt auf den nächsten Befehl "pop eax") @@n: pop eax //Adresse vom Stack holen add eax,-5 //und zurückrechnen auf den Anfang der Funktion ... //weiter im Text end; |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Mit Vista hat es insofern zu tun, dass es nur dort nicht mit dem @ Funktioniert. Das Szenario ist folgendes: Ich habe ein Programm, welches ich nach dem Prinzip von Nicos InMemExe direkt aus einer Resource starte.
Rufe ich in diesem unter XP CreateThread auf, wird der Thread ganz normal gestartet, wie es sein sollte. Rufe ich nun CreateThread unter Vista auf, wird ERROR_BAD_EXE_FORMAT von GetLastError zurückgegeben. Deshalb dachte ich, könnte man die Adressen der Funktionen erst mit einem einfachen Aufruf [ThreadProc(nil)] ermitteln, in einer globalen Variable speichern und dann die Adresse an CreateThread übergeben .. Edit: Grade mal getestet. Die Adresse wird korrekt ermittelt, der Aufruf von CreateThread schlägt leider immer noch fehl =/ |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Zitat:
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Zitat:
Vielleicht wurde einfach nur CreateThread modifizert. Wenn jemand ein Beispiel zum Aufruf von NtCreateThread hätte, würde mir das vielleicht weiterhelfen. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Hast du auch mal gesehen ob der Anfang der Funktion wirklich der Anfang ist. Manchmal (also bei längeren Funktionen) packt der Compiler noch einiges davor.
Edit: Hast du mal die ImageBase überprüft? |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Ja, starte ich die EXE auf normale Weise funktioniert das CreateThread. Das sollte also nicht der Fehler sein. Was muss ich bei der ImageBase beachten?
Versuch mit NtCreateThread (Alle nativen Funktionen schlagen fehl -.- Ich weiß aber auch nicht genau, was ich da alles initialisieren muss und vor allem wie ..):
Delphi-Quellcode:
function ThreadProc(P: Pointer): Cardinal; stdcall;
begin MessageBox(0, 'Thread', 'Info', MB_SYSTEMMODAL); end; procedure DoCreateThread; const THREAD_TERMINATE = $0001; THREAD_SUSPEND_RESUME = $0002; THREAD_GET_CONTEXT = $0008; THREAD_SET_CONTEXT = $0010; THREAD_SET_INFORMATION = $0020; THREAD_QUERY_INFORMATION = $0040; THREAD_SET_THREAD_TOKEN = $0080; THREAD_IMPERSONATE = $0100; THREAD_DIRECT_IMPERSONATION = $0200; THREAD_SET_LIMITED_INFORMATION = $0400; THREAD_QUERY_LIMITED_INFORMATION = $0800; THREAD_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $03FF; var ThreadHandle: Cardinal; DesiredAccess: Cardinal; ObjectAttributes: OBJECT_ATTRIBUTES; ProcessHandle: Cardinal; ClientID: CLIENT_ID; ThreadContext: CONTEXT; UserStack: USER_STACK; CreateSuspended: Boolean; P: Pointer; begin DesiredAccess := THREAD_ALL_ACCESS; ObjectAttributes.Length := SizeOf(OBJECT_ATTRIBUTES); ObjectAttributes.RootDirectory := 0; ObjectAttributes.ObjectName := nil; ObjectAttributes.Attributes := 0; ObjectAttributes.SecurityDescriptor := nil; ObjectAttributes.SecurityQualityOfService := nil; ProcessHandle := GetCurrentProcess; FillChar(ThreadContext, SizeOf(CONTEXT), 0); ThreadContext.Eip := Longint(@ThreadProc); UserStack.FixedStackLimit := Pointer($1000000); UserStack.FixedStackBase := Pointer($1000000); if not NT_SUCCESS(NtAllocateVirtualMemory(ProcessHandle, @UserStack.ExpandableStackBottom, 0, UserStack.FixedStackLimit, MEM_RESERVE, PAGE_READWRITE)) then begin MessageBox(0, 'NtAllocateVirtualMemory1 failed', '', 0); end; UserStack.ExpandableStackBase := Pointer(Cardinal(UserStack.ExpandableStackBottom) + Cardinal(UserStack.FixedStackLimit)); UserStack.ExpandableStackLimit := Pointer(Cardinal(UserStack.ExpandableStackBase) - Cardinal(UserStack.FixedStackBase)); if not NT_SUCCESS(NtAllocateVirtualMemory(ProcessHandle, UserStack.ExpandableStackLimit, 0, UserStack.FixedStackBase, MEM_RESERVE, PAGE_READWRITE)) then begin MessageBox(0, 'NtAllocateVirtualMemory2 failed', '', 0); end; if not NT_SUCCESS(NtCreateThread(@ThreadHandle, DesiredAccess, @ObjectAttributes, ProcessHandle, @ClientID, @ThreadContext, @UserStack, CreateSuspended)) then begin MessageBox(0, 'NtCreateThread failed', '', 0); end; end; |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
ERROR_BAD_EXE_FORMAT tritt zum Beispiel auf wenn eine 32-Bit-Anwendung auf Vista x64 eine 64-Bit-DLL anzieht (anziehen will).
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Hat das irgendwas mit
![]() Hast du in deiner Exe eigentlich funktionierende globale Variablen? Dann könnte man die Image-Base nämlich ausschließen, da globale Variablen ja wie Funktionszeiger absolut adressiert werden. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
@Apollonius: Ja da hatte ich mich schonmal mit der Sache beschäftigt. Globale Variablen funktionieren ..
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Ob es an der geänderten Image Base liegt, kannst Du doch ganz simpel ausprobieren, indem Du die eingebettete Exe standalone startest. Wenn das auch nur Fehler 193 liefert, dann verweigert Vista wohl einfach Exen die nicht bei $00400000 im Speicher anfangen. Warum muss es denn überhaupt eine komplette Exe sein? Kannst Du nicht einfach etwas relevanten Code in eine frei relozierbare Form bringen und einfach irgendwo im Speicher ausführen? Ich kann Dir da gerne helfen, dazu muss ich dann mir aber natürlich den ganzen Kram anschauen.
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Also es scheint nicht an der ImageBase zu liegen, da das Programm normal ausgeführt keinerlei Fehler verursacht. Aber auch wenn meine eigene ImageBase 0x004000000 ist und ich das Programm aus der Resource ausführe bekomme ich 193 wenn ich versuche CreateThread aufzurufen .. es muss irgendeinen Grund geben, den ich bisher übersehen habe.
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Wir können ja leider nicht testen (mir fehlt schonmal das BS dazu). Aber gib doch mal aktuelle Adressen des Codes aus, oder sende es per Message. Kannst du mit dem@-Operator die Adresse einer anderen Funktionsvariablen (var x:function(...)) zuweisen und diese dann starten?
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Du meinst so:
Delphi-Quellcode:
Ja das funktioniert :)
function ThreadProc(P: Pointer): Cardinal; stdcall;
begin MessageBox(0, 'Thread', 'Info', MB_SYSTEMMODAL); Result := 0; end; var X: function(P: Pointer): Cardinal; stdcall; ... @X := @ThreadProc; X(nil); |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
hmmm :roll:
Jetzt könnte man noch schauen, wie sieht der Stack aus vor dem Aufruf con CreateThread, und wie die Sprungadresse. Und dass dann vergleichen... Wird ja immer umständlicher. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Wie kann ich das nachgucken? Mit OllyDbg? Weil ich starte ja praktisch den Prozess neu und injiziere dann den Code der EXE aus der Resource.
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Erhlich gesagt: keine Ahnung :pale: Aber irgendetwas muss ja anders sein.
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Ich muss mir noch den grundlegenden Artikel mit dem inmemexe durchlesen, bin gerade bei meinen Eltern zu Besuch :) Aber hast Du auch dafür gesorgt, dass die injizierte Exe mit allen notwendigen Imports und Relocs versehen wird? Allerdings würd das nicht direkt erklären warum das auf XP geht und auf Vista nicht. Handelt es sich eigentlich um ein 32-Bit oder 64-Bit Vista?
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Es ist ein 32 Bit Vista. Ich habe einfach die Funktionen von Nico aufgerufen und so wie ich das verstanden habe, wird ja der Speicher des Zielprozesses sozusagen überschrieben und nacheinander alle Sections der Quelldatei in den Speicher der Zieldatei geschrieben. Die Relocations und Imports sollten also eigentlich vorhanden sein.
Außer dem CreateThread funktioniert die injizierte EXE ja auch. Habe es jetzt mal hier unter Vista testweise mit der nativen NtCreateThreadEx versucht, in der Hoffnung, dass diese evtl. funktioniert. War allerdings nicht der Fall. Das normale NtCreateThread zum Laufen zu bekommen ist mir bisher noch nicht gelungen, allerdings befürchte ich, dass dieser Ansatz das Problem auch nicht lösen kann .. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
![]() also da wird etwas in der laufenden EXE geändert ^^ Innerhalb der If Result Then Begin-Abfrage wird die EXE getautscht und in der neuen EXE was ersetzt ... stattdessen kann man auch die ganze EXE ersetzten :stupid: |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Mh, wüsste nicht, wie mir das jetzt weiterhelfen könnte :P Das Ändern der laufenden EXE mache ich ja frei nach Nicos InMemExe Beispiel ..
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Nur ist es doch garnicht nötig erst soweit auszuholen
und so richtig scheint es ja über die InMemExe ja auch nicht zu laufen ;) |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Unter XP läuft alles perfekt, nur halt unter Vista nicht. Würde mich auch so einfach mal interessieren, was da so grundlegend geändert wurde.
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Nunja, wenn in Programm an einem anderem Platz geladen werden muß, dann muß Windows doch die Adressen verschieben.
Wenn beide Programme an die selbe Adresse geladen werden sollen, dann muß doch die InMemExe werschoben und alle Zeiger die auf sie zeigen müssen ebenfalls zur neuen Position verschoben werden ... vielleicht hat Microsoft da was geändert? ich hätte da eher gedacht daß es gesser geht wenn die InMemExe eine andere Position hat, als die laufende Exe :gruebel: (warum hat dein Programm eigentlich nicht ImageBase = $004000000 ? ... nur mal so aus Neugierde) |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Nene die Sache ist da noch bisschen komplizierter. Die ImageBase habe ich mittlerweile auch wieder auf $004000000 festgelegt, allerdings musste ich bemerken, dass es auch mit dieser ImageBase unter Vista nicht funktioniert.
Das Prinzip der InMemExe ist ja folgendes: Es wird der Zielprozess suspended gestartet. Danach werden alle ImageNtSections der QuellEXE durchgegangen und mittels VirtualAllocEx und WriteProcessMemory in den Zielprozess gebracht. So sollte man praktisch die QuellEXE im Kontext des Zielprozesses ausführen, was ja auch funktioniert. Nur der komische ERROR_BAD_EXE_FORMAT Fehler unter Vista im Zusammenhang mit CreateThread gibt mir Rätsel auf. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Du hast OldGrumpy's Frage zu den 64 Bit noch nicht beantwortet ... also nutzt du nun ein Vista64?
[add] übersehn Wenn ja, dann kommt dieser Fehler wohl ganz schön oft da vor :shock: ![]() [add] :gruebel: |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Hat er doch:
Zitat:
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Autsch, also dass das so funktioniert, ist echt erstaunlich. Es gibt aber Randbedingungen die Du vielleicht nicht kennst. Wenn Du einen Prozess suspended startest, dann geht der Systemloader erstmal hin, erzeugt einen Prozess, lädt das Image in den Speicher, lädt DLLs dazu die in der Import table vermerkt sind, erzeugt die ganzen Tabellen mit Systemadressen (die Funktionsnamen werden in konkrete Adressen aufgelöst und in einer Sprungtabelle vermerkt), TLS behandelt, und noch einiges mehr. Erst danach kehrt der Systemloader zurück. Wenn Du jetzt die Exe im Prozess mit Deiner eigenen überschreibst, dann muessten IMHO:
- Die Abhängigkeiten 1:1 identisch sein, d.h. alle Imports gleich (alle DLLs und Funktionen daraus) - Der Einsprungpunkt identisch sein (es sei denn man geht hin und ändert die Prozessorregister des Hauptthreads entsprechend) - Die Exe an der original image base address liegen und ausgeführt werden (da keine Relocations bearbeitet werden) Ich vermute mal stark, dass Vista im Zuge der verbesserten Systemsicherheit da zusätzliche Checks verpasst bekommen hat. Ich kann mich gerne mal in der Richtung umhören, vielleicht weiss da jemand was :) |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mir eine Unit nach dem InMemExe Prinzip gebastelt. Vielleicht hilft es dir, wenn du den Code siehst.
//Edit 1: Ich bemerke grade etwas .. und zwar funktioniert der CreateThread aufruf unter Vista doch. Allerdings nur unter gewissen Vorraussetzungen. Zum Testen habe ich als Zielprozess die ganze Zeit notepad.exe verwendet. Jetzt habe ich testweise mal firefox.exe genommen und siehe da es funktioniert oO Woran könnte das liegen? Ein extra Schutz für MS Dateien? Mit iexplore.exe funktioniert es auch nicht. //Edit 2: Verwende ich in den Microsoft Exen CreateThread ist der Fehler ERROR_BAD_EXE_FORMAT, verwende ich die native NtCreateThreadEx Funktion, welche erst unter Vista zur Verfügung steht, liefert SysErrorMessage: "%1 ist keine gültige Win32 Anwendung!" |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
ERROR_BAD_EXE_FORMAT kommt meist als Fehler zurück wenn ImageDosHeader.e_magic, ImageNtHeaders.Signature oder die Characteristics nicht korrekt ist. Das heißt, dass dein Pointer möglicherweise auf was falsches zeigt? möööööglich wäre es.
Du könntest aber noch die 2 Programme vergleichen (also die PE-header) und unterschiede feststellen (zB ImageBase, welche Tabellen sind vorhanden und welche nicht (Bound IAT, etc.)). Benutz Stud PE für die analyse der Dateien, ist ein gutes Programm für sowas. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Der Pointer ist richtig. Was ich beim ersten analysieren mit PE Explorer schon festegestellt habe, ist, dass die Characteristics von iexplore und firefox zum Beispiel unterschiedlich sind.
Ich lade mir jetzt mal Stud PE runter und vergleiche die Images :) IEXPLORE: Characteristics: 102 FIREFOX: Characteristics: 10F Ansonsten scheint alles (bis auf die verschiedenen Imports / Exports) gleich zu sein. //Edit: Teilweise erscheint bei NtCreateThreadEx auch noch der Fehler: "Unzulässiger Zugriff auf einen Speicherbereich" |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
versuche mal
Delphi-Quellcode:
Gruß Hagen
procedure ThreadProc(); stdcall; export;
exports ThreadProc; procedure Test; var P: Pointer; begin P := GetProcAddress(Instance, 'TheadProc'); CreateThread(..., P, ..); end; |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Funktioniert leider auch nicht. GetLastError liefert mir jetzt: "%1 ist keine zulässige Win32-Anwendung"
- Bei nicht MS Exen funktioniert es allerdings. :gruebel: |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Dann liegt es möglicherweise daran das MS Exe Dateien diese Data Directories haben
Edit: also ich glaube es liegt eher an IMAGE_DIR_ENTRY_BOUND_IMPORT. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Zitat:
Zitat:
Zitat:
Und wie ich oben schon erwähnte, müssen die Exen für diese Tauschaktion recht ähnlich sein. Auf jeden Fall muss das Characteristics-Field identisch sein. Bit 0 nicht gesetzt heisst zum Beispiel dass das File Relocations enthält. Wenn dann Exe und PE-Header dazu im Konflikt stehen, könnte das schon ausreichen. JFTR: Meine notepad.exe (XP) hat auch nicht 0x00400000 als image base sondern 0x01000000 :) Allerdings Characteristics 0x010f, womit teilweise erklärt sein dürfte, warum es unter XP geht, aber nicht unter Vista. |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Okay, danke für eure Antworten, ich werde das heute Abend nach der Schule nochmal genauer testen. :)
|
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
bei dem iexplore7 könnte es auch dran liegen dass der in ner sandbox gestartet wird unter vista (unter xp nicht).
die sandbox spielt dabei "firewall" zwischen dem prozess des iexplore und dem system. vielleicht liegt es auch daran dass dieser effekt auftritt. notepad allerdings benutzt IMHO diese sandbox methode nicht.. gruß Reli |
Re: Adresse einer Funktion ohne @ ermitteln (evtl über CS:IP
Es tritt bei allen MS Executables auf. Egal ob Notepad, Calc, Cmd, IExplore, Explorer, etc .. das ist vollkommen egal. Ich versuche jetzt mal die BoundIAT zu nullen.
Zitat:
// Edit 1: Das Nullen der IMAGE_DIR_ENTRYs bringt nichts. Und mir fällt noch etwas auf. Kopiere ich z.b. notepad.exe unter dem Namen notepad2.exe (oder irgeneinen Anderen), will die Datei nicht mehr starten :wall: Es passiert einfach nichts. // Edit 2: :arrow: Ich habs. Es liegt doch an der ImageBase -.- Ich bemerke grade, dass die MS Dateien alle die ImageBase 0x01000000 haben, mein Programm aber ganz normal 0x00400000. Setze ich die ImageBase von Notepad auf $00400000, dann lässt sich Notepad zwar nicht mehr starten, aber ich kann die Resource in den Prozess injizieren und CreateThread funktioniert auch. Nur möchte ich ja grade verhindern irgendwie die Dateien selbst zu verändern und sei es nur den Header anzupassen. Kann man den Code zum Injizieren nicht irgendwie anpassen, sodass an der richtigen ImageBase injiziert wird und die injizierte EXE Resource aber trotzdem noch die richtigen Adressen verwendet? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:19 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