---
# System prepended metadata

title: Assignment_13

---

## REE / Prof. Smits / WS 22-23 / Hochschule Mannheim
### Team 12 <br> Names: Mike, Gabriel, Kyrill <br>MatNr.: 1921224, 1925874, 1926420



# Assignment_13

- Schreiben Sie auf, wie Sie vorgegangen sind, und zwar so, dass ein fachkundiger Dritter Ihre Schritte nachvollziehen kann.
- Gab es Probleme?
- Welche Information konnten Sie extrahieren?
- Falls es ein Flag gab, wie lautete das Flag?


## Reconnaissance

Folgende Datei wurde zu verfügung gestellt und sollte Untersucht werden:
[password_check_4](https://gitty.informatik.hs-mannheim.de/ree-lecture/assignments/src/branch/master/Assignment_13/password_check_4)
 
### $ file
Die Datei wurde zuerst mit dem Programm file untersucht. Es handelt sich um ein 64-bit Programm, welches dynamisch gelinkt ist und nciht gestrippt wurde.
```
$file password_check_4 
password_check_4: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4f2b3472be169d1c2bd8475cdd0a07d9a67ebae3, not stripped
```
Da weder das Program Strings noch der Hex-Editor uns das richtige Passwort oder die Flagge einzeigt, verwenden wir im folgenden den Debugger gdb. 

### $ gdb
Im folgenden untersuchen wir das Programm mit gdb:
```
$ gdb -q password_check_4
$ set disassembly-flavor intel
$ disassemble main
```

Die Ausgabe, sieht wie folgt aus:
Adresse | Offset | Befehl | Argumente | Kommentare
-- | -- | -- | -- | --
0x00000000000009da | <+0>:	 | push | rbp |
0x00000000000009db | <+1>:	 | mov  | rbp,rsp |
0x00000000000009de | <+4>:	 | sub  | rsp,0x130 |
0x00000000000009e5 | <+11>:	 | mov  | DWORD PTR [rbp-0x124],edi |
0x00000000000009eb | <+17>:	 | mov  | QWORD PTR [rbp-0x130],rsi |
0x00000000000009f2 | <+24>:	 | mov  | rax,QWORD PTR fs:0x28 |
0x00000000000009fb | <+33>:	 | mov  | QWORD PTR [rbp-0x8],rax |
0x00000000000009ff | <+37>:	 | xor  | eax,eax |
0x0000000000000a01 | <+39>:	 | lea  | rax,[rbp-0x110] |
0x0000000000000a08 | <+46>:	 | lea  | rdx,[rip+0x1c55]| # 0x2664
0x0000000000000a0f | <+53>:	 | mov  | esi,0xff |
0x0000000000000a14 | <+58>:	 | mov  | rdi,rax |
0x0000000000000a17 | <+61>:	 | call | 0xc9e <read_password> |
0x0000000000000a1c | <+66>:	 | mov  | edi,0x9 |
0x0000000000000a21 | <+71>:	 | call | 0x8b0 <malloc@plt> |
0x0000000000000a26 | <+76>:  | mov  | QWORD PTR [rbp-0x120],rax |
0x0000000000000a2d | <+83>:	 | mov  | rax,QWORD PTR [rbp-0x120] |
0x0000000000000a34 | <+90>:	 | mov  | r8d,0x10 |
0x0000000000000a3a | <+96>:	 | lea  | rcx,[rip+0x1c23] | # 0x2664
0x0000000000000a41 | <+103>: | mov  | edx,0x8 |
0x0000000000000a46 | <+108>: | lea  | rsi,[rip+0x2025db] | # 0x203028 <PASSWORD>
0x0000000000000a4d | <+115>: | mov  | rdi,rax |
0x0000000000000a50 | <+118>: | call | 0xb0f <xor_crypt> |
0x0000000000000a55 | <+123>: | mov  | rax,QWORD PTR [rbp-0x120] |
0x0000000000000a5c | <+130>: | add  | rax,0x8 |
0x0000000000000a60 | <+134>: | mov  | BYTE PTR [rax],0x0 |
0x0000000000000a63 | <+137>: | mov  | rdx,QWORD PTR [rbp-0x120] |
0x0000000000000a6a | <+144>: | lea  | rax,[rbp-0x110] |
0x0000000000000a71 | <+151>: | mov  | rsi,rdx |
0x0000000000000a74 | <+154>: | mov  | rdi,rax |
0x0000000000000a77 | <+157>: | call | 0x890 <strcmp@plt> |
0x0000000000000a7c | <+162>: | test | eax,eax |
0x0000000000000a7e | <+164>: | jne  | 0xae5 <main+267> |
0x0000000000000a80 | <+166>: | mov  | edi,0x15 |
0x0000000000000a85 | <+171>: | call | 0x8b0 <malloc@plt> |
0x0000000000000a8a | <+176>: | mov  | QWORD PTR [rbp-0x118],rax |
0x0000000000000a91 | <+183>: | mov  | rax,QWORD PTR [rbp-0x118] |
0x0000000000000a98 | <+190>: | mov  | r8d,0x10 |
0x0000000000000a9e | <+196>: | lea  | rcx,[rip+0x1bbf] | # 0x2664
0x0000000000000aa5 | <+203>: | mov  | edx,0x14 |
0x0000000000000aaa | <+208>: | lea  | rsi,[rip+0x20255f] | # 0x203010 <FLAG>
0x0000000000000ab1 | <+215>: | mov  | rdi,rax |
0x0000000000000ab4 | <+218>: | call | 0xb0f <xor_crypt> |
0x0000000000000ab9 | <+223>: | mov  | rax,QWORD PTR [rbp-0x118] |
0x0000000000000ac0 | <+230>: | add  | rax,0x14 |
0x0000000000000ac4 | <+234>: | mov  | BYTE PTR [rax],0x0 |
0x0000000000000ac7 | <+237>: | mov  | rax,QWORD PTR [rbp-0x118] |
0x0000000000000ace | <+244>: | mov  | rdi,rax |
0x0000000000000ad1 | <+247>: | call | 0x810 <puts@plt> |
0x0000000000000ad6 | <+252>: | mov  | rax,QWORD PTR [rbp-0x118] |
0x0000000000000add | <+259>: | mov  | rdi,rax |
0x0000000000000ae0 | <+262>: | call | 0x800 <free@plt> |
0x0000000000000ae5 | <+267>: | mov  | rax,QWORD PTR [rbp-0x120] |
0x0000000000000aec | <+274>: | mov  | rdi,rax |
0x0000000000000aef | <+277>: | call | 0x800 <free@plt> |
0x0000000000000af4 | <+282>: | mov  | eax,0x0 |
0x0000000000000af9 | <+287>: | mov  | rcx,QWORD PTR [rbp-0x8] |
0x0000000000000afd | <+291>: | xor  | rcx,QWORD PTR fs:0x28 |
0x0000000000000b06 | <+300>: | je   | 0xb0d <main+307> |
0x0000000000000b08 | <+302>: | call | 0x830 <__stack_chk_fail@plt> |
0x0000000000000b0d | <+307>: | leave| |
0x0000000000000b0e | <+308>: | ret  | |


bei den Offset <+157> kann man erkennen, dass eine Funktion <strcmp@plt > (String Compare) aufgerufen wird und danach getestet wird ob die Eingabe stimmt. Wenn diese nicht stimmt, wird ein Jump ausgeführt an das Ende vom Programm, ohne die Flag auszugeben.
    
```
0x0000000000000a77 <+157>:  call  0x890 <strcmp@plt>
0x0000555555400a7c <+162>:  test  eax,eax
0x0000555555400a7e <+164>:  jne   0xae5 <main+267>
```
    
Man könnte die Zeile <+164>  mit "nop" erstezten um an die Flag ```FLAG{xor or not xor}``` zu kommen, aber dadurch kommt man nicht an das Passwort. Da es in der Übung explizit gefragt wird "die Eingabeparameter der Funktion und eventuell Rückgaben" mit einem Breakpoint zu untersuchen, hört unsere Aufgabe hier noch nicht auf.      


## Untersuchung mit Breakpoint
Um die richtige Stelle für unseren Breakpoint zu finden, sehen wir uns das Programm noch einmal an:

Bei Offset <+118> wird eine Funktion aufgerufen, die xor_crypt genannt wird. 

    0x0000555555400a50  <+118>:  call   0xb0f <xor_crypt> 
    
Die ersten beiden Parameter, die an eine Funktion übergeben werden, sind normalerweise rdi und rsi. Diese beiden Register wurden zuvor gefüllt. Das Register rsi wurde wahrscheinlich mit einem XOR-verschlüsselten Passwort aus dem Speicher in <+108> geladen, ein Kommentar bestätigt dies zusätzlich.
    
    0x0000555555400a46  <+108>:  lea   rsi,[rip+0x2025db] # 0x203028 <PASSWORD>

Das Register rdi wurde zuvor mit dem Inhalt des rax-Registers im Offset <+115> gefüllt. Das rax-Register wiederum wurde zuvor in Offset <+83> mit einer Speicheradresse gefüllt, die in Offset <+71> und <+76> mit malloc reserviert wurde.
    
    0x0000000000000a21  <+71>:   call  0x8b0 <malloc@plt>
    0x0000000000000a26  <+76>:   mov QWORD PTR [rbp-0x120],rax
    0x0000000000000a26  <+76>:   mov   QWORD PTR [rbp-0x120],rax
    0x0000000000000a2d  <+83>:   mov   rax,QWORD PTR [rbp-0x120]
    0x0000000000000a4d  <+115>:  mov  rdi,rax
    
Daher kann man davon ausgehen, dass sich das Ergebnis der Funktion xor_crypt entweder im Standard-Rückgaberegister rax oder in der Speicheradresse befindet, die im Register rdi übergeben wurde.
    
Ein sinnvoller Breakpoint wäre ein Moment, nachdem das Programm das Passwort bei Offset <+118> entschlüsselt hat. Wir setzen also unseren Breakpoint bei der Funktion "xor_crypt" und starten das Programm:
```
(gdb) break xor_crypt
Breakpoint 1 at 0xb13
(gdb) run
Starting program: /home/kali/ree/gitty/Assignment_13/password_check_4 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
```
Das Programm läuft normal, fragt nach einem Passwort, hier geben wir einen Dummy-Wert z.B. "test" ein und fahren fort, bis wir den gesetzten Breakpoint erreichen:
```    
Enter password: test
Breakpoint 1, 0x0000555555400b13 in xor_crypt ()
```
Jetzt sind wir bei der Funktion, die das Passwort entschlüsselt. Um auf das Ergebnis der Funktion zuzugreifen, müssen wir mit dem Befehl "next" einen Schritt weitergehen.     
```    
(gdb) next
Single stepping until exit from function xor_crypt,
which has no line number information.
0x0000555555400a55 in main ()
```    
Das Passwort ist jetzt entschlüsselt und zwischengespeichert. Wir können uns die Informationen zu den Register mit "info register" anzeigen lassen:
```    
(gdb) i r
rax            0x8                 8
rbx            0x0                 0
rcx            0x61                97
rdx            0x33                51
rsi            0x33                51
rdi            0x555555604ac0      93824992955072
rbp            0x7fffffffddc0      0x7fffffffddc0
rsp            0x7fffffffdc90      0x7fffffffdc90
r8             0x10                16
r9             0x77                119
r10            0x5d                93
r11            0x7ffff7df4c60      140737351994464
r12            0x7fffffffded8      140737488346840
r13            0x5555554009da      93824990841306
r14            0x0                 0
r15            0x7ffff7ffd020      140737354125344
rip            0x555555400a55      0x555555400a55 <main+123>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
```
    
Der Wert des rax-Registers ist 8, es scheint also uninteressant zu sein. Werfen wir einen Blick auf das rdi-Register: 
```    
(gdb) x /s 0x555555604ac0
0x555555604ac0: "mutti123"
    
```
Bingo! Im rdi-Register steht die Adresse des unverschlüsselten Passworts, dass wir auslesen können.  
    
## Weitere Überlegungen
Bei dem Offset <+61> wird eine Funktion aufgerufen, welche ein Passwort einliest.
    
    0x0000555555400a17  <+61>:  call  0xc9e <read_password>
   
Später bei Offset <+157> wird die Funktion strcmp aufgerufen, die testet, ob das entschlüsselte Passwort und das eingebene Passwort übereinstimmen.

    0x0000555555400a77  <+157>:  call x890 <strcmp@plt> 
   
Man könnte auch einen Breakpoint bei strcmp am Offset <+157> setzen, um zu sehen, welche beiden Adressen an die Funktion übergeben werden. Die erste Adresse befindet sich vermutlich im rdi-Register und die zweite Adresse im rsi-Register. Eine der Speicheradressen enthält wahrscheinlich das von uns eingelesene Passwort und die andere Speicheradresse enthält das entschlüsselte Passwort, das hinterlegt wurde und zuvor an Offset <+118> entschlüsselt wurde. Wir haben diese Annahme überprüft und sie scheint richtig zu sein, denn wir erhalten das gleiche Ergebnis wie zuvor im Abschnitt "Untersuchung mit Breakpoint" beschrieben.
    
Wenn die Passwörter nicht übereinstimmt springt das Programm (am Offset <+164> mit jne) an das Ende und beendet sich. 
    
    0x0000555555400a7e <+164>:  jne    0xae5 <main+267>
    
Wenn das Passwort jedoch  übereinstimmt, dann wird am Offset <+218> die Flagge entschlüsselt und am Offset <+247> asugegeben.
    
    0x0000555555400ab4  <+218>:  call  0xb0f <xor_crypt>
    0x0000555555400ad1  <+247>:  call  0x810 <puts@plt>
    
    
## Ergebnisse
**Flag:** ```FLAG{xor or not xor} ```
**Passwort:** ```mutti123```