批量检查APK是否具有指定的权限。
为测试组的妹子提供的。
效果如下:
目录结构如下:
源代码思路:
1、将apk文件变为zip文件。这里是修改后缀
2、解压文件到指定目录。可以只解压其中mainfest.xml文件
3、移动xml文件到反编译的工具目录下。运行Bat将二进制xml转为txt文本
4、读取配置文件,比对字符串,得出你想要的结果。
具体代码,请去下载工程吧。
部分代码:
package com.wuwenfu; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; public class FileUtils { // 修改apk为zip /** * @author Administrator * @param apk文件路径 * c:\\1.apk * @param zip文件保存的路径 * 如c:\\1 * @param b * 源文件是否删除。false表示不删除 true 表示删除 * @return 返回zip文件的路径 * */ public static String apkToZip(String apkPath, String zipPath, Boolean b) { // TODO Auto-generated method stub File apk = new File(apkPath); // 获取apk文件的名字。去掉后缀。作为zip文件名 String apkName = apk.getName(); int p = apkName.indexOf(".apk"); String zipName = apkName.substring(0, p) + ".zip"; File zip = new File(zipPath + File.separatorChar + zipName); // 检查文件是否存在、存在则删除 if (zip.exists()) { zip.delete(); } if (b) { // 重命名 apk.renameTo(zip); } else { // 读取文件 到另一个文件 FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(apk); fos = new FileOutputStream(zip); int c = 0; byte[] bys = new byte[1024]; while ((c = fis.read(bys)) != -1) { // fos.write(bys); fos.write(bys, 0, c); fos.flush(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { fos.close(); fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return zip.getAbsolutePath(); } /** * @description 移动文件到指定路径.是剪切操作 * @param 源文件的路径 * c:\\1.txt * @param 指定的目录 * c:\\1 */ public static void moveTo(String from, String to) { // TODO Auto-generated method stub File fromF = new File(from); String toName = to + File.separatorChar + fromF.getName(); File toF = new File(toName); fromF.renameTo(toF); } public static void log(String logPath, String logstr) { File f = new File(logPath); FileOutputStream fos = null; try { fos = new FileOutputStream(f, true); try { fos.write(logstr.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { fos.flush(); fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * @param mainfest文件的路径 * @return String[2]。第一个参数表示 有多少权限。第二个参数则是权限的字符串.第三个参数。是否具有配置文件中的3个权限 */ public static String[] readPermission(String mainfesttxtPath) { // 读取配置文件的参数 InputStream in; String pr1 =""; String pr2 =""; String pr3 =""; try { in = new BufferedInputStream(new FileInputStream("e:\\test\\per.properties")); Properties pr = new Properties(); pr.load(in); pr1 = pr.getProperty("pr1").toLowerCase(); pr2 = pr.getProperty("pr2").toLowerCase(); pr3 = pr.getProperty("pr3").toLowerCase(); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String[] returnArray = new String[3]; File f = new File(mainfesttxtPath); FileInputStream fis = null; StringBuffer sb = new StringBuffer(); try { fis = new FileInputStream(f); int c = 0; byte[] bys = new byte[1024]; try { while ((c = fis.read(bys)) != -1) { // fos.write(bys); sb.append(new String(bys, 0, c)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } String temp = sb.toString().toLowerCase(); // 判断有多少权限 int count = 0; // 获得最后一次出现的位置 String findStr = "<uses-permission"; int p = temp.indexOf(findStr); while (-1 != p) { count++; // System.out.println("第"+count+"权限"); p = temp.indexOf("<uses-permission", p + findStr.length()); } returnArray[0] = count + ""; // 截取权限的字符串 // 找到第一次的位置。 // 找到最后一次的位置。 // 截取字符串即可 int p1 = temp.indexOf("<uses-permission"); int p2 = temp.lastIndexOf("</uses-permission>"); String perStr = temp.substring(p1, p2); returnArray[1] = perStr + "</uses-permission>"; //判断是否具备制定的3个权限。这里全部转换为小写字母进行比对 String configPerStr = ""; if(temp.indexOf(pr1) > 0){ configPerStr +="[具备"+pr1+"权限]"; } if(temp.indexOf(pr2) > 0){ configPerStr +="[具备"+pr2+"权限]"; } if(temp.indexOf(pr3) > 0){ configPerStr +="[具备"+pr3+"权限]"; } returnArray[2] = configPerStr; return returnArray; } /** * 获得目录下的文件。这里只获取一级。不递归。 * * @param 目录的路径 * @return 目录下文件的数组. */ public static File[] getDirFile(String dirPath) { // TODO Auto-generated method stub File f = new File(dirPath); File[] fs = null; if (f.isDirectory()) { fs = f.listFiles(); } return fs; } /** * apk文件。获取权限数据方法。 */ public static void apkPer(File af) { // String apk = "e:\\test\\TTXL-FengWang-release-1504271406.apk"; String apk = af.getAbsolutePath(); // String apk ="e:\\test\\AndroidManifest.apk"; String zipTargetPath = "e:\\test\\zips"; String logPath = "e:\\test\\log.txt"; String resultPath = "e:\\test\\result.txt"; //当前的时间 Date d = new Date(); DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); FileUtils.log(logPath, "\r\n\r\n\r\n--------------------" + af.getName() + "开始--------"+format.format(d)+"-----------------"); // 将apk文件变成zip文件 String zipPath = FileUtils.apkToZip(apk, zipTargetPath, false); FileUtils.log(logPath, "\r\n--->>获得zip文件"); // 取得zip文件路径 // System.out.println(zipPath); // 解压zip文件。 try { FirstZip.unzip(zipPath, "e:\\test\\unzips"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 解压需要时间。这里需要等待 try { Thread.sleep(1000 * 3); } catch (InterruptedException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } FileUtils.log(logPath, "\r\n--->>完成解压"); // 移动main.xml文件到指定目录下。执行bat FileUtils.moveTo("e:\\test\\unzips\\AndroidManifest.xml", "e:\\test\\apktools"); FileUtils.log(logPath, "\r\n--->>移动完成"); // 执行cmd命令. String cmd = "cmd /c start e:\\test\\apktools\\AXMLPrinter.bat"; Runtime rt = Runtime.getRuntime(); try { Process p = rt.exec(cmd); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } FileUtils.log(logPath, "\r\n--->>运行bat"); try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 解析mainfest.txt文件。 // 这里读取txt文件。取出里面的权限字符串。 // 这里可以转成xml。读取里面的节点 // 权限字符串。以<uses-permission 与</uses-permission>之间。 String mainfestPath = "e:\\test\\apktools\\AndroidManifest.txt"; String[] perArray = FileUtils.readPermission(mainfestPath); // 组合下字符串。 String result = "\r\n---------" + af.getName() + "---------------------"; result += "\r\n拥有的权限数量为" + perArray[0]; // result += "\r\n具体权限为" + perArray[1]; result +="\r\n制定的权限是否具备:"+perArray[2]; result += "\r\n------------------------------"; FileUtils.log(resultPath, result); FileUtils.log(logPath, "\r\n--->>处理权限"); FileUtils.log(logPath, "\r\n-------------------" + af.getName() + "结束-------------------------"); // System.out.println(perArray[0]); // System.out.println("-------------------------"); // System.out.println(perArray[1]); } }
最后补充。这里的解压缩包,使用了apache的ant.jar。自己去下载下吧。博客园没附件功能。。。。
工程下载地址:http://download.csdn.net/detail/douniwan123654/8645939
QQ:540045865
热爱生活,热爱编程。