Gros

pwnable.kr - unexploitable

Checksec:

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

We have also source code:

#include <stdio.h>
void main(){
    // no brute forcing
    sleep(3);
    // exploit me
    int buf[4];
    read(0, buf, 1295);
}

and in asm:

.text:0000000000400544 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400544 public main
.text:0000000000400544 main proc near
.text:0000000000400544
.text:0000000000400544 buf= byte ptr -10h
.text:0000000000400544
.text:0000000000400544 ; __unwind {
.text:0000000000400544 push    rbp
.text:0000000000400545 mov     rbp, rsp
.text:0000000000400548 sub     rsp, 10h
.text:000000000040054C mov     edi, 3          ; seconds
.text:0000000000400551 mov     eax, 0
.text:0000000000400556 call    _sleep
.text:000000000040055B lea     rax, [rbp+buf]
.text:000000000040055F mov     edx, 50Fh       ; nbytes
.text:0000000000400564 mov     rsi, rax        ; buf
.text:0000000000400567 mov     edi, 0          ; fd
.text:000000000040056C mov     eax, 0
.text:0000000000400571 call    _read
.text:0000000000400576 leave
.text:0000000000400577 retn
.text:0000000000400577 ; } // starts at 

Short and easy, just buffer overflow there. The problem: ASLR and no printing function (so no leaks). The solution: find and use int80 or syscall instruction at known address (in binary’s .text section).

✦ ➜ ROPgadget --binary ./unexploitable | grep -i syscall
✦ ➜ ROPgadget --binary ./unexploitable | grep -i int    
0x000000000040064e : int1 ; add rsp, 8 ; pop rbx ; pop rbp ; ret

Nope, but lets try with pwndbg:

pwndbg> search -x 0f05 unexploitable
unexploitable   0x400560 syscall
pwndbg> x/10i 0x400560
   0x400560 <main+28>:  syscall 
   0x400562 <main+30>:  add    BYTE PTR [rax],al
   0x400564 <main+32>:  mov    rsi,rax
   0x400567 <main+35>:  mov    edi,0x0
   0x40056c <main+40>:  mov    eax,0x0
   0x400571 <main+45>:  call   0x400430 <read@plt>
   0x400576 <main+50>:  leave  
   0x400577 <main+51>:  ret

There it is! Now we can construct ROP and end it with syscall. What syscall? Well, here are few ways:

Or was, some time ago. Now you can easily read more about the technique anywhere (even pwntools have helpers for it).