首页
社区
课程
招聘
[原创]看雪CTF-2017秋季赛第二题
发表于: 2017-10-29 09:54 5831

[原创]看雪CTF-2017秋季赛第二题

2017-10-29 09:54
5831

总的来说这道题设计的比较巧妙吧。使用了声东击西的套路。首先放了一个烟雾弹,让人误以为关键点在某个地方,然而那里根本不是核心点。只是一个假“据点”。过多的在那里纠缠就只会浪费你的时间。

首先看下程序。没又任何保护可以直接调试:

然后ida打开。由于没有任何保护措施,所以直接搜索字符串,查找关键字符:

如上图所示,发现了关键位置。然后直接跟上去。可以发现关键逻辑点:

在这个关键跳转前面能发现三个函数。第一个是输入输出函数。用于获取用户的输入已经显示程序的信息。下面两个函数就是“加密”函数了。为什么要打引号?因为后面会降到。这只是个幌子,逗你玩的。在这里纠结那你就中计了:)

现在大概说一下目前看到的“关键逻辑”(假逻辑):

首先有一个变量:dword_41B034。他的初始值是2。然后跟进伪加密函数1可以发现一些逻辑:

如图可知,伪加密函数1的逻辑就是进行一系列的if判断然后如果满足条件则变量dword_41B034自减1。第二个“加密函数”也是一样的原理:


这两个伪加密函数最后就构成一个方程组。现在整理如下:

5 * (y - x) + y == 0x8F503A42

13 * (y - x) + x == 0xEF503A42

17 * (y - x) + y == 0xF3A94883

7 * (y - x) + x == 0x33A94883

看到scanf你想到了什么?作为一个搞安全的人。看到scanf第一反应应该是缓冲区溢出。这是本能反应。如果你没这个意识,这说明你还是需要再学习一个…..

既然想到了缓冲区溢出。那么就可以试着构造。溢出的原理很简单:

如上图所示。可以发现很多信息:

a) 函数依靠eax返回参数。Eax的值就是一个指针,指向一个buffer,这个buffer保存着我们输入的信息(就是“aaaabbbb”)

b) 函数的堆栈显示了输入信息所保存的方式。以及函数的返回地址。根据栈的排列方式不难想到,可以通过构造输入来覆盖返回地址,然后就达到了溢出的目的——让程序执行我们想让他执行的代码

c) 综合上图的“%s”可以发现,所有的输入是被当作字符串来保存的。因此输入的字母a和字母b都被当作了字符串。因此这里需要考虑ascii码的转换问题。同时数据在内存中是小端排序(这个是常识了)

接下来按照上述原理。直接构造输入。我们看到在程序清空堆栈之前,我们输入的信息保存的地址是0x18ff38.然后返回地址保存在0x18ff48。这两个地址相减得:0x10(十进制16)所以这很容易算出。如果要覆盖返回地址需要构造12字节的信息外加4个字节的返回地址。也就是说输入结构如下:A+B+C+返回地址。然后ida上可以看到成功分支的地址是:0x0040102F。因此对照ascii表构造输入如下:

如图所示这样构造其实也是可以解决问题的。但是比赛规则限制,正确的注册码只能由字母+数字组成。这说明此题还有其他的解。因此断定一定还有我们没有发现的逻辑。所以搜索特征值进行寻找。对于加密解密来说。一些经典的特征如下:

a) JMP EAX

b) shl等各自位移指令

c) XOR运算指令

上述这些指令都是加密算法精彩用到的。很容易就能找到关键点。(用最笨的方法。Ida直接向下翻,就可以找到啦:))其次,由于这是比赛。比赛的程序其实都很小。这其实大大降低了逆向的难度。不管你这个程序用了什么花哨的技术。你这么小一个程序,他逆向的难度和复杂度始终都不会高到哪里去。因此在这里多说几句。各位逆向界的新手们,千万要正确对待creakme比赛。不要以为自己能破解creakme。就沾沾自喜。就以为自己已经算是学会了,入门了。相信我。在一个只有几KB大小的creakme程序中。不管使用了多么复杂的反调试,反分析技术。相对都是很容易破解的。因为代码量级在那摆着。但是如果你真的进入这个行业接手真的破解项目。你会恍然大悟:什么ctf,什么creakme。简直就是too simple。Sometimes naive。现在随便一个程序都是几百兆,N个G。在这种量级的代码中进行逆向那才是真的复杂。即使作者不做任何保护。你分析它都非常困难。在海量的汇编代码中如果没有经验和技巧。很容易就迷失在代码的海洋中啦。如果作者又加上各自反调试。那难度呈指数级上涨。这才是真正的逆向工程。我们现在的crf比赛真的是小儿科,连入门都算不上:)

