menu 牢记自己是菜
动态调试CrackMe160 练习4
180 浏览 | 2020-04-23 | 阅读时间: 约 5 分钟 | 分类: crackme160 | 标签:
请注意,本文编写于 220 天前,最后修改于 220 天前,其中某些信息可能已经过时。

0x1 前言

总的来说这道题还是蛮有意思的,确实花费了我蛮多时间的,但是好在我还是乐在其中的。这一周算是一个过度周吧,学校里面的事情目前总体也不算太多,但是我已经预感到之后会有一大堆事情的到来了。但是没有办法呀,我不想干活呀。我觉得每天复习复习数据库已经是我的极限了,其他多余的一点事情都不想干。但是昨天群里面的web大佬们好像很嗨的样子,他们聊的东西我也不太明白(想了想我好像小专业也是网络安全的吧233)。具体就是我们有一个学长,对那个网站做了一个渗透测试。具体的流程我也没太听懂,大概就是前端的代码逻辑有点问题,导致了一些数据的泄露。其实想了想,其实现在网络上根本就没有绝对的安全,无非就是维护成本和攻击成本罢了。像我这个服务器里面有很多漏洞,很多漏洞我都能看得明白是个啥,但是我不想修也没钱请人修,甚至我连我的服务器日志有些时候都懒得看。为啥?因为没有必要,里面的信息他不重要没必要保护。同理,我觉得学长们就算是把渗透测试的报告交上去,他们也不一定会去修复。主要是我们的信息可能也不太值钱,我大一在外联的时候,就有人问我们买个人信息,新生的个人信息,大概就是一页(大概20来个)五块钱。所以呀,我们现在就是在互联网上裸奔,只要有心人想,那我们一定藏不住!刚开始的时候,我以为我们安全专业可以保护所有人,随着我的逐渐深入,我发现我们可能连自己现在或者是未来都保护不好。不说啦,说远啦!就是一句话自己太菜还要努力。


0x2 题目分析

首先我们先打开题目,由于crackme160属于很早很早的游戏了,所以基本上都是32位的程序,我们直接上OD。运行一下,发现我发现,这个程序居然没有按钮。学过一点C#,知道按钮是一个基本的相应事件的函数接口,但是没有按钮的话,我们就要想想其他的方式了。

我们先看看,是否有一些字符串的关键提示。如果作者刻意隐藏字符串的话我们再想办法。很幸运我们通过字符串找到了关键的判断,我们尝试修改Z标志位,越过判断。好的我们看见了输入注册码成功后的程序状态。

好的既然找到了关键判断,那么我们就在这个函数上下断点,看看程序是如何运行的。由于没有按钮,我们在输入完用户名和密码之后,发现程序是没有反应的,于是尝试的点了一下图片位置,果然断点被命中了。但是这个程序恶心就恶心在主函数里面有很多垃圾循环,我愣是没看懂他想干嘛。那我们只能从对比cmp下手了,cmp也很简单,将一段内存地址里面的数字与0x85进行比较,如果成功,那么就判断注册码通过。这里我出现了一个想法,也可以算是一个失误。因为仔细看这个寻址方式不难发现是一个esi+常量的间接寻址方式,所以一开始我认为是通过name与注册码之间的一些算法讲这个esi引导到一个正确的地址,而正确的地址里面记录的使0x85.于是我搜索了内存空间中的所有0x85,将所有的地址记录下来,一个一个付给esi想去寻找那个正确地址。很不幸我没有找到,说明这个想法是错误的。(主要是因为前几次的esi随着我的输入发生了改变,所以我产生了这种想法)
那有没有可能还有一个关键的判断,在判断成功后将0x85赋值进入这个内存地址。于是我查询了0x85所在的代码段,果不其然,我找到了一个mov,和一个关键判断。

nice,上面的cmp就像是一个套娃,与之前的很像,只不过是将0x85换成了0x3e。我们按照上面相同的方法,我们定位到了一个函数,给这个函数打上断点后,发现了一个很有意思的现象,就是每当我们在注册窗口输入(换种说法就是在键盘的缓冲区又字符的时候)就会触发这个断点,然后程序经历了花里胡哨的操作后,然后假装啥也没发生,继续等待你的输入。这里我大概就猜到这个程序的一个基本流程。就是在你输入注册码的时候,每一位他都在与生成的注册码进行比对,如果正确了或者是有一瞬间是正确的,程序都会将那个内存地址里面的数据置为0x85(至于瞬间对后,然后又不对了,程序是否会再将那里的数据变为0我们有进行验证),然后点击图片位置进行判断。
那么下面就好办了,我们仔细的研究一下这个主要函数。首先发现了两个很可疑的字符串。

在调用最后一个call之前我们在内存处找到了一个字符串,很长并且有中文。把它dump出来,测试一下果然是注册码,但是是一个拼接的注册码,后面明显有一部分是我们的用户名。我们搜索一下,发现了两个字符串。

但是我们发现了一个问题,就是在注册码中少了一个数字,是没有在内存中间的,那么这位应该是计算出来的。我们找到那个数字出现的call,从栈,寄存器一步一步追上去。发现这个数字的原数据是来自于字符串的长度加上5。

之后我们看一下那个call,发现了一个%d,如果对scanf和printf熟悉的话,大概能猜到,这可能是一个10进制的转换函数,我们多输入几个name验证一下,果然就是十进制转化。(不想看代码就偷懒了)
总结一下:注册码=string1(自带)+十进制(len(name)+5)+string2(自带)+name。


0x3 总结

这道题其实算法只要明白具体流程之后,还是十分的简单的。主要就是突出了一个新奇,在没有按钮之后我们该如何应对,如何逆向,从何下手。但是整个程序里面有很多很多我觉得没啥用的垃圾循环,也不知道是因为编译的原因还是作者故意的,反正是我看不太懂。我很好奇,这些垃圾循环到底是什么,要是我有幸得到答案,我会在这里为自己答疑的!

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!