首页 > 代码库 > 为了CTF比赛,如何学习逆向和反汇编?

为了CTF比赛,如何学习逆向和反汇编?

作者:无名侠
链接:https://www.zhihu.com/question/23810828/answer/138696052
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

元旦节马上就要过去,赶紧趁着12点之前写完回答。

====
如果觉得本文对你有用,请点个赞并关注一下我吧~
====

我做逆向大概四年左右,虽然我没有参加过CTF,但还是可以写一些关于如何学习逆向方面的内容~

逆向实际上是很枯燥的工作,我能从枯燥中感到快乐,这就是支撑我学习逆向的动力了。

学习逆向后有什么用?难道就仅仅能用来比赛?破解啊!网上下载的破解版软件总是怕有毒,我就自己瞎折腾,技术提升了,软件也免费用了。女神爱玩捕鱼达人这类的游戏,破解工作就由我代劳了,女神说:“哇好厉害哦~”。另外还有一个用处,钱多,这里我不多谈,怕查水表。有人可能又会说到外挂,会逆向比那些不会逆向的外挂作者不知道高到哪里去了。一般的外挂作者靠CE之类的工具暴力搜索,显然这样做很容易出现一些百思不得其解的东西,而这些东西通过逆向手段是很容易找到答案的。偶尔分析分析游戏,累了还可以把别人的外挂给逆了,多爽?要多爽有多爽,黑吃黑。黑!真的是太黑了!

CTF中有多种平台的逆向,比较常见的是x86指令集的windows PC逆向和ARM指令集的Android 逆向,我建议先从PC逆向开始。Android逆向的水深,涉及不少东西,我会在后面大概讲解。

为什么要从PC逆向开始?因为这方面的资料很多,前面回答提到的书籍也都是PC的,所以我建议从PC逆向开始学习,常用书《加密与解密》。

PC逆向学习路线:
1、先学汇编!!必须学!!从8086汇编开始学,再到32位,有兴趣可以玩玩64位。
2、调试技能(OD、Windbg这些)
3、编程技能(WinAPI多多少少要知道一点,MSDN文档一定要会看)
4、脱壳
5、漏洞分析

PC逆向学习书籍推荐:
8086汇编(王爽)-> x86从实模式到保护模式(可选)-> 加密与解密 -》0day安全:软件漏洞分析技术

真正的逆向水平通过看书是无法提升的!

我个人认为逆向不存在学习路线和学习套路的说法,也没有捷径可走,唯一的捷径就是多练习!多练习!多练习!Practice Makes Perfect!

逆向完尽量写分析文章整理思路,文章可以发表在看雪、吾爱这类的论坛,也可以发在自己的博客,这属于学习总结的一个过程吧。平时没事的时候多看一点其他大神发的分析文章。除了吾爱看雪这类的老论坛,各大安全公司也有自己博客,文章都是经过精选的,非常不错!
安全博客-阿里聚安全
百度安全应急响应中心
安全客 - 有思想的安全新媒体

===============================================================
现在我们来谈Android逆向。

众所周知,Android是基于Linux内核的,App大部分要用Java开发,小部分会用到jni,其中涉及到Java、C/C++,意味着你需要学习多门“汇编”语言。

Android App 大部分是基于Java开发的,实际上并不是用的Java的原生虚拟机,Android的解释器是Google自己开发的,叫做Dalvik(不谈ART), 名字由来很玄学,这里不过多探讨。Dalvik虚拟机跑的指令集是Dalvik指令集,一般反编译后用smali语法来表示。所以学习Android逆向的第一件事情就是学习Smali语法。

如何反编译一个APK? 如果你去网上搜索的话,一般博客都会写各种牛X命令行工具,一言以蔽之就是要用N多工具才能成功反编译一个APK文件。

其实网上有很多集成化工具,比如:Android Killer,拖入Apk即可反编译。JEB也是一门不错的工具,拖入APK即可,在汇编区域按下Tab键就可以得到Java源码,JEB反编译出来的源码很美!

学习资料整理:
Android 逆向终极版,移动平台,加密与解密,鱼C论坛
看完后,破解几个小游戏没什么问题的。

