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
Java: Wieso funktioniert der Zähler vom Stack nicht?

Außer folgender Klasse gibt es noch eine Klasse Queue und Stack. Kann mir jemand erklären, warum die Münzen des 1 und 2 Euro sowie des 50 Cents Stapels funktionieren und die des 20 und 10 Cent Stapels nicht? Danke.

package muenzen;

import java.util.*;

public class muenzen {
  public static int muenze;
  public static int ausgabe, zaehler, zaehler2, zaehler3, zaehler4, zaehler5;
  public static double wert2, wert;

  static Scanner sc = new Scanner(System.in);
  static Stack<Integer> muenzen = new Stack<>();
  static Stack<Integer> zehncent = new Stack<>();
  static Stack<Integer> zwanzigcent = new Stack<>();
  static Stack<Integer> fuenfzigcent = new Stack<>();
  static Stack<Integer> eineuro = new Stack<>();
  static Stack<Integer> zweieuro = new Stack<>();
  
  public static void stapelerstellen() {
    for (int i = 0; i < 20; i++) {
      System.out.println("Welchen Wert hat die Münze? (10 Cent/ 20 Cent/ 50 Cent/ 1 Euro/ 2 Euro)");
      muenze = sc.nextInt();

      if (muenze == 1) {
        eineuro.push(muenze);
      }
      else if (muenze == 2) {
        zweieuro.push(muenze);
      }
      else if (muenze == 10) {
        zehncent.push(muenze);
      }
      else if (muenze == 20) {
        zwanzigcent.push(muenze);
      }
      else if (muenze == 50) {
        fuenfzigcent.push(muenze);
      }
      else {
        System.out.println("Ungültige Eingabe. Bitte probieren Sie es erneut.");
      }
    }
  }

  public static void stapelausgabe() {
    zaehler = 0;
    zaehler2 = 0;
    zaehler3 = 0;
    zaehler4 = 0;
    zaehler5 = 0;

    while (!eineuro.isEmpty() || !zweieuro.isEmpty() || !zehncent.isEmpty() || !zwanzigcent.isEmpty() || !fuenfzigcent.isEmpty() ) {
      while (!eineuro.isEmpty()) {
        eineuro.pop();
        zaehler = zaehler + 1;
      }

      wert = zaehler;
      System.out.println("Auf dem 1€ Stapel liegen/liegt " + zaehler + " Münze(n). Er hat somit einen Wert von " + wert + "€");

      while (!zweieuro.isEmpty()) {
        zweieuro.pop();
        zaehler2 = zaehler2 + 1;
      }

      wert = zaehler2 * 2;
      System.out.println("Auf dem 2€ Stapel liegen/liegt " + zaehler2 + " Münze(n). Er hat somit einen Wert von " + wert + "€");

      while (!fuenfzigcent.isEmpty()) {
        fuenfzigcent.pop();
        zaehler3 = zaehler3 + 1;
      }

      wert = zaehler3 * 50 / 100;
      wert2 = wert * 100;
      System.out.println("Auf dem 50 Cent Stapel liegen/liegt " + zaehler3 + " Münze(n). Er hat somit einen Wert von " + wert + "€ oder " + wert2 + " Cent");

      while (!zwanzigcent.isEmpty()) {
        zwanzigcent.pop();
        zaehler4 = zaehler4 + 1;
      }

      wert = zaehler4 * 20 / 100;
      wert2 = wert * 100;
      System.out.println("Auf dem 20 Cent Stapel liegen/liegt " + zaehler4 + " Münze(n). Er hat somit einen Wert von " + wert + "€ oder " + wert2 + " Cent");

      while (!zehncent.isEmpty()) {
        zehncent.pop();
        zaehler5 = zaehler5 + 1;
      }

      wert = zaehler5 * 10 / 100;
      wert2 = wert * 100;
      System.out.println("Auf dem 10 Cent Stapel liegen/liegt " + zaehler5 + " Münze(n). Er hat somit einen Wert von " + wert + "€ oder " + wert2 + " Cent");
    }
  }

