[GUET-CTF2019]number_game[数独]

news/2024/12/22 14:26:41/

目录

题目

 学到的知识点:


题目

在buu上看到了一道数独题,没见过,记录一下

下载附件,查壳,无壳,在IDA中打开,直接找到主函数

unsigned __int64 __fastcall main(int a1, char **a2, char **a3)
{__int64 v4; // [rsp+8h] [rbp-38h]__int64 input; // [rsp+10h] [rbp-30h] BYREF__int16 v6; // [rsp+18h] [rbp-28h]__int64 v7; // [rsp+20h] [rbp-20h] BYREF__int16 v8; // [rsp+28h] [rbp-18h]char v9; // [rsp+2Ah] [rbp-16h]unsigned __int64 v10; // [rsp+38h] [rbp-8h]v10 = __readfsqword(0x28u);input = 0LL;v6 = 0;v7 = 0LL;v8 = 0;v9 = 0;scanf("%s", &input);if ( function(&input) )                       // 0<v5[i]<=4并且len(v5)==10{v4 = function_1(&input, 0LL, 10LL);         // 建树function_2(v4, &v7);                        // 令v7=input// 中序遍历  递归v9 = 0;function_3(&v7);                            // 将中序遍历后的数据存入到一段内存中if ( function_4() )                         // 这里进行判断是是将中序遍历转换后的字符串{                                           // 实际上就是根据中序遍历求出原本的输入puts("TQL!");printf("flag{");printf("%s", &input);puts("}");}else{puts("your are cxk!!");}}return __readfsqword(0x28u) ^ v10;
}

 大致理一下思路,可以看到

首先输入一串字符串,在function函数中进行了判断(确保输入的值在字符‘0’~‘4’之间,并且长度要为10)

接着在function_1中进行建树

_QWORD *__fastcall sub_400758(__int64 input, int i, signed int len)
{char cnt; // [rsp+1Fh] [rbp-11h]_QWORD *v6; // [rsp+28h] [rbp-8h]cnt = *(i + input);if ( cnt == ' ' || cnt == '\n' || i >= len )  // 判段输入不为空格和换行符return 0LL;v6 = malloc(0x18uLL);                         // 申请一块内存*v6 = cnt;                                    // 存储根结点v6[1] = function_1(input, 2 * i + 1, len);    // 递归调用,存储左子树和右子树v6[2] = function_1(input, 2 * (i + 1), len);return v6;
}

 再在function_2中进行中序遍历的变换

__int64 __fastcall sub_400807(__int64 v4, __int64 v7)
{__int64 result; // raxresult = v4;if ( v4 ){function_2(*(v4 + 8), v7);                  // 左子树*(v7 + dword_601080++) = *v4;               // 保存根结点return function_2(*(v4 + 16), v7);          // 右子树}return result;
}

 把经过中序变换的数据在fnction_3里面存储到一段内存中

__int64 __fastcall sub_400881(char *a1)
{__int64 result; // raxbyte_601062 = *a1;byte_601067 = a1[1];byte_601069 = a1[2];byte_60106B = a1[3];byte_60106E = a1[4];byte_60106F = a1[5];byte_601071 = a1[6];byte_601072 = a1[7];byte_601076 = a1[8];result = a1[9];byte_601077 = a1[9];return result;
}

 最后进入function_4函数,function_4函数是一个数独游戏函数,代码如下

__int64 sub_400917()
{unsigned int v1; // [rsp+0h] [rbp-10h]int i; // [rsp+4h] [rbp-Ch]int j; // [rsp+8h] [rbp-8h]int k; // [rsp+Ch] [rbp-4h]v1 = 1;for ( i = 0; i <= 4; ++i )                    // 5*5数独游戏{for ( j = 0; j <= 4; ++j ){for ( k = j + 1; k <= 4; ++k ){if ( *(&unk_601060 + 5 * i + j) == *(&unk_601060 + 5 * i + k) )// 每行数无重复元素v1 = 0;if ( *(&unk_601060 + 5 * j + i) == *(&unk_601060 + 5 * k + i) )// 每列数无重复元素v1 = 0;}}}return v1;
}

5*5的数独函数,两个if语句判断要求每行元素不重复,每列元素不重复

大致思路就是输入一段字符串,进行给定二叉树的存储,然后再中序遍历存储,最后判断是否满足数独函数,满足则输出正确,反之,错误

二叉树如何存储的呢?树的结构与对应输入树的值存储关系如下

