Wie kriege ich mit ROP einen "/bin/sh" Pointer in rdi?

Ich versuche, rücksprungorientierte Programmierung (ROP) zu lernen.

Und zwar habe ich ein Programm mit einem Pufferüberlauf auf dem Stack, und ich möchte das Programm dazu bringen, /bin/sh zu öffnen.

Das geht mit dem execve Syscall, wenn ich die richtigen Instruktionen finden kann, um die Funktionsparameter vorzubereiten. Das ist die Signatur von execve:

int execve(const char *pathname, char *const _Nullable argv[], char *const _Nullable envp[]);

Also muss ich die folgenden Register setzen:

  • rax = 0x3b (Syscallnummer von execve)
  • rdi = "/bin/sh" Pointer
  • rsi = NULL
  • rdx = NULL

Die folgenden Instruktionen habe ich bereits gefunden:

pop rax ; ret
pop rdi ; ret
pop rsi ; ret
pop rdx ; ret
syscall

Ich kann also die Instruktionen und Registerwerte mit dem Pufferüberlauf auf den Stack schreiben und so meine Register füllen. Das Problem ist aber, dass ich einen "/bin/sh" Pointer in rdi brauche (also nicht "/bin/sh" im Register, sondern eine Speicheradresse, an der "/bin/sh" steht).

Ich kann natürlich "/bin/sh" in den Puffer auf dem Stack schreiben, aber leider ist die Speicheradresse jedes Mal anders und ich kenne sie vorher nicht.

Ich weiß, dass "/bin/sh" in libc vorkommt, aber auch dort ist die Speicheradresse jedes Mal anders und ich kenne sie vorher nicht.

Wie komme ich also an einen "/bin/sh" Pointer? Gibt es Tricks oder bestimmte Instruktionen, nach denen ich mich umsehen sollte?

hacken, Hack, Programm, programmieren, pointer, Assembler, Hacker, Hacking, Informatik, IT-Sicherheit, Shell, stack, x64, assemblersprache, Assembly, Exploit, hacken lernen, IT-Sicherheitsexperte, Register, Capture The Flag
Programm dass Subtrahieren soll durch Addition?

Hallo Leute heute eine etwas untypische Aufgabe:

Wir schreiben das Jahr 2042. Nach einer extremen Verschärfung der Finanzkrise können die Universitäten nur noch sehr preiswerte Rechner anschaffen. Zum Glück hat der führende Prozessorhersteller Inrola gerade einen neuen Chip namens Untium auf den Markt gebracht. Dieser Chip ist so preiswert, weil er nur noch genau eine Instruktion hat nämlich „subtract-and-branch-on-less-zero“. Dieser Befehl hat vier Parameter, Quelle 1 (Q1), Quelle 2 (Q2), Zielregister (ZR) und Sprungadresse (SA). Wird der Befehl aufgerufen, berechnet er Q1 − Q2, schreibt das Ergebnis in ZR und springt dann nach SA, wenn das Ergebnis, das er in ZR geschrieben hat, kleiner als 0 ist (sonst folgt die Bearbeitung des Befehls in der folgenden Zeile). Der Untium-Prozessor verfügt über 6 Ganzzahlregister, $1 bis $6. Als Quelle kann entweder ein Register oder eine ganzzahlige Konstante angegeben werden, ZR ist immer ein Register. SA gibt die Nummer des Befehls an, zu dem eventuell gesprungen werden soll.Als Studierende kommt Ihnen die Ehre zuteil, den ersten Rechner dieses Typs, den SPOZ-I zu testen. Da zu einem so frühen Zeitpunkt noch keine Compiler zur Verfügung stehen, müssen sie den 1-Befehl-Assembler benutzen. Ein Assemblerprogramm besteht aus Zeilen der Form:

Q1, Q2, ZR, SA // optional kann hier ein Kommentar stehen

Ich soll jetzt herausfinden, sie eine wie eine Addition durchgeführt werden kann. Dabei seien die Sum-

manden in den Registern $1 und $2 vorgegeben. Die Summe soll nach der Berechnung in $3 stehen. Ich bin da leider nicht gehirntechnisch in der Lage, die Aufgabe zu lProgramm dass Subtrahieren soll durch Additionösen...

Programm, Assembler, Register
Wie sind die Registerkonvention im Assembler zu verstehen?

Guten Morgen,
ich bin Schülerstudentin und sitze seit ca 1 Woche an einer Aufgabe in Mips, die wir nun endlich fertig haben. Nun sind wir allerdings auf ein Problem gestoßen und zwar wissen wir nicht wie wir mit den Registerkonventionen umzugehen haben.

Ich zähle nun einmal die Regeln zu einer Funktion mit Funktionsaufrufen (nicht Blattfunktion auf), darunter (in dick) befinden sich meine Fragen und Kommentare.

Konventionen:

– Sichere $ra auf dem Stack!

Ist für uns klar, denn die Returnadresse geht sonst nach einem Funktionsaufruf verloren und es kommt zu einer Endlosschleife.

– Weise Variablen, die nach einem Aufruf benötigt werden, an

einen $si Register zu und sichere zuvor $si auf dem Stack.

– weise Variablen, die nach einem Aufruf nicht länger benötigt

werden, an einen $ti Register zu

Ich nehme diese zwei Punkte einmal zusammen, denn hier beginnt das böse Übel.
Wie ist das denn eigentlich gemeint ? Ich persönlich verstehe es so, dass die $si Register vor dem Aufruf in den Stack geladen werden müssen, wenn sie in der aufzurufenden Funktion auch vorhanden sind. Und durch das Speichern wird der Wert nicht überschrieben. Die Frage wäre nun, wenn ich ein Register (z.b für einen Counter) benötige, dass nicht in der aufzurufenden Funktion vorkommt, ich es auch auf den Stack speichern muss, oder ob es dann ein t Register wird, statt ein s?

Man sagt ja, dass die t-Register sind für die Haltung kurzlebiger (temporärere) Variablen bestimmt sind. Nur was ist damit genau gemeint?

– kopiere Argumente ($ai) , die nach einem Aufruf benötigt

werden, in ein $si-Register und sichere zuvor $si auf dem

Keller

Was meint man hiermit genau.

Es wäre sehr nett, wenn ihr konkret werden würdet, denn ich verstehe das meiste im Internet schon nicht.

Vielen Dank im Voraus

Luisa

Computer, Mathematik, CPU, programmieren, Assembler, Informatik, Programmiersprache, Register

Meistgelesene Fragen zum Thema Register