为什么有些语言可以被反编译?而有的不能?

作者:hillin
链接:https://www.zhihu.com/question/21853681/answer/74134768
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

要理解这个问题,先要看「正」编译的过程是怎样的。
你有一个想法,这是一种人类自然语言可以表达出来的东西。你利用编程技能,把它「翻译」成你熟悉的一种编程语言:

然后编译器(compiler)将它翻译成机器所能理解的语言:

这中间的每一步都是一个「信息丢失」的过程。比如你说,我要把这些数排个序。然后你轻车熟路地写了个冒泡排序。你的原始动机其实已经一定程度上从你的代码里丢失了——有经验的人可能可以一眼看出你这段代码是在排序,而新手小明看到的只有一些for和if之类的东西。如果是更复杂的功能,那么可能过一段时间你自己都看不懂自己当时是想干什么。从程序语言到机器语言的过程其实也是一样的。这两个过程其实都是把「做什么」转换成「怎么做」的过程,转换完成之后,究竟一开始是要做什么,这个信息已经丢失了。

所谓「反编译」,其实就是找回这些丢失的信息的过程。从这个角度上来说,你阅读一段代码的过程,其实就是在将它「反编译」成自然语言。如果要完美地反编译,那只存在一种可能,就是信息完全没有丢失——比如说你阅读的这段代码有充分的注释,或者它使用了一种你所知晓的模式(这也是为什么大家一再强调注释和设计模式的重要性)。对于从机器语言到程序语言的反编译过程,也是一样。

比如说有比反编译更低级(非贬义)的过程,叫做反汇编:

严格来说汇编语言也是一种编程语言,不过我们在这里把它和我们常说的高级编程语言(包括C语言)区分开。

这个步骤里,我在汇编和机器语言里使用的是双向实线箭头,因为它们是可以互相转换的。从汇编语言到机器语言的过程中没有丢失任何信息——因为两者的指令是一一对应的,因此反汇编可以轻松达成。

这就是很多程序语言只能反汇编、不能(难以,下同)反编译的原因。一般我们管这种语言叫「编译语言」,又称「原生语言」。代表有C、C++等。

那为什么有的语言可以反编译呢?这又要从机器语言说起。就像不同地域的人所用的语言不同一样,不同的机器说的语言也不尽相同。用行话说,叫「指令集不同」。比方说,你的电脑和你的手机,指令集一般是不一样的。一段程序要让不同的机器都能执行,只能分别翻译(编译)成相应的机器语言。这个过程太麻烦了,于是人们想了个办法,搞出了一种叫解释语言的东西(此处未考证解释语言是否就是因此发明的,只是帮助理解)。解释语言的整个流转过程是这样的:

解释语言有两种执行方式,这取决于执行端的「解释器」是如何工作的。一种是直接解释执行,中间就没有机器语言什么事情了,但这种方式效率很低。因此现代的解释语言基本上都会采用第二种方式,也就是经由图中上部的路径,先通过JIT编译的方式翻译成机器语言,然后再执行,保证执行效率。JIT编译大致可以理解为「我需要用到什么就编译什么」,这个过程常常是在执行过程中同步进行的。
「解释器」的英文interpreter,其实就是名词「翻译」的意思。这好比你国外交部发了封文件到各国大使馆,再由大使馆的工作人员分别翻译成相应的语言,传达给目标国相关部门。代表性的解释语言如Javascript,它要在不同机器的浏览器上都能正确执行,所以采用这种方式。
但是这样一来,程序代码就必须提供给每一台执行端机器了。这可是泄密啊。对于防止泄密,最直接的方式自然是加密。

有锁就有钥匙,同时也有开锁术;有加密也就有破解。这时候所谓的「反编译」,其实就是破解加密算法。这一点就不展开聊了。

后来,人们觉得解释语言执行得实在有点慢,于是又想了一个办法:把一些可以前期做掉的工作先做掉,只留着那些跟目标机器有关的工作,到时候再说。于是程序被处理成了一种叫做「中间语言」,或者叫「字节码」的东西:

这个过程一般也叫做编译。中间语言词汇少,比较精炼,执行起来也更快。这些语言一般也会用上JIT技术,进一步把中间语言编译成机器语言(而非解释执行),执行效率也就跟那些原生的编译语言不相上下了。这种语言代表性的有C#、Java等。

程序语言可以编译成中间语言,反过来,中间语言也可以在一定程度上反编译成程序语言。这是因为采用这种编译方式的编程语言为了保证它们的高级特性(比如说反射),在编译的过程中保留了源程序的绝大部分信息,只有很少的信息丢失;也正是因为丢失了这一部分信息,中间语言通常不能完美地反编译——最常见的就是反编译出来的程序中局部变量的名字都丢了,被替换成了由反编译器自动生成的名字。但这样反编译出来的程序,结构和功能都是完备的,可读性也有一定的保障。一般来说,我们所说的可以反编译的程序都是指这样一类语言写就的程序。

