Any function that returns a pointer to the string once it acts on it is a prime target. There are many that do this, including stuff like gets()
, strcpy()
and fgets()
. We''l keep it simple and use gets()
as an example.
First, let's make sure that some register does point to the buffer:
Now we'll set a breakpoint on the ret
in vuln()
, continue and enter text.
We've hit the breakpoint, let's check if RAX points to our register. We'll assume RAX first because that's the traditional register to use for the return value.
And indeed it does!
We now just need a jmp rax
gadget or equivalent. I'll use ROPgadget for this and look for either jmp rax
or call rax
:
There's a jmp rax
at 0x40109c
, so I'll use that. The padding up until RIP is 120
; I assume you can calculate this yourselves by now, so I won't bother showing it.
Awesome!
Using Registers to bypass ASLR
ret2reg simply involves jumping to register addresses rather than hardcoded addresses, much like . For example, you may find RAX always points at your buffer when the ret
is executed, so you could utilise a call rax
or jmp rax
to continue from there.
The reason RAX is the most common for this technique is that, by convention, the return value of a function is stored in RAX. For example, take the following basic code:
If we compile and disassemble the function, we get this:
As you can see, the value 0xdeadbeef
is being moved into EAX.