CTF_WriteUp(部分) | Incognito 5.0
学的密码,玩的杂项,练的 Web,但把 Reverse 打穿了(?
排名 95/275,虽然没写出来几道题但还是记录一下解题过程。
Crypto
Di Dah
简介
Beneath flickering lights, echoes play their games, In voltage's fluctuations, telegraph's silent claims.
附件
dah-di-di-di-dit dah-dah-dah-dah-dit dah-di-di-di-dit di-di-di-dah-dah dah-dah-di-di-dit di-di-di-di-dah dah-di-di-di-dit dah-di-di-di-dit dah-dah-di-di-dit dah-di-di-dit di-di-di-di-dah dah-di-dit di-di-di-dah-dah dah-dah-dah-dah-dah dah-dah-di-di-dit di-di-dah-dah-dah dah-dah-di-di-dit di-di-di-dah-dah di-di-di-dah-dah di-di-di-dah-dah di-di-di-di-dit di-di-dah-dit di-di-di-dah-dah di-di-di-di-dah dah-di-di-di-dit dit dah-di-di-di-dit di-di-di-di-dah di-di-di-di-dit di-di-dah-dit di-di-di-di-dah di-di-di-di-dah di-di-di-dah-dah di-dah-dah-dah-dah di-di-di-di-dah di-di-di-di-dah di-di-di-di-dah dah-dah-dah-dah-dah dah-di-di-di-dit dah-dah-dah-di-dit di-di-di-di-dit di-di-dah-dit di-di-di-di-dit dah-dah-di-di-dit dah-di-di-di-dit dah-dah-dah-di-dit di-di-di-dah-dah di-dah-dah-dah-dah dah-dah-di-di-dit di-dah di-di-di-dah-dah di-di-di-dah-dah dah-dah-di-di-dit di-di-dah-dah-dah di-di-di-dah-dah di-di-di-dah-dah dah-dah-di-di-dit di-di-dah-dah-dah dah-dah-di-di-dit dah-di-dit dah-dah-dah-dah-dah di-dah
分析
这种非 A 即 B 的谜面容易联想到摩斯电码,尝试将 dah
换成 -
,di/dit
换成 .
,得到如下摩斯电码:
-.... ----. -.... ...-- --... ....- -.... -.... --... -... ....- -.. ...-- ----- --... ..--- --... ...-- ...-- ...-- ..... ..-. ...-- ....- -.... . -.... ....- ..... ..-. ....- ....- ...-- .---- ....- ....- ....- ----- -.... ---.. ..... ..-. ..... --... -.... ---.. ...-- .---- --... .- ...-- ...-- --... ..--- ...-- ...-- --... ..--- --... -.. ----- .-
解码得到一串十六进制字符串:
696374667B4D307273335F346E645F44314440685F5768317A337233727D0A
Hex Decode 得到 flag ictf{M0rs3_4nd_D1D@h_Wh1z3r3r}
。
工具及参考
Reverse
Vault
简介
Can you get the access?
附件
分析
文件是 ELF 文件头,故更改文件扩展名为 *.elf,用 IDA 打开,根据流程图和提示语句看出是通过输入 flag 进行判断,正确输出 Access Granted!
,错误输出 Access Denied!
:
F5 查看反汇编文件:
代码第 8 行输入了需要判断的 s1,在第 10 行将 s1 与 v3 进行比较,当二者相等时 s1 的值即为 flag。而 v3 的值来自于第 9 行的函数 flag(),进入 flag() 函数:
函数返回值来自 ascii_values_1 数组的前 26 个字节元素,查看 ascii_values_1 数组,共 26 字节:
将所有字节由 16 进制转为字符,得到 flag:
Vault2
简介
Simply ask the flag ¯_(ツ)_/¯
附件
分析
文件头仍是 ELF,将文件扩展名改为 *.elf,用 IDA 打开:
相似的流程图,但存在两层 if 判断。F5 查看反汇编文件:
第 6 行输入的 v4 在第 8 行被传入 checkFlag() 函数,当函数范围值不为 0 的时候判断 v4 的值为 flag。查看 checkFlag() 函数:
传入的参数 v4 作为 a1 存在于 checkFlag() 函数,当第 8 行拷贝 a1 得到的 dest 经过第 9 行的 mysteryFunction() 函数后与第 6+7 行设定的参数 s2 的前 23 字符相等时,strncmp() 函数返回的 0 与参数 0 相等,checkFlag() 函数返回 1。即 flag 的值等同于 s2 的前 23 个字符。
值得注意的是,第 6 行对参数 s2 传入 16 个字符,而第 7 行的 0x7F73357C5C7B32
赋值时从数组第 15 位(从 0 开始计数)开始赋值,覆盖了上一行传入的最后一个字符 2
。
查看 mysteryFunction() 函数:
外层函数的 dest 作为 a1 的参数。函数将 i+a1 指针指向的值与 (i%5)+1
按位异或直至 i+a1 指针指向的值为 \0
(即字符串末尾空字符)跳出循环并结束函数,按位异或的结果作为 result 返回,与外层 checkFlag() 函数的 s2 比较。
咱通过 s2 的值来还原 v4,exp:
// 数据小端模式存储,共16+7-1个字符
char result[] = { 'h','a','w','b','~','w','6','q','5','d','c','n','0','[','n',0x32,0x7b,0x5c,0x7c,0x35,0x73,0x7f };
char p_i_and_a1[22];
for (int i = 0; i < 22; ++i) {
p_i_and_a1[i] = result[i] ^ ((i % 5) + 1);
printf("%c", p_i_and_a1[i]);
}
return 0;
运行得到 flag ictf{v4r1abl3_k3y_x0r}
。
Vault3
简介
Asking you last time for the flag.
附件
分析
文件同为 ELF 文件头,更改扩展名为 *.elf 后用 IDA 打开文件,是熟悉的判断语句流程图:
F5 反汇编,题面与上一题大差不差:
查看 checkFlag() 函数:
这里 s2 的前半部分赋值被更改为 leyh{V2z4x#3q^x\"
,除去转义字符共 16 个字符。第 8 行的 v4 似乎无用,但查看流程图后发现它实际同样被拼接在 s2 末尾。外层 main() 函数中用户输入的 v4 被作为 a1 传入当前函数 checkFlag(),在第 9 行拷贝给 dest 后经 encrypt() 函数计算,返回结果的前 24 个字符与 s2 相比较,当二者相同时 checkFlag() 返回 1 给外层
main() 函数。
查看 encrypt() 函数:
传入的 dest 成为 encrypt() 函数的 a1。函数逐一检查 i+a1 指针所指位置的值,当读到空字符时跳出循环返回。
查看 rotateChar() 函数,对于空字符之前的值,该函数若读到大小写字母则循环前移 3 个字符(如 A→D)。
同样通过 s2 的值来还原 v4,exp:
// 数据小端模式存储,共16+7=23个字符
char result[] = { 'l','e','y','h','{','V','2','z','4','x','#','3','q','^','x','\"',0x77,0x6c,0x5d,0x5b,0x30,0x56,0x7f };
char out[23];
for (int i = 0; i < 23; ++i) {
if (result[i] > 96 && result[i] <= 122) // 小写字母
result[i] = (result[i] - 97 - 3) % 26 + 97;
if (result[i] <= 64 || result[i] > 90)
result[i];
if (result[i] > 64 && result[i] <= 90) {
result[i] = (result[i] - 65 - 3) % 26 + 65;
}
out[i] = (result[i] ^ (i % 4));
printf("%c", out[i]);
}
return 0;
得到 flag ictf{R0t4t!0n_w!th_X0R}
。