  public static void main(String[] args) {
    stapelerstellen();
    stapelausgabe();
  }
}
programmieren, Java, Eclipse, Programmiersprache, Zähler, stack
Umgekehrte Polnische Notation / Postfix-Notation über Stack programmieren, so richtig?

Hallo,

ich soll die umgekehrte polnische Notation / Postfix-Notation in Java mit Hilfe eines Stacks programmieren. Dafür stehen mir nur folgende Informationen zur Verfügung:

public class IntegerStack {
  public boolean emptystack();
  public int head();
  public void push(int i);
  public int pop();
}

Leider zeigt ein Testfall als Fehler Folgendes an:

IntegerStack s = new IntegerStack();
String[] input = {"1", "2", "*", "3", "4", "*", "+"};
Calculator(input, s);
System.out.println(s.compareHistory(new String[] {
  "[1]",
  "[1, 2]",
  "[1]",
  "[]",
  "[2]",
  "[2, 3]",
  "[2, 3, 4]",
  "[2, 3]",
  "[2]",
  "[2, 12]",
  "[2]",
  "[]",
  "[14]",
  "[]" }
));

// erwartet:
true
// erhalten:
wrong history length: target 14 - is 0
false

Ich kann diesen Fehler nicht deuten. Kann mir bitte jemand sagen, was da falsch sein soll? Ich weiß nicht, was ich beheben soll.

Anbei mein Code:

public int Calculator(String[] input, IntegerStack s) {
  s = new IntegerStack();

  for (int i = 0; i < input.length; i++) {
    switch(input[i]) {
      case "+":
        int x = s.pop();
        int y = s.pop();

      
          s.push(y + x);
        
        break;
      case "-":
        x = s.pop();
        y = s.pop();

       
          s.push(y - x);
        
        break;
      case "/":
        x = s.pop();
        y = s.pop();

      
          s.push(y / x);
       
        break;
      case "*":
        x = s.pop();
        y = s.pop();

        
          s.push(y * x);
        
        break;
      case " ":
        break;
      default:
        if (input[i] != null) {
          s.push(Integer.parseInt(input[i]));
        }
        else {
        }
        ;
      }
    }

    int z = s.pop();
    return z;
  }
Computer, Freizeit, Studium, Schule, Mathematik, programmieren, Java, Informatik, Physik, stack, Algorithmen und Datenstrukturen
Pivotwahl bei Quicksort und Quickselect?

Guten Abend,

ich bräuchte mal kurz Hilfe bei folgenden Aufgaben, bitte. Es geht mir darum, dass ich einfach nicht versteh', was zu tun ist. Wir hatten in der Vorlesung den Quicksort-Algorithmus. Ich weiß, dass bei Quicksort das zu sortierende Array in immer kleiner Teilarrays eingeteilt wird, wobei das größere Array zuerst auf den Stack gelegt wird. Das Pivotelement ist entweder das linke oder das rechte und man setzt dann links und rechts einen Pointer am entsprechenden Teilarray. Ist das erste Element des zu sortierenden Teilarrays, welches größer als das Pivotelement ist, gefunden, und es findet sich vom rechten Pointer aus das erste Element, welches kleiner als das Pivotelement ist, so werden diese vertauscht. Bei Überkreuzungen tausche jenes Element auf dass der linke Pointer zeigt mit dem Pivotelement. So hatten wir's zumindest in der Vorlesung (Partitionswahl). Zu den Aufgaben

Aufgabe 1

Ein wichtiger Faktor für die Laufzeit von Quicksort und Quickselect (das Auswahlverfahren des k-kleinsten Elements analog zu Quicksort) ist die Wahl des Pivotelements. Das Pivotelement sollte die zu sortierende Folge in zwei möglichst gleich große Teilfolgen aufspalten.Gegeben sei eine unsortierte Folge mit n paarweise verschiedenen Elementen. Weiterhin sei r(x) die Position des Elements x in der sortierten Folge. Eine mögliche Strategie für die Pivotwahl ist:Wähle uniform zufällig 7 Elemente aus der Eingabefolge und gib das viertkleinste als Pivotelement aus. Dabei können Elemente in der Auswahl mehrmals vorkommen (Ziehen mit Zurücklegen)

