这篇文章主要介绍两个方面,一个是介绍一些android反编译工具的使用,第二个方面是,因为自己觉得,每个工具都要自己运行一些命令,感觉有些麻烦,于是便想把这些工具整合到一起,用java写,其实这些工具的调用就是执行一些bat,这便成了如何在java中执行bat和exe程序的问题了。
先说第一个方面:
这里用到的主要有三个工具,下载的话就自己去下一下吧。
1. dex2jar:将apk中的classes.dex转化成jar文件,得到的文件名为classes-dex2jar.jar。这个无法自己设定结果文件的放置目录。
使用方法:打开命令行工具cmd,进入到dex2jar.bat的目录,执行
dex2jar.bat classes.dex
其中classes.dex可对apk文件解压之后得到。
2. jd-gui:可以直接查看反编译后的jar包源代码,即查看dex2jar生成的classes-dex2jar.jar。
这个使用没什么讲的,图形化的。当然也可以使用命令行,在第二方面会说明
3. apkTool:将apk反编译,生成程序的源代码和图片、XML配置、语言资源等文件,可自己指定输出结果的目录
使用方法:打开命令行工具cmd,进入到dex2jar.bat的目录,执行
apktool.bat d -f a.apk result
其中result为输出结果的目录。
第二个方面:
在java中执行bat、exe主要采用以下方式:
private final String dex2jarBat="cmd/c start "+dex2jarDirPath+"\\d2j-dex2jar.bat --force";
String cmd=apkToolBat+" "+apkPath+" "+resultDir+"\\apkToolResult";
//命令行
Runtimeruntime=Runtime.getRuntime();
try {
runtime.exec(cmd);
return true;
}catch(IOException e) {
e.printStackTrace();
}
先注意一点,bat、exe执行时,bat、exe本身所在的路径中的文件夹不能有空格,同时传入的参数(比如apk的路径),这个参数对应的apk所在的路径中的文件夹也不能有空格。
比如:
D:\Android Developer\dex2jar.bat D:\a.apk,错误,因为Android Developer之间有空格,因改为D:\AndroidDeveloper\dex2jar.bat D:\a.apk
整合这些工具的全部代码如下(写的不好,还望指正)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/*
* 整合dex2jar、jdgui、apkTool工具
* */
//结果保存在D:\Eclipse\workspace\androidDecompile\src\result目录下
public class AndroidDecompile {
private final String resultDir="D:\\Eclipse\\workspace\\androidDecompile\\src\\";
private String dex2jarDirPath="D:\\Eclipse\\workspace\\androidDecompile\\decompileTool\\dex2jar-0.0.9.15";
private String apkToolDirPath="D:\\Eclipse\\workspace\\androidDecompile\\decompileTool\\apktool";
private String jdGuiDirPath="D:\\Eclipse\\workspace\\androidDecompile\\decompileTool\\jd-gui-0.3.5.windows";
private String apkPath;
private final String dex2jarBat="cmd /c start "+dex2jarDirPath+"\\d2j-dex2jar.bat --force";
//使用 --force 指定如果结果文件存在则替换原有的
private final String jdGuiBat="cmd /c start "+jdGuiDirPath+"\\jd-gui.exe";
private final String apkToolBat="cmd /c start "+apkToolDirPath+"\\apktool.bat d -f";
public AndroidDecompile(String apkPath){
if(!new File(apkPath).exists()){
System.err.println("apk文件不存在");
return;
}
this.apkPath=apkPath;
}
@SuppressWarnings("resource")
public File getClassesDexFile(){//获取apk解压中的classes.dex文件
System.out.println("正在获取apk中的classes.dex文件");
File apkFile=new File(apkPath);
try {
ZipFile apkZip=new ZipFile(apkFile);//获取apk文件对应的zip文件
Enumeration<?> entries =apkZip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String entryName = entry.getName();
if(entryName.equals("classes.dex")){
System.out.println("找到classes.dex文件");
if(!new File(resultDir+"result").exists()){//将取出的classes.dex文件放于result目录下
File dir=new File(resultDir+"result");
dir.mkdir();
}
OutputStream outputStream=new FileOutputStream(resultDir+"result\\classes.dex");
InputStream inputStream=apkZip.getInputStream(entry);
int len=0;
while((len=inputStream.read())!=-1){
outputStream.write(len);
}
return new File(resultDir+"result\\classes.dex");
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String runDex2Jar(File dexFilePath){//调用dex2jar.bat命令
/*注意bat命令路径文件夹名中不能包含空格*/
System.out.println("正在执行dex2jar.bat,将classes.dex文件转换为classes_dex2jar.jar");
Runtime runtime=Runtime.getRuntime();
try {
String cmd=dex2jarBat+" "+dexFilePath.getAbsolutePath();
runtime.exec(cmd);
return new File("classes-dex2jar.jar").getAbsolutePath();
} catch (IOException e) {
System.out.println("执行dex2jar.bat命令出错");
e.printStackTrace();
}
return null;
}
public boolean runJdGui(String jarFilePath){
System.out.println("正在打开可视化程序jd-Gui");
Runtime runtime=Runtime.getRuntime();
try {
String cmd=jdGuiBat+" "+System.getProperty("user.dir")+"\\classes-dex2jar.jar";
runtime.exec(cmd);
return true;
} catch (IOException e) {
System.out.println("执行jd-gui.exe程序出错");
e.printStackTrace();
}
return false;
}
public boolean runApkTool(){//运行apkTool,反编译得到程序的源代码、图片、XML配置、语言资源等文件
System.out.println("正在运行apkTool工具");
String cmd=apkToolBat+" "+apkPath+" "+resultDir+"\\apkToolResult";
//命令行
Runtime runtime=Runtime.getRuntime();
try {
runtime.exec(cmd);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
AndroidDecompile androidDecompile=new AndroidDecompile("./src/enriched1.apk");
String pathString=androidDecompile.runDex2Jar(androidDecompile.getClassesDexFile());
androidDecompile.runJdGui(pathString);
androidDecompile.runApkTool();
}
}