学习完Smali逆向之后呢? 你如果想深入学习不想止步于破解几个小游戏,那就要去学习ARM汇编!
ARM才是移动平台的老大!
ARM是一种指令集,这种指令集的CPU普遍用于移动设备、嵌入式设备,也就是说,我们使用的手机绝大部分都是用ARM指令集的处理器,所以学习ARM钱途光明啊~

实用性不多讲,ARM逆向能赚很多钱是真的,这个不多讲了。

移动逆向交流群:471525564
偶尔讨论撩妹技术~

个人总结:
学习逆向一定要多练习,纸上谈兵卵用没有,浪费时间!在实际分析程序的时候头脑要清晰,建议用草稿纸画一画流程,我在夜间头脑很清晰,所以实际分析工作我都在晚上做,白天学习理论知识或写点代码。遇到困难千万不要退缩,积极寻找解决方案。 逆向破解往往会有很多种方法,不要因为一种方法的成功而沾沾自喜,尝试所有你想到的方法!最后,珍惜生活,多关心身边的朋友,他们真的不一样!


========================= 附带一遍我曾经写的关于如何学习汇编 ====================
最近有不少汇编初学者来问笔者:汇编怎么学?先学汇编还是先学C?汇编学了有什么用?学了汇编对理解编程有帮助吗?笔者接触汇编也不过两三年,写不出高深的文章,但是笔者也是过来人,也曾遇到过这些问题,笔者希望用通俗的语言给读者讲解我是如何看待这些问题的。注意这是春节在高速路上堵着无聊之作。

首先,恭喜你,知道”汇编”这个名词已经说明你对计算机有一定的了解程度,你想通过学习”汇编”这个途径来深入了解计算机的运作原理。”深入了解计算机运作原理”这个概念很泛,学习汇编最多是让你了解软件层面的原理,以及如何利用硬件罢了。然而计算机是由硬件和软件组成,汇编是汇编,硬件是硬件.就算你汇编再牛,你也有可能完全不知道什么是冯诺依曼,哈佛,什么是流水线,MMU,什么是段页式,什么是三态门。汇编,只是众多工具中的一种,它很重要,但只是对机器而言,对程序员来说,未必.一个写Android APP的工程师不懂汇编也能开发出很好的应用,一个写协议栈的工程师不懂汇编也能做出很优雅的协议.对于大部分的程序员来说,了解,是他们对汇编最高的理解层次,从进化论的角度来讲,这可能就说明了汇编对非BSP的程序员来说并不是十分重要.

所以,想学习硬件原理,汇编或许不是很好的途径。

汇编有很多种,不同的处理器都有一套自己的汇编语言,我们该如何选择? 如果你想做一名Windows平台安全工程狮,那么就需要学习x86汇编,因为Windows是运行在x86架构上的操作系统。x86又有16位,32位,64位,看着心都凉了半截。前辈认为我们应该从8086汇编开始学,8086汇编实际上就是16位的x86汇编。虽然现在8086处理器已经绝种了,但是我也认为应该从8086开始学习。相比32位的x86,16位更加简单,很容易学的,而且16位的汇编是32位的一个子集,学了并不是一无用处。在学习32位汇编时就很轻松,你会有一种海阔天空,会当云绝顶的感觉。地址空间从1M变成4G的,就像你一夜暴富一样。再也不用仔细考虑小运算是否会溢出。。。x86 32位引入了保护模式,引入了分页机制,这是实现现代操作系统的基础,大家学有余力可以深入了解,如果是定位是内核工程狮,那么这些就是基本功了。假如有一天你对你家的路由器感兴趣了,你想对它进行XXOO,那么你有可能需要学习MIPS汇编 ,市场上的大部分路由是MIPS架构的 。还是有些人,比较喜欢非主流,去跑去学习一些根本触碰不到的东西,往往只能纸上谈兵,挂载到嘴上,吹几个牛逼罢了,其实我是想说学习自己需要的方面,不要把精力浪费在没用的方向。有些人对我说汇编算个什么卵,用机器码编程的才牛逼,对于这种人,我也只有呵呵呵的笑。

