写点什么

写给小白看的,逆向工程怎么上路?

用户头像
Machine Gun
关注
发布于: 21 小时前

什么是逆向工程

先给大家出一道思考题


用 C 语言设计一个程序,验证输入的密码是否是“12345678”,如果验证成功,就输出“success”,如果验证失败,则输出“failed”。


我想,大部分新手小白估计会这么写:


#include <stdio.h>#include <string.h>
int main() {
char buf[10] = {0}; scanf("%s", buf); if (strcmp(buf, "12345678") == 0) { printf("success"); } else { printf("failed"); }
return 0;}
复制代码


上面的代码编译后,会生成一个可执行程序,咱们来对这个可执行文件进行一下反编译,看看能看到什么?


下图是在反编译神器 IDA 中,可执行文件反编译出来的汇编指令图:



可以非常清晰的看到一些字符串的信息:"success"、"failed"、"1234567。


再认真一看,main 函数中有一个分支判断,根据判断的结果,走入左右两个分支,分别输出"success"和"failed"。


如果新手看不懂上面的反汇编图,那可以再使用 IDA 的神级功能:F5 反编译高级语言功能,直接将上面的汇编程序再进一步还原成 C 语言。



可以对照一下上图中的 C 函数代码和原来我们的源代码,还原度非常的高了,字符串比较的功能逻辑暴露无遗


可以看到,通过这种方式进行密码匹配,非常不安全,对方拿到你的程序一反编译,就能看到密码是什么了。


不过咱们今天的文章主题不是探讨如何进行安全地进行密码比较,而是另一个主题:逆向工程。


什么是逆向工程,维基百科中的解释如下:


逆向工程(Reverse Engineering),又称反向工程,是一种技术过程,即对一项目标产品进行逆向分析及研究,从而演绎并得出该产品的处理流程、组织结构、功能性能规格等设计要素,以制作出功能相近,但又不完全一样的产品。


逆向工程的概念起源于商业和军事领域,后延伸到软件领域。


在软件领域,通过对程序文件进行逆向分析,推导出程序对源代码设计的过程,称为软件逆向工程。比如上面通过分析可执行文件还原出 C 代码,分析 jar 包/class 文件还原出 Java 源码,这都属于软件逆向工程。


软件逆向工程是网络安全领域中的一个重要分支,网络黑客通过逆向工程可以获得目标的程序原理,破解软件的权限,这一般发生在商业软件领域。另外一方面,黑客通过逆向分析也常用来发现软件漏洞,用来对其发起攻击,Windows 作为一个不开源的操作系统,就经常遭遇这样的事情。


本文就来探讨一下,逆向工程一般是怎么进行的,需要学习哪些东西?

程序反编译

逆向的一开始,通过会对目标进行反编译。


作为软件开发者,对编译这个词应该不会陌生,我们写好了程序代码,然后使用编译器将其转换成可执行的程序,这个过程叫做编译。


反编译,自然就是这个过程的逆过程,那该选择什么样的程序进行反编译呢?


对于 C、C++、Golang 等类型语言编写的程序,我们一般使用 IDA 进行反汇编。



对于 Java 语言编写的 class 文件和 jar 文件,我们一般使用 jd-gui 进行反编译。


对于 C#语言编写的可执行程序,我们一般使用 reflector 进行反编译。


所以学习上面三款反编译工具的使用对学习逆向工程非常重要

可执行文件格式

不同的操作系统平台具有不同的可执行文件格式,如 Windows 上的 PE 文件、Linux 平台的 ELF 文件、MacOS 上的 Mach-O 文件


一个可执行文件中除了源代码生成的汇编指令,还有静态数据(如代码中引用到的字符串),导入导出信息,文件属性信息等等,掌握提取这些信息,会对咱们了解目标程序非常有帮助。



这就需要学习不同平台上可执行文件的格式,尤其是 PE 文件和 ELF 文件,是逆向工程中最常打交道的文件格式。

CPU 指令集

在逆向分析程序时,最主要的精力和时间就是在阅读和分析反编译出来的汇编指令。


所以 CPU 的指令集和汇编语言是搞逆向的同学必学的一门课。


常见的 PC 端 CPU 就是 Intel 的 x86、x64 和 AMD64,移动端的就是 ARM 架构。建议先从最基本的 x86 开始学习,尤其要注意网络上很多教程讲的还是 16 位实模式下的汇编语言,非常容易误导人。实模式当然要了解,但要把精力放在保护模式下 32 位汇编语言。



等 x86 入了门,可以扩展学习 x64,到后期再扩展学习 ARM。


学习汇编语言,不仅仅是学习汇编指令,更是在学习了解 CPU,CPU 有哪些寄存器,分别有什么用,它是如何访问内存,如何进行寻址,如何进行运算等等。

高级语言特性

咱们逆向工程的目标大都是用 C/C++/Java/C#这样的高级语言编写出来的程序,要想还原出程序的代码逻辑,如果不懂高级语言本身那肯定是不行的。


当然,做逆向的同学,不必要像专业的开发同学那样对这些语言的特性烂熟于心,掌握很多编程技能,这倒不用。


但掌握这些语言的基本编程技能还是有必要。拿 C 语言来说,C 语言中函数调用原理,参数如何传递,函数中的局部变量如何分布,数组如何存储,结构体成员如何内存布局,指针又是如何实现的等等,这些基础概念咱们得知道,不然拿到反汇编代码,也不知道如何与高级语言进行转换。



像上面说到的这些 C 语言知识,学习的时候要自己对比源码和编译后的汇编指令长什么样,反复对比学习,产生条件反射。除了这些,还要关注 C++中面向对象实现原理,虚函数机制,this 指针如何传参,new 和 delete/delete []等等在汇编指令层如何实现。


有些人说,咱不是有 F5 大法吗,直接一键搞定?当然 F5 功能非常强大,我也不反对使用工具,但我们不能过分依赖于工具,不然就变成一个彻底的工具人,尤其是对于初学者,自己尝试从汇编指令转换成高级语言,会让自己对技术底层原理理解的更加透彻。而且,有很多时候 F5 功能用不了,那个时候还得靠自己的知识上!

软件调试

很多时候,光靠静态分析无法实现目标,比如程序进行了加壳等技术,在静态分析下看到的全是错误的指令代码,甚至让反编译工具无法分析。


这个时候,就需要结合动态分析技术一块儿上,让程序实际运行起来,再来对其进行分析,所以,掌握软件调试技术,也是逆向工程中不可缺失的一环


结语

以上,就是我总结的几点学习逆向工程需要关注的知识点,希望对大家有帮助。



另外,我整理了一套逆向工程学习的书籍、资料、软件工具、使用教程,已经打包好了,由于资料敏感,就不公开传播了,有需要的朋友,可以点击下方,即可免费领取

【资料分享】


用户头像

Machine Gun

关注

还未添加个人签名 2021.03.28 加入

需要获取网络安全/渗透测试学习资料工具的朋友可联系V:machinegunjoe666 免费索取

评论

发布
暂无评论
写给小白看的,逆向工程怎么上路?