├── .gitignore
├── README.md
├── image
└── example.gif
├── pom.xml
└── src
└── main
├── java
├── UI
│ ├── ChangeZ_Tool.form
│ ├── ChangeZ_Tool.java
│ └── JavaSource.java
└── Util
│ └── JavaUtil.java
└── resources
└── META-INF
└── MANIFEST.MF
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | /target/
26 | /out/
27 | /.idea/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java内存马分析辅助工具
2 |
3 | 目的是快速完成重复性的工作,内存马编写测试分析总离不开下面三部分的互相转换
4 |
5 | java源码 <--> class字节码 <--> base64编码
6 |
7 | 其中java编译为class需要对应环境依赖,工具不考虑做,剩下的就是class字节码和base64互转,以及base64直接查看java源码。
8 |
9 | 通过base64保存class文件和直接查看java源码的功能。
10 |
11 | ### 使用方法
12 |
13 | ```bash
14 | java -jar GuiTool-1.0.jar
15 | ```
16 |
17 | ### 待办
18 | - [x] base64保存class文件
19 | - [x] base64直接查看java源码
20 | - [ ] 上传class转化为base64
21 | - [ ] ...
22 |
23 |
24 | 
25 |
26 | ### 参考链接
27 | https://github.com/java-decompiler/jd-core
--------------------------------------------------------------------------------
/image/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YPS233/JavaGuiTool/189bba1741e18e21cc8a301917fb1cfd3e9e322f/image/example.gif
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | GuiTool
9 | 0.1
10 |
11 |
12 |
13 |
14 | io.github.skylot
15 | jadx-core
16 | 1.4.2
17 |
18 |
19 |
20 | io.github.skylot
21 | jadx-java-input
22 | 1.4.2
23 |
24 |
25 |
26 |
27 |
28 | google
29 | google Public Repositories
30 | https://maven.google.com/
31 |
32 |
33 |
34 |
35 | 8
36 | 8
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-assembly-plugin
44 |
45 |
46 | package
47 |
48 | single
49 |
50 |
51 |
52 |
53 |
54 | UI.ChangeZ_Tool
55 |
56 |
57 |
58 |
59 | jar-with-dependencies
60 |
61 | false
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/main/java/UI/ChangeZ_Tool.form:
--------------------------------------------------------------------------------
1 |
2 |
75 |
--------------------------------------------------------------------------------
/src/main/java/UI/ChangeZ_Tool.java:
--------------------------------------------------------------------------------
1 | package UI;
2 |
3 | import Util.JavaUtil;
4 |
5 | import javax.swing.*;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.io.File;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.util.*;
12 |
13 | public class ChangeZ_Tool {
14 | private JTextArea textAreaBase64;
15 | private JButton Button_toclass;
16 | private JPanel root;
17 | private JButton button_tojava;
18 |
19 | public ChangeZ_Tool() {
20 | textAreaBase64.setLineWrap(true); //激活自动换行功能
21 | textAreaBase64.setWrapStyleWord(true); // 激活断行不断字功能
22 |
23 | Button_toclass.addActionListener(new ActionListener() {
24 | @Override
25 | public void actionPerformed(ActionEvent e) {
26 | String base64Data = textAreaBase64.getText();
27 | System.out.println(base64Data);
28 | byte[] b = Base64.getDecoder().decode(base64Data);
29 |
30 | JFileChooser chooser = new JFileChooser();
31 | chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
32 | int returnVal = chooser.showOpenDialog(Button_toclass);
33 | if (returnVal == JFileChooser.APPROVE_OPTION) { //如果符合文件类型
34 |
35 | String dirPath = chooser.getSelectedFile().getAbsolutePath(); //获取绝对路径
36 | String filepath = dirPath + File.separator + "res.class";
37 | System.out.println(filepath);
38 | File saveFile = new File(filepath);
39 | try {
40 | FileOutputStream fos = new FileOutputStream(saveFile);
41 | fos.write(b);
42 | fos.flush();
43 | fos.close();
44 | JOptionPane.showMessageDialog(root, "保存成功,路径为:" + filepath);
45 |
46 | }catch (IOException exception){
47 | exception.printStackTrace();
48 | }
49 |
50 | System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName()); //输出相对路径
51 | }else {
52 | System.out.println("not a dir path");
53 | }
54 |
55 |
56 |
57 | }
58 | });
59 | button_tojava.addActionListener(new ActionListener() {
60 | @Override
61 | public void actionPerformed(ActionEvent e) {
62 | String base64Data = textAreaBase64.getText();
63 | Map javaMap = null;
64 | try {
65 | javaMap = JavaUtil.base64Tojava(base64Data);
66 | }catch (IllegalArgumentException ei){
67 | JOptionPane.showMessageDialog(null, "非法的base64字符串", "错误", JOptionPane.INFORMATION_MESSAGE);
68 |
69 | }
70 | catch (IOException ex) {
71 | throw new RuntimeException(ex);
72 | }
73 |
74 | JavaSource js = new JavaSource(javaMap);
75 |
76 | }
77 | });
78 | }
79 |
80 |
81 | public static void main(String[] args) {
82 | JFrame frame = new JFrame("ChangeZ_Tool");
83 | frame.setContentPane(new ChangeZ_Tool().root);
84 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
85 | frame.setSize(600,400);
86 | //frame.pack();
87 | frame.setVisible(true);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/UI/JavaSource.java:
--------------------------------------------------------------------------------
1 | package UI;
2 |
3 | import javax.swing.*;
4 | import javax.swing.event.ListSelectionEvent;
5 | import javax.swing.event.ListSelectionListener;
6 | import java.awt.*;
7 | import java.awt.event.MouseEvent;
8 | import java.awt.event.MouseListener;
9 | import java.util.ArrayList;
10 | import java.util.Map;
11 | import java.util.Vector;
12 |
13 | public class JavaSource implements MouseListener {
14 |
15 | Vector leftData;
16 | Vector rightData;
17 | JList left;
18 |
19 | JTextPane right;
20 | JScrollPane leftPanel, rightPanel;
21 |
22 | Map data;
23 |
24 | public JavaSource(Map data) throws HeadlessException {
25 |
26 | this.data = data;
27 |
28 | ArrayList keys = new ArrayList<>();
29 | for(String s: data.keySet()){
30 | keys.add(s);
31 | }
32 |
33 |
34 | JDialog frame = new JDialog();
35 | frame.setTitle("Java Source Code");
36 | frame.setVisible(true);
37 | frame.setSize(800,600);
38 |
39 | leftData = new Vector<>(keys);
40 | left = new JList<>(leftData);
41 | leftPanel = new JScrollPane(left);
42 |
43 | rightData = new Vector<>();
44 | right = new JTextPane();
45 | rightPanel = new JScrollPane(right);
46 |
47 | frame.setLayout(new GridLayout(1, 4));
48 | frame.add(leftPanel);
49 | frame.add(rightPanel);
50 |
51 | left.addListSelectionListener(new ListSelectionListener() {
52 | @Override
53 | public void valueChanged(ListSelectionEvent e) {
54 | // 获取所有被选中的选项索引
55 | int[] indices = left.getSelectedIndices();
56 | // 获取选项数据的 ListModel
57 | ListModel listModel = left.getModel();
58 |
59 | String currentSelect = null;
60 | // 输出选中的选项
61 | for (int index : indices) {
62 | currentSelect = listModel.getElementAt(index);
63 | // System.out.println("选中: " + index + " = " + listModel.getElementAt(index));
64 | }
65 | // System.out.println(data.get(currentSelect));
66 | String showCode = data.get(currentSelect);
67 | // left.setListData(data.get(currentSelect));
68 | right.setText(showCode);
69 | }
70 | });
71 |
72 |
73 | }
74 |
75 | @Override
76 | public void mouseClicked(MouseEvent e) {
77 |
78 | }
79 |
80 | private void doubleClick(MouseEvent e) {
81 |
82 | }
83 |
84 | @Override
85 | public void mousePressed(MouseEvent e) {
86 |
87 | }
88 |
89 | @Override
90 | public void mouseReleased(MouseEvent e) {
91 |
92 | }
93 |
94 | @Override
95 | public void mouseEntered(MouseEvent e) {
96 |
97 | }
98 |
99 | @Override
100 | public void mouseExited(MouseEvent e) {
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/Util/JavaUtil.java:
--------------------------------------------------------------------------------
1 | package Util;
2 |
3 | import jadx.api.JadxArgs;
4 | import jadx.api.JadxDecompiler;
5 |
6 | import javax.swing.*;
7 | import java.io.*;
8 | import java.nio.file.Paths;
9 | import java.util.*;
10 | import java.nio.file.Files;
11 |
12 |
13 | public class JavaUtil {
14 | public static Map base64Tojava(String base64Data) throws IOException {
15 | byte[] b = Base64.getDecoder().decode(base64Data);
16 | String tempPath = System.getProperty("java.io.tmpdir");
17 | String outputPath = tempPath + "output/";
18 | writeFile(tempPath + "temp.class", b);
19 | System.out.println(outputPath);
20 |
21 | JadxArgs jadxArgs = new JadxArgs();
22 | jadxArgs.setInputFile(new File(tempPath + "temp.class"));
23 | jadxArgs.setOutDir(new File(outputPath));
24 | try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
25 | jadx.load();
26 | jadx.save();
27 | } catch (Exception e) {
28 | JOptionPane.showMessageDialog(null, "反编译失败", "错误", JOptionPane.INFORMATION_MESSAGE);
29 | e.printStackTrace();
30 | }
31 | List fileList = new ArrayList<>();
32 | findJava(new File(outputPath), fileList);
33 |
34 | HashMap map = new HashMap();
35 | getJava(fileList, map);
36 |
37 | // delete temp dir
38 | deleteDirectory(new File(outputPath));
39 | return map;
40 | }
41 |
42 |
43 | public static void writeFile(String filepath, byte[] content) throws IOException {
44 | File f = new File(filepath);
45 | FileOutputStream fos = new FileOutputStream(f);
46 | fos.write(content);
47 | fos.close();
48 | }
49 |
50 | public static void findJava(File outputFile, List fileList) {
51 | File[] files = outputFile.listFiles();
52 | for (File i : files) {
53 | if (i.isDirectory()) {
54 | findJava(i, fileList);
55 | }
56 | if (i.isFile()) {
57 | if (i.getName().endsWith(".java")) {//判断名
58 | fileList.add(i);
59 | }
60 | }
61 |
62 | }
63 | }
64 |
65 | public static void getJava(List Files, HashMap map) throws IOException {
66 | for(File f: Files){
67 | String content = getContent(f.getPath());
68 | map.put(f.getName(),content);
69 | }
70 | }
71 |
72 | public static String getContent(String filePath) throws IOException {
73 | BufferedReader reader = new BufferedReader(new FileReader(filePath));
74 | StringBuilder stringBuilder = new StringBuilder();
75 | String line = null;
76 | String ls = System.getProperty("line.separator");
77 | while ((line = reader.readLine()) != null) {
78 | stringBuilder.append(line);
79 | stringBuilder.append(ls);
80 | }
81 |
82 | stringBuilder.deleteCharAt(stringBuilder.length() - 1);
83 | reader.close();
84 |
85 | String content = stringBuilder.toString();
86 | return content;
87 | }
88 |
89 | public static void deleteDirectory(File directory) {
90 |
91 | //文件是否为目录
92 | if(directory.isDirectory()) {
93 | File[] files = directory.listFiles();
94 |
95 | //如果目录包含任何文件
96 | if(files != null) {
97 | for(File file : files) {
98 |
99 | //如果子目录为非空,则进行递归调用
100 | deleteDirectory(file);
101 | }
102 | }
103 | }
104 | directory.delete();
105 | }
106 |
107 | public static void main(String[] args) throws IOException {
108 | String base64data = "yv66vgAAADQAZgoAFQA1CgA2ADcHADgKAAMAOQgAOgoACAA7CAA8BwA9BwA+CgAIAD8KAEAAQQcAQggAQwkARABFCgBGAEcKAAkASAoAQABJBwBKCgAVAEsHAEwHAE0BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEANExvcmcvc3UxOC9tZW1zaGVsbC90ZXN0L2dsYXNzZmlzaC9UZXN0R3JpenpseUZpbHRlcjsBAApoYW5kbGVSZWFkAQBmKExvcmcvZ2xhc3NmaXNoL2dyaXp6bHkvZmlsdGVyY2hhaW4vRmlsdGVyQ2hhaW5Db250ZXh0OylMb3JnL2dsYXNzZmlzaC9ncml6emx5L2ZpbHRlcmNoYWluL05leHRBY3Rpb247AQABYwEAEUxqYXZhL2xhbmcvQ2xhc3M7AQABbQEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQADY3R4AQA2TG9yZy9nbGFzc2Zpc2gvZ3JpenpseS9maWx0ZXJjaGFpbi9GaWx0ZXJDaGFpbkNvbnRleHQ7AQAKY29ubmVjdGlvbgEANkxvcmcvZ2xhc3NmaXNoL2dyaXp6bHkvbmlvL3RyYW5zcG9ydC9UQ1BOSU9Db25uZWN0aW9uOwEAB2NoYW5uZWwBACVMamF2YS9uaW8vY2hhbm5lbHMvU2VsZWN0YWJsZUNoYW5uZWw7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAFExqYXZhL2xhbmcvQ2xhc3M8Kj47AQANU3RhY2tNYXBUYWJsZQcATAcATgcAOAcATwcASgEACkV4Y2VwdGlvbnMHAFABAApTb3VyY2VGaWxlAQAWVGVzdEdyaXp6bHlGaWx0ZXIuamF2YQwAFgAXBwBODABRAFIBADRvcmcvZ2xhc3NmaXNoL2dyaXp6bHkvbmlvL3RyYW5zcG9ydC9UQ1BOSU9Db25uZWN0aW9uDABTAFQBABxzdW4ubmlvLmNoLlNvY2tldENoYW5uZWxJbXBsDABVAFYBAAV3cml0ZQEAD2phdmEvbGFuZy9DbGFzcwEAE2phdmEvbmlvL0J5dGVCdWZmZXIMAFcAWAcAWQwAWgBbAQAQamF2YS9sYW5nL09iamVjdAEAGUhUVFAvMS4xIDIwMCBPSyBzdTE4IHl5ZHMHAFwMAF0AXgcAXwwAYABhDABiAGMMAGQAZQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAB0AHgEAMm9yZy9zdTE4L21lbXNoZWxsL3Rlc3QvZ2xhc3NmaXNoL1Rlc3RHcml6emx5RmlsdGVyAQAsb3JnL2dsYXNzZmlzaC9ncml6emx5L2ZpbHRlcmNoYWluL0Jhc2VGaWx0ZXIBADRvcmcvZ2xhc3NmaXNoL2dyaXp6bHkvZmlsdGVyY2hhaW4vRmlsdGVyQ2hhaW5Db250ZXh0AQAjamF2YS9uaW8vY2hhbm5lbHMvU2VsZWN0YWJsZUNoYW5uZWwBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAMZ2V0Q2xvc2VhYmxlAQAjKClMb3JnL2dsYXNzZmlzaC9ncml6emx5L0Nsb3NlYWJsZTsBAApnZXRDaGFubmVsAQAnKClMamF2YS9uaW8vY2hhbm5lbHMvU2VsZWN0YWJsZUNoYW5uZWw7AQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAIWphdmEvbmlvL2NoYXJzZXQvU3RhbmRhcmRDaGFyc2V0cwEABVVURl84AQAaTGphdmEvbmlvL2NoYXJzZXQvQ2hhcnNldDsBABBqYXZhL2xhbmcvU3RyaW5nAQAIZ2V0Qnl0ZXMBAB4oTGphdmEvbmlvL2NoYXJzZXQvQ2hhcnNldDspW0IBAAR3cmFwAQAZKFtCKUxqYXZhL25pby9CeXRlQnVmZmVyOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwAhABQAFQAAAAAAAgABABYAFwABABgAAAAvAAEAAQAAAAUqtwABsQAAAAIAGQAAAAYAAQAAABMAGgAAAAwAAQAAAAUAGwAcAAAAAQAdAB4AAgAYAAABBQAHAAYAAABQK7YAAsAAA00stgAEThIFuAAGOgQZBBIHBL0ACFkDEglTtgAKOgUZBQS2AAsZBS0EvQAMWQMSDbIADrYAD7gAEFO2ABFXpwAFOgQqK7cAE7AAAQANAEUASAASAAQAGQAAACYACQAAABcACAAYAA0AGwAUABwAJgAdACwAHgBFACIASAAgAEoAIwAaAAAAPgAGABQAMQAfACAABAAmAB8AIQAiAAUAAABQABsAHAAAAAAAUAAjACQAAQAIAEgAJQAmAAIADQBDACcAKAADACkAAAAMAAEAFAAxAB8AKgAEACsAAAAZAAL/AEgABAcALAcALQcALgcALwABBwAwAQAxAAAABAABADIAAQAzAAAAAgA0";
109 | Map m = base64Tojava(base64data);
110 | System.out.println(m);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: UI.ChangeZ_Tool
3 |
4 |
--------------------------------------------------------------------------------