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}

posted @ 2024-04-18 02:15  Guanz  阅读(14)  评论(0编辑  收藏  举报