APKTOOL是目前反编译ANDROID apk的主要工具,可以反编译出APK里的资源文件和smali代码,而有些APK开发者为了防止自己的代码被反编译,针对APKTOOL工具加固代码,使得APKTOOL无法运行正常,比如这篇文章介绍的Android应用资源文件格式解析与保护对抗研究,因此有必要根据具体情况修改APKTOOL源码重新编译,本人花了一天时间来编译调试,现将具体的过程分享一下。
一. 下载源码
APKTOOL源码下载,github上直接DOWNLOAD或者使用GIT来下载,最好使用GIT,它依赖什么项目就会自动的去下载。
二. 源码编译
编译可以直接使用APKTOOL目录下的gradlew.bat命令,我使用了ANDROID STUDIO来编译源码。
1. 源码导入ANDROID STUDIO
“FILE”->”OPEN…”->源码目录
2. 编译
最右边”Gradle”->刷新同步
这时会自动的从网络上下载指定版本的gradle,如果gradle设置的是offline的话,gradle同步不了,需将gradle设置的offline的选择去掉。
“FILE”->”Settings”->”Build,Execution,Deployment”->”Gradle”
同步成功的话,gradle窗口会出现如下的任务列表。
在任务列表里选择如下的任务双击运行,APLTOOL的主要类在brut.apktool:apktool-cli模块里,运行”fatjar”任务生成项目的jar文件。
这时会在项目目录下自动创建了brut.apkool.smali文件夹(文件夹不存在的话),然而编译会报错,找不到brut.apkool.smali下的源码。
因为brui.apktool:apktool-cli依赖brui.apktool:apktool-lib,brui.apktool:apktool-lib依赖brut.apkool.smali下的模块,brui.apktool:apktool-lib的build.gradle内容如下:
dependencies {
compile("junit:junit:4.10") {
exclude(module: 'hamcrest-core')
}
compile project(':brut.j.dir'),
project(':brut.j.util'),
project(':brut.j.common'),
project(':brut.apktool.smali:util'),
project(':brut.apktool.smali:dexlib2'),
project(':brut.apktool.smali:baksmali'),
project(':brut.apktool.smali:smali'),
depends.snakeyaml,
depends.xmlpull,
depends.guava,
depends.commons_lang
testCompile depends.xmlunit
}
brut.apkool.smali下源码是空的,这是另一个项目的源码,需要先下载下来。
有两种方式下载:
1. 直接访问https://github.com/JesusFreke/smali下载源码,源码下载完成后将目录下的所有文件复制到brut.apkool.smali文件夹下。
2. 使用gradlew.bat applyPatches命令,这个会将本项目依赖的其他项目源码都同步下来,并下载到指定的目录里,不过这需要先按照git。
smali源码添加完成后再次运行任务,还是会报错”util”模块找不到。
查看brut.apktool.smali:baksmali的build.gradle内容
dependencies {
compile project(':util')
compile project(':dexlib2')
compile depends.commons_cli
compile depends.guava
testCompile depends.junit
testCompile project(':smali')
}
其依赖util模块,而在目录下明明就有util模块,为什么找不到它呢?
通过上网查找了一下资料,了解了每个项目只能有一个settings.gradle,包含本项目下的所有的模块,apktool的settings.gradle内容如下:
include 'brut.j.common',
'brut.j.util',
'brut.j.dir',
'brut.apktool.smali:util',
'brut.apktool.smali:dexlib2',
'brut.apktool.smali:baksmali',
'brut.apktool.smali:smali',
'brut.apktool.smali:dexlib2:accessorTestGenerator',
'brut.apktool:apktool-lib',
'brut.apktool:apktool-cli'
其中并没有util模块,这里之所以是util,是因为brut.apkool.smali是我后加入的另一个项目,在它的项目settings.gradle文件里是包含了,内容如下:
include 'util', 'dexlib2', 'baksmali', 'smali', 'dexlib2:accessorTestGenerator'
所以直接编译brut.apkool.smali是可以的,如果放在APKTOOL项目里编译就有问题了,解决方法就是将’:util’改为’:brut.apktool.smali:util’,同理其他的也一起改掉。
修改完了再次运行任务,还是报错。
在brut.apktool\apktool-lib\src\main\java\brut\androlib\src\SmaliDecoder.java文件里出现了两个错误,ClassPath没有dontLoadClassPath静态变量,baksmaliOptions没有DIFFPRE静态变量,我也没弄明白我下载的都是最新的smali代码,为什么smali类里会没有相关变量。
ClassPath.dontLoadClassPath = mDebug;
options.registerInfo = (mDebug ? baksmaliOptions.DIFFPRE : 0);
我把ClassPath.dontLoadClassPath = mDebug;直接去掉,baksmaliOptions.DIFFPRE改为baksmaliOptions.ALL。
修改完后终于编译通过了,在Apktool\brut.apktool\apktool-cli\build\libs目录下成功生成apktool-cli.jar。
三. 调试
“Edit Configurations”->”+”->jar application设置如下内容->”ok”
在apktool-cli下的[email protected]设置断点,Shift+F9调试成功。