この大会は2024/4/16 19:00(JST)~2024/4/17 7:00(JST)に開催されました。
今回は個人で参戦。結果は850点で275チーム中79位でした。
自分で解けた問題をWriteupとして書いておきます。
Vault (Reverse 150)
Ghidraでデコンパイルする。
undefined8 main(void) { int iVar1; char *pcVar2; char local_78 [112]; printf("Enter the secret code: "); __isoc99_scanf(&DAT_0010201c,local_78); pcVar2 = (char *)flag(); iVar1 = strcmp(local_78,pcVar2); if (iVar1 == 0) { puts("Access Granted!"); pcVar2 = (char *)flag(); puts(pcVar2); } else { puts("Access Denied!"); } return 0; } undefined1 * flag(void) { int local_c; for (local_c = 0; local_c < 0x1a; local_c = local_c + 1) { flagArray.0[local_c] = (char)*(undefined4 *)(ascii_values.1 + (long)local_c * 4); } flagArray.0[26] = 0; return flagArray.0; } ascii_values.1 XREF[2]: flag:0010118a(*), flag:00101191(*) 00104040 69 00 00 undefine 00 63 00 00 00 74 00104040 69 undefined169h [0] XREF[2]: flag:0010118a(*), flag:00101191(*) 00104041 00 undefined100h [1] 00104042 00 undefined100h [2] 00104043 00 undefined100h [3] 00104044 63 undefined163h [4] 00104045 00 undefined100h [5] 00104046 00 undefined100h [6] 00104047 00 undefined100h [7] 00104048 74 undefined174h [8] 00104049 00 undefined100h [9] 0010404a 00 undefined100h [10] 0010404b 00 undefined100h [11] 0010404c 66 undefined166h [12] 0010404d 00 undefined100h [13] 0010404e 00 undefined100h [14] 0010404f 00 undefined100h [15] 00104050 7b undefined17Bh [16] 00104051 00 undefined100h [17] 00104052 00 undefined100h [18] 00104053 00 undefined100h [19] 00104054 77 undefined177h [20] 00104055 00 undefined100h [21] 00104056 00 undefined100h [22] 00104057 00 undefined100h [23] 00104058 65 undefined165h [24] 00104059 00 undefined100h [25] 0010405a 00 undefined100h [26] 0010405b 00 undefined100h [27] 0010405c 6c undefined16Ch [28] 0010405d 00 undefined100h [29] 0010405e 00 undefined100h [30] 0010405f 00 undefined100h [31] 00104060 63 undefined163h [32] 00104061 00 undefined100h [33] 00104062 00 undefined100h [34] 00104063 00 undefined100h [35] 00104064 30 undefined130h [36] 00104065 00 undefined100h [37] 00104066 00 undefined100h [38] 00104067 00 undefined100h [39] 00104068 6d undefined16Dh [40] 00104069 00 undefined100h [41] 0010406a 00 undefined100h [42] 0010406b 00 undefined100h [43] 0010406c 65 undefined165h [44] 0010406d 00 undefined100h [45] 0010406e 00 undefined100h [46] 0010406f 00 undefined100h [47] 00104070 5f undefined15Fh [48] 00104071 00 undefined100h [49] 00104072 00 undefined100h [50] 00104073 00 undefined100h [51] 00104074 74 undefined174h [52] 00104075 00 undefined100h [53] 00104076 00 undefined100h [54] 00104077 00 undefined100h [55] 00104078 30 undefined130h [56] 00104079 00 undefined100h [57] 0010407a 00 undefined100h [58] 0010407b 00 undefined100h [59] 0010407c 5f undefined15Fh [60] 0010407d 00 undefined100h [61] 0010407e 00 undefined100h [62] 0010407f 00 undefined100h [63] 00104080 72 undefined172h [64] 00104081 00 undefined100h [65] 00104082 00 undefined100h [66] 00104083 00 undefined100h [67] 00104084 65 undefined165h [68] 00104085 00 undefined100h [69] 00104086 00 undefined100h [70] 00104087 00 undefined100h [71] 00104088 76 undefined176h [72] 00104089 00 undefined100h [73] 0010408a 00 undefined100h [74] 0010408b 00 undefined100h [75] 0010408c 33 undefined133h [76] 0010408d 00 undefined100h [77] 0010408e 00 undefined100h [78] 0010408f 00 undefined100h [79] 00104090 72 undefined172h [80] 00104091 00 undefined100h [81] 00104092 00 undefined100h [82] 00104093 00 undefined100h [83] 00104094 73 undefined173h [84] 00104095 00 undefined100h [85] 00104096 00 undefined100h [86] 00104097 00 undefined100h [87] 00104098 31 undefined131h [88] 00104099 00 undefined100h [89] 0010409a 00 undefined100h [90] 0010409b 00 undefined100h [91] 0010409c 6e undefined16Eh [92] 0010409d 00 undefined100h [93] 0010409e 00 undefined100h [94] 0010409f 00 undefined100h [95] 001040a0 67 undefined167h [96] 001040a1 00 undefined100h [97] 001040a2 00 undefined100h [98] 001040a3 00 undefined100h [99] 001040a4 7d undefined17Dh [100] 001040a5 00 undefined100h [101] 001040a6 00 undefined100h [102] 001040a7 00 undefined100h [103]
ascii_values.1について、4バイトごとにASCIIコードを文字にする。
#!/usr/bin/env python3 codes = [0x69, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00] flag = '' for i in range(0, len(codes), 4): flag += chr(codes[i]) print(flag)
ictf{welc0me_t0_rev3rs1ng}
Vault 2 (Reverse 200)
Ghidraでデコンパイルする。 undefined8 main(void) { int iVar1; undefined local_88 [128]; puts("Enter the flag:"); iVar1 = __isoc99_scanf("%127s",local_88); if (iVar1 != 0) { iVar1 = checkFlag(local_88); if (iVar1 == 0) { puts("Incorrect flag. Try again!"); } else { puts("Congratulations! You\'ve solved the challenge."); } } return 0; } bool checkFlag(char *param_1) { int iVar1; char local_a8 [128]; undefined8 local_28; undefined7 local_20; undefined uStack_19; undefined7 uStack_18; local_28 = 0x7136777e62776168; local_20 = 0x6e5b306e636435; uStack_19 = 0x32; uStack_18 = 0x7f73357c5c7b; strncpy(local_a8,param_1,0x80); mysteryFunction(local_a8); iVar1 = strncmp(local_a8,(char *)&local_28,0x17); return iVar1 == 0; } void mysteryFunction(long param_1) { int local_c; for (local_c = 0; *(char *)(param_1 + local_c) != '\0'; local_c = local_c + 1) { *(byte *)(param_1 + local_c) = *(byte *)(param_1 + local_c) ^ (char)local_c + (char)(local_c / 5) * -5 + 1U; } return; }
入力データをmysteryFunction関数をかけて、checkFlagの各値と一致するものをブルートフォースで求める。
#!/usr/bin/env python3 def mystery(c, index): return c ^ index - (index // 5) * 5 + 1 enc = (0x7136777e62776168).to_bytes(8, 'little') enc += (0x6e5b306e636435).to_bytes(7, 'little') enc += (0x32).to_bytes(1, 'little') enc += (0x7f73357c5c7b).to_bytes(6, 'little') flag = '' for i in range(len(enc)): for code in range(32, 127): if mystery(code, i) == enc[i]: flag += chr(code) break print(flag)
ictf{v4r1abl3_k3y_x0r}
Vault 3 (Reverse 300)
Ghidraでデコンパイルする。
undefined8 main(void) { int iVar1; undefined local_88 [128]; puts("Enter the flag:"); iVar1 = __isoc99_scanf("%127s",local_88); if (iVar1 != 0) { iVar1 = checkFlag(local_88); if (iVar1 == 0) { puts("Incorrect flag. Try again!"); } else { puts("Congratulations! You\'ve solved the challenge."); } } return 0; } bool checkFlag(char *param_1) { int iVar1; char local_a8 [128]; undefined8 local_28; undefined8 local_20; undefined8 local_18; local_28 = 0x7a32567b6879656c; local_20 = 0x22785e7133237834; local_18 = 0x7f56305b5d6c77; strncpy(local_a8,param_1,0x80); encrypt(local_a8,(int)param_1); iVar1 = strncmp(local_a8,(char *)&local_28,0x18); return iVar1 == 0; } void encrypt(char *__block,int __edflag) { byte bVar1; char cVar2; int local_14; for (local_14 = 0; __block[local_14] != '\0'; local_14 = local_14 + 1) { bVar1 = (byte)(local_14 >> 0x1f); cVar2 = rotateChar((int)(char)(((char)local_14 + (bVar1 >> 6) & 3) - (bVar1 >> 6) ^ __block[local_14]),3); __block[local_14] = cVar2; } return; } uint rotateChar(byte param_1,int param_2) { uint uVar1; if (((char)param_1 < 'a') || ('z' < (char)param_1)) { if (((char)param_1 < 'A') || ('Z' < (char)param_1)) { uVar1 = (uint)param_1; } else { uVar1 = (param_2 + (char)param_1 + -0x41) % 0x1a + 0x41; } } else { uVar1 = (param_2 + (char)param_1 + -0x61) % 0x1a + 0x61; } return uVar1; }
入力データをencrypt関数をかけて、checkFlagの各値と一致するものをブルートフォースで求める。
#!/usr/bin/env python3 def encrypt(c, index): v1 = index >> 0x1f v2 = rotateChar((index + (v1 >> 6) & 3) - (v1 >> 6) ^ c, 3) return v2 def rotateChar(a, b): if a < ord('a') or ord('z') < a: if a < ord('A') or ord('Z') < a: c = a else: c = (b + a - 0x41) % 0x1a + 0x41 else: c = (b + a - 0x61) % 0x1a + 0x61 return c enc = (0x7a32567b6879656c).to_bytes(8, 'little') enc += (0x22785e7133237834).to_bytes(8, 'little') enc += (0x7f56305b5d6c77).to_bytes(7, 'little') flag = '' for i in range(len(enc)): for code in range(32, 127): if encrypt(code, i) == enc[i]: flag += chr(code) break print(flag)
ictf{R0t4t!0n_w!th_X0R}
Warmup (Web 100)
http://statesman.ictf5.ninja/src/App.jsxの冒頭に以下のように書いてある。
import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/App.jsx");import.meta.env = {"VITE_FAKE_FLAG": "N07F4K3F14G", "VITE_ENDPOINT": "http://20.55.192.124:5000/decrypt", "VITE_FLAG": "ictf{wElc0Me_T0_1ctf}", "BASE_URL": "/", "MODE": "development", "DEV": true, "PROD": false, "SSR": false};import * as RefreshRuntime from "/@react-refresh";
これにフラグが含まれている。
ictf{wElc0Me_T0_1ctf}
Di Dah (Crypto 100)
モールス信号に変換する。
-.... ----. -.... ...-- --... ....- -.... -.... --... -... ....- -.. ...-- ----- --... ..--- --... ...-- ...-- ...-- ..... ..-. ...-- ....- -.... . -.... ....- ..... ..-. ....- ....- ...-- .---- ....- ....- ....- ----- -.... ---.. ..... ..-. ..... --... -.... ---.. ...-- .---- --... .- ...-- ...-- --... ..--- ...-- ...-- --... ..--- --... -.. ----- .-
https://morsecode.world/international/translator.htmlでデコードする。
696374667B4D307273335F346E645F44314440685F5768317A337233727D0A
これをhexデコードする。
$ echo 696374667B4D307273335F346E645F44314440685F5768317A337233727D0A | xxd -r -p ictf{M0rs3_4nd_D1D@h_Wh1z3r3r}
ictf{M0rs3_4nd_D1D@h_Wh1z3r3r}