Ret2esp / Ret2reg
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
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 active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat 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.
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial jmp
shellcode like:
And write the shellcode early in the stack.
You can find an example of this technique in https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp with a final exploit like:
You can see another example of this technique in 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 reduce the address of $esp
and then a jmp esp;
to jump to the shellcode:
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).
You can find some examples here:
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
.
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:
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):
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
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:
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:
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.
NX: 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.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)