Using ret2reg

Source

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.

#include <stdio.h>

void vuln() {
    char buffer[100];
    gets(buffer);
}

int main() {
    vuln();
    return 0;
}

Analysis

First, let's make sure that some register does point to the buffer:

$ r2 -d -A vuln

[0x7f8ac76fa090]> pdf @ sym.vuln 
            ; CALL XREF from main @ 0x401147
┌ 28: sym.vuln ();
│           ; var int64_t var_70h @ rbp-0x70
│           0x00401122      55             push rbp
│           0x00401123      4889e5         mov rbp, rsp
│           0x00401126      4883ec70       sub rsp, 0x70
│           0x0040112a      488d4590       lea rax, [var_70h]
│           0x0040112e      4889c7         mov rdi, rax
│           0x00401131      b800000000     mov eax, 0
│           0x00401136      e8f5feffff     call sym.imp.gets           ; char *gets(char *s)
│           0x0040113b      90             nop
│           0x0040113c      c9             leave
└           0x0040113d      c3             ret

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!

Exploitation

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!

Last updated

Was this helpful?