美文网首页
修改混淆jar中类方法

修改混淆jar中类方法

作者: 诸葛不亮丶 | 来源:发表于2019-06-27 16:39 被阅读0次

    1.字节码出现类名与包名冲突

    使用这个工具:jarjar工具

    • 创建一个rule文件,如rule.txt,内容如下:
    rule 原包名.** 目标包名.@1
    

    例如:

    rule a.b.c.** x.y.z.@1
    rule a.b.c.** a.b.c.@1
    

    然后运行jarjar工具,将要修改的jar包old.jar按照rule.txt的规则产生新的jar包new.jar

    java -jar jarjar-1.4.jar process rule.txt old.jar new.jar
    

    2. 利用javaassist修改对应方法

    • 添加依赖
    
    sourceCompatibility = 1.8
    
    dependencies {
        compile 'io.reactivex.rxjava2:rxjava:2.1.16'
        compile fileTree('libs/javassist.jar')
    }
    
    • 导入类
    public class Clazz {
    
        private String JAR_DIR = "";
        private String JAR_NAME = "";
        private String PKGNAME = "";
        private String CLASSNAME = "";
    
        private Clazz() {
        }
    
        public interface Builder {
            Clazz CLAZZ = new Clazz();
        }
    
        public interface Presenter {
            void onHack(CtClass ctClass) throws Exception;
        }
    
        public static Clazz initialize(String libDir, String libName) {
            Clazz clazz = Builder.CLAZZ;
    
            clazz.JAR_DIR = libDir;
            clazz.JAR_NAME = libName;
            return clazz;
        }
    
    
        @SuppressWarnings("ResultOfMethodCallIgnored")
        public void hackClass(String pkgName, String className, Presenter presenter) {
    
            PKGNAME = pkgName;
            CLASSNAME = className;
    
            // jar包路径
            // class位置
            // 输入class路径, jar uvf命令替换jar
    //            String command = String.format("cd %s; jar uvf %s %s", JAR_DIR, JAR_NAME, clazzPath);
    //            String[] cmd = {"/bin/sh", "-c", command};
            Observable.create((ObservableOnSubscribe<String>) emitter -> {
                // jar包路径
                String jar = getJarPath();
                File file = new File(jar);
                if (file.exists()) {
                    emitter.onNext(jar);
                    emitter.onComplete();
                } else {
                    emitter.onError(new FileNotFoundException(jar + " NOT FOUND!"));
                }
    
            }).map(jarPath -> {
                ClassPool classPool = ClassPool.getDefault();
    
                classPool.insertClassPath(jarPath);
    
                // class位置
                String clazz = getClazzName();
                CtClass ctClass = classPool.get(clazz);
    
                if (presenter != null) {
                    presenter.onHack(ctClass);
                }
                return ctClass.toBytecode();
            }).map(bytes -> {
                String clazzPath = getClazzPath();
    
                File dstFile = new File(clazzPath);
                if (!dstFile.getParentFile().exists()) {
                    dstFile.getParentFile().mkdirs();
                }
                FileOutputStream output = new FileOutputStream(dstFile);
    
                output.write(bytes);
                output.flush();
                return dstFile.getAbsolutePath();
            }).map(savePath -> {  // 输入class路径, jar uvf命令替换jar
                String clazzPath = getClazzPath();
    
    //            String command = String.format("cd %s; jar uvf %s %s", JAR_DIR, JAR_NAME, clazzPath);
    //            String[] cmd = {"/bin/sh", "-c", command};
                String command = String.format("jar uvf %s %s", getJarPath(), clazzPath);
    
                return exec(command);
    
            }).subscribe(status -> {
                if (status == 0) {
                    String command = String.format("rm -rf %s", getClazzRootPath());
                    Runtime.getRuntime().exec(command);
                }
                System.out.printf("status: %d\t%s\n", status, Thread.currentThread().getName());
            });
    
        }
    
        private String getJarPath() {
            return String.format("%s/%s", JAR_DIR, JAR_NAME);
        }
    
        private String getClazzRootPath() {
            String rootPath;
            int index = PKGNAME.indexOf(".");
            if (index > 0) {
                rootPath = PKGNAME.substring(0, index);
            } else {
                rootPath = getClazzPath();
            }
    
            return rootPath;
        }
    
        private String getClazzPath() {
            String clazzPath;
            if (PKGNAME.isEmpty()) {
                clazzPath = String.format("%s.class", CLASSNAME);
            } else {
                clazzPath = String.format("%s/%s.class", PKGNAME.replace(".", "/"), CLASSNAME);
            }
            return clazzPath;
        }
    
        private String getClazzName() {
            String clazzName;
            if (PKGNAME.isEmpty()) {
                clazzName = CLASSNAME;
            } else {
                clazzName = String.format("%s.%s", PKGNAME, CLASSNAME);
            }
            return clazzName;
        }
    
    
        public static int exec(String... commands) throws IOException, InterruptedException {
            int status = 1;
            if (commands == null) {
                return status;
            }
            File wd = new File(".");
            Process proc = Runtime.getRuntime().exec("/bin/bash", null);
            if (proc != null) {
                BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
                for (String command : commands) {
                    out.println(command);
                }
                out.println("exit");
                String line;
                while ((line = in.readLine()) != null) {
                    System.out.println(line);
                }
                status = proc.waitFor();
                in.close();
                out.close();
                proc.destroy();
            }
            return status;
        }
    
        public static int exec2(String... commands) throws IOException, InterruptedException {
            int status = 1;
            if (commands == null) {
                return status;
            }
            String command = String.join(";", commands);
            String[] cmd = {"/bin/sh", "-c", command};
            Process proc = Runtime.getRuntime().exec(cmd);
            if (proc != null) {
                BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    System.out.println(line);
                }
                status = proc.waitFor();
                in.close();
                proc.destroy();
            }
            return status;
        }
    
    
        public static String readContent(String path) throws IOException, NotFoundException {
    
            File file = new File(path);
    
            if (!file.exists()) {
                throw new NotFoundException("Not Found: " + file.getAbsolutePath());
            }
            BufferedReader in = new BufferedReader(new FileReader(file));
            String line;
    
            StringBuilder buffer = new StringBuilder();
    
            while ((line = in.readLine()) != null) {
                buffer.append(line).append("\n");
            }
            in.close();
            return buffer.toString();
    
        }
    }
    
    
    • 开始hook(写一个测试方法,修改charles.jar)
    // dir: jar包目录
    // charles.jar:  要修改的jar包名
     Clazz.initialize("dir", "charles.jar")
                    .hackClass("com.xk72.charles", "oFTR", ctClass -> {
    
                        CtMethod ctMethod = ctClass.getDeclaredMethod("lktV", null);
                        ctMethod.setBody("{return \"Crack by me!\";}");
    
                    });
    

    3. 还原原包包名

    按方法1修改即可。

    END

    • PS:
    // 如果方法体过大,采用读文本的形式setBody
    String content = Clazz.readContent("method.txt");
    ctMethod.setBody(content);
    

    method.txt内容如下:

    {
      return "Crack by me!";
    }
    

    相关文章

      网友评论

          本文标题:修改混淆jar中类方法

          本文链接:https://www.haomeiwen.com/subject/lfprcctx.html