
先给大家出一道思考题
用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的指令集和汇编语言是搞逆向的同学必学的一门课。
常见的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功能用不了,那个时候还得靠自己的知识上!
很多时候,光靠静态分析无法实现目标,比如程序进行了加壳等技术,在静态分析下看到的全是错误的指令代码,甚至让反编译工具无法分析。
这个时候,就需要结合动态分析技术一块儿上,让程序实际运行起来,再来对其进行分析,所以,掌握软件调试技术,也是逆向工程中不可缺失的一环

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

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

所以我开始关注ruby,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出
给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R
我在我的Rails3示例应用程序上使用CarrierWave。我想验证远程位置上传,因此当用户提交无效URL(空白或非图像)时,我不会收到标准错误异常:CarrierWave::DownloadErrorinImageController#createtryingtodownloadafilewhichisnotservedoverHTTP这是我的模型:classPaintingtrue,:length=>{:minimum=>5,:maximum=>100}validates:image,:presence=>trueend这是我的Controller:classPaintingsC
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
我正在研究使用EventMachine支持的twitter-streamrubygem来跟踪和捕获推文。我对整个事件编程有点陌生。我如何判断我在事件循环中所做的任何处理是否导致我落后?有没有简单的检查方法? 最佳答案 您可以通过使用周期性计时器并打印出耗时来确定延迟。如果您使用的是1秒的计时器,您应该已经过了大约1秒,如果它更长,您就知道您正在减慢react器的速度。@last=Time.now.to_fEM.add_periodic_timer(1)doputs"LATENCY:#{Time.now.to_f-@last}"@
啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组
在Ruby中有运算符(operator)。在API中,他们没有命名它的名字,只是:Theclassmustdefinetheoperator...Comparableusestoimplementtheconventionalcomparison......theobjectsinthecollectionmustalsoimplementameaningfuloperator...它叫什么名字? 最佳答案 参见上面的@Tony。然而,它也被称为(俚语)“宇宙飞船运算符(operator)”。
电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑
电脑上可以截取图片吗?如果可以,该如何操作呢?相信很多小伙伴都只知道一两种截图的方式,知道的并不全面。其实,电脑上有多种方式截图的,而且非常方便。电脑怎么截图?今天我们就来教大家如何使用电脑截取图片的8种常用方式!操作环境:演示机型:Delloptiplex7050系统版本:Windows10方法一:系统自带截图具体操作:同时按下电脑的自带截图键【Windows+shift+S】,可以选择其中一种方式来截取图片:截屏有矩形截屏、任意形状截屏、窗口截屏和全屏截图。 方法二:QQ截图具体操作:在电脑登录QQ,然后同时按下【Ctrl+Alt+A】,可以任意截图你需要的界面,可以把截图的页面直接下载,
我正在研究Ruby解释器是如何实现的,并且出现了一个问题,但我还没有得到答案。这就是标题中的那个:因为Class(r_cClass)将super设置为自身(忽略元类,因为实际上super是r_cClass的元类),如果我向Class对象发送一个方法,这将在Class的方法表中查找'类(class)。但是Class的类是Class,所以我不应该最终寻找Class的实例方法吗?但事实并非如此,因为在文档中Class类方法和Class实例方法是分开的。在Ruby的eval.c中的search_method中,我没有发现对Class类有什么特别的检查。任何人都可以阐明这一点吗?