上山砍大树 发表于 2019-11-20 20:36

攻防世界 (reverse) csaw2013reversing2

1.看题下载看格式

看题目说明:听说运行就能拿到flag,但是是乱码。
从题目中好像发现不了什么问题。
下载附件,看格式是.exe文件,拖入ida后发现文件格式是pe,证明在windows环境可运行。

打开下载好的目标文件,发现是界面这样的:


从中看出一堆乱码,点击三个按钮都是关闭程序。因为不是很明白这个题要做什么,所以我们直接将其拖入ida进行分析。

2.ida静态调试
打开ida后,查找main()函数然后看main()函数流程图:


为了方便我把执行路径标号为01way和02way。
然后F5查看反汇编代码:



可以看到出现了一个IsDebuggerPresent()函数,我百度了下,这个函数的作用检测调试器,如果检测到被调试了,那么就会直接终止程序。
所以动态调试时遇到这个函数需要nop掉。

查看字符串,发现没有什么神秘的字符串,所以我们可以猜测flag应该是经过一定的算法得来的。

然后接下来我们进行分析main()函数的反汇编代码,发现有个if判断语句,如果if成立,那么执行完里面的语句,就会直接调用ExitProcess(0xFFFFFFFF)退出(即02way);
如果if条件不成立,那么就会执行下面的代码(即01way)。

可以看到我们想要的flag在MessageBoxA(0, key_value + 1, "Flag", 2u),所以我们猜得到flag的流程就是

[*]if条件语句为false
[*]调用函数MessageBoxA(0, key_value + 1, "Flag", 2u);


即选择01way流程走可能会得出flag。

而其他的变量函数看起来比较麻烦,所以我们选择不分析其他代码段的意义而直段到od里试试运气:

首先在main()函数首地址下断点,进行单步调试。

经过单步调试,我们最后调用了MessageBoxA(0, key_value + 1, "Flag", 2u);然后我们可以看到


运行时验证了我们先前按照01way走从而得出flag猜想是错误的。

那么既然01way是错误的,那么通过02way可不可能得出flag呢?

那么就试试看吧如何才能跳转到02way:

就在01way和02way的判断条件处进行操作,这时候就需要再次分析main()函数的流程


可以判断出地址在0040108A处将jnz的跳转标志寄存器改掉就可以实现跳转了。
经过验证是改变Z标志位。
所以动态调试时执行到108A的判断跳转语句时改z标志位就可以跳转到02way执行路线上。


经过02way流程的单步操作,flag还是没有出来。


这个时候其实我就自闭了,静下心来,心想如果简单地只对if动手就能得到flag那就太无聊了,然后我就回头静下心来看了看main()的反汇编代码,发现key_value很让人怀疑,下面的分析:

其中有三个函数跟key_value有关系:

1.key_value = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
2.sub_401000(v3 + 4, (int)key_value);
3.MessageBoxA(0, key_value + 1, "Flag", 2u);

而我们可以看出,执行了sub_401000,就不执行MessageBoxA;执行了MessageBoxA,就不能执行sub_401000。
而我们点开sub_401000函数后,发现对于key_value的处理异常繁琐。

所以我们可以推测应该需要把sub_401000处理过的key_value放入MessageBoxA进行下一步处理得出flag(合理猜测:)

所以我们的猜想2就是;
先执行sub_401000(v3 + 4, (int)key_value),然后将ExitProcess进行nop或者跳转到MessageBoxA的首地址开始调用MessageBoxA函数,然后得出flag。

我们怀着这样纯真的想法,对比ida的main()函数汇编流程图在相应的位置进行修改:
004010A3 jmp   short loc_4010EF -->jmp 004010B9 ;sub_401000调用完毕后后即跳转到MessageBoxA函数首地址。
(别忘了nop 掉__debugbreak()函数,把int 3改为nop)

然后你就得到了令人开心的界面:



猜想成功!果然key_value是很重要的,而且sub_401000和MessageBoxA对key_value的共同处理决定了最后的eax的值

分析MessageBoxA就会得知是将保存的数据给eax后,eax自增后得出的flag(od中的text就是输出的flag),果然key_value很重要。

我做这个题目的时候有点心急了,我觉得静下心来分析分析main()函数的流程图和汇编代码应该能快速发现问题的切入点。
不过做题做多了可能会更能静下心来分析分析吧,慌是因为自己没底气啊。:0

祝你我都好!
:P

上山砍大树 发表于 2019-11-21 11:14

唐子啊 发表于 2019-11-21 00:30
看的我眼花缭乱,我还是个弟弟啊,这么残忍吗,看来我好需要努力学习

其实这篇文章是我本次解决问题的思路,写writeup的时候也思考过是不是直接带着上帝视角把一些问题讲明白。但是我想我作为一个reverse小白,做的题目也是入门的题目,所以我希望能用我自己的角度把对问题处理的思路理清楚,讲明白。
其实并不是你们看不懂,而是我写的思路流程并不是那么清晰,往深了谈及本篇内容的说并不是由因果驱动发现问题解决问题的,而是站在我自己在做这道题的思路来的。所以本篇文章可能更多的记录我在做题时候的流程和思路,而没有做好清晰直白的描述。这是我的问题,我自己以后会改进文章的思路的。
如果谈本题的清晰总结的话,我已经放到评论区了,希望朋友你可以看一下。最后谢谢各位的提议反馈和支持!

上山砍大树 发表于 2019-11-21 10:53

这个题目做完后的总结就是:
1.注意反调试函数需要nop掉。
2.一般函数完毕后,函数会出栈,即把控制权返回给主函数,而本题if判断语句为真进入函数后,执行完函数后并不会把执行权返回给主函数main(),而是给了另一个函数ExitProcess()。而此函数执行后就会跳过main()函数中对key_value进行操作的MessageBoxA函数,而MessageBoxA函数可以推测对flag有很大的影响,毕竟第一次od执行完MessageBoxA后,弹窗就会出现乱码的“flag”。所以出题人不想让我们同时执行 sub_401000()和MessageBoxA()函数,那我们就把它们放在一起执行,看看结果如何,然后发现这两个函数同时执行可以得出flag。
这样就可以证明key_value是直接影响flag的,所以对key_value的执行运算的函数都有可能成为突破点

Devil_Kiss 发表于 2019-11-20 21:16

看的我眼花缭乱,我还是个弟弟啊,这么残忍吗,看来我好需要努力学习

cdevil 发表于 2019-11-20 21:22

好详细的解答,给楼主点赞

yufengnigel 发表于 2019-11-20 21:44

我还以为是游戏

shghe 发表于 2019-11-20 22:23

我也以为是游戏~~~{:1_896:}

ifdashui 发表于 2019-11-20 23:01

有点看不懂呀

唐子啊 发表于 2019-11-21 00:30


看的我眼花缭乱,我还是个弟弟啊,这么残忍吗,看来我好需要努力学习

2Burhero 发表于 2019-11-21 01:05

有空看看

wushuai514 发表于 2019-11-21 09:17

有点看不懂呀!!!
页: [1] 2 3
查看完整版本: 攻防世界 (reverse) csaw2013reversing2