批量检查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

 

posted on 2015-04-29 16:28  jsRunner  阅读(722)  评论(0编辑  收藏  举报

导航