> 文章列表 > GDOUCTF2023 Reverse题解

GDOUCTF2023 Reverse题解

GDOUCTF2023 Reverse题解

文章目录

  • 题目附件
  • Check_Your_Luck
  • TEA
    • 基本逻辑:
    • show函数
    • setKey函数
    • encode函数(tea算法):
    • judge函数
    • 解题脚本
  • doublegame
    • snakefun
    • 迷宫
    • 关键循环

题目附件

链接:https://pan.baidu.com/s/1W0GisS4R-rHYHK4Bu167_g?pwd=nw4c

Check_Your_Luck

可以看到五条方程,根据方程可以求解出对应的值

GDOUCTF2023 Reverse题解

Z3库解不出来,所以用了在线解方程云算网(原名云算子)-在线求解线性方程组 (yunsuan.info)

flag: NSSCTF{4544_123_677_1754_777}

TEA

基本逻辑:

  1. 调用show函数,提示输入输出
  2. 以十六进制读取输入,可以得知共10*4=40字符
  3. 设置key数组
  4. 将input复制到arr数组中
  5. tea加密
  6. judge判断是否正确
  7. 输出flag
    GDOUCTF2023 Reverse题解

mainfun代码:

__int64 mainfun()
{char *v0; // rdi__int64 i; // rcxchar v3[32]; // [rsp+0h] [rbp-20h] BYREFchar v4; // [rsp+20h] [rbp+0h] BYREFint v5; // [rsp+24h] [rbp+4h]int result; // [rsp+44h] [rbp+24h]unsigned int key[12]; // [rsp+68h] [rbp+48h] BYREFint input[16]; // [rsp+98h] [rbp+78h] BYREFint arr[31]; // [rsp+D8h] [rbp+B8h] BYREFint j; // [rsp+154h] [rbp+134h]int k; // [rsp+174h] [rbp+154h]int m; // [rsp+194h] [rbp+174h]v0 = &v4;for ( i = 102i64; i; --i )//没作用{*v0 = 0xCCCCCCCC;v0 += 4;}sub_7FF7B3C8137F(&unk_7FF7B3C93009);	//没作用v5 = 32;//tea循环次数result = 0;key[0] = 1234;key[1] = 5678;key[2] = 9012;key[3] = 3456;	//设置key,但是这里设置的值是混淆的,下方会重新设置memset(input, 0, 40ui64);arr[15] = 0;arr[23] = 0;show();			//提示flag输入是以0x12345678这样的形式for ( j = 0; j < 10; ++j )scanf("%x", &input[j]);	//以16进制读取,共10个,所以有10*4=40字符setKey(key);		//设置keycopy(input, arr);		//将input的内容复制到arrencode(input, key);	//对input加密result = judge(input);	//判断加密后的数组是否正确if ( result )	{printf("you are right\\n");for ( k = 0; k < 10; ++k ){for ( m = 3; m >= 0; --m )printf("%c", (arr[k] >> (8 * m)));	//如果正确则输出input,即flag}}else{printf("fault!\\nYou can go online and learn the tea algorithm!");}sub_7FF7B3C81311(v3, &unk_7FF7B3C8AE90);return 0i64;
}

show函数

GDOUCTF2023 Reverse题解

setKey函数

GDOUCTF2023 Reverse题解

encode函数(tea算法):

__int64 __fastcall tea(unsigned int *arr, unsigned int *key)
{__int64 result; // raxint v3; // [rsp+44h] [rbp+24h]int i; // [rsp+64h] [rbp+44h]unsigned int v5; // [rsp+84h] [rbp+64h]unsigned int sum; // [rsp+C4h] [rbp+A4h]result = sub_7FF7B3C8137F(&unk_7FF7B3C93009);//没用for ( i = 0; i <= 8; ++i ){v5 = 0;sum = 0xF462900 * i;//delta与标准的tea并不同v3 = i + 1;do{++v5;arr[i] += sum ^ (arr[v3] + ((arr[v3] >> 5) ^ (16 * arr[v3]))) ^ (sum + key[sum & 3]);arr[v3] += (sum + key[(sum >> 11) & 3]) ^ (arr[i] + ((arr[i] >> 5) ^ (16 * arr[i])));sum += 0xF462900;//关键算法和tea区别不大}while ( v5 <= 32 );                         // 注意这里是从0到32,共33次循环result = (i + 1);}return result;
}

