[GUET-CTF2019]number_game学习笔记

[GUET-CTF2019]number_game学习笔记

提要

此题一开始让我疑惑的地方就是那些递归算法的逆向问题,最后到底会生成哪些元素,我自己分析甚至最后生成的字符数量都不对,其实还是没法很清晰地分析递归算法的结果,另外就是对一些特殊的形式还是不够敏感,比如这串代码

这个递归有两层,分别是2*a+1和2*a+2,前面还有个直接赋值的,这不是有点像前序遍历吗?题目中出现的加密都不是毫无章法的加密,看到一个加密算法的时候要先将它和已知的加密算法向比较,先从整体理解再深入到细节中,直接分析细节容易让认识片面,只知道一些自己推出来的结论。

题目开始

先找到关键函数(下面这俩)

显然这里的sub_400917是关键,点开看看,知道了这个问题是一个数独问题(5*i,5*j和两层循环说明了,该问题的主要对象是一个5*5的矩阵),再看中间两个if,意思就是同行同列不允许有相同的值,这就是个简化版(不考虑一个9宫格之内的重复)的数独呀!

矩阵如上图👆

    导出unk_6001060的数据,先做数独得到这里第6行的数字。

难点

    但是说回来我遇到的问题,就是分析不清楚这个递归malloc了多少存储空间,存了多少字符。

现在再来看,这就是一个构建二叉树的过程(二叉树不是本身就存在的,总得先建立出来吧),每次调用函数会导致两次递归,两次递归分别代表查询左子树和查询右子树,不管后面递归最终返回的是什么,这次递归返回的都是v6的值,但v6是个地址,所以v6[1]等的值也被返了回来,对v6[1]的递归也是这样,直到到达10这个界限,所有的返回值都变成了0。那么那些递归就不算了,偶数奇数都有,所以这1个数应该是全覆盖,其实最终就是存了3个指针,其中底下两个指针下面又开辟了一个24bit的空间,也就是一个双亲加上他的两个儿子的指针就是这24bit。最后三个三个叠加成了一个有10个节点的二叉树。

大概就这样。每个三角形都申请了一个24bit。

 

再看后来这个函数,还是熟悉的配方,熟悉的两层递归,但是和之前一个函数确实长得不是特别像,但是这还真就是二叉树中序遍历,而这个函数的作用就是返回中序遍历序列,但是上边那个还说得清楚,这个我是真输出全靠猜,看到v4每次都是+8或者+16这样的,这就正好是一个字符,两次调用函数在两边,中间一个直接的赋值,就有点中序遍历那味儿了。

做完这两步以后就把原来输入进5*5数独里的值在内存中的顺序变了。分析时用0123456789这些下标,画出二叉树,然后中序遍历这棵二叉树就可以得到新的顺序7381940526,然后把我们之前推断的输入(0421421430)按照这个对应关系调换位置,就可以得到最后的flag了。

得到flag为flag{1134240024}

    注:本题动态调试也可以,在分析到这是一个二叉树遍历问题时,用0123456789作为输入进行动态调试,可以查看v7这个位置的数据直接得到7381940526的对应关系。

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值