在学习完一门汇编语言后再去学习其他平台汇编就会很容易了,或许只要一周一天甚至几个小时就能掌握新的汇编语言,笔者学习arm汇编时就是这样的。这是因为汇编难,是难在汇编生硬的思想,汇编简单,是指令简洁,比起学习一门高级语言容易很多!汇编是枯燥的,但是汇编代码能更好的体现一个人的思维!目标使你看清使命,产生动力!这句话很赞,特别适合汇编初学者,如果没有目标,你就像是无头苍蝇一样,找不着北。我有个朋友,三年前认识的,这位朋友看我写汇编代码觉得很牛逼,就让我教他。 我愉快的答应了并且还给了他《汇编语言》这本神书,然而他没有目标,三年后,前几天的事情吧,他依然在问我如何搭建汇编环境,怎么用OD。 这就是没有目标造成的,对汇编盲目崇拜,学习汇编不是因为别人也学习了汇编。

如何定目标? 对于极客来说,DIY什么的再好不过了,这和汇编有什么关系呢? 学习汇编,你能编写自己的“操作系统”,虽然称它为“操作系统”有点过了,当这何尝不是一种鼓励呢?别人问你为什么学习汇编,你回答说:"我研究系统内核的!" 档次瞬间就上去了。 编写“操作系统”的乐趣很多啊,笔者也是开发过自己的“操作系统”黑漆漆的屏幕上输出了历史性的“Hello world”,第一次读取硬盘,访问神秘莫测的显存,都充满了无限的乐趣。学习汇编可以赚钱!可以赚钱!可以赚钱!是的我没有开玩笑,但是这似乎有些不符合天朝的法律,仅供参考。赚钱其实只是为了吸引你的眼球罢了,做技术的,就不应该把金钱放在第一位! 对于做逆向来学,汇编是基础功,对汇编的熟练程度决定了你在工作岗位是否吃香。吾爱论坛也有很多用RMB求破解的,作为一名Cracker,对汇编的熟练程度也直接决定了你的吃香程度。为什么有人愿意花大价钱求破解?因为汇编难啊,算法难啊,他们看不懂啊,而你掌握了核心技术,你看得懂啊,这些就是给你送钱的啊。偶尔写一篇破文发在吾爱看雪,骗一篇精华不是挺有成就感的吗?

学习汇编能帮助理解编程?这个论点是正确的!但是对于解释性的脚本语言来说就有点不适用了,因为脚本都是解释执行的,解释器是中介 。你学习了汇编,C语言中的指针对你来说只能算是小菜。你会感叹用着C指针好幸福啊! 如果此时你在去用一些高级内存管理,什么垃圾回收一类的,你会感觉好繁琐好繁琐! 如今编译优化很牛逼了,偷梁换柱,移星大法的事情是很常有的,要调试这样的代码是很蛋疼,有时候你根本找不到出错的原因,这时候你就需要对程序进行反汇编,从汇编的角度思考你的程序。BUG常有,而Debugger不常有。Debugger指的是调试技术很精湛的人。所以学习汇编能增加你的调试技术,早日成为调戏师!不过换句话说,你总会在某些黑暗的地方被迫阅读汇编代码..........还有一点好处便是你在写代码的时候随时都会从汇编的角度来考虑代码的效率问题。学了汇编可以盗窃别人的智慧啊,说好听的我们是借鉴别人的智慧,学习别人的智慧,这和法律并不冲突,比如哪天你发现一个压缩算法好牛逼啊,可以将1G压缩成10M,然而这个软件又是闭源软件,甚至是收费软件,这时候就能通过逆向分析的手段来破解这个程序,或者用逆向分析的手段来学习压缩算法的原理,最后你的智商爆表或者受到祖上仙人保佑,你研究出可以将1G压缩到1M的超级逆天级算法,得了图领奖务必请我吃饭。

来一个大跳跃吧。比如有一天你看到了这种反人类的代码: a[i]=i++ 你会如何思考?一般程序猿会想,应该是先算 a[i] 的地址吧,一些学过一点汇编的人可能会想,应该从右边开始计算吧?CPU寄存器就那么几个,按照运算顺序貌似符合逻辑。但是这条语句在不同编译器下编译的结果是千奇百怪的,所以还是得需要通过反汇编,来看编译器是如何来编译a[i]=i++这句代码的。学习汇编!不要被编译器蒙蔽了双眼!

有的人可能还担心自己太老不适合学习汇编。其实并不是这样的,你看看教汇编的教授哪个不是老骨头啊,汇编下至6岁上至80岁都适合学习!

为了CTF比赛,如何学习逆向和反汇编?