按照上文的方法。果然可以找到一段数据:

这其实就已经非常明显了。这么小的一个程序为什么会有一大段数据?(当然如果是商业级的软件,几百上千兆的程序,那这一点都不奇怪,很正常)可以猜测。这段数据要么就是程序运行时解密的密文数据。要么就是一段被ida当成数据的代码。然而,结果比想象中的要简单。这不是密文,而是明文的代码。只不过是被ida当成了数据。重新分析后如下:

如图可见。这段shellcode的代码地址是0x 00413131。而且可以看到很多跳转指令。熟悉的人一眼就明白。这里其实是花指令。而且是最简单的花指令。就是来回跳一跳,吓唬吓唬你而已。相信我。所有的花指令都是纸老虎。复杂的花指令可以用插件记录程序流程分析一下脱花。简单的花指令(就像本题中遇到的这种)根本不用鸟它。完全是战五渣。直接肛正面……

最后我整理了一下脱花后的代码如下:

如上文所属。整理下来,其实就是三个方程组:

(D1-D2)*4+D1+D3 = 0xEAF917E2

(D1-D2)*2+D1-D2+D1+D3 = 0xE8F508C8                                                                                                    

(D1-D2)*2+D1-D2+D1-D3 = 0x0C0A3C68

其中D1,D2,D3就是我们输入的信息。大小为DWORD。

现在确定了这里才是真正的加密函数。那么要做的就是解方程并且构造输入信息。

首先解方程的方法很多。我是自己写的代码。代码如下:

如上文所属。整理下来,其实就是三个方程组:


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (9)
雪    币: 10902
活跃值: (3288)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
2
文章很认真  分析比较到位  给予精华鼓励!
2017-10-29 15:04
0
雪    币: 3508
活跃值: (4634)
能力值: ( LV13,RANK:437 )
在线值:
发帖
回帖
粉丝
3
路过,挺厉害的小伙
2017-10-29 15:20
0
雪    币: 202
活跃值: (16)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
首先膜拜大神,另外斗胆提一问  怎么知道ASCII  0x10  就是^P呢,  哪里有相关资料呢,  我找了好久
2017-10-29 15:57
0
雪    币: 6977
活跃值: (1786)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
讲的很透彻,自己跟着做了一遍,受益匪浅
2017-10-30 13:59
0
雪    币: 5
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
自己跟着做了一遍,但是花指令那块不太懂。。。
2017-10-30 19:47
0
雪    币: 424
活跃值: (40)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
7
无头骑士 自己跟着做了一遍,但是花指令那块不太懂。。。
这是最基础的东西啦。我已经说了。这个花指令就是吓唬人的。并没有什么卵用。你别管那些跳转就好啦。。。。其实花指令这个技术本身就是吓唬人的。他只是垃圾代码,本身不会影响程序运行。
2017-10-30 21:26
0
雪    币: 424
活跃值: (40)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
8
skygarth 首先膜拜大神,另外斗胆提一问 怎么知道ASCII 0x10 就是^P呢, 哪里有相关资料呢, 我找了好久[em_5]
这个我就不解答啦。你稍微动点脑筋还是可以解决的这是基础
2017-10-30 21:31
0
雪    币: 4522
活跃值: (2146)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
IDA  怎么把哪个转换成花指令的
2017-10-30 22:20
0
雪    币: 28
活跃值: (52)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
cqzhou IDA 怎么把哪个转换成花指令的
在IDA中直接摁字母C就可以了
2017-10-31 02:08
0
游客
登录 | 注册 方可回帖
返回
//