Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Rechenschritte im Programm rückwärts auflösen

Nach dieser Lektion: Ich kann eine Prüfung aus Addieren, xor und Subtrahieren rückwärts auflösen.

Lektion, 65 Min.10 BefehleReverse-Engineering-Lab: Programme mit gdb, radare2, strace und ltrace in einer VM lesen

Eine Prüfung aus drei Rechenschritten

Manche Programme prüfen eine Zahl nicht mit einem festen Wert. Sie rechnen erst, etwa mit Addieren, xor und Subtrahieren, und vergleichen das Ergebnis.

Wer die Schritte im Assembler liest, kann sie rückwärts rechnen und die Zahl bestimmen, die die Prüfung besteht.

Am Ende dieser Lektion

Notiz

Ich kann eine Prüfung aus Addieren, xor und Subtrahieren rückwärts auflösen.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Konstanteeine feste Zahl im Befehl0x19
Hexadezimalein Zahlensystem mit 16 Ziffern, geschrieben mit 0x davor0x2b
xorverknüpft zwei Zahlen Bit für Bit, gleiche Bits ergeben 0
Umkehrungder Rechenschritt, der einen anderen aufhebt
Zielwertdie Zahl, mit der die Prüfung am Ende vergleicht
Überlaufeine 32-Bit-Zahl beginnt nach 4294967295 wieder bei 0

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein Programm prüft eine Zahl in drei Schritten

Das Programm zahl bekommt eine Zahl und rechnet damit: erst xor mit einer Zahl, dann plus, dann minus. Ist das Ergebnis der Zielwert, sagt es „Zahl stimmt“.

Die vier Zahlen stehen beim Bauen in der Befehlszeile. So kann eine Lehrkraft jedem Studierenden ein anderes Programm geben. Danach löschen Sie wieder den Quelltext.

Den Übungsordner anlegen, falls er fehlt

Befehl
mkdir -p ~/uebung

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

In den Übungsordner wechseln

Befehl
cd ~/uebung

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Den Quelltext von zahl schreiben

Befehl
printf '%s\n' '#include <stdio.h>' '#include <stdlib.h>' 'static int pruefe(unsigned n) {' '    unsigned x = n;' '    x = x ^ MASKE;' '    x = x + PLUS;' '    x = x - MINUS;' '    return x == ZIEL;' '}' 'int main(int argc, char **argv) {' '    if (argc != 2) {' '        puts("Aufruf: zahl ZAHL");' '        return 2;' '    }' '    if (pruefe((unsigned)strtoul(argv[1], 0, 10))) {' '        puts("Zahl stimmt.");' '        return 0;' '    }' '    puts("Zahl stimmt nicht.");' '    return 1;' '}' > zahl.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das Programm mit vier Zahlen bauen

Befehl
gcc -O0 -no-pie -fno-stack-protector -DMASKE=43 -DPLUS=25 -DMINUS=9 -DZIEL=1000 -o zahl zahl.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Den Quelltext löschen

Befehl
rm zahl.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Jeder Rechenschritt wird ein Befehl

Der Compiler macht aus jeder Zeile x = x ^ … einen Befehl: xor, add oder sub. Die Zahl steht als Konstante im Befehl, meist hexadezimal geschrieben.

Die Funktion heißt pruefe. Lesen Sie ihre Befehle mit objdump. Das grep behält die Zeilen mit Befehlen. Achten Sie auf xor, add, sub und das cmp am Ende.

Die Befehle der Funktion pruefe ansehen

Befehl
objdump -d -M intel --no-show-raw-insn --disassemble=pruefe zahl | grep '^ '

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: Befehl, hexadezimale Zahl und Schritt

BefehlZahl im BefehlDer Schritt
xor …,0x2b0x2b ist 43x wird mit 43 xor verknüpft
add …,0x190x19 ist 25x wird um 25 größer
sub …,0x90x9 ist 9x wird um 9 kleiner
cmp …,0x3e80x3e8 ist 1000Vergleich mit dem Zielwert

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Eine hexadezimale Zahl umrechnen

Befehl
echo $((0x3e8))

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Rückwärts rechnen heißt: letzten Schritt zuerst aufheben

Das Programm rechnet xor, dann plus, dann minus. Sie beginnen beim Zielwert und heben die Schritte in umgekehrter Reihenfolge auf: erst das Minus, dann das Plus, zuletzt das xor.

Ein Plus hebt ein Minus auf, und umgekehrt. Ein xor mit derselben Zahl hebt sich selbst auf.

Beispiel: vom Zielwert 1000 zurück zur Zahl

Schritt zurückRechnungErgebnis
Start beim Zielwert10001000
sub 9 aufheben1000 + 91009
add 25 aufheben1009 - 25984
xor 43 aufheben984 xor 431011

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Den Rückweg in der Shell rechnen

Befehl
echo $(( ((1000 + 9) - 25) ^ 43 ))

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die gefundene Zahl ausprobieren

Befehl
./zahl 1011

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ein häufiger Fehler

Warnung

Viele rechnen die Schritte in derselben Reihenfolge zurück, in der das Programm sie ausführt. Das ergibt eine falsche Zahl. Das Programm hat zuletzt subtrahiert, also müssen Sie zuerst addieren. Heben Sie die Schritte von unten nach oben auf.

Eine 32-Bit-Zahl läuft über

Zahlen im Prozessor haben 32 Bit. Die größte ist 4294967295, danach beginnt sie wieder bei 0. Zieht ein Programm von einer kleinen Zahl etwas Größeres ab, kommt eine sehr große Zahl heraus.

Beim Zurückrechnen gilt dasselbe. Python rechnet mit dem Rest nach 4294967296, damit das Ergebnis im Bereich bleibt.

Null minus eins mit 32 Bit

Befehl
echo $(( (0 - 1) & 4294967295 ))

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Weiterführend

Bauen Sie zahl neu, mit anderen Zahlen als -DMASKE, -DPLUS, -DMINUS und -DZIEL. Lesen Sie die vier Konstanten aus objdump, rechnen Sie die Zahl zurück und prüfen Sie sie mit ./zahl.

Die Programme des Labs lesen Sie später auf dieselbe Weise. Dort stehen Ihnen die Zahlen nicht in der Befehlszeile zur Verfügung.

Über dieses Lab und seinen Quellcode: Reverse-Engineering-Lab: Programme mit gdb, radare2, strace und ltrace in einer VM lesen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.