Java字节码的base64转Java源码小工具

在做java内存马相关分析和开发的时候,免不了总是要base64,字节码和java源码各种来回转化,每次都手动操作很麻烦,写个工具自动化把字节码的base64转化为java源码。
其实反向从java源码到base64字符串也有需求,但是涉及到编译以及依赖,所以只需要classtobase64即可,比较简单。

实现

反编译器

这个步骤涉及到了反编译,需要找一个反编译的库,java反编译用的最多的就是jd-core和jadx两个。
分析了一下发现jd-core使用比较简单,但是jd-core是针对于jar包实现的,反编译时传入的class名是一个internalName,也就是org/apache/jsp/ccc.class这样带有包路径的类名,或者干脆是一个jar包全部反编译,参考jd-core
但是我的需求是只有一个base64,也就是一个class文件,不知道具体的类名和包名,需要反编译器反编译后告诉我类名,因此不太合适。
所以选择了jadx,使用方法参考Use jadx as a library

其中第二步是要在pom.xml中添加谷歌仓库来加载aapt的依赖,如下:

<repositories>
    <repository>
        <id>google</id>
        <name>google Public Repositories</name>
        <url>https://maven.google.com/</url>
    </repository>
</repositories>

第三步中需要按照要反编译的输入类型选择对应插件,这里说的添加插件就是把对应的依赖添加到pom.xml中,我需要反编译class,使用jadx-java-input,所以依赖如下:

<!-- https://mvnrepository.com/artifact/io.github.skylot/jadx-core -->
<dependency>
    <groupId>io.github.skylot</groupId>
    <artifactId>jadx-core</artifactId>
    <version>1.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.skylot/jadx-java-input -->
<dependency>
    <groupId>io.github.skylot</groupId>
    <artifactId>jadx-java-input</artifactId>
    <version>1.4.2</version>
</dependency>

完成后即可参考链接中的代码反编译

最终代码

考虑到方便使用,可以写一个图形界面,也可以用springboot打包一个web使用html写页面,这里写一个工具类,界面部分自由发挥。

jadx在使用的时候需要选择输入的class和结构输出目录,没有提供直接用字节码作为输入的接口(废话,人家是命令行工具),也没必要看源码去改了,用一个目录过度一下,这里选系统的temp目录:

String tempPath = System.getProperty("java.io.tmpdir")+File.separator;

思路是先把base64解码得到字节码写到临时class文件中,用jadx反编译,结果保存到${temp}/output/,再遍历这个目录找到所有java文件取出类名和内容返回。

效果:

源码:

import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;

import java.io.*;
import java.util.*;

public class JavaUtil {
    public static Map base64Tojava(String base64Data) throws IOException {
        byte[] b = Base64.getDecoder().decode(base64Data);
        String tempPath = System.getProperty("java.io.tmpdir")+File.separator;
        String outputPath = tempPath + "output/";
        writeFile(tempPath + "temp.class", b);

        JadxArgs jadxArgs = new JadxArgs();
        jadxArgs.setInputFile(new File(tempPath + "temp.class"));
        jadxArgs.setOutDir(new File(outputPath));
        try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
            jadx.load();
            jadx.save();
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<File> fileList = new ArrayList<>();
        findJava(new File(outputPath), fileList);

        HashMap map = new HashMap();
        getJava(fileList, map);
        return map;
    }


    public static void writeFile(String filepath, byte[] content) throws IOException {
        File f = new File(filepath);
        FileOutputStream fos = new FileOutputStream(f);
        fos.write(content);
        fos.close();
    }

    public static void findJava(File outputFile, List<File> fileList) {
        File[] files = outputFile.listFiles();
        for (File i : files) {
            if (i.isDirectory()) {
                findJava(i, fileList);
            }
            if (i.isFile()) {
                if (i.getName().endsWith(".java")) {//判断名
                    fileList.add(i);
                }
            }

        }
    }

    public static void getJava(List<File> Files, HashMap map) throws IOException {
        for(File f: Files){
            String content = getContent(f.getPath());
            map.put(f.getName(),content);
        }
    }

    public static String getContent(String filePath) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        StringBuilder stringBuilder = new StringBuilder();
        String line = null;
        String ls = System.getProperty("line.separator");
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        reader.close();

        String content = stringBuilder.toString();
        return content;
    }
    
     public static void main(String[] args) throws IOException {
        String base64data = "yv66vgAAADQAZg......";
        Map m = base64Tojava(base64data);
        System.out.println(m.get("TestGrizzlyFilter.java"));
    }
posted @ 2022-07-08 16:01  ChanGeZ  阅读(397)  评论(0编辑  收藏  举报