Das Programm mitten im Vergleich anhalten
Der Debugger gdb startet ein Programm unter seiner Aufsicht und hält es an einer Stelle an, die Sie bestimmen. Dann lesen Sie Register und Speicher, also genau das, was das Programm in diesem Moment vergleicht.
Das hilft, wenn ein Text erst beim Start entsteht und in der Datei nirgends als Ganzes steht.
Am Ende dieser Lektion
Notiz
Ich kann ein Programm in gdb anhalten und lesen, welche zwei Texte es vergleicht.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Debugger | ein Werkzeug, das ein Programm anhält und seinen Speicher zeigt | gdb |
| Haltepunkt | eine Stelle, an der der Debugger das Programm anhält | break main |
| Zeiger | eine Adresse, die auf Daten im Speicher zeigt | |
| rdi | das Register mit dem ersten Argument einer Funktion | |
| rsi | das Register mit dem zweiten Argument einer Funktion | |
| x/s | der gdb-Befehl, der den Text an einer Adresse zeigt |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Programm baut sein Wort erst beim Start
Das Programm bib prüft einen Ausweiscode. Der richtige Code steht nicht als Ganzes in der Datei. Er entsteht beim Start aus drei Teilen: einem Wort, einem Formatstück und einer Zahl.
Bauen Sie es wie in den Lektionen davor und löschen Sie den Quelltext. Danach zeigt strings, was in der Datei steht, und was nicht.
Den Übungsordner anlegen, falls er fehlt
mkdir -p ~/uebungHier 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
cd ~/uebungHier 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 bib schreiben
printf '%s\n' '#include <stdio.h>' '#include <string.h>' 'int main(int argc, char **argv) {' ' char code[32];' ' if (argc != 2) {' ' puts("Aufruf: bib CODE");' ' return 2;' ' }' ' snprintf(code, sizeof code, "%s%d", "bib", 2026 + 1);' ' if (strcmp(argv[1], code) == 0) {' ' puts("Ausweis gueltig.");' ' return 0;' ' }' ' puts("Ausweis ungueltig.");' ' return 1;' '}' > bib.cHier 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 bauen
gcc -O0 -no-pie -fno-stack-protector -o bib bib.cHier 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
rm bib.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Was strings in bib findet
strings bib | grep -E "bib|%s"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
gdb hält das Programm an einem Haltepunkt an
Der Code ist nirgends zu lesen. Aber das Programm muss ihn mit strcmp vergleichen, und dabei liegen beide Texte im Speicher. Also halten Sie das Programm bei strcmp an.
Der Ablauf hat zwei Schritte. Erst break main, damit das Laden fertig ist, dann break strcmp. Das Ladeprogramm ruft strcmp auch selbst auf, und gdb würde sonst dort zuerst anhalten. LD_BIND_NOW=1 lässt es alles vorher binden.
Die zwei Texte bei strcmp lesen
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run falsch' -ex 'break strcmp' -ex 'continue' -ex 'x/s $rdi' -ex 'x/s $rsi' bib 2>&1 | grep '^0x'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: was die zwei Ausgabezeilen zeigen
| Zeile | Register | Der Text |
|---|---|---|
| Erste Zeile | rdi | Das Wort, das Sie auf der Kommandozeile mitgegeben haben |
| Zweite Zeile | rsi | Der Text, mit dem das Programm vergleicht |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Register enthält eine Adresse
Ein Register hält eine Zahl. Bei einem Argument vom Typ Text ist es die Adresse, an der der Text beginnt. x/s liest den Text ab dieser Adresse, bis er endet.
info registers rdi rsi zeigt die zwei Zahlen selbst, einmal in Hexadezimal und einmal als Dezimalzahl. Das grep behält nur diese zwei Zeilen.
Die zwei Adressen selbst ansehen
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run falsch' -ex 'break strcmp' -ex 'continue' -ex 'info registers rdi rsi' bib 2>&1 | grep -E '^(rdi|rsi)'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 denken, break strcmp halte beim Aufruf aus dem eigenen Programm. gdb hält aber beim ersten Aufruf von strcmp überhaupt, auch beim Aufruf des Ladeprogramms. Halten Sie zuerst in main an. Prüfen Sie dann, ob der erste Text Ihre eigene Eingabe ist.
Weiterführend
Lesen Sie den zweiten Text und rufen Sie ./bib damit auf. Gibt das Programm „Ausweis gueltig.“ aus?
Ändern Sie die Zeile mit run falsch in run x. Welche Zeile der Ausgabe ändert sich, welche nicht? Das erklärt, warum der zweite Text der feste ist.