首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

没事儿下个副本吧?逆向新手踩坑指南

cvx

老规矩,坐下,打开电脑,最好能泡一杯茶,手边再放一个肉夹馍。。。

由于上一次吃过没查壳的亏,所以这次要先看一看有没有壳,用PEiD打开看一看:

很好,没有壳,先直接运行看一看,找一找关键字符串:

这样,我们就有了关键字符串,直接IDA打开(一定要先用IDA打开,高手都是这样的,即使不是,也要假装是),然后通过IDA的字符串查看功能(shift+F12)来找我们需要的字符串:

除了我们想要的字符串还有满满的意外收获,先等等再说,直接双击“welcome to zsctf”,然后按下X,通过交叉引用来到了我们想要的函数:

这是函数最开始反编译以后的样子,很多函数名称不是很友好,在这里,我想很多老师傅应该都会上手修改函数名称,改成对人阅读友好的名字,举个例子,第9行和第10行一眼就能看出来这是C里面的printf函数,这里,单击一下这个函数,然后按下n,就会跳出来修改函数名称的窗口:

直接修改为printf,ok以后,就能看到所有函数名称一样的地方全部变成了我们修改的字样:

通过不断地双击函数,查看函数的功能,修改函数或者变量的名称,最终修改函数名称变成了这个样子:

第17行的函数进入以后是这个样子的:

好多函数,不可能一一分析,那么猜测应该是花指令,这段代码有可能是对输入进行判断也有可能是处理输入字符串,等等再说,先看后面的函数。从第14行我们能得到输入的字符串长度是24,第20行应该是对处理过的字符串进行验证,只能是0-9,a-f。会不会是进行了md5加密?不管他,后面还有一个关键的函数,check。进入check函数以后,这个check卡了我很长时间,很长时间,有多久往下看:

第一眼看上去简直复杂得不得了,这还怎么看???继续改名字!!!一边改名字一边分析各个函数,比如变量a1就是我们输入的字符串,那么a2的类型就不是int,应该是char类型的,这里按下键盘上的y来修改变量类型:

修改完以后我们看起来费力的第23行一下子变得简单起来了,前后对比如下:

按照这样的思路各种修改同时也是分析程序的各个功能,最终得到这样的逻辑:经过处理的字符串传递进来以后,每两个字符一组,第一个字符对应第一个switch,第二个字符对应第二个witch。结合此函数的结尾部分:

不难得出,第一个表示方向,第二个表示步长,通过两个switch语句达到这个功能,byte_541168[]开始的地方是一串字符串【delru0123456789】。在这里的时候我就疑惑了,从d到9一共15个字符,整个选择一共有16个,这是什么意思?搞不懂啊,卡在这里很久很久····于是放弃思考15与16的问题,打算进入down_check函数看一看:

我基本就歇菜到这四个检查函数里了,这四个检查函数大同小异,都是判断,然而就是这个判断逻辑搞不懂。做不出来题目就认真玩游戏,认真玩游戏,认真玩游戏,重要的话说三遍!!

于是在我翻车以后我打算继续逆向,还是回到熟悉的地方重新开始,正好这个时候学了一些东西,get到了以前一直忽略的一个地方,就是函数的类型,不是所有的函数都有返回值,就像这几个函数一样:

函数返回以后没有对其他进行赋值操作,那么,这四个函数应该都是void类型的函数,然而,在我打开down_check函数的时候,简直亮瞎我的眼:

怎么可能是int类型?!!改!单击sub_462D60以后按下y,改成void以后,世界清晰了许多,感觉人生特别美好,阳光特别灿烂,再来一次翻车都没问题。

于是,按照这样的思路依次修改这四个文件,并且把传递的参数也进行名字上的修改,一边改,又一边分析了程序,然后阳光再次普照大地,还是以down_check为例:

如上图,传递两个参数,一个是当前已经走的步数,一个是要走几步,这里,如果要想将i的值重新赋给*steps,必须满足两个条件:

1:i/26

2:dword_540548[i]^dword_540068[i]==0

两个条件同时满足才能避免return,并且完成i的自增。这一点非常重要,因为先判断dword_540548[i]^dword_540068[i]=0以后才进行i的自增。表示先判断能不能往下走,再把步数加上去。或者说站在迷宫中的一个点的时候先判断能往哪里走,再把步数加上来。如果判断顺序颠倒一下,表示在迷宫的一个点可以从哪里来。这是一个往哪里走和从哪里来的问题。