judge函数

GDOUCTF2023 Reverse题解

解题脚本

#include <stdio.h>
int main()
{
int v3; // [rsp+44h] [rbp+24h]
int i; // [rsp+64h] [rbp+44h]
unsigned int v5; // [rsp+84h] [rbp+64h]
int sum; // [rsp+C4h] [rbp+A4h]
int key[4] = {2233,4455,6677,8899 };
unsigned int arr[10];
arr[0] = 0x1A800BDA;
arr[1] = 0xF7A6219B;
arr[2] = 0x491811D8;
arr[3] = 0xF2013328;
arr[4] = 0x156C365B;
arr[5] = 0x3C6EAAD8;
arr[6] = 0x84D4BF28;
arr[7] = 0xF11A7EE7;
arr[8] = 0x3313B252;
arr[9] = 0xDD9FE279;
for (i = 8; i >=0; i--)
{
v5 = 0;
sum = 0xF462900 * i;
for (int j = 0; j < 33; j++)
sum += 0xF462900;
v3 = i + 1;
do
{
sum -= 0xF462900;
arr[v3] -= (sum + key[(sum >> 11) & 3]) ^ (arr[i] + ((arr[i] >> 5) ^ (16 * arr[i])));
arr[i] -= sum ^ (arr[v3] + ((arr[v3] >> 5) ^ (16 * arr[v3]))) ^ (sum + key[sum & 3]);
++v5;
} while (v5 <= 32);//33次循环
}
for (int k = 0; k < 10; ++k)
{for (int m = 3; m >= 0; --m)printf("%c", (arr[k] >> (8 * m)));
}
//HZCTF{hzCtf_94_re666fingcry5641qq}
return 0;

doublegame

进来找不到关键函数,查看strings看到类似迷宫的东西,根据字符串可以定位到关键函数

GDOUCTF2023 Reverse题解

snakefun

通过patch可以修改得分判断条件,从而进入game2
GDOUCTF2023 Reverse题解

__int64 __fastcall snakefun(int a1, int a2)
{char *v2; // rdi__int64 i; // rcxchar v5[32]; // [rsp+0h] [rbp-20h] BYREFchar v6; // [rsp+20h] [rbp+0h] BYREFchar chr[212]; // [rsp+24h] [rbp+4h] BYREFv2 = &v6;for ( i = 10i64; i; --i ){*(_DWORD *)v2 = -858993460;v2 += 4;}sub_7FF6BD89141A((__int64)&unk_7FF6BD8A90A6);if ( dword_7FF6BD8A1E60[42 * a2 + 42 * dword_7FF6BD8A0178 + a1 + dword_7FF6BD8A0174] == 2 ){++dword_7FF6BD8A0170;score += 10;sub_7FF6BD8911A9(7i64);sub_7FF6BD89130C(0i64, 22i64);printf(aD_2, (unsigned int)score);          // 当前得分setFood();                                  // 生成食物}else if ( dword_7FF6BD8A1E60[42 * a2 + 42 * dword_7FF6BD8A0178 + a1 + dword_7FF6BD8A0174] == 1|| dword_7FF6BD8A1E60[42 * a2 + 42 * dword_7FF6BD8A0178 + a1 + dword_7FF6BD8A0174] == 4 ){Sleep(0x3E8u);system("cls");sub_7FF6BD8911A9(7i64);sub_7FF6BD89130C(28i64, 8i64);sub_7FF6BD8911DB();                         // 分数还差一点if ( score > 16 )                           // score13371337sub_7FF6BD89136B();                       // jump to game 2sub_7FF6BD8910E6();                         // 保存最高记录失败sub_7FF6BD89130C(28i64, 11i64);printf("GAME OVER");while ( 1 ){sub_7FF6BD89130C(28i64, 14i64);printf(asc_7FF6BD89D320);                 // 是否再来一局scanf_0("%c", chr);if ( chr[0] == 'y' || chr[0] == 'Y' )break;if ( chr[0] == 'n' || chr[0] == 'N' ){sub_7FF6BD89130C(28i64, 16i64);exit(0);}sub_7FF6BD89130C(28i64, 16i64);printf(asc_7FF6BD89D3A0);                 // 选择错误}system("cls");someidea();                                 // 提示}return sub_7FF6BD8913B1(v5, &unk_7FF6BD89CFC0);
}
/* Orphan comments:
打破最高记录
继续加油,最高记录分为
*/

迷宫

这是迷宫图:

GDOUCTF2023 Reverse题解

注意这里多了一堵墙

GDOUCTF2023 Reverse题解

下面还有一个大循环

关键循环

v24 = 0;key = 0;hang = 15;lie = 0;shang = 7;                                    // 8行slie = 20;                                    // 21列for ( j = 0; j <= 20; ++j )puts(&Buffer[22 * j]);                      // 打印迷宫printf("Please to save the cat!\\n");while ( hang != shang || lie != slie )        // 好像不是走到@的位置{chr = getchar();switch ( chr ){case 's':if ( Buffer[22 * hang + 22 + lie] != '0' ){Buffer[22 * hang++ + lie] = ' ';Buffer[22 * hang + lie] = '@';}break;case 'w':if ( Buffer[22 * hang - 22 + lie] != '0' ){Buffer[22 * hang-- + lie] = ' ';Buffer[22 * hang + lie] = '@';}break;case 'a':if ( Buffer[22 * hang - 1 + lie] != '0' ){if ( Buffer[22 * hang - 1 + lie] == '*' )// 先到*这里v7[20] = '0';	//设置墙Buffer[22 * hang + lie--] = ' ';Buffer[22 * hang + lie] = '@';}break;default:if ( chr == 'd' && Buffer[22 * hang + 1 + lie] != '0' ){Buffer[22 * hang + lie++] = ' ';Buffer[22 * hang + lie] = '@';}break;}system("cls");for ( j = 0; j <= 20; ++j )puts(&Buffer[22 * j]);                    // 打印迷宫puts(&v19[100 * v24]);                      // 请救猫if ( v7[20] == '0' ){key = judge(0i64);                        // 判断keyif ( key == 13376013 ){v24 = 1;v7[20] = ' ';                           // 打通终点前的墙Buffer[22 * hang + lie] = ' ';hang = 15;lie = 0;v11[0] = '@';                           // 回到起点++v24;}else{printf("error");}}}

循环功能:

  1. shang,slie是终点;hang,lie是当前位置

  2. 从@的位置出发,经路径dddssssddwwwwddssddwwwwwwddddssa救到小猫后回到起点;同时小猫所在位置由’*‘变为’ ',且第8行第20列的空格变为0

  3. 然后要求输入key,key可以根据judge函数反推出来是13371337

  4. 再从起点出发,经路径dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd走出迷宫

  5. 所以path:dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd key:13371337

  6. 根据提示可以求出flag:NSSCTF{811173b05afff098b4e0757962127eac13371337}

提示函数:

GDOUCTF2023 Reverse题解

位置由’*‘变为’ ',且第8行第20列的空格变为0

  1. 然后要求输入key,key可以根据judge函数反推出来是13371337

  2. 再从起点出发,经路径dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd走出迷宫

  3. 所以path:dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd key:13371337

  4. 根据提示可以求出flag:NSSCTF{811173b05afff098b4e0757962127eac13371337}