中间语言可以被反编译;加密又会被破解,而且执行前还要解密,会带来额外的性能开销。有没有办法能让代码既能有效执行,又不被截获代码的人所利用呢?这时候人们从一些职业素养很差的程序员那里得到了启发。

实现一个相同的功能,可以有无数种形式的代码。你恪尽职守,认认真真地写注释,准确地命名函数和变量, 严格按照规范进行缩进和换行;小明却相反,完全没有注释,变量全部用abcd乃至故意误导别人(var mySon = laowang.Son),缩进换行邋遢,尤其是在大括号前不换行,让大家很不满。于是老板想,我们先把小明开除掉,然后给你发奖金并要求大家按照你的方式写代码,并且开发一个工具,唤作「混淆器」,在发布时再把代码处理成小明写的那种样子:

这样代码即使被反编译和解密了,别人看也看不懂,不小心还会被带到坑里去。代码毕竟是写给人看的,只是偶尔让机器跑一跑,所以没有可读性的代码是没有价值的。这种方法一出,广受好评,于是变成了一种非常普遍的做法。注意图中省略了中间代码和JIT的步骤,混淆通常会跟这些技术一起使用。

时间: 2024-10-15 10:29:55

为什么有些语言可以被反编译?而有的不能?的相关文章

Java代码的编译与反编译那些事儿

编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级语言(Low-level Language)和高级语言(High-level Language). 机器语言(Machine Language)和汇编语言(Assembly Language)属于低级语言,直接用计算机指令编写程序. 而C.C++.Java.Python等属于高级语言,用语句(Statement)编写程序,语句是计算

Java 编译与反编译

编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级语言(Low-level Language)和高级语言(High-level Language). 机器语言(Machine Language)和汇编语言(Assembly Language)属于低级语言,直接用计算机指令编写程序. 而C.C++.Java.Python等属于高级语言,用语句(Statement)编写程序,语句是计算

编译与反编译GNU Linux语言文件方法

/*********************************************************************  * Author  : Samson  * Date    : 11/21/2014  * Test platform:  *              3.13.0-24-generic  *              GNU bash, 4.3.11(1)-release  * ************************************

apk反编译生成程序的源代码和图片、XML配置、语言资源等文件

在APP开发工程中,有时候我们可以通过APK反编译来借鉴下别人的思想,但是切不可用于不正当的用途!了解反编译的程序员也不必担心,可以多去了解下APP安全加密技术,这样就不用担心自己的APP被反编译了!当然本文的目的只是分享. apk反编译生成程序的源代码和图片.XML配置.语言资源等文件. 具体步骤: 1.下载 apktool 下载地址:https://code.google.com/p/android-apktool/downloads/list 2.解压 apktool,打开DOS命令行工具

Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正

一.前言 在之前的破解过程中可以看到我们唯一离不开的一个神器那就是apktool了,这个工具多强大就不多说了,但是如果没有他我们没法涉及到后面的破解工作了,这个工具是开源的,也是使用Java语言开发的,代码相对简单,我们今天就来分析一下他的大体逻辑,注意是大体逻辑哦,因为如果要一行一行代码分析,首先觉得没必要,其次浪费时间,有了源码,谁看不懂呢.至于为什么要分析这个工具其实原因只有一个,就是我们在之前的反编译过程中会发现,总是有那么几个apk应用不让我们那么容易的反编译,他们就利用apktool

反编译Android APK及防止APK程序被反编译

原文出处 反编译Android APK及防止APK程序被反编译 怎么逆向工程对Android Apk 进行反编译 google Android开发是开源的,开发过程中有些时候会遇到一些功能,自己不知道该怎么做,然而别的软件里面已经有了,这个时候可以采用反编译的方式,解开其他的程序,来了解一些它 的做法,同时啊,还可以借鉴别人的软件结构,资源文件:作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看.此方式主要目的是为了促进开发者学习,借鉴好的代

Android APK反编译就这么简单 详解(附图)

在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看.下面是我参考了一些文章后简单的教程详解. (注:反编译不是让各位开发者去对一个应用破解搞重装什么的,主要目的是为了促进开发者学习,借鉴好的代码,提升自我开发水平.) 测试环境: win 7 使用工具: CSDN上下载地址: apktool (资源文件获取)  下载      

Android 反编译与防止被反编译

泉贸软件工作室原创.原帖地址:http://www.svch0st.com/cont.asp?id=38 Android App使用Java语言进行开发,因此十分容易就可以被反编译出近乎原始的程式码.也因为这个特性,许多人在写Android App的时候会喜欢去反编译别人写好的程式,再挪为己用,虽然很不道德,但这也是一种有效提升软体开发速度的方法.但换个角度想,如果是自己写的程式码被盗走的话,这就对自己不太有利了,所以学习如何防止自己程式码被偷也是一个很重要的课题. Android App的安装

【转】Android APK反编译就这么简单 详解(附图)

转载地址:http://blog.csdn.net/vipzjyno1/article/details/21039349 在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮 的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看. 下面是我参考了一些文章后简单的教程详解. (注:反编译不是让各位开发者去对一个应用破解搞重装什么的,主要目的是为了促进开发者学习,借鉴好的代码,提升自