还有值得一提的就是,在对四个函数进行分析的时候,通过他一直和26做除法能推断出来这个迷宫一行26个,一共12行。没错,就是12行!你也许会问:在down_check里明明是i/26>10嘛,你想想,如果你在第12行,你上面至少11行,那么,这个时候,你是不能down的,只有在第11行的时候,你能down,此时你的i/26取整等于10。

怪不得把我卡得死死的。到这里,距离我坐下,打开电脑已经三个月过去了,当然,中间有其他事情,还有过年。

现在,我们找到了四个不同方向的检查函数,问题来了,迷宫呢?!!!四个check函数里做异或的地址都不一样,这是想干什么?这里又卡了好久好久,真的好久,久到开始怀疑人生。后来又翻了一次车,才想明白一件事情:每个检查函数里都有做异或的字符串,表示这个点能向哪个方向移动,那么我把同样的一个i,对应的四个check函数合并起来,是不是就得到了迷宫!!!迷宫就是一个12×26的矩阵!!!

有了想法立刻行动,直接用IDA的python接口写脚本,把每个方向的check函数中做异或的地方提取出来,比如提取up_check出来看看:

提取出来是这样的:

然后把提出来的四个列表合起来,我用Pycharm跑了一次试了试:

显示效果不好,把他放在notepa++上效果好很多:

问题又来了:我在哪儿?我要去哪儿?回到IDA,找到了这个线索:

最开始的时候steps为0,在20行又有311的数字,结合上面的12×26=312,推断出就是从迷宫左上角走到右下角了。

路线图是这样的:

根据整个switch语句的判断,能得到这样的一串数字:【06360836063b0839073e0639】。此时大家别忘了,还有一个函数在孤独的等着我:

这个函数就是我刚开始怀疑的那个md5加密,因为转换过后的字符是有限制的。IDA我是不看了,那个太复杂,干脆动态调试一下试试:

前面就不说怎么找关键位置,直接从定位关键字以后开始输入字符串:

此时根据输入的字符串定位到加密的地方:

在这里要根据堆栈段的内容将内存段的地址改过去,方便查看数据的变动,注意地址,0x4EFD58是我们输入字符串的原始存储地,0x56D090相当于复制了一份。在一步一步跟的时候发现是先将输入字符串的第17个字符和1做了异或然后到这里的。然后继续F8,一步一步跟,跟到下面这个地方的时候一直在反复循环,于是我打算在这里下两个端点,一个是每次循环,一个是整个循环跳出:

此时要重点关注数据窗口的数据:

此时多按几次F9,发现数据窗口的内容发生了改变:

这里看到了第一个字符,再次多按F9的时候,变成了这样:

数字4的ASCII码为0×34,用字符串的表示为str[3],第四个字符,数字对上了,根据前面第17个字符先和1做异或,这里猜测应该是这样的逻辑:

a=’123456′

a[0]则表示1

a[1]则表示2

那么

b = a[i]^i

让程序跑完这一段,得到加密后的字符串:

程序跑完以后再F8几次,注意寄存器的表示,能发现想下面这样一样,把原来存放字符串的地方的值变成了加密后的字符串,也就是0x4EFD58这个地方:

然后继续F8,看看程序要到哪里去:

这里很明显有四个比较,而且0×30是数字0,0×39是数字9,0×61是字母a,0×66是字母f,返回IDA查看一下我们的宏观判断:

我们已经成功跳出了加密函数,进入了字符合法性判断,还剩下一个就是验证自己的算法猜想。

自己写一段python代码验证一下:

猜想得到验证,搞定这题!

直接上代码找flag~!

最后把第17个字符替换一下就行。

然而我提交以后发现不对。不对?!!!!!为啥?

此时想到了用程序判断一次试试,然后我发现我忽略了一个点:

最开始的时候意外收获的字符串给忘了,程序运行完以后会生成一个flag.png文件,这个文件不完整,我用电脑软件扫描不出来,后来进入IDA亲自手拖这段数据(强迫症是不会用手机直接扫描的)

在这里直接复制到hex里面保存。注意png文件的开头和结尾是:文件头:89504E47 文件尾:AE426082

最后成功扫描出了结果:

此题逆向至此结束,结合了在IDA里重命名,更改类型,IDA脚本,OD的熟练使用。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180409B14SIH00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券