AndroidAPK的反编译和重新打包

您所在的位置:网站首页 安卓apk混淆工具 AndroidAPK的反编译和重新打包

AndroidAPK的反编译和重新打包

2023-03-15 08:12| 来源: 网络整理| 查看: 265

反编译

Android程序打完包之后得到的是一个APK文件,这个文件是可以直接安装到Android手机上的,我们反编译其实也就是对这个APK文件进行反编译。Android的反编译主要又分为两个部分,一个是对代码的反编译,一个是对资源的反编译。

开始学习之前,我们需要准备一个APK文件,项目很简单,代码如下所示:

public class MainActivity extends AppCompatActivity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "You clicked me!", Toast.LENGTH_SHORT).show(); } }); } } RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> RelativeLayout>

运行效果: 这里写图片描述

反编译Java代码

1、首先我们需要这两个工具:dex2jar 和 jd-gui 工具下载地址

2、将APK文件改后缀为zip然后用解压缩软件打开,取出里面的classes.dex文件,如下图所示: 这里写图片描述

3、将从apk文件中得到的classes.dex文件放入dex2jar工具的目录中,如下图: 这里写图片描述

4、在命令行中进入dex2jar工具的目录,执行命令:d2j-dex2jar.bat classes.dex,如下图所示: 这里写图片描述

5、待命令执行完成后,在dex2jar工具的目录中会发现多了一个文件classes-dex2jar.jar 这里写图片描述

6、用jd-gui工具(jd-gui.exe)查看刚刚生成的jar文件,如下图所示: 这里写图片描述

我们的代码已经反编译成功了,MainActivity中的代码非常清晰,基本已经做到了90%以上的还原。但是如果想要做到100%的代码还原还是非常有难度的,因为像setContentView()方法传入的参数,其实就是一个资源的id值而已,那么这里反编译也就只能将相应的id值进行还原,而无法变成像R.layout.activity_main这样直观的代码展示。 另外,除了MainActivity之外,还有很多其它的代码也被反编译出来了,因为当前项目有引用support-v4包,这些引用的library也会作为代码的一部分被打包到classes.dex文件当中,因此反编译的时候这些代码也会一起被还原。

反编译XML代码

方法一(AXMLPrinter2):

将解压得到的AndroidManifest.xml文件放到AXMLPrinter2.jar所在目录, 双击该目录下的XmlDecode.bat,可以生成xml对应的txt,它即是解码后的XML。 这里写图片描述

打开看看: 这里写图片描述

方法二(apktool1.5.2): 将APK文件Decompile.apk拷贝到apktool1.5.2文件夹目录下,然后cmd也进入到这个目录下,执行命令:apktool d Decompile.apk。 其中d是decode的意思,表示我们要对Decompile.apk这个文件进行解码。那除了这个基本用法之外,我们还可以再加上一些附加参数来控制decode的更多行为:

-f 如果目标文件夹已存在,则强制删除现有文件夹(默认如果目标文件夹已存在,则解码失败)。 -o 指定解码目标文件夹的名称(默认使用APK文件的名字来命名目标文件夹)。 -s 不反编译dex文件,也就是说classes.dex文件会被保留(默认会将dex文件解码成smali文件)。 -r 不反编译资源文件,也就是说resources.arsc文件会被保留(默认会将resources.arsc解码成具体的资源文件)。

上述命令的执行结果如下图所示: 这里写图片描述

这就说明反编译资源已经成功了。现在你会发现在当前目录下多了一个Decompile文件夹,这个文件夹中存放的就是反编译的结果了。 这里写图片描述

打开AndroidManifest.xml,同样可以看到反编译之后的结果。

重新打包

那么对于反编译出来的文件夹,我们能不能重新把它打包成APK文件并安装呢?答案是肯定的。

重打包成APK

首先我们来看一下通过apktool反编译后的包目录情况,见上面。其中,res文件夹下存放的是反编译出来的所有资源,smali文件夹下存放的是反编译出来的所有代码,AndroidManifest.xml则是经过反编译还原后的manifest文件。

这里值得一提的是smali文件夹,如果你进入到这个文件夹中你会发现它的目录结构和我们源码中src的目录结构是几乎一样的,主要的区别就是所有的java文件都变成了smali文件。smali文件其实也是真正的源代码,只不过它的语法和java完全不同,它有点类似于汇编的语法,是Android虚拟机所使用的寄存器语言,语法结构大概如下所示: 这里写图片描述

看不懂没关系,但即使是这样,也可以对程序的逻辑做一定程度的修改了。比如说当我们点击按钮时会弹出You clicked me!这样一句Toast,逻辑是写在MainActivity按钮点击事件的匿名类当中的,因此这段代码反编译之后一定就会在MainActivity$1.smali这个文件当中,让我们打开瞧一瞧,部分代码如下所示: 这里写图片描述

第49行也太明显了,就是我们弹出的Toast内容,我们稍微修改下改成I changed it!保存。

我们现在来把反编译后的Decompile文件夹重新打包成APK吧,其实非常简单,只需要在cmd中执行命令:apktool b Decompile 其中b是build的意思,表示我们要将Decompile文件夹打包成APK文件 重打包过程中如果遇到brut.common.BrutException:at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.java)等错误,错误截图如下图所示 这里写图片描述

