tip:数独规则
每一行,每一列,并且划分的小块里面都必须由1~9组成(针对九宫格,当然有变种)
1、moectf2021的 numgame
入门级别的数独题,直接开门见山
首先是输入字符串,接着按顺序依次将box中为0的数用输入赋值。
紧跟着是3个check函数,分别检查行,检测列,和划分的宫格,因为是入门题目,所以下面也有提示是sudu,如果check成功,那么用输入跟magic异或便能得到flag。
依次进入3个check函数分析
check1
check2
check3
求解数独,如果是标准的九宫格,直接网上找在线求解器求解即可。
在线数独求解:https://shudu.gwalker.cn/
根据解出的数独数组,来还原输入,与magic异或便是flag,直接输入正确输入便得到flag。
2、[GUET-CTF2019]number_game
数独变种改变了宫格的大小 将9x9变为 5x5 并且只分了一个宫格。
改后为0~4的输入,并且在sub_400917函数之前,有递归赋值,如sub_400758和sub_400807函数,如下。
不过仔细观察结构,第一个函数应该是将输入按照先序创建二叉树,第二个循环则是将转化成的二叉树进行中序遍历,将结果赋值到数组中。
最后一个if判断里面则是彰显出了数独的特征,行列不能有相等。
"""
1 4 # 2 3
3 0 # 1 #
0 # 2 3 #
# 3 # # 0
4 2 # # 1
"""
很容易解出为满足数独要求的串0421421430,这是由输入变化而来的,所以要掌握变化规律。
1、手撸树的遍历推变化
0-9正好和输入的标号对应起来,直接进行移位就可以了,就是0 在输入中的下标为7, 4 在输入中的下标为3 依次还原。
table='7381940526'
enc='0421421430'
input=[0]*10
for i in range(len(enc)):
input[ord(table[i])-48]=enc[i]
print(''.join(input))
2、动态调试看字符串变化
另解:当然,如果没能识别出是有关树的一些遍历,还可以通过动态调试找出一些变化规律,因为那两个函数只是进行递归赋值。
当然在动调时,修改eip跳过判断函数,最好要跳到函数的第一条指令,如下图也就是0x0000000000400A76 处,如果跳到中间,可能很多量的初始化会出现问题
输入为:0123456789 (直接用下标来代替更容易看出变化)
单步过sub_400881函数便能看到转换后的字符串
和我们上面分析出树的遍历所得到的结果是一样的,但却减少了代码分析量,这也体现出动调的优势,能在短时间内得到想要的结果。
以上则是最近遇到的一些基础的数论题,如果有问题还请师傅们指正,之后遇到新解法也会再次更新~。