美文网首页
修改混淆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中类方法

    1.字节码出现类名与包名冲突 使用这个工具:jarjar工具 创建一个rule文件,如rule.txt,内容如下:...

  • android studio混淆

    混淆代码如下: 具体错误忘记包含xml字段错误修改方法如下 jar包EventBus报错 实体类被混淆修改方法如下...

  • Android Studio打Jar包方式(可混淆)

    一、普通生成Jar包 二、 普通生成Jar包自定义类名jar生成方式,可以去除资源 三、混淆后的jar生成方式,可...

  • Android 代码混淆

    代码混淆的作用代码混淆,就是把java文件在生成class文件是,类名,方法名等JAVA元素修改成没有意义的名称,...

  • arr包混淆Tips

    对引用的jar包开启混淆出现如何信息反馈 解决方法在你的buidl.gradle中添加:

  • gradle脚本生成jar包

    生成Jar包 指定模块下执行 gradle makeJar 生成混淆jar idea中打包所有jar为可发布tar...

  • Android Studio开启混淆

    使用Android Stduio开启混淆本篇主要介绍在Studio中lib库中jar包的混淆和phone中对apk...

  • iOS学习笔记02-UIScrollView

    父类UIView方法 UIScrollView中容易混淆的属性 contentSize 内容尺寸 contentI...

  • SpringBoot应用部署于外置Tomcat容器

    修改pom文件的 打包方式 由 jar->war 添加 jar 启动类的同级目录 添加类 期间 如果报错Faile...

  • Android混淆 - 常用框架

    不混淆指定的jar库 Android类 okio Gson Eventbus 微信支付 环信客服 小米push B...

网友评论

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

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