可以通过如下方式解决: 尝试将aapt.exe的路径加到属性的Path环境变量中; 尝试分析错误原因针对apk中重打包的错误原因进行处理,本文发现错误是style属性”@*android:style/Theme.Light”找不到,改为”android:Theme.Light”后,重新用上面的命令进行重打包解决了该问题。重打包结果如下 这里写图片描述

编译成功后,会在Decompile文件夹下生成两个新的文件夹,build和dist,其中dist下存放的就是新生成的APK文件。

APK签名

其实重打包后的APK是没有签名的,需要进行签名,签名后才能够在Android终端上进行安装。 每个发布的应用都有自己的一个唯一合法的ID,这个就是应用自身的签名,签名可以保证你软件升级的一致性,使用相同签名的应用可以实现覆盖安装,而不一致的签名将无法共享使用数据,也即是无法覆盖安装,这样可以防止别人篡改,盗用开发者的应用,造成对开发者利益的损害。那么如何为自己的应用进行签名呢? APK签名之两步走:

创建一个key 使用key对apk签名

创建一个key: 创建key,需要用到java的keytool.exe工具(该工具位于java环境的安装目录下的jdk1.8.0_91\jre\bin,不同jdk版本可能略有差异),使用产生的key对apk签名用到的是jarsigner.exe (位于安装目录下的jdk1.8.0_91\bin),如果你正确安装了java环境,并配置了正确的环境变量,那么你可以直接打开运行命令窗口输入命令: keytool -genkey -alias watson.keystore -keyalg RSA -validity 40000 -keystore watson.keystore 说明: -genkey 产生密钥 -alias watson.keystore key的别名 watson.keystore -keyalg RSA 使用RSA算法对签名加密 -validity 40000 证书有效期限4000天 -keystore watson.keystore 生成key的存放路径,你可以生成到指定路径(例如:D:\watson.keystore 在D盘根目录生成key文件,文件名为watson.keystore,如果不指定绝对路径将在当前cmd所在目录生成key文件)

注:我这里alias和keystore命名相同,其实完全可以不同的。

输入以上命令之后,需要输入一些信息,ps:提示输入口令的时候是不会有任何显示的,只管输入就是了,请牢记自己输入的两个口令!!!如下图: 这里写图片描述

至此,我们的key就生成好了,在你的输入路径下。 这里写图片描述

使用key对apk签名: 有了key之后在cmd中执行签名命令就可以进行签名了(注意我们生成的APK在dist目录下,我们需要将它copy到key所在的目录下,也就是apktool1.5.2目录下),签名命令格式如下: jarsigner -verbose -keystore watson.keystore -signedjar Decompile_signed.apk Decompile.apk watson.keystore 说明: -verbose 输出签名的详细信息 -keystore watson.keystore 使用key的绝对路径,就是在第一步中生成的key -signedjar Decompile_signed.apk Decompile.apk watson.keystore 正式签名,三个参数中依次为签名后产生的文件Decompile_signed,要签名的文件Decompile.apk和密钥库(也就是我们上面的alias)watson.keystore 这里写图片描述

签名成功,在相同目录下会生成签名后的APK文件。 这里写图片描述

至此apk文件的签名介绍完毕,你的签名文件也可以拿出去供用户使用了,但是谷歌还提供一个优化工具对你的apk文件进行优化,用法介绍如下:

zipalign(压缩对齐)优化

签名之后的APK文件现在已经可以安装到手机上了,不过在此之前Android还极度建议我们对签名后的APK文件进行一次对齐操作,因为这样可以使得我们的程序在Android系统中运行得更快。对齐操作使用的是zipalign工具,该工具存放于/tools/目录下,将这个目录配置到系统环境变量当中就可以在任何位置执行此命令了。命令格式如下: zipalign -v 4 Decompile_signed.apk Decompile_aligned.apk 说明: 这样,zipalign能够使apk文件中未压缩的数据在4个字节边界上对齐(一般4个字节是一个性能很好的值),这样android系统就可以使用mmap()(请自行查阅这个函数的用途)函数读取文件,可以在读取资源上获得较高的性能。

在4个字节边界上对齐的意思就是指编译器把4个字节作为一个单位来进行读取的数据资源,因此,CPU能够对变量进行较之前不对齐更高效、快速的访问。 对齐的根源:android系统中的Davlik虚拟机使用自己专有的格式DEX,DEX的结构是紧凑的,为了让运行时的性能更好,可以进一步用”对齐”进一步优化,但是大小一般会有所增加。

这里写图片描述

对齐操作完成,在相同目录下会生成对齐后的APK文件。 这里写图片描述

安装此APK文件(需要删除反编译之前的APK,因为签名不匹配),运行效果: 这里写图片描述

至此,完美实现了APK的重新打包。

APK的反编译和重新打包就介绍到这里,那么如何防止自己的APK被反编译呢?这就需要用到代码混淆了,感兴趣的童鞋可以参考我的这篇文章Android proguard代码混淆。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3