layout: post
title: 2年逆向研究心得-谈谈我对逆向的一些认识
categories: Reverse_Engineering
description: 2年逆向研究心得-谈谈我对逆向的一些认识
keywords:
url: https://lichao890427.github.io/ https://github.com/lichao890427/
1.定义的给出
下面是软件工程中普遍对于逆向工程枯燥的定义:逆向工程是一个广义概念,是指从可运行的程序系统出发,运用解密、反汇编、系统分析、动态调试等多种技术对软件进行分析,推导出软件产品的结构、流程、算法、软件架构、设计模式、运行方法、相关资源及文档等这一过程。软件逆向的整个过程统称为软件逆向工程,过程中所采用的技术统称为软件逆向工程技术。究其义,这是个软件安全方面的技术。
2.我的逆向之旅
逆向从这个词看上去,也可知道是非一般IT知识,一般的IT知识都是C++/JAVA/算法/数据结构之流,高级点的不外乎设计模式/操作系统/汇编/数据库/directx之流,逆向是哪里来的呢。如果去网上找的话,几乎铁定被误导,因为那些是做工业模型的逆向,与软件无关,而网上的所谓“逆向教学视频”也有很多只是反汇编而已,而需要花钱的那种视频则是讲了一点C语言编译成的汇编形式皮毛而已,至少在我看来是如此。我很庆幸自己可以发现和研究出很多东西,尽管这些成果最后在看书时发现前人已经研究过了,不过仍然有很多他们也没有研究全面的地方,同时实践性太差,这也是我准备出书的目的。作为一个仅有4年编程经历的人来说,我与西电/逆向/百度皆有很深的渊源。大四那时候有个软件叫飞鸽传书,局域网传文件的当时很火,不过默认ip段有限,当我自己手动改了配置文件后,可以和许多网段用户通信了,舍友惊讶的问我,你把这个exe改了?我说不是啊,我只改了配置文件,然而在我心里一直想知道如何能随意改exe。大四的时候突然喜欢上编程,而刚学2年第一次接触到逆向,那时正在考研,我从小就喜欢搞破坏,当然破坏软件我也喜欢了,在之后2年研究的时间很少,第一年需要修完3年的课,很忙,第二年去南大基本都是老师逼着干活,很烦躁,真正的研究时间都是挤出来的。上研之前的暑假去了南大,也就是在2012年8月第一次接触到逆向,当时看的是《C++反汇编与逆向分析》,照着例子自己编译小程序玩的逆向。刚学了几天理论就打算试试南大拨号软件njubrass,经过不到一个礼拜的研究居然将其逆向,并编译出了自己的拨号软件上网!!!这个软件是mfc的,包含Cstring操作/加解密算法/拨号api,当时看着自己的软件能拨号,代码和资源都恢复了,而且可以自己随意DIY界面,非常有成就感。之后一年上研一就一发不可收拾,逆向了众多小exe,包括微软自带那些记事本什么的,逆向了tracert.exe,unlocker软件等,在研二第二次去南大的时候我发扬了原先的逆向手段,将其应用到android和java领域。我当时逆向了记事本,然而睿思上有人说这个有什么用,师兄也曾经说我逆向这些水平什么都不算,小打小弄,出不来什么真东西,大公司不看重你这个,同时睿思也有人嘲笑说看你毕业时找什么样的工作。但是呢,事实上我通过逆向记事本研究到了几种编码方式和著名的“联通变眼镜”问题,同时百度也是很欣赏我的,即使我只研究了很短时间的逆向,且最大的软件也只逆向了unlocker;逆向星空屏保时,第一次写错了一句话导致星星走位不对,很搞笑;研一上实验课时u盘被实验室机器感染了,病毒被我带回去直接逆向成源码了;贵州省保密局在使用原先的保密检查工具期间发现序列号获取有问题,由于国家机关特殊限制无法直接分析其原因,最后采用逆向著名的Everest的获取序列号部分的代码,替换了原先代码成功解决问题。;通过逆向分析同类医学挂号软件得到人体图查询的实现逻辑;通过逆向ES文件浏览器和掌上南大得到控件实现逻辑。;在制作Android挂号助手初期应老师的要求制作和某挂号程序相同的功能,而该程序带有手机类型限制,因此采用逆向分析手段去除保护代码,使程序得以运行,此时还不会java和android!;逆向分析了扫雷内挂机制http://www.0xaa55.com/thread-411-1-1.html和布雷原理http://www.0xaa55.com/thread-410-1-1.html;在完成毕业论文期间系统研究了Windows下C/C++程序的软件逆向方式,分析了各种语言元素并总结出了一般软件逆向分析方法,其中深入分析了SEH机制和类结构的实现原理。api hook和远程注入都是通过逆向学到的,证明我研究逆向并不是在浪费时间。很多次通过逆向第三方软件发现其中存在的问题,这里包括师兄曾写的一个小程序。如今的我,还是以分析小程序为主,看看特殊程序的功能是如何实现的,解读别人的别具匠心。
其他做过的事还有:逆向专用地址转换器,知道了迅雷快车飞速地址转换算法/逆向虐杀原形和魔兽争霸启动程序研究同步机制,研究暴雪storm.dll中的库函数另类实现/通过逆向网盘搜索工具自制最强网盘搜索工具等。
3.逆向适合谁学
一门技巧,总体来说,有兴趣即可学,只是学的速度不同,学的速度与悟性/分析能力/洞察力/记忆力/经验/运气/自信/毅力等成正比。学逆向前提是有浓厚兴趣/有破坏欲和偷窥欲_/有毅力,而且至少需要掌握汇编和一门高级语言。真正的逆向资料网上很少,很多东西基本上不可能百度到,而是靠经验和悟性,毕竟这是一门真正的技术,要很高的悟性和分析能力,需要长期投入才有回报,大家都会了了优势就没了,我在论坛里和书里也仅仅是略扯些皮毛而已,真正的经验是不会外传的,不过这些微不足道的经验则是初学者的基石,最近我发的这些文章研究水平自认为已经接近国外高手那些帖子了,比如C++ under the hood。一般这种文章基本上在说一个事实,这个事实一般写源码的人和这些逆向者知道,而探究其原理和思考并不多,如果经常看我的帖子,会发现我会提出最吻合的观点并尝试进行解释和证明,这个过程是越研究越透彻的,虽然可能会出错。
4.编程/反汇编/逆向的关系
普通编程并不需要逆向,除非别人有什么小功能实在做不出来业务资料可查而却有样例程序,抑或要做外挂破解之类。而要学逆向则一定要学精通编程,否则调试技术再好也没用,另外逆向什么类型的程序,你首先需要很熟悉编写那种类型的程序,否则举步维艰。高级语言程序的逆向和该语言元素的关系,就如微分和积分的关系,试问微分形式都不知道,如何反推呢。如果不能反推,那么所做的工作仅仅是“反汇编”,且对于高级语言特性则完全流失掉了。要逆向,就要逆向到适合的最高语言层级,这样才符合当今软件世界的发展,如果软件是C/C++编的,就应该恢复成C/C++的,python的就恢复成python的,java的就恢复成java的,不要字节码。再者如今的编译器在优化能力方面已经很强大,所以知道了一个高级语言debug产生的汇编形式外,还要明白release在其基础上究竟会怎样优化,知己知彼才能成功。编程到了一定境界,自然知道底层会怎么做,不过要系统深究起来,还是要研究逆向,这样可以写出基于编译器的高效程序。至于反汇编,我始终认为反汇编不是逆向,因为反汇编是一种机械行为仅仅将机器码转化为汇编代码,软件足以胜任,而逆向则不是,他需要有技术和艺术的人翻译成漂亮的高级语言代码,甚至分析出可复用的软件框架/设计模式/算法高级元素。而要分析出这些元素,如前所述,你得会设计软件框架/设计模式/算法,这样才知道所见的究竟是个什么。
5.如何进行逆向
工欲善其事,必先利其器。对于现在的软件,想要进行逆向首先要有工具,工具提供了代码分析/符号解析/流程分析等实用功能。没有这些功能,基本上无法逆向现有软件。尤其是dos时代程序员可能想着用debug.exe或者hiew什么古老玩意,可是时代变了,常规编程已经都需要专用工具,更别说逆向!。现今进行软件逆向对于静态分析一定要用IDA,而动态调试可以用windbg和ollydbg。IDA的分析能力和扩展能力可以秒杀任何其他静态分析工具,别的工具基本没有存在必要。而2款调试器则是windows下调试程序所必备的,windbg更强大也更难用一些。要抛弃hiew w32dasm c32dasm,记住现在是高级软件的时代。ida的强大之处在于除了可以反汇编,还可以任意加载插件,最强大的插件当属Hex-rays。该款插件可以将汇编语言转换成C语言伪代码,之所以说伪代码,是因为他的等级介于汇编和C语言之间,有很多C语言特新仍然无法转换出来,不过已经是中级语言语法了,同时IDA还有调试插件。除了静态工具和动态工具,其实还有辅助工具如日志记录/程序行为监视工具等。逆向就是要结合静态分析和动态分析,静态分析特点是量比较大,很容易迷失在代码中,而不是很多“高手”所谓静态分析不适合处理C++动态行为,其实是可以分析的只不过会很艰难。而动态分析是让程序执行起来,执行的含义就是让程序在你当前特定环境下选择一条条的分支语句执行,这也意味着很多分支无法走到,然而这一次运行已经能给出大概的执行轮廓,因此执行流程更清楚。如果搞破解的话,很轻易下个断点什么的就找到某些关键语句了,这样可以加快静态分析速度。然而有些情况例如你的程序不兼容你现在的平台无法运行,或者你的程序是个病毒不想运行,那么还是要用静态分析,或者借助虚拟机。对于大型软件要取关键代码,就需要先用动态调试找到关键代码所在处,之后对这一段结合使用静态分析和动态分析。这里始终强调一点:世界上目前没有C++反编译器,也没有完美的C语言反编译器,因为编译器的优化程度实在是太大了,不容易做到。
6.逆向和破解的关系
破解程序,是你发现了一个关键点,在这个关键点上下功夫,用调试器想办法找到和捕获该关键点。而逆向则相当于程序所有位置都视为关键点,要分析到所有分支,所以如果有人仅仅通过动态调试逆向了软件,那么这一定仅仅是破解而已,因为动态调试一次直走一个分支,没办法看到全局,而静态分析相反,它可以看到全局,但是由于信息量太大容易使人陷进去。总体来说,破解可算逆向的一部分,却又有区别。破解是犯法和猥琐的,好似一个强奸犯,做完就走,而逆向呢,则像上帝,根据模型造出人体。2种都造人,只不过后者很复杂很累。一般来说,破解就是用来解除一些软件限制,比如注册机/内存改写/爆破/去除时间限制等。
7.逆向工程和编译原理的关系
本人暂时没学过编译原理,只有少量了解,不做过多评论,不过有一点是确定的,编译原理解决的是编译器如何对待你的代码,如何进行初步处理,这是一种语法语义句法上的问题,并不直接影响汇编结果,但是可以通过常见行为去推测编译器该如何做,而不同编译器有不同优化方法,且显然也不会公开。唯一能了解到这些不同的就是靠直接逆向分析编译出的文件。简言之,对于一句高级语言,编译原理做的是所有编译器会怎样进行初步处理,而逆向工程则是告诉你特定编译器最终处理结果。显然逆向工程更直接一些,而编译原理可以用来做参考。同时多学点操作系统知识也会有溢出,毕竟人家研究几十年的东西不是你一朝一夕就可以理解的。
8.我擅长和不擅长的
一般很少有人直面自己的缺点,我却无所畏惧,因为假使别人和我同等程度同等条件同等情况去学,不见得做的比我好。我逆向过MFC程序,windows api程序,驱动(别怕,这个其实是最容易逆向的),病毒,易语言程序,混淆程序,java程序,android程序, com组件。对于vb delphi bcb 和linux平台相关的逆向没有做过,因为不用这些语言。最近一年抽出时间研究逆向都是被逼无奈的。
9.逆向是不是F5 & 逆向是不是体力活
前一句话是我在面360的时候一个高级工程师告诉我的,他认为静态分析很低级,而逆向主要靠动态调试,同时他认为静态分析就是F5一下。不过我始终不以为然,因为我主要靠静态分析工作,不过有必要我会使用动态分析,使用动态分析会大大简化逆向这一过程,因为其实这是靠手动设置几个关键点进行研究操作的,而静态分析则相对盲目多了。另外很多人认为静态分析就是F5这个也是不对的,F5只是调用Hex-ray进行中间语言的翻译,他能加快普通常见语句分析速度,而对于特殊用法和很多语法之外的元素识别能力很差,比如对于类/异常,靠F5是得不到任何有用东西的,静态分析最终靠分析能力和经验,有这2个才会提速。该面试官很鄙视我,显示他什么都会,而我却走的不是正路,这种态度就好比我认为无米之炊没什么可以鄙视的,你有米我没米你就鄙视我,但是我没有米我也做出来饭了,虽然我才学2年做饭,且做的饭没有登峰造极,但不应该因此受到鄙视,如果在我这个情况,你也不见得比我强。我学不到2年能分析出如此多的程序,并有自己的研究能力,也不是普通人就可以随便做到的,我自认为还是有天赋的,而且我会以自己的成果证明静态分析是有用的,觉得没用是因为你根本没有深入了解。如果静态分析很精熟的话,是可以做出插件的,那时效率就会更高,媲美动态分析也未可知,毕竟现在静态调试软件都有了!当然现在的我还没有此种实力,不过我认为,5年以后就会有了,我也知道调试的厉害之处,不过苦于眼下研究的东西比较耗时间,在我进了百度以后会有人教我,那时的速度和层次就不是现在这样的了,你认为不熟练是一种罪,我却认为你看不到我的学习能力也是一种罪。
现在的软件几乎没有用纯汇编写的了,因此理论上直接F5即快又省事,这样是对的,不过很多情况下,F5翻译的结果并不对,如果没有足够经验分辨出哪里对哪里错是最要命的,因为这将导致重新编写的软件无法运行。作为一个真正“逆向”爱好者而言,要先学会“微分”才好,这样F5得到的奇怪结果可能仅用一眼且不用看反汇编就可以轻松搞定了。比如一般经过优化的库函数IDA识别失败的概率很大,此时就需要你这种经验了。
逆向是不是体力活呢?在我而言不是的,纯看你怎么定义逆向的,如果仅仅是分析成F5那样结果的,那确实是体力活,但是事实上每个软件都有自己的变数,你不可能逆向的软件都一个套路,可能每个软件用了不同的技术,而你只研究了一个模块就说二者是相同的,其实只看到了冰山一角,和许多其他工作一样,逆向包括体力活和脑力活,体力活就是F5和众多插件可以做到的,而脑力活则需要去分析的,如果你不按(3.逆向适合谁学)说的,没有独到的分析能力而去探别人早都研究出来的东西,花了很多精力之后说“这是体力活”那么只能说你太笨。聪明的人会节省体力活时间完成脑力活,这和普通编程以及你做其他工作是一样的,没有智商哪都跑不了。。。
10.C/C++逆向书籍,这里只挑逆向专著
- 《C++反汇编与逆向分析技术揭秘》主要描述C/C++语言元素微分形式,静态分析
- 《IDA Pro权威指南》第一版和第二版 主要讲解IDA的各种用法
- 《IDA Pro代码破解揭秘》比较混杂
- 《反编译技术与软件逆向分析》主要为编译原理
- 《黑客反汇编揭秘》第一版和第二版 主要讲解C/C++语言元素微分形式/调试技术/PE格式/软件保护
- 《软件逆向分析实用技术》较杂,不优秀
- 《逆向工程揭秘》应用逆向/破解/解密/保护
- 《Inside Windows Debugging》Windbg用法