.a) Berechne die Wahrscheinlichkeit für das Ereignis: n/4 < r(Pivot) ≤ 3n/4.

b) Nach wie vielen unabhängigen Wiederholungen der Pivotwahl ist zu erwarten, dass der Rang des Pivotelements das erste Mal außerhalb des Intervalls aus Aufgabenteil a) liegt? Hinweis: Du darfst annehmen, dass n= 4·kfür ein k∈N.

Aufgabe 2

Konstruiere eine Folge der Länge7, so dass Quickselect bei Verwendung der Pivotfunktionpivot(links, rechts) =⌈(links+rechts)/2⌉ auf der Suche nach dem viertgrößten Schlüssel die Problemgröße stets nur um 1verringert. Der Algorithmus soll insgesamt also sieben Schritte benötigen, bis er terminiert. Wende Quickselect auf Ihre Folge an, um die Korrektheit zu zeigen

Ansatz Ich verstehe hier nicht, wie n/4 gemeint ist. Wir hatten in der Vorlesung immer das Pivotelement ganz links oder ganz rechts. Jetzt steht hier "Pivot(links,rechts) = [(links+rechts)/2]. Greift man sich also da Element in der Mitte? Das ist bei einer Folge der Länge 7 doch nicht möglich, oder? WIe gehe ich allgemein vor um eine solche Folge zu finden.

LG

Jensek81

Computer, Schule, Mathematik, programmieren, rechnen, Array, Informatik, Theoretische Informatik, Algorithmus, stack, Binomialverteilung, Quicksort, Sortieralgorithmus, Algorithmen und Datenstrukturen
C Programmierung: Scanf-befehl funktioniert nicht nach If- Anweisung

Guten Tag habe da ein Problem bei einem Programm an dem ich gerade arbeite: Ich soll mit Kommandos (list, pop, push und exit) einen Stack mit zeichen füllen, das letzte zeichen löschen, eine Liste des Stacks ausgeben oder das Programm verlassen. Momentan funktioniert nur das verleassen des Programms, da der Scanf-befehl hinter der if-Anweisung nach dem Kompilieren nicht ausgeführt wird, um ein Zeichen einzulesen. (fgetc() hat auch nicht funktioniert).

Vielleicht kann mir ja jemand erklären woran es liegt.

Quelltext:

include include include define NSTACK 15

int main(){ //Anfang Main

//Variablendeklaration char eingabe[6]; char stack[NSTACK]; char item; char z; //zwischenspeicher für zeichen int sp=0; //Ende Variablendeklaration

printf("\nStack auffüllen (bis 15 Zeichen)\n");
printf("Liste der Befehle:\n\n");
printf("list = Liste des Stacks anzeigen\n");
printf("push = Zeichen auf den Stack legen\n");
printf("pop = Zeichen vom Stapel nehmen\n");
printf("exit = Programm beenden\n\n");

 while(eingabe){    //Eingabeschleife

  printf("\nBitte geben Sie ihren Befehl ein: ");
  scanf("%s", &eingabe);
  printf("eingegebener Befehl: %s\n", eingabe);

  
  if (strcmp(eingabe,"exit") == 0){             //exit
printf("\n!!Das Programm wird beendet!!\n");
exit(1);
  } //ende exit
  
  else if (strcmp(eingabe,"push") == 0){            //push
scanf("%c", &z);
printf("Zeichen wird auf Stack gelegt\n");
  } //ende push
  else if (strcmp(eingabe,"pop") == 0){         //pop
printf("Das obertste Zeichen wird entfernt\n");
  } //ende pop
  else if (strcmp(eingabe,"list") == 0){            //liste ausgeben
printf("Die Liste des Stacks wird ausgegeben\n");
printf("%s\n", &stack);
  } //ende list
  
 }  //Ende eingabeschleife
 


printf("\ntest");

printf("\n\n"); return 0; } //Ende Main

programmieren, Informatik, scan, stack, C (Programmiersprache)

Meistgelesene Fragen zum Thema Stack