Added writeups
This commit is contained in:
115
de/false_flags.md
Normal file
115
de/false_flags.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# False Flags
|
||||
|
||||
`falseFlags` ist eine einsteigerfreundliche Reverse-Engineering-Challenge. Wir erhalten eine Binärdatei, die mehrere "falsche" Flaggen enthält, und unser Ziel ist es, die richtige zu identifizieren.
|
||||
|
||||
## 1. Erste Analyse
|
||||
|
||||
Wir beginnen mit der Untersuchung des Dateityps und der grundlegenden Eigenschaften.
|
||||
|
||||
```bash
|
||||
$ file false_flags
|
||||
false_flags: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=..., for GNU/Linux 3.2.0, stripped
|
||||
```
|
||||
|
||||
Es ist eine Standard-64-Bit-ELF-ausführbare Datei. Versuchen wir, sie auszuführen. Die Challenge ist auch remote verfügbar unter `<SERVER_IP>:1301`.
|
||||
|
||||
```bash
|
||||
$ nc <SERVER_IP> 1301
|
||||
=== The Vault of Falsehoods ===
|
||||
There are many keys, but only one opens the door.
|
||||
Enter the password: test
|
||||
[-] Wrong! That was merely a decoy.
|
||||
```
|
||||
|
||||
Da die Beschreibung "versteckte Passwörter in der Binärdatei" erwähnt, ist der `strings`-Befehl ein guter erster Schritt, um zu sehen, was drin ist.
|
||||
|
||||
```bash
|
||||
$ strings false_flags | grep flag
|
||||
{flag:This_Is_Definitely_Not_It}
|
||||
{flag:Try_Harder_To_Find_The_Key}
|
||||
{flag:Strings_Are_Misleading_You}
|
||||
...
|
||||
{flag:Reverse_Engineering_Is_Cool}
|
||||
...
|
||||
```
|
||||
|
||||
Wir sehen eine lange Liste potenzieller Flaggen. Wir könnten sie eine nach der anderen ausprobieren, aber das ist mühsam (und "Brute-Force" ist nicht der elegante Weg!). Wir müssen herausfinden, mit *welchem* spezifischen String das Programm unsere Eingabe vergleicht.
|
||||
|
||||
## 2. Statische Analyse
|
||||
|
||||
Wir können die Binärdatei mit `objdump` analysieren, um uns den Assembler-Code anzusehen. Da die Binärdatei "stripped" ist, sehen wir keine Funktionsnamen wie `main`. Wir können jedoch den Einsprungpunkt finden.
|
||||
|
||||
```bash
|
||||
$ readelf -h false_flags | grep "Entry point"
|
||||
Entry point address: 0x4019f0
|
||||
```
|
||||
|
||||
Der Einsprungpunkt ist bei `0x4019f0`. Wenn wir an dieser Adresse disassemblieren, sehen wir den Startcode (`_start`), der `__libc_start_main` aufruft. Das erste Argument für `__libc_start_main` ist die Adresse von `main`.
|
||||
|
||||
```bash
|
||||
$ objdump -d -M intel --start-address=0x4019f0 --stop-address=0x401a20 false_flags
|
||||
|
||||
00000000004019f0 <.text+0x830>:
|
||||
...
|
||||
401a08: 48 c7 c7 52 1b 40 00 mov rdi,0x401b52 <-- Adresse von main
|
||||
401a0f: 67 e8 5b 15 00 00 addr32 call 0x402f70 <-- Aufruf von __libc_start_main
|
||||
...
|
||||
```
|
||||
|
||||
Also befindet sich `main` bei `0x401b52`. Disassemblieren wir sie.
|
||||
|
||||
```bash
|
||||
$ objdump -d -M intel --start-address=0x401b52 --stop-address=0x401c50 false_flags
|
||||
```
|
||||
|
||||
In der Ausgabe sehen wir früh in der Funktion einen Aufruf:
|
||||
|
||||
```assembly
|
||||
401ba0: e8 70 ff ff ff call 0x401b15
|
||||
401ba5: 89 85 6c ff ff ff mov DWORD PTR [rbp-0x94],eax
|
||||
```
|
||||
|
||||
Der Rückgabewert (in `eax`) wird in `[rbp-0x94]` gespeichert. Diese Variable wird später verwendet, um auf ein Array zuzugreifen. Schauen wir uns an, was `0x401b15` tut.
|
||||
|
||||
```bash
|
||||
$ objdump -d -M intel --start-address=0x401b15 --stop-address=0x401b52 false_flags
|
||||
|
||||
0000000000401b15 <.text+0x955>:
|
||||
...
|
||||
401b4b: b8 0c 00 00 00 mov eax,0xc
|
||||
401b50: 5d pop rbp
|
||||
401b51: c3 ret
|
||||
```
|
||||
|
||||
Trotz einiger Schleifenlogik davor gibt die Funktion letztendlich `0xc` (dezimal 12) zurück. Dieser Index wird verwendet, um die richtige Flagge aus dem Array von Strings auszuwählen, die wir früher gesehen haben.
|
||||
|
||||
## 3. Die Lösung
|
||||
|
||||
Jetzt müssen wir einfach den String am Index 12 (beginnend bei 0) in der Liste finden, die wir früher gefunden haben.
|
||||
|
||||
0. {flag:This_Is_Definitely_Not_It}
|
||||
1. {flag:Try_Harder_To_Find_The_Key}
|
||||
2. {flag:Strings_Are_Misleading_You}
|
||||
...
|
||||
10. {flag:Do_Not_Trust_Simple_Strings}
|
||||
11. {flag:Index_Twelve_Is_Not_Real_11}
|
||||
12. {flag:Reverse_Engineering_Is_Cool}
|
||||
|
||||
Der String bei Index 12 ist:
|
||||
`{flag:Reverse_Engineering_Is_Cool}`
|
||||
|
||||
Überprüfen wir dies, indem wir uns mit dem Remote-Server verbinden:
|
||||
|
||||
```bash
|
||||
$ nc <SERVER_IP> 1301
|
||||
=== The Vault of Falsehoods ===
|
||||
There are many keys, but only one opens the door.
|
||||
Enter the password: {flag:Reverse_Engineering_Is_Cool}
|
||||
|
||||
[+] Correct! Access Granted.
|
||||
[*] The flag is indeed: {flag:Reverse_Engineering_Is_Cool}
|
||||
```
|
||||
|
||||
## Fazit
|
||||
|
||||
Diese Challenge zeigt, dass `strings` zwar interessante Daten offenbaren kann, das Verständnis der *Logik* (Kontrollfluss) des Programms jedoch oft notwendig ist, um nützliche Daten von Täuschungen zu unterscheiden.
|
||||
Reference in New Issue
Block a user