‘壹’ 为什么我反编译一个exe文件原封不动转为.exe就报错了。
世界上的大多数事物都是存在不可逆特性的,比如说生鸡蛋煮成熟鸡蛋很容易,但把熟鸡蛋再还原为生鸡蛋就几乎不可能了,也许将来的科技能够实现,但至少现在还没听说过。
程序的编译和反编译也是一样,一个电脑程序从供人类阅读的高级语言编译为供CPU解读的机器语言,这是一个质变的过程,比方说某个运算结果可以用多种算法实现,那么你想往上回溯时,究竟选择那种算法呢?你可能会说,让反编译软件随便选一种吧,那么问题来了,再继续往上回溯的时候,很有可能就跟原程序完全不同了。所以,尽管“条条大路通罗马”,但要想从罗马回到原来的出发点就不是容易的事了。因此,到目前为止,尚未有反编译软件能够把一个exe文件完整无误地反编译为源程序的(当然也许极简单的程序可以,比如hello world),而程序本来就是严谨的东西,差一个字也可能会产生十万八千里的误差。所以,反编译的结果只能用作参考,不能把它当作实际代码。
‘贰’ java反编译
如今JAVA语言在全世界范围正如火如荼般的流行,它广范地应用在INTERNET的数据库、多媒体、CGI、及动态网页的制作方面。1999年在美国对JAVA程序员的需求量首次超过C++!
作者因最近分析一些JAVA程序,对JAVA的反编译进行了一番了解,下面将我所了解的情况作以下介绍,希望对JAVA爱好者有所帮助。
JAVA是采用一种称做“字节编码”的程序结构,分为小程序(嵌入到HTML文件中)和应用程序(直接在命令状态下执行)两种类型。无论哪种结构,一旦用JAVAC 命令编译后,均变成后缀为CLASS的同名可执行文件。这种文件是不可阅读的代码。
经查阅了SUN公司的JDK(JDK1.1.3)文档资料后,我找到了一个据称是可反编译JAVA的JAVAP文件(EXE),这个文件位于\JDK\BIN\ 下面,经按说明使用后,感到失望,原来这个“反编译”仅可反编译出JAVA程序的数据区(定义)、若干方法和类的引用等。
这里我用了一个简单例子来说明问题。
JAVA的源程序hello_java.java如下:
import java.applet.*;
import java.awt.*;
public class hello_java extends Applet
{
public void paint(Graphics g)
{
g.drawString("Hello Java!\n",20,20);
}
}
经用反编译命令:javap -c -package -public -private hello_java hello.java
得到的反编译结果(hello.java)如下:(有关javap命令的选择参数请见其使用说明,这里-c表示选择了反编译)
Compiled from hello_java.java
public synchronized class hello_java extends java.applet.Applet
/* ACC_SUPER bit set */
{
public void paint(java.awt.Graphics);
public hello_java();
Method void paint(java.awt.Graphics)
0 aload_1
1 ldc #1
3 bipush 20
5 bipush 20
7 invokevirtual #6
10 return
Method hello_java()
0 aload_0
1 invokespecial #5 ()V>
4 return
}
‘叁’ android 如何对apk文件进行反编译以及重新
第一:使用apktool直接反编译apk
第六:把生成的hellodemo.apk安装到手机,可以看到主界面上已经显示的是hello,而不再是你好。说明反编译重新打包成功!
‘肆’ 如何反编译android应用并重新打包
反编译android步骤入下:
第一:使用apktool直接反编译apk
第六:把生成的hellodemo.apk安装到手机,可以看到主界面上已经显示的是hello,而不再是你好。说明反编译重新打包成功!
‘伍’ exe的安装包,如何反编译查看代码
1、首先新建一个android项目,里面只有一个mainactivity,而且主界面只会显示一个字符串:你好。
2、下面,切换到这个项目生成的apk文件所在的目录,可以看到有一个hellodemo.apk。
3、在命令行输入:apktool
d
-r
hellodemo.apk。可以看到在当前目录下生成了一个hellodemo文件夹。
4、进入到hellodemo\smali\com\example\hello,打开mainactivity.smali。找到:
const-string
v1,
"\u4f60\u597d",
修改为:
const-string
v1,
"hello",
5、然后在命令行输入:apktool
b
hellodemo
hellodemo1.apk。这回重新打包成hellodemo1.apk。
6、然后给新生成的apk进行签名。把这个apk拷贝到autosign的目录下面,然后切换过去,在命令行输入:java
-jar
signapk.jar
testkey.x509.pem
testkey.pk8
hellodemo1.apk
hellodemo.apk。
7、把生成的hellodemo.apk安装到手机,可以看到主界面上已经显示的是hello,而不再是你好。说明反编译重新打包成功!
‘陆’ perl如何避免反编译
为了保护Perl源代码,常用的有三种方法。
1.
使用Perl自带的perlcc工具。这个工具有一个最大的弱点:它只能作用于一个perl文件。假如你和我一样写了十几二十几个perl包,主程序里倒是空空如也,估计要郁闷死。用也是可以用的,就是要把所有的源代码到一个文件,取消所有的package定义,把原来不同package下面同名的函数改名,不同的package里面的同名全局变量也要改名。然后
$perlcc -o hello hello.pl
得到可执行程序hello. Perlcc的原理是把perl程序转换成C程序,然后用GNU
C编译器编译。它在Windows上也可以用,但需要额外安装C编译器,比如Intel C或者MS Microsoft Visual
C。由于perlcc把代码先变C再变可执行程序,反编译出来的源码很难看懂,所以安全性很高。但是把所有的代码写一个文件,模块也不能用了,这简直是从地铁时代回到乌蓬船时代,我想不会有人觉得舒服。何况这样混杂后的代码该如何维护升级和做版本控制呢,头大。另外,perlcc有申明,不保证它编译出来的东西能用(参见$perldoc
perlcc)。我没遇到这个情况,而是遇到了perlcc直接就对我的程序编译不通过,没戏唱了。{2006.12.15更新:找到perl不能编译我的程序的原因了:1.
只能用use 不能用require,模块文件名的后缀都改成.pm, use后跟不带后缀的文件名就可以。2.
所有的全局数组,必须用my, our,
或者local来定义,不可以用缺省作用范围。第二点其实应该是perlcc的一个bug了,因为关联数组和简单变量都没有这个问题。}
2. perl2exe,据说很好用,但令人沮丧的是要license, 而且据说跨平台还有问题。
3. PAR(Perl Archive Toolkit)。这个命名法则是类似于JAR(Java
Archive)。下载下来以后还要从CPAN上下载一些依赖性模块。CPAN模块果然好装,每个模块都是
$perl Makefile.PL
$make
$make install
就能装好。最后安装PAR。装好以后会在/usr/bin/下面添加一些工具。我不关心别的,就要用pp:
$pp -o hello hello.pl
这样生成的hello就是可执行文件,而且把用到的perl模块文件也全打包进来了。运行的时候它会在/tmp/par-username/下生成一个叫
cache-123456789之类的临时文件夹,打开看看可以发现就是自己的源代码。这样不是没达到我想要的隐藏源代码的目的么?原来还需要启动过滤器:
$pp -f Bleach -o hello hello.pl
或者
$pp -f Bytecode -o hello hello.pl
前面的Bleach过滤器是PAR自己实现的,而Bytecode这种过滤方式是Perl的标准格式(需要Perl
5.8.1以上版本支持)。过滤之后,临时文件夹里面的文件就不是简单可读了。当然是有办法crack,
但这和恢复带初始变量名的源代码是两回事。
‘柒’ 如何将手机apk 安装包反编译和重新打包签名
android应用安装到手机的是一个apk文件。apk是可以用工具进行反编译并重新打包的。本文将介绍下如何用apktool对apk进行反编译并重新打包。
工具/原料
apktool
auto sign
方法/步骤
首先我们新建一个android项目,里面只有一个MainActivity,而且主界面只会显示一个字符串:你好。
下面,我们切换到这个项目生成的apk文件所在的目录,可以看到有一个hellodemo.apk。
在命令行输入:apktool d -r hellodemo.apk。可以看到在当前目录下生成了一个hellodemo文件夹。
进入到hellodemo\smali\com\example\hello,打开MainActivity.smali。找到:
const-string v1, "\u4f60\u597d",
修改为:
const-string v1, "hello",
然后在命令行输入:apktool b hellodemo hellodemo1.apk。这回重新打包成hellodemo1.apk。
然后给新生成的apk进行签名。把这个apk拷贝到autosign的目录下面,然后切换过去,在命令行输入:java -jar signapk.jar testkey.x509.pem testkey.pk8 hellodemo1.apk hellodemo.apk。
步骤阅读
把生成的hellodemo.apk安装到手机,可以看到主界面上已经显示的是hello,而不再是你好。说明反编译重新打包成功!
‘捌’ java 反编译到底是什么
你理解的反编译没有问题,应该是你的插件或操作的问题。
你用 JD-GUI 软件试试看
‘玖’ 如何实现APK的反编译得到APK的源码
最新的反编译不用此方法, 有最新的一键自动反编译工具:
这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧,google了一下,确实很简单,以下是我的实践过程。
在此郑重声明,贴出来的目的不是为了去破解人家的软件,完全是一种学习的态度,不过好像通过这种方式也可以去汉化一些外国软件。
注:本Android反编译教程,在Windows7-Ultimate-64bit操作系统上,测试通过!
下述所需的反编译工具包 下载
一、反编译Apk得到Java源代码
首先要下载两个工具:dex2jar和JD-GUI
前者dex2jar是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工具,可以直接查看Jar包的源代码。以下是下载地址:
dex2jar:http://laichao.googlecode.com/files/dex2jar-0.0.7-SNAPSHOT.zip
JD-GUI:http://laichao.googlecode.com/files/jdgui.zip
具体步骤:
首先将apk文件,将后缀改为zip,解压,得到其中的classes.dex,它就是java文件编译再通过dx工具打包而成的;
解压下载的dex2jar,将classes.dex复制到dex2jar.bat所在目录。在命令行下定位到dex2jar.bat所在目录(在DOS命令下CD 目录)
运行
dex2jar.bat classes.dex
生成
classes.dex.dex2jar.jar
生成jar文件的截图如下:
运行JD-GUI(jd-gui.exe),打开上面生成的jar包,即可看到源代码了
HelloAndroid源码(编译前的apk源码对照)如下:
二、反编译apk生成程序的源代码和图片、XML配置、语言资源等文件
如果是汉化软件,这将特别有用。首先还是下载工具,这次用到的是apktool
下载地址:http://code.google.com/p/android-apktool/downloads/list
下载:apktool1.4.1.tar.bz2 和 apktool-install-windows-r04-brut1.tar.bz2(两个包都下载)
具体步骤:
将下载的两个包解压到同一个文件夹下,应该会有三个文件:aapt.exe,apktool.bat,apktool.jar
在命令行下定位到apktool.bat文件夹,输入以下命令:apktool d C:\*.apk C:\*文件夹,如下图:
命令行解释:apktool d [apk文件 ] [输出文件夹]
反编译的文件如下(AndroidManifest.xml为例):
特别注意:你要反编译的文件一定要放在C盘的根目录里(其实不用放在C盘根目录也行)
例如:在D盘目录D:\apktool1.4.1
cd /d D:\apktool1.4.1 //切换到D盘目录,包含HelloAndroid.apk以及aapt.exe,apktool.bat,apktool.jar三个文件
apktool.bat d -f HelloAndroid.apk HelloAndroid // apktool反编译命令,注意 d和
-f 的写法
将反编译完的文件重新打包成apk,很简单,输入apktool b c:\***文件夹(你编译出来文件夹)即可,命令如下:这个主意你文件所在盘
打包apk后的文件在目录C:\HelloAndroid下,生成了两个文件夹:
build
dist
其中,打包生成的HelloAndroid.apk,在上面的dist文件夹下,Ok
最后,再介绍一款刚出来的反编译工具 Androidfby ,它是一款对上述步骤进行了封装的图形界面工具,下载地址
但是,针对部分签名的apk,无法实现反编译,但本博客方法则仍然可以反编译成功!仅供参考使用
另外,作为应用开发者,肯定不希望自己的代码被反编译的,下一遍博客将讲述如何通过混淆代码防止被别人反编译
Android如何防止apk程序被反编译
作为Android应用开发者,不得不面对一个尴尬的局面,就是自己辛辛苦苦开发的应用可以被别人很轻易的就反编译出来。
Google似乎也发现了这个问题,从SDK2.3开始我们可以看到在android-sdk-windows\tools\下面多了一个proguard文件夹
proguard是一个java代码混淆的工具,通过proguard,别人即使反编译你的apk包,也只会看到一些让人很难看懂的代码,从而达到保护代码的作用。
下面具体说一说怎么样让SDK2.3下的proguard.cfg文件起作用,先来看看android-sdk-windows\tools\lib\proguard.cfg的内容:
[html] view
plainprint?
1. -optimizationpasses 5
2. -dontusemixedcaseclassnames
3. -
4. -dontpreverify
5. -verbose
6. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7.
8. -keep public class * extends android.app.Activity
9. -keep public class * extends android.app.Application
10. -keep public class * extends android.app.Service
11. -keep public class * extends android.content.BroadcastReceiver
12. -keep public class * extends android.content.ContentProvider
13. -keep public class * extends android.app.backup.BackupAgentHelper
14. -keep public class * extends android.preference.Preference
15. -keep public class com.android.vending.licensing.ILicensingService
16.
17. -keepclasseswithmembernames class * {
18. native <methods>;
19. }
20.
21. -keepclasseswithmembernames class * {
22. public <init>(android.content.Context, android.util.AttributeSet);
23. }
24.
25. -keepclasseswithmembernames class * {
26. public <init>(android.content.Context, android.util.AttributeSet, int);
27. }
28.
29. -keepclassmembers enum * {
30. public static **[] values();
31. public static ** valueOf(java.lang.String);
32. }
33.
34. -keep class * implements android.os.Parcelable {
35. public static final android.os.Parcelable$Creator *;
36. }
从脚本中可以看到,混淆中保留了继承自Activity、Service、
Application、BroadcastReceiver、ContentProvider等基本组件以及
com.android.vending.licensing.ILicensingService,
并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考<proguard_path>/examples中的例子及注释。)
让proguard.cfg起作用的做法很简单,就是在eclipse自动生成的default.properties文件中加上一句“proguard.config=proguard.cfg”就可以了
完整的default.properties文件应该如下:
[html] view
plainprint?
1. # This file is automatically generated by Android Tools.
2. # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3. #
4. # This file must be checked in Version Control Systems.
5. #
6. # To customize properties used by the Ant build system use,
7. # "build.properties", and override values to adapt the script to your
8. # project structure.
9.
10. # Project target.
11. target=android-9
12. proguard.config=proguard.cfg
大功告成,正常的编译签名后就可以防止代码被反编译了。反编译经过代码混淆的apk得到的代码应该类似于下面的效果,是很难看懂的:
如果您使用的是2.3之前的SDK版本也没关系,把上面的proguard.cfg文件复制一份放到项目中,然后进行相同的操作即可
‘拾’ 如何防止程序员反编译
Java从诞生以来,其基因就是开放精神,也正因此,其可以得到广泛爱好者的支持和奉献,最终很快发展壮大,以至于有今天之风光!但随着java的应用领域越来越广,特别是一些功能要发布到终端用户手中(如Android开发的app),有时候,公司为了商业技术的保密考虑,不希望这里面的一些核心代码能够被人破解(破解之后,甚至可以被简单改改就发布出去,说严重点,就可能会扰乱公司的正常软件的市场行为),这时候就要求这些java代码不能够被反编译。
这里要先说一下反编译的现象。因为java一直秉持着开放共享的理念,所以大家也都知道,我们一般共享一个自己写的jar包时,同时会共享一个对应的source包。但这些依然与反编译没有什么关系,但java的共享理念,不只是建议我们这样做,而且它自己也在底层上“强迫”我们这么做!在java写的.java文件后,使用javac编译成class文件,在编译的过程,不像C/C++或C#那样编译时进行加密或混淆,它是直接对其进行符号化、标记化的编译处理,于是,也产生了一个逆向工程的问题:可以根据class文件反向解析成原来的java文件!这就是反编译的由来。
但很多时候,有些公司出于如上述的原因考虑时,真的不希望自己写的代码被别人反编译,尤其是那些收费的app或桌面软件(甚至还有一些j2ee的wen项目)!这时候,防止反编译就成了必然!但前面也说过了,因为开放理念的原因,class是可以被反编译的,那现在有这样的需求之后,有哪些方式可以做到防止反编译呢?经过研究java源代码并进行了一些技术实现(结果发现,以前都有人想到过,所以在对应章节的时候,我会贴出一些写得比较细的文章,而我就简单阐述一下,也算偷个懒吧),我总共整理出以下这几种方式:
代码混淆
这种方式的做法正如其名,是把代码打乱,并掺入一些随机或特殊的字符,让代码的可读性大大降低,“曲线救国”似的达到所谓的加密。其实,其本质就是打乱代码的顺序、将各类符号(如类名、方法名、属性名)进行随机或乱命名,使其无意义,让人读代码时很累,进而让人乍一看,以为这些代码是加过密的!
由其实现方式上可知,其实现原理只是扰乱正常的代码可读性,并不是真正的加密,如果一个人的耐心很好,依然可以理出整个程序在做什么,更何况,一个应用中,其核心代码才是人们想去了解的,所以大大缩小了代码阅读的范围!
当然,这种方式的存在,而且还比较流行,其原因在于,基本能防范一些技术人员进行反编译(比如说我,让我破解一个混淆的代码,我宁愿自己重写一个了)!而且其实现较为简单,对项目的代码又无开发上的侵入性。目前业界也有较多这类工具,有商用的,也有免费的,目前比较流行的免费的是:proguard(我现象临时用的就是这个)。
上面说了,这种方式其实并不是真正加密代码,其实代码还是能够被人反编译(有人可能说,使用proguard中的optimize选项,可以从字节流层面更改代码,甚至可以让JD这些反编译软件可以无法得到内容。说得有点道理,但有两个问题:1、使用optimize对JDK及环境要求较高,容易造成混淆后的代码无法正常运行;2、这种方式其实还是混淆,JD反编译有点问题,可以有更强悍的工具,矛盾哲学在哪儿都是存在的^_^)。那如何能做到我的class代码无法被人反编译呢?那就需要我们下面的“加密class”!
加密class
在说加密class之前,我们要先了解一些java的基本概念,如:ClassLoader。做java的人已经或者以后会知道,java程序的运行,是类中的逻辑在JVM中运行,而类又是怎么加载到JVM中的呢(JVM内幕之类的,不在本文中阐述,所以点到为止)?答案是:ClassLoader。JVM在启动时是如何初始化整个环境的,有哪些ClassLoader及作用是什么,大家可以自己问度娘,也不在本文中讨论。
让我们从最常见的代码开始,揭开一下ClassLoader的一点点面纱!看下面的代码:
Java代码
publicclassDemo{
publicstaticvoidmain(String[]args){
System.out.println(“helloworld!”);
}
}
上面这段代码,大家都认识。但我要问的是:如果我们使用javac对其进行编译,然后使用java使其运行(为什么不在Eclipse中使用Runas功能呢?因为Eclipse帮我们封闭,从而简化了太多东西,使我们忽略了太多的底层细节,只有从原始的操作上,我们才能看到本质),那么,它是怎么加载到JVM中的?答案是:通过AppClassLoader加载的(相关知识点可以参考:http://hxraid.iteye.com/blog/747625)!如果不相信的话,可以输出一下System.out.println(Thread.currentThrea().getContextLoader());看看。
那又有一个新的问题产生了:ClassLoader又是怎样加载class的呢?其实,AppClassLoader继承自java.lang.ClassLoader类,所以,基本操作都在这个类里面,让我们直接看下面这段核心代码吧:
看到这里,已经没有必要再往下面看了(再往下就是native方法了,这是一个重大伏笔哦),我们要做的手脚就在这里!
手脚怎么做呢?很简单,上面的代码逻辑告诉我们,ClassLoader只是拿到class文件中的内容byte[],然后交给JVM初始化!于是我们的逻辑就简单了:只要在交给JVM时是正确的class文件就行了,在这之前是什么样子无所谓!所以,我们的加密的整个逻辑就是:
在编译代码时(如使用ant或maven),使用插件将代码进行加密(加密方式自己选),将class文件里面的内容读取成byte[],然后进行加密后再写回到class文件(这时候class文件里面的内容不是标准的class,无法被反编译了)
在启动项目代码时,指定使用我们自定义的ClassLoader就行了,而自定义的部分,主要就是在这里做解密工作!
如此,搞定!以上的做法比较完整的阐述,可以仔细阅读一下这篇文章:https://www.ddtsoft.com/#developerworks/cn/java/l-secureclass/文章中的介绍。
通过这个方法貌似可以解决代码反编译的问题了!错!这里有一个巨大的坑!因为我们自定义的ClassLoader是不能加密的,要不然JVM不认识,就全歇菜了!如果我来反编译,呵呵,我只要反编译一下这个自定义的ClassLoader,然后把里面解密后的内容写到指定的文件中保存下来,再把这个加了逻辑的自定义ClassLoader放回去运行,你猜结果会怎样?没错,你会想死!因为你好不容易想出来的加密算法,结果人家根本不需要破解,直接就绕过去了!
现在,让我们总结一下这个方法的优缺点:实现方式简单有效,同时对代码几乎没有侵入性,不影响正常开发与发布。缺点也很明显,就是很容易被人破解!
当然啦,关于缺点问题,你也可以这么干:先对所有代码进行混淆、再进行加密,保证:1、不容易找到我们自定义的那个ClassLoader;2、就算找到了,破解了,代码可读性还是很差,让你看得吐血!(有一篇文章,我觉得写得不错,大家可以看一看:http://www.scjgcj.com/#blog/851544)
嗯,我觉得这个方法很好,我自己也差点被这个想法感动了,但是,作为一个严谨的程序员,我真的不愿意留下一个隐患在这里!所以,我继续思索!
高级加密class
前面我们说过有个伏笔来着,还记得吧?没错,就是那个native!native定义的方法是什么方法?就是我们传说中的JNI调用!前面介绍过的有一篇文章中提到过,其实jvm的真实身份并不是java,而是c++写的jvm.dll(windows版本下),java与dll文件的调用就是通过JNI实现的!于是,我们就可以这样想:JNI可以调用第三方语言的类库,那么,我们可不可以把解密与装载使用第三方语言写(如C++,因为它们生成的库是不好反编译的),这样它可以把解密出来的class内容直接调jvm.dll的加载接口进行初始化成class,再返回给我们的ClassLoader?这样,我们自定义的ClassLoader只要使用JNI调用这个第三方语言写的组件,整个解密过程,都在黑盒中进行,别人就无从破解了!
嗯,这个方法真的很不错的!但也有两个小问题:1.使用第三方语言写,得会第三方语言,我说的会,是指很溜!2.对于不同的操作系统,甚至同一操作系统不同的版本,都可能要有差异化的代码生成对应环境下的组件(如window下是exe,linux是so等)!如果你不在乎这两个问题,我觉得,这个方式真的挺不错的。但对于我来说,我的信条是,越复杂的方式越容易出错!我个人比较崇尚简洁的美,所以,这个方法我不会轻易使用!
对了,如果大家觉得这个方法还算可行的话,可以推荐一个我无意中看到的东西给大家看看(我都没有用过的):jinstall,
更改JVM
看到这个标题,我想你可能会震惊。是的,你没看错,做为一个程序员,是应该要具有怀疑一切、敢想敢做的信念。如果你有意留心的话,你会发现JVM版本在业界其实也有好几个版本的,如:Sun公司的、IBM的、Apache的、Google的……
所以,不要阻碍自己的想象力,现在没有这个能力,并不代表不可能。所以,我想到,如果我把jvm改了,在里面对加载的类进行解密,那不就可以了吗?我在设计构思过程中,突然发现:人老了就是容易糊涂!前面使用第三方语言实现解密的两个问题,正好也是更改JVM要面对的两个问题,而且还有一个更大的问题:这个JVM就得跟着这个项目到处走啊!