用0~9的数输入来测试输出的顺序。经过变换后的结果是 :7381940526

数独矩阵为

手动解出结果为:0421421430,只要使输入的结果经过变换后满足此顺序即可

借用一下大佬的脚本解密

map = [7, 3, 8, 1, 9, 4, 0, 5, 2, 6] # 对应关系
v7 = [48, 52, 50, 49, 52, 50, 49, 52, 51, 48]
flag=[0]*10for i in range(10):flag[map[i]] = chr(v7[i])
flag=''.join(flag)
print('flag{'+flag+'}')
# 1134240024

 学到的知识点:

  • 二叉树相关的题目类型
  • 怎么判断代码是数独游戏
  • 额外补充一个在别的题目中遇到的:凯撒加密代码的标志是:

           *v7 = (v5 - 48 + a) % 10 + 48

            *v7=(v5-97+a)%26+97

其中a表示偏移量,但是凯撒加密不会移位数字,但有的题目是凯撒加密的变种,会移位数字


http://www.ppmy.cn/news/103607.html

相关文章

CH341的SPI接口编程说明

CH341的SPI接口特性&#xff1a; 1、提供3个片选信号&#xff0c;SCS0~SCS2&#xff1b; 2、SPI 默认工作模式0&#xff0c;不支持修改&#xff1b; 3、SPI Clock速率固定&#xff0c;小于2MHz&#xff1b; 4、支持MSB/LSB传输&#xff1b; 引脚序号功能说明15~17SCS0~SCS…

在网络安全领域,这些都是比较牛的中国黑客!

1994年前后&#xff0c;国内出现最早一批黑客&#xff0c;其中以龚蔚、天山等顶级黑客为代表&#xff1b;2000年左右&#xff0c;第二代黑客出现&#xff0c;他们的技术特点与前辈相仿&#xff0c;深入研究网络安全技术&#xff0c;有自己的理论和产品&#xff1b;而后第三代黑…

记录两个Windows和Mac上部署阿里Canal无法启动的神坑

目录 一、问题列表 二、解决方案 三、参考资料 四、配置详解 五、数据库相关操作 一、问题列表 1、问题一&#xff1a;点击 startup.bat 窗口出现后立马闪退的问题。 2、问题二&#xff1a;启动后日志文件报错&#xff1a; ERROR com.alibaba.otter.canal.deployer.Cana…

全球化企业应如何统筹规划财务共享中心?

中冶国际携手用友构建海外财务共享体系 中冶国际工程集团有限公司&#xff08;简称&#xff1a;中冶国际&#xff09;成立于2006年&#xff0c;是中国冶金科工股份有限公司&#xff08;简称&#xff1a;中国中冶&#xff09;的全资子公司&#xff0c;也是中国五矿集团和中国中…

C++中的函数组合:用std::function实现编程艺术

C中的函数组合&#xff1a;用std::function实现编程艺术 1. 引言1.1 C中的函数式编程 (Functional Programming in C)1.2 函数组合的概念和价值 (Concept and Value of Function Composition)1.3 std::function概述 (Overview of std::function) 2. 如何在C中实现函数组合 (Imp…

DOM事件、冒泡和捕获、事件代理

DOM是用来呈现以及与任意 HTML 或 XML 文档交互的 API。DOM 是载入到浏览器中的文档模型&#xff0c;以节点树的形式来表现文档&#xff0c;每个节点代表文档的构成部分 DOM事件流有3个阶段&#xff1a;捕获阶段&#xff0c;目标阶段&#xff0c;冒泡阶段&#xff1b; 三个阶段…

Redis(六)主从模式与哨兵机制

文章目录 一、主从模式配置一主二从集群 二、哨兵机制哨兵模式演示&#xff1a;哨兵如何监控节点「主观下线」与[客观下线]哨兵如何选新主节点由哪个哨兵进行转移如何通知客户端新主节点的信息? 一、主从模式 配置一主二从集群 开启三个linux&#xff0c;并安装redis info …

【Python笔记(1) ——Python基础知识】

文章目录 1. 标识符2. 关键字3. 引号4. 编码5. 输入输出6. 缩进7. 多行8. 注释9. 数据类型10. 运算符10.1 常用运算符10.2 运算符优先级 1. 标识符 在 Python 中标识符是用来标识变量、函数、类等用户自定义对象的命名。标识符的命名规则是&#xff1a; 可以是字母、数字、下…