Added writeups

This commit is contained in:
m0rph3us1987
2026-03-08 12:22:39 +01:00
parent a566ea77d1
commit a79656b647
43 changed files with 6940 additions and 0 deletions

104
de/echo_chamber.md Normal file
View File

@@ -0,0 +1,104 @@
# Echo Chamber
Hallo! Willkommen zum Write-up für **Echo Chamber**. Dies ist eine klassische "pwn"-Challenge, die eine sehr verbreitete, aber mächtige Schwachstelle demonstriert: die **Format-String-Schwachstelle**.
In dieser Challenge erhalten wir ein kompiliertes Binary. Wenn wir den ursprünglichen Quellcode nicht haben, verwenden wir Tools wie **Ghidra**, um das Binary zu dekompilieren und zu sehen, was das Programm "unter der Haube" macht.
---
## 1. Erste Erkundung (Reconnaissance)
Wenn wir das Programm ausführen, bittet es um eine Eingabe und gibt sie "echoförmig" zurück:
```text
Welcome to the Echo Chamber!
Give me a phrase, and I will shout it back: Hello!
You said: Hello!
```
Die Beschreibung des Entwicklers gibt uns einen Hinweis:
> "Der Entwickler behauptet, es sei vollkommen sicher, weil 'es keinen Code ausführt, sondern nur Text druckt'."
Dies ist eine klassische "Berühmte letzte Worte"-Situation in der IT-Sicherheit! Schauen wir uns den dekompilierten Code an, um zu verstehen, warum.
## 2. Analyse des dekompilierten Codes (Ghidra)
Beim Öffnen des Binarys in Ghidra finden wir die Funktion `vuln()`. Hier ist der Pseudocode, den wir erhalten:
```c
void vuln(void)
{
char acStack_a0 [64]; // Unser Eingabepuffer
char local_60 [72]; // Hier wird das Flag gespeichert
FILE *local_18;
local_18 = fopen64("flag.txt","r");
if (local_18 == (FILE *)0x0) {
puts("Flag file is missing!");
exit(0);
}
// 1. Das Flag wird in local_60 eingelesen
fgets(local_60,0x40,local_18);
fclose(local_18);
puts("Welcome to the Echo Chamber!");
printf("Give me a phrase, and I will shout it back: ");
// 2. Unsere Eingabe wird in acStack_a0 eingelesen
fgets(acStack_a0,0x40,(FILE *)stdin);
printf("You said: ");
// 3. SCHWACHSTELLE: Unsere Eingabe wird direkt an printf übergeben!
printf(acStack_a0);
putchar(10);
return;
}
```
Siehst du die Zeile `printf(acStack_a0);`? Das ist unser "goldenes Ticket".
## 3. Die Schwachstelle: Format-Strings
In C erwartet `printf`, dass sein erstes Argument ein **Format-String** ist (wie `"%s"` oder `"Hallo %s"`). Wenn ein Entwickler die Benutzereingabe direkt an `printf` übergibt, kann der Benutzer seine eigenen Format-Spezifizierer angeben.
Wenn `printf` einen Spezifizierer wie `%p` (Pointer drucken) oder `%x` (Hexadezimalwert drucken) sieht, sucht es nach dem nächsten Argument auf dem **Stack**. Wenn wir keine Argumente angeben, beginnt `printf` einfach damit, alles auszugeben, was sich bereits auf dem Stack befindet!
### Wo ist das Flag?
Wenn wir uns die Ghidra-Ausgabe ansehen, bemerken wir, dass sowohl `acStack_a0` (unsere Eingabe) als auch `local_60` (das Flag) **lokale Variablen** sind. Das bedeutet, dass beide direkt nebeneinander auf dem Stack gespeichert sind.
## 4. Ausnutzen des "Echos"
Wenn wir eine Kette von Format-Spezifizierern wie `%p %p %p %p %p %p...` senden, können wir `printf` dazu bringen, den Inhalt des Stacks auszugeben. Da das Flag auf dem Stack liegt, wird es schließlich mit ausgedruckt!
Versuche dies als Eingabe:
`%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p`
Das Programm wird mit einer Reihe von Hexadezimal-Adressen antworten. Einige dieser Werte sind tatsächlich die ASCII-Zeichen unseres Flags.
### Little Endianness
Wenn du die Hex-Werte siehst, denke daran, dass moderne Systeme die **Little Endian**-Byte-Reihenfolge verwenden. Das bedeutet, dass die Bytes in umgekehrter Reihenfolge gespeichert werden.
Wenn du zum Beispiel `0x7b67616c66` siehst und diese Bytes von Hexadezimal in ASCII umwandelst:
- `66` = `f`
- `6c` = `l`
- `61` = `a`
- `67` = `g`
- `7b` = `{`
Der Wert `0x7b67616c66` repräsentiert also `flag{` in umgekehrter Reihenfolge!
## 5. Alles zusammenfügen
Um die Challenge zu lösen:
1. Verbinde dich mit dem Dienst.
2. Sende viele `%p`-Spezifizierer, um den Stack auszulesen (Leak).
3. Identifiziere die Hex-Werte, die wie lesbarer Text aussehen (beginnend mit `0x...` und ASCII-Werte enthaltend).
4. Kehre die Bytes um (Endianness) und wandle sie in Zeichen um.
5. Kombiniere die Teile, um das Flag zu finden!
## Gelernte Lektionen
Selbst wenn ein Programm "nur Text druckt", ist es nicht sicher, wenn es `printf` falsch verwendet. Die Lösung ist einfach: Verwende immer `printf("%s", buffer);`. Dies stellt sicher, dass die Eingabe als reine Zeichenkette behandelt wird und nicht als Code oder Anweisungen für die Funktion.
Viel Erfolg beim Hacken!