第一次提交

This commit is contained in:
tzdwindows 7
2025-02-05 15:02:27 +08:00
commit d06b32a92f
44 changed files with 3219 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
package com.axis.innovators.box;
import com.axis.innovators.box.events.GlobalEventBus;
import com.axis.innovators.box.events.SettingsLoadEvents;
import com.axis.innovators.box.events.SubscribeEvent;
import com.axis.innovators.box.gui.FridaWindow;
import com.axis.innovators.box.gui.MainWindow;
import com.axis.innovators.box.tools.FolderCreator;
import com.axis.innovators.box.tools.LibraryLoad;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
/**
* 主类
* @author tzdwindows 7
*/
public class Main {
static {
LibraryLoad.loadLibrary("FridaNative");
}
@SubscribeEvent
public void onSettingsLoad(SettingsLoadEvents event) {
JLabel placeholder = new JLabel("设置功能开发中...", SwingConstants.CENTER);
placeholder.setFont(new Font("微软雅黑", Font.PLAIN, 24));
placeholder.setForeground(new Color(127, 140, 153));
event.content().add(placeholder, BorderLayout.CENTER);
// 我不想写这个了你们自己实现
}
public static void main(String[] args) {
// 注册事件
GlobalEventBus.EVENT_BUS.register(new Main());
// 设置系统外观
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ignored) {}
// 创建窗口
SwingUtilities.invokeLater(() -> {
MainWindow ex = new MainWindow();
int id = 0;
MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory("调试工具",
"debug/debug.png",
"用于调试指定Windows工具的一个分类");
debugCategory.addTool(new MainWindow.ToolItem("Frida注入工具", "debug/frida/frida_main.png",
"使用frida注入目标进程的脚本程序 " +
"\n作者tzdwindows 7", ++id, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
FridaWindow fridaWindow = new FridaWindow(owner);
fridaWindow.setVisible(true);
}
}));
// 在后面注册你自己的项或是添加你自己的分类
// ....
ex.addToolCategory(debugCategory);
ex.initUI();
ex.setVisible(true);
});
}
}

View File

@@ -0,0 +1,138 @@
package com.axis.innovators.box.events;
import com.axis.innovators.box.gui.MainWindow;
import java.awt.*;
/**
* 分类栏的渲染事件
* @author tzdwindows 7
*/
public class CategoryRenderingEvent {
private final MainWindow.CustomTabbedPaneUI ui;
private final Graphics graphics;
private final int tabPlacement;
private final int tabIndex;
private final int x;
private final int y;
private final int width;
private final int height;
private final boolean isSelected;
private boolean isEnd = false;
public CategoryRenderingEvent(MainWindow.CustomTabbedPaneUI ui, Graphics graphics, int tabPlacement, int tabIndex, int x, int y, int width, int height, boolean isSelected) {
this.ui = ui;
this.graphics = graphics;
this.tabPlacement = tabPlacement;
this.tabIndex = tabIndex;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isSelected = isSelected;
}
public MainWindow.CustomTabbedPaneUI getUi() {
return ui;
}
public Graphics getGraphics() {
return graphics;
}
public int getTabPlacement() {
return tabPlacement;
}
public int getTabIndex() {
return tabIndex;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public boolean isSelected() {
return isSelected;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean end) {
isEnd = end;
}
public static class paintTabBorder {
private final MainWindow.CustomTabbedPaneUI event;
private final Graphics graphics;
private final int tabPlacement;
private final int tabIndex;
private final int x;
private final int y;
private final int width;
private final int height;
private final boolean isSelected;
public paintTabBorder(MainWindow.CustomTabbedPaneUI event, Graphics graphics, int tabPlacement, int tabIndex, int x, int y, int width, int height, boolean isSelected) {
this.event = event;
this.graphics = graphics;
this.tabPlacement = tabPlacement;
this.tabIndex = tabIndex;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isSelected = isSelected;
}
public MainWindow.CustomTabbedPaneUI getEvent() {
return event;
}
public Graphics getGraphics() {
return graphics;
}
public int getTabPlacement() {
return tabPlacement;
}
public int getTabIndex() {
return tabIndex;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public boolean isSelected() {
return isSelected;
}
}
}

View File

@@ -0,0 +1,150 @@
package com.axis.innovators.box.events;
import java.lang.reflect.Method;
import java.util.*;
/**
* 事件总线
* @author tzdwindows 7
*/
public class EventBus {
private static int maxID = 0;
private final int busID;
private final Map<Class<?>, List<Subscriber>> eventSubscribers = new HashMap<>();
private final Map<Object, List<Subscriber>> targetSubscribers = new HashMap<>();
private boolean shutdown;
public EventBus() {
this.busID = maxID++;
}
private static class Subscriber {
final Object target;
final Method method;
final Class<?> eventType;
Subscriber(Object target, Method method, Class<?> eventType) {
this.target = target;
this.method = method;
this.eventType = eventType;
}
}
/**
* 注册目标对象的事件监听器
* @param target 目标对象
*/
public void register(Object target) {
if (targetSubscribers.containsKey(target)) {
return;
}
List<Subscriber> subs = new ArrayList<>();
for (Method method : getAnnotatedMethods(target)) {
SubscribeEvent annotation = method.getAnnotation(SubscribeEvent.class);
if (annotation == null) {
continue;
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
continue;
}
Class<?> eventType = paramTypes[0];
Subscriber sub = new Subscriber(target, method, eventType);
eventSubscribers.computeIfAbsent(eventType, k -> new ArrayList<>()).add(sub);
subs.add(sub);
}
if (!subs.isEmpty()) {
targetSubscribers.put(target, subs);
}
}
/**
* 获取目标对象中所有带有 @SubscribeEvent 注解的方法
* @param target 目标对象
* @return 方法集合
*/
private Set<Method> getAnnotatedMethods(Object target) {
Set<Method> methods = new HashSet<>();
Class<?> clazz = target.getClass();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(SubscribeEvent.class)) {
methods.add(method);
}
}
clazz = clazz.getSuperclass();
}
return methods;
}
/**
* 注销目标对象的事件监听器
* @param target 目标对象
*/
public void unregister(Object target) {
List<Subscriber> subs = targetSubscribers.remove(target);
if (subs == null) {
return;
}
for (Subscriber sub : subs) {
List<Subscriber> eventSubs = eventSubscribers.get(sub.eventType);
if (eventSubs != null) {
eventSubs.remove(sub);
if (eventSubs.isEmpty()) {
eventSubscribers.remove(sub.eventType);
}
}
}
}
/**
* 发布事件
* @param event 事件对象
* @return 返回事件是否被取消的状态
*/
public boolean post(Object event) {
if (shutdown) {
return false;
}
boolean cancelled = false;
Class<?> eventType = event.getClass();
List<Subscriber> subs = eventSubscribers.get(eventType);
if (subs == null) {
return cancelled;
}
// 创建副本以避免并发修改异常
List<Subscriber> copySubs = new ArrayList<>(subs);
for (Subscriber sub : copySubs) {
try {
sub.method.setAccessible(true);
sub.method.invoke(sub.target, event);
} catch (Exception e) {
handleException(event, e);
}
}
return cancelled;
}
/**
* 关闭事件总线,停止处理事件
*/
public void shutdown() {
shutdown = true;
}
/**
* 处理事件处理过程中出现的异常
* @param event 事件
* @param e 异常
*/
private void handleException(Object event, Exception e) {
e.printStackTrace();
}
}

View File

@@ -0,0 +1,8 @@
package com.axis.innovators.box.events;
/**
* @author tzdwindows 7
*/
public class GlobalEventBus {
public static final EventBus EVENT_BUS = new EventBus();
}

View File

@@ -0,0 +1,25 @@
package com.axis.innovators.box.events;
import com.axis.innovators.box.gui.MainWindow;
import javax.swing.*;
import java.awt.*;
/**
* 主窗口事件
* @author tzdwindows 7
*/
public class MainWindowEvents {
/**
* 在更新主窗口时调用
*/
public record update(MainWindow mainWindow, Graphics g) {
}
/**
* 在初始化主窗口时调用
*/
public record initialize(MainWindow mainWindow, JPanel mainPanel) {
}
}

View File

@@ -0,0 +1,12 @@
package com.axis.innovators.box.events;
import javax.swing.*;
/**
* 当设置被初始化加载时被调用
* 可以在这里添加新的设置选项
*
* @author tzdwindows 7
*/
public record SettingsLoadEvents(JDialog dialog, JPanel content) {
}

View File

@@ -0,0 +1,12 @@
package com.axis.innovators.box.events;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* 事件注解,事件订阅注解,用于标记事件监听方法
* @author tzdwindows 7
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface SubscribeEvent {
}

View File

@@ -0,0 +1,47 @@
package com.axis.innovators.box.events;
import javax.swing.*;
import java.awt.*;
/**
* 选项卡Ui事件当设置选项卡Ui属性时被调用
* @author tzdwindows 7
*/
public class TABUIEvents {
private final JComponent javax;
private final JPanel card;
public TABUIEvents(JPanel card, JComponent c){
this.javax = c;
this.card = card;
}
public JComponent getJavax() {
return javax;
}
public JPanel getCard() {
return card;
}
/**
* 选项卡更新事件
*/
public static class update {
private final JComponent javax;
private final Graphics graphics;
public update(Graphics g, JComponent c){
this.javax = c;
this.graphics = g;
}
public JComponent getJavax() {
return javax;
}
public Graphics getGraphics() {
return graphics;
}
}
}

View File

@@ -0,0 +1,298 @@
package com.axis.innovators.box.gui;
import org.tzd.frida.windows.CallbackMessage;
import org.tzd.frida.windows.Frida;
import org.tzd.frida.windows.FridaRunnable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class FridaWindow extends JDialog {
private JTextArea scriptArea;
private JTextArea logArea;
private JTextField pidField;
private boolean isRepetition = false;
public FridaWindow(Window owner) {
super(owner, "Frida 注入工具", ModalityType.APPLICATION_MODAL);
initializeUI();
}
private void initializeUI() {
setSize(800, 600);
setLocationRelativeTo(getOwner());
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color1 = new Color(235, 241, 250);
Color color2 = new Color(255, 255, 255);
GradientPaint gp = new GradientPaint(0, 0, color1, getWidth(), getHeight(), color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
};
mainPanel.setLayout(new BorderLayout(10, 10));
mainPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
// 输入面板
JPanel inputPanel = createInputPanel();
mainPanel.add(inputPanel, BorderLayout.NORTH);
// 脚本编辑区
JPanel scriptPanel = createScriptPanel();
mainPanel.add(scriptPanel, BorderLayout.CENTER);
// 日志输出
JPanel logPanel = createLogPanel();
mainPanel.add(logPanel, BorderLayout.SOUTH);
setContentPane(mainPanel);
}
private JPanel createInputPanel() {
JPanel panel = new JPanel(new GridLayout(1, 3, 10, 10));
panel.setOpaque(false);
pidField = new JTextField("请输入进程PID");
pidField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
pidField.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(57, 56, 56)),
BorderFactory.createEmptyBorder(5, 10, 5, 10)
));
//JButton attachButton = new JButton("附加进程");
//styleButton(attachButton, new Color(70, 130, 180));
//attachButton.setEnabled(false);
JButton browseButton = new JButton("选择进程");
styleButton(browseButton, new Color(60, 179, 113));
browseButton.addActionListener(this::openProcessSelectionWindow);
panel.add(pidField);
//panel.add(attachButton);
panel.add(browseButton);
return panel;
}
private JPanel createScriptPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.setBorder(BorderFactory.createTitledBorder("脚本编辑器"));
scriptArea = new JTextArea();
scriptArea.setFont(new Font("Consolas", Font.PLAIN, 14));
JScrollPane scrollPane = new JScrollPane(scriptArea);
scrollPane.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5));
buttonPanel.setOpaque(false);
JButton injectButton = new JButton("注入脚本");
styleButton(injectButton, new Color(220, 20, 60));
injectButton.addActionListener(this::handleInject);
buttonPanel.add(injectButton);
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(buttonPanel, BorderLayout.SOUTH);
return panel;
}
private JPanel createLogPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(0, 150));
panel.setBorder(BorderFactory.createTitledBorder("日志输出"));
panel.setOpaque(false);
logArea = new JTextArea();
logArea.setEditable(false);
logArea.setFont(new Font("微软雅黑", Font.PLAIN, 12));
JScrollPane scrollPane = new JScrollPane(logArea);
scrollPane.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
panel.add(scrollPane);
return panel;
}
private void styleButton(JButton button, Color bgColor) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setFocusPainted(false);
button.setBackground(bgColor);
button.setForeground(Color.black);
button.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
}
private void handleInject(ActionEvent e) {
try {
long pid = Long.parseLong(pidField.getText());
String script = scriptArea.getText();
Frida frida = new Frida(script, pid);
if (!isRepetition) {
frida.run(() -> {
// 执行注入操作
}).execute(frida1 -> frida1.addCallbackMessage(message ->
SwingUtilities.invokeLater(() ->
logArea.append("[LOG] " + message + "\n")
)
)).start();
isRepetition = true;
} else {
frida.run(() -> {}).execute(frida12 -> {}).start();
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "无效的进程ID", "错误", JOptionPane.ERROR_MESSAGE);
}
}
private void openProcessSelectionWindow(ActionEvent e) {
// 打开一个窗口显示所有进程的ID、名称和图标
ProcessSelectionWindow selectionWindow = new ProcessSelectionWindow(this);
selectionWindow.setVisible(true);
}
// 选择进程的子窗口
private static class ProcessSelectionWindow extends JDialog {
private List<ProcessInfo> processList; // 存储所有进程信息
private JTable table;
public ProcessSelectionWindow(Window owner) {
super(owner, "选择进程", ModalityType.APPLICATION_MODAL);
setSize(600, 400);
setLocationRelativeTo(owner);
initializeUI();
}
private void initializeUI() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
// 获取所有进程信息
processList = getProcesses();
// 创建搜索框
JPanel searchPanel = new JPanel();
searchPanel.setLayout(new BorderLayout());
JTextField searchField = new JTextField();
searchField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
filterProcesses(searchField.getText());
}
@Override
public void removeUpdate(DocumentEvent e) {
filterProcesses(searchField.getText());
}
@Override
public void changedUpdate(DocumentEvent e) {
filterProcesses(searchField.getText());
}
});
searchPanel.add(new JLabel("搜索进程: "), BorderLayout.WEST);
searchPanel.add(searchField, BorderLayout.CENTER);
panel.add(searchPanel, BorderLayout.NORTH);
// 显示进程信息的表格
String[] columns = {"进程名称", "进程ID"};
Object[][] data = getTableData(processList);
table = new JTable(data, columns);
JScrollPane scrollPane = new JScrollPane(table);
panel.add(scrollPane, BorderLayout.CENTER);
JButton selectButton = new JButton("选择");
selectButton.addActionListener(e -> {
int selectedRow = table.getSelectedRow();
if (selectedRow >= 0) {
long selectedPid = (Long) table.getValueAt(selectedRow, 1); // 注意这里获取的是PID列
((FridaWindow) getOwner()).pidField.setText(String.valueOf(selectedPid));
dispose();
}
});
panel.add(selectButton, BorderLayout.SOUTH);
setContentPane(panel);
}
private void filterProcesses(String query) {
List<ProcessInfo> filteredList = new ArrayList<>();
for (ProcessInfo process : processList) {
if (process.getName().toLowerCase().contains(query.toLowerCase())) {
filteredList.add(process);
}
}
// 更新表格数据
Object[][] filteredData = getTableData(filteredList);
table.setModel(new DefaultTableModel(filteredData, new String[]{"进程名称", "进程ID"}));
}
private Object[][] getTableData(List<ProcessInfo> processes) {
Object[][] data = new Object[processes.size()][2];
for (int i = 0; i < processes.size(); i++) {
ProcessInfo process = processes.get(i);
data[i] = new Object[]{process.getName(), process.getPid()};
}
return data;
}
private List<ProcessInfo> getProcesses() {
List<ProcessInfo> processList = new ArrayList<>();
try {
// 执行cmd命令获取所有进程信息
Process process = Runtime.getRuntime().exec("tasklist /fo csv /nh");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
String[] columns = line.split(",");
if (columns.length > 1) {
long pid = Long.parseLong(columns[1].replaceAll("\"", "").trim());
String processName = columns[0].replaceAll("\"", "").trim();
processList.add(new ProcessInfo(pid, processName));
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return processList;
}
}
// 存储进程信息的类
private static class ProcessInfo {
private long pid;
private String name;
public ProcessInfo(long pid, String name) {
this.pid = pid;
this.name = name;
}
public long getPid() {
return pid;
}
public String getName() {
return name;
}
}
}

View File

@@ -0,0 +1,36 @@
package com.axis.innovators.box.gui;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
/**
* 负责加载图片
* @author tzdwindows 7
*/
public class LoadIcon {
private static final String ICON_PATH = "/icons/";
public static ImageIcon loadIcon(String filename, int size) {
try {
String fullPath = ICON_PATH + filename;
URL imgUrl = LoadIcon.class.getResource(fullPath);
if (imgUrl == null) {
return createPlaceholderIcon(size);
}
Image image = new ImageIcon(imgUrl).getImage();
return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH));
} catch (Exception e) {
return createPlaceholderIcon(size);
}
}
private static ImageIcon createPlaceholderIcon(int size) {
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
return new ImageIcon(img);
}
}

View File

@@ -0,0 +1,716 @@
package com.axis.innovators.box.gui;
import com.axis.innovators.box.events.*;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.*;
import java.util.List;
/**
* 显示窗口(显示的主窗口)
* @author tzdwindows 7
*/
public class MainWindow extends JFrame {
private final Map<JComponent, Float> cardScales = new HashMap<>();
private final Map<JComponent, Integer> cardElevations = new HashMap<>();
// 选项卡颜色
private final Color CARD_COLOR = Color.WHITE;
private final List<ToolCategory> categories = new ArrayList<>();
// 是否启用背景图片
private final boolean isBackground = true;
// 启动背景图片后是否启动背景模糊
private final boolean isBlur = true;
public MainWindow() {
setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage());
}
/**
* 添加工具分类
* @param category 工具分类
*/
public void addToolCategory(ToolCategory category){
categories.add(category);
}
public void initUI() {
setTitle("轴创工具箱 v1.0");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1200, 800);
setLocationRelativeTo(null);
JPanel mainPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color1 = new Color(235, 241, 250);
Color color2 = new Color(255, 255, 255);
GradientPaint gp = new GradientPaint(0, 0, color1, getWidth(), getHeight(), color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
if (isBackground) {
try {
ImageIcon backgroundImage = LoadIcon.loadIcon("start_page.png", 500);
if (isBlur) {
BufferedImage bufferedImage = toBufferedImage(backgroundImage.getImage());
BufferedImage blurredImage = applyGaussianBlur(bufferedImage, 5);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
int x = (getWidth() - blurredImage.getWidth()) / 2;
int y = (getHeight() - blurredImage.getHeight()) / 2;
g2d.drawImage(blurredImage, x, y, this);
} else {
int x = (getWidth() - backgroundImage.getIconWidth()) / 2;
int y = (getHeight() - backgroundImage.getIconHeight()) / 2;
g2d.drawImage(backgroundImage.getImage(), x, y, this);
}
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
mainPanel.setLayout(new BorderLayout(20, 20));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
mainPanel.add(createHeader(), BorderLayout.NORTH);
mainPanel.add(createCategoryTabs(), BorderLayout.CENTER);
GlobalEventBus.EVENT_BUS.post(new MainWindowEvents.initialize(this, mainPanel));
add(mainPanel);
}
private BufferedImage toBufferedImage(Image img) {
if (img instanceof BufferedImage) {
return (BufferedImage) img;
}
BufferedImage bimage = new BufferedImage(
img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
return bimage;
}
/**
* 对图像应用动感模糊效果。
*
* @param srcImage 需要应用动感模糊的源图像。
* 这个参数应该是一个 `BufferedImage` 类型的对象。
* @param radius 动感模糊的半径,决定模糊效果的范围。
* 半径越大,模糊范围越广,模糊效果越强。
* @param angle 动感模糊的角度,决定模糊效果的方向。
* 角度单位为度表示从正Y轴顺时针的旋转角度。
* 比如:
* - `0` 表示水平方向的模糊。
* - `90` 表示垂直方向的模糊。
* - 其他角度则表示不同方向的模糊。
* @return 返回应用了动感模糊效果的 `BufferedImage` 图像。
* 原始图像不会被修改,返回的是处理过的新图像。
*/
public BufferedImage applyMotionBlur(BufferedImage srcImage, int radius, int angle) {
double radian = Math.toRadians(angle);
float[] matrix = new float[radius * radius];
float sum = 0.0f;
int index = 0;
for (int y = -radius / 2; y <= radius / 2; y++) {
for (int x = -radius / 2; x <= radius / 2; x++) {
float weight = (float) (Math.cos(radian) * x + Math.sin(radian) * y);
if (Math.abs(weight) < 1) {
matrix[index++] = 1.0f;
sum += 1.0f;
} else {
matrix[index++] = 0.0f;
}
}
}
return getBufferedImage(srcImage, radius, matrix, sum);
}
private BufferedImage getBufferedImage(BufferedImage srcImage, int radius, float[] matrix, float sum) {
for (int i = 0; i < matrix.length; i++) {
matrix[i] /= sum;
}
Kernel kernel = new Kernel(radius, radius, matrix);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
return convolve.filter(srcImage, null);
}
/**
* 应用高斯模糊效果到给定的图像。
*
* @param srcImage 输入的原始图像,类型为 `BufferedImage`。
* @param radius 高斯模糊的半径,表示模糊的强度。半径越大,模糊效果越强。
* @return 返回模糊处理后的图像,类型为 `BufferedImage`。
*/
public BufferedImage applyGaussianBlur(BufferedImage srcImage, int radius) {
if (radius > 100) {
radius = 100;
}
float[] matrix = new float[radius * radius];
float sigma = radius / 2f;
float sum = 0.0f;
int index = 0;
for (int y = -radius / 2; y <= radius / 2; y++) {
for (int x = -radius / 2; x <= radius / 2; x++) {
float weight = (float) Math.exp(-(x * x + y * y) / (2 * sigma * sigma));
matrix[index] = weight;
index++;
sum += weight;
}
}
return getBufferedImage(srcImage, radius, matrix, sum);
}
private JComponent createCategoryTabs() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setOpaque(false);
tabbedPane.setBackground(new Color(0, 0, 0, 0));
tabbedPane.setBorder(null);
tabbedPane.setUI(new CustomTabbedPaneUI());
for (ToolCategory category : categories) {
JPanel toolsPanel = createToolsPanel(category);
toolsPanel.setOpaque(false);
toolsPanel.setBorder(null);
JScrollPane scrollPane = new JScrollPane(toolsPanel);
scrollPane.setBorder(null);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar();
verticalScrollBar.setUI(new CustomScrollBarUI());
verticalScrollBar.setPreferredSize(new Dimension(10, 100));
tabbedPane.addTab(
category.getName(),
LoadIcon.loadIcon(category.getIcon(), 24),
scrollPane
);
}
return tabbedPane;
}
private JPanel createToolsPanel(ToolCategory category) {
JPanel panel = new JPanel(new GridLayout(0, 3, 20, 20));
for (ToolItem tool : category.getTools()) {
panel.add(createToolCard(tool));
}
panel.setOpaque(false);
panel.setBorder(null);
return panel;
}
private JPanel createHeader() {
JPanel header = new JPanel(new BorderLayout());
header.setOpaque(false);
header.setBorder(BorderFactory.createEmptyBorder(15, 30, 15, 30));
// 创建标题
JLabel title = new JLabel("轴创工具箱");
title.setFont(new Font("微软雅黑", Font.BOLD, 28));
title.setForeground(new Color(44, 62, 80));
//JLabel iconLabel = new JLabel(LoadIcon.loadIcon("logo.png", 28));
//iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
JButton settings = new JButton(LoadIcon.loadIcon("settings.png", 32));
settings.setContentAreaFilled(false);
settings.addActionListener(e -> showSettings());
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
titlePanel.setOpaque(false);
//titlePanel.add(iconLabel);
titlePanel.add(title);
header.add(titlePanel, BorderLayout.WEST);
header.add(settings, BorderLayout.EAST);
return header;
}
@Override
public void update(Graphics g) {
GlobalEventBus.EVENT_BUS.post(new MainWindowEvents.update(this, g));
super.update(g);
}
private void showSettings() {
JDialog dialog = new JDialog(this, "系统设置", true);
dialog.setSize(600, 400);
dialog.setLocationRelativeTo(this);
JPanel content = new JPanel(new BorderLayout());
content.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
//JLabel placeholder = new JLabel("设置功能开发中...", SwingConstants.CENTER);
//placeholder.setFont(new Font("微软雅黑", Font.PLAIN, 24));
//placeholder.setForeground(new Color(127, 140, 153));
//content.add(placeholder, BorderLayout.CENTER);
GlobalEventBus.EVENT_BUS.post(new SettingsLoadEvents(dialog, content));
dialog.add(content);
dialog.setVisible(true);
}
private JPanel createToolCard(ToolItem tool) {
JPanel card = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制阴影
int elevation = cardElevations.getOrDefault(this, 2);
for (int i = 0; i < elevation; i++) {
g2d.setColor(new Color(0, 0, 0, 20 - i * 2));
g2d.fillRoundRect(i, i, getWidth() - i * 2, getHeight() - i * 2, 15, 15);
}
float scale = cardScales.getOrDefault(this, 1.0f);
int offset = (int) ((scale - 1) * getWidth() / 2);
g2d.translate(-offset, -offset);
g2d.scale(scale, scale);
super.paintComponent(g2d);
g2d.dispose();
}
};
card.setLayout(new BorderLayout(15, 15));
card.setBackground(CARD_COLOR);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(225, 229, 234), 1),
BorderFactory.createEmptyBorder(20, 20, 20, 20)
));
card.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
JLabel iconLabel = new JLabel(LoadIcon.loadIcon(tool.icon(), 64));
iconLabel.setHorizontalAlignment(SwingConstants.CENTER);
// 文字面板
JPanel textPanel = new JPanel();
textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
textPanel.setOpaque(false);
JLabel titleLabel = new JLabel(tool.title());
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
titleLabel.setForeground(new Color(44, 62, 80));
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
JTextArea descArea = new JTextArea(tool.description());
descArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));
descArea.setForeground(new Color(127, 140, 153));
descArea.setLineWrap(true);
descArea.setWrapStyleWord(true);
descArea.setEditable(false);
descArea.setOpaque(false);
descArea.setAlignmentX(Component.CENTER_ALIGNMENT);
card.setToolTipText(createToolTipHTML(tool));
textPanel.add(titleLabel);
textPanel.add(Box.createVerticalStrut(10));
textPanel.add(descArea);
card.add(iconLabel, BorderLayout.NORTH);
card.add(textPanel, BorderLayout.CENTER);
// 鼠标悬停动画
card.addMouseListener(new CardMouseAdapter(card, tool));
card.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
SwingUtilities.invokeLater(() -> {
});
}
});
card.setUI(new PanelUI() {
@Override
public void installUI(JComponent c) {
GlobalEventBus.EVENT_BUS.post(new TABUIEvents(card, c));
super.installUI(c);
}
@Override
public void update(Graphics g, JComponent c) {
GlobalEventBus.EVENT_BUS.post(new TABUIEvents.update(g, c));
super.update(g, c);
}
});
return card;
}
private BufferedImage captureWindowImage(Window window) {
try {
Rectangle bounds = window.getBounds();
BufferedImage capture = new Robot().createScreenCapture(bounds);
return capture.getSubimage(0, 0, window.getWidth(), window.getHeight());
} catch (AWTException e) {
e.printStackTrace();
return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
}
}
private static JPanel getjPanel(BufferedImage[] blurredImage, Window window) {
JPanel blurPanel = new JPanel() {
private float currentOpacity = 1.0f;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (blurredImage[0] != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentOpacity));
g2d.drawImage(blurredImage[0], 0, 0, null);
g2d.dispose();
}
}
};
// 面板属性设置
blurPanel.setBounds(0, 0, window.getWidth(), window.getHeight());
blurPanel.setOpaque(false);
return blurPanel;
}
private String createToolTipHTML(ToolItem tool) {
return "<html><body style='width: 300px; padding: 10px;'>" +
"<h3 style='color: #2c3e50; margin: 0 0 8px 0;'>" + tool.getName() + "</h3>" +
"<p style='color: #7f8c99; margin: 0;'>" + tool.description() + "</p>" +
"</body></html>";
}
private void animateHover(JComponent component, float targetScale, int targetElevation) {
final int ANIMATION_DURATION = 200;
final float startScale = cardScales.getOrDefault(component, 1.0f);
final int startElevation = cardElevations.getOrDefault(component, 2);
new Timer(10, new AbstractAction() {
long startTime = -1;
@Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long elapsed = System.currentTimeMillis() - startTime;
float progress = Math.min(1.0f, elapsed / (float) ANIMATION_DURATION);
// 使用缓动函数实现平滑动画
float easedProgress = (float) (1 - Math.pow(1 - progress, 3));
float currentScale = startScale + (targetScale - startScale) * easedProgress;
int currentElevation = (int) (startElevation + (targetElevation - startElevation) * easedProgress);
cardScales.put(component, currentScale);
cardElevations.put(component, currentElevation);
component.repaint();
if (progress >= 1.0f) {
((Timer) e.getSource()).stop();
}
}
}).start();
}
// 工具类别内部类
public static class ToolCategory {
private final String name;
private final String icon;
private final String description;
private final List<ToolItem> tools = new ArrayList<>();
/**
* 一个大的分类项类
* @param name 分类项的显示名称
* @param icon 分类项的图标resources的路径
* @param description 分类项的描述
*/
public ToolCategory(String name, String icon, String description) {
this.name = name;
this.icon = icon;
this.description = description;
}
/**
* 注册工具的方法
* @param tool 工具项
*/
public void addTool(ToolItem tool) {
tools.add(tool);
}
public String getDescription() {
return description;
}
public String getIcon() {
return icon;
}
public String getName() {
return name;
}
public List<ToolItem> getTools() {
return tools;
}
}
// 工具项数据类
/**
* 工具注册类
* @param title 工具的标题(显示名称)
* @param icon 工具的图标resources的路径
* @param description 工具的描述
* @param id 工具的id请不要重复注册相同id的工具
* @param action 工具的点击事件
*/
public record ToolItem(String title, String icon, String description, int id, Action action) {
private static JPanel getjPanel() {
JPanel content = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 渐变背景
GradientPaint gp = new GradientPaint(
0, 0, new Color(245, 247, 250),
getWidth(), getHeight(), new Color(255, 255, 255)
);
g2d.setPaint(gp);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 20, 20);
// 边框阴影
g2d.setColor(new Color(0, 0, 0, 20));
g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
}
};
content.setLayout(new BorderLayout(20, 20));
content.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
return content;
}
public String getName() {
return title;
}
}
// 分类栏面卡
public static class CustomTabbedPaneUI extends BasicTabbedPaneUI {
private static final Color SELECTED_COLOR = new Color(183, 202, 221);
private static final Color UNSELECTED_COLOR = new Color(125, 174, 237);
@Override
protected void paintTabBackground(Graphics g, int tabPlacement,
int tabIndex, int x, int y, int w, int h,
boolean isSelected) {
CategoryRenderingEvent event = new CategoryRenderingEvent(this, g, tabPlacement, tabIndex, x, y, w, h, isSelected);
GlobalEventBus.EVENT_BUS.post(event);
if (event.isEnd()){
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (isSelected) {
g2d.setColor(SELECTED_COLOR);
} else {
g2d.setColor(UNSELECTED_COLOR);
}
g2d.fillRoundRect(x + 2, y + 2, w - 4, h - 4, 10, 10);
g2d.dispose();
}
@Override
protected void paintTabBorder(Graphics g, int tabPlacement,
int tabIndex, int x, int y, int w, int h,
boolean isSelected) {
GlobalEventBus.EVENT_BUS.post(new CategoryRenderingEvent.paintTabBorder(this, g,
tabPlacement,
tabIndex, x, y, w, h, isSelected));
}
}
private class CardMouseAdapter extends MouseAdapter {
private final JPanel card;
private final ToolItem tool;
private Timer pressTimer;
private Timer releaseTimer;
public CardMouseAdapter(JPanel card, ToolItem tool) {
this.card = card;
this.tool = tool;
}
@Override
public void mousePressed(MouseEvent e) {
startPressAnimation();
}
@Override
public void mouseReleased(MouseEvent e) {
startReleaseAnimation(() -> tool.action().actionPerformed(
new ActionEvent(card, ActionEvent.ACTION_PERFORMED, "")
));
}
@Override
public void mouseExited(MouseEvent e) {
if (pressTimer != null && pressTimer.isRunning()) {
startReleaseAnimation(null);
}
}
private void startPressAnimation() {
if (pressTimer != null && pressTimer.isRunning()) {
return;
}
pressTimer = new Timer(10, new AbstractAction() {
private final long startTime = System.currentTimeMillis();
@Override
public void actionPerformed(ActionEvent e) {
float progress = Math.min(1.0f,
(System.currentTimeMillis() - startTime) / 150f);
// 使用二次缓动函数
float scale = 1.0f - 0.1f * (float) Math.pow(progress, 0.5);
cardScales.put(card, scale);
card.repaint();
if (progress >= 1.0f) {
((Timer) e.getSource()).stop();
}
}
});
pressTimer.start();
}
private void startReleaseAnimation(Runnable callback) {
if (pressTimer != null) {
pressTimer.stop();
}
if (releaseTimer != null && releaseTimer.isRunning()) {
return;
}
final float startScale = cardScales.getOrDefault(card, 1.0f);
releaseTimer = new Timer(10, new AbstractAction() {
private final long startTime = System.currentTimeMillis();
@Override
public void actionPerformed(ActionEvent e) {
float progress = Math.min(1.0f,
(System.currentTimeMillis() - startTime) / 200f);
// 使用弹性缓动函数
float scale = startScale +
(1.0f - startScale) * (float) (1 - Math.pow(1 - progress, 3));
cardScales.put(card, scale);
card.repaint();
if (progress >= 1.0f) {
((Timer) e.getSource()).stop();
if (callback != null) {
callback.run();
}
}
}
});
releaseTimer.start();
}
}
public static class CustomScrollBarUI extends BasicScrollBarUI {
@Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 设置轨道背景颜色
Color trackColor = new Color(240, 240, 240);
g2d.setColor(trackColor);
g2d.fillRoundRect(
trackBounds.x,
trackBounds.y,
trackBounds.width - 1,
trackBounds.height - 1,
5, 5 // 圆角半径
);
}
@Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color thumbColor = new Color(180, 180, 180);
g2d.setColor(thumbColor);
g2d.fillRoundRect(
thumbBounds.x,
thumbBounds.y,
thumbBounds.width - 1,
thumbBounds.height - 1,
5, 5
);
Color borderColor = new Color(160, 160, 160);
g2d.setColor(borderColor);
g2d.drawRoundRect(
thumbBounds.x,
thumbBounds.y,
thumbBounds.width - 1,
thumbBounds.height - 1,
5, 5
);
}
@Override
protected void paintDecreaseHighlight(Graphics g) {}
@Override
protected void paintIncreaseHighlight(Graphics g) {}
}
}

View File

@@ -0,0 +1,38 @@
package com.axis.innovators.box.tools;
import java.io.File;
/**
* 在当前jar下创建文件夹
* @author tzdwindows 7
*/
public class FolderCreator {
public static final String LIBRARY_NAME = "library";
public static String getLibraryFolder() {
String folder = createFolder(LIBRARY_NAME);
if (folder == null) {
System.out.println("Library folder creation failure");
return null;
}
return folder;
}
/**
* 创建文件夹
* @param folderName folder name
* @return folder path
*/
private static String createFolder(String folderName) {
String jarDir = System.getProperty("user.dir");
File folder = new File(jarDir, folderName);
if (!folder.exists()) {
if (!folder.mkdir()) {
System.out.println("Folder creation failure");
return null;
}
}
return folder.getAbsolutePath();
}
}

View File

@@ -0,0 +1,40 @@
package com.axis.innovators.box.tools;
/**
* 在程序链接库文件中加载指定链接库
* @author tzdwindows 7
*/
public class LibraryLoad {
public static final String LIBRARY_NAME = FolderCreator.getLibraryFolder() + "\\";
/**
* 加载链接库
* @param libraryName 链接库名称
*/
public static void loadLibrary(String libraryName) {
String libraryWithExtension = addLibraryExtension(libraryName);
System.load(LIBRARY_NAME + libraryWithExtension);
}
/**
* 判断并添加正确的库文件后缀
* @param libraryName 链接库名称
* @return 带有后缀名的库文件名称
*/
private static String addLibraryExtension(String libraryName) {
String os = System.getProperty("os.name").toLowerCase();
if (libraryName.toLowerCase().endsWith(".dll")
|| libraryName.toLowerCase().endsWith(".so")) {
return libraryName;
}
if (os.contains("win")) {
return libraryName + ".dll";
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
return libraryName + ".so";
} else {
return libraryName;
}
}
}

View File

@@ -0,0 +1,87 @@
package org.tzd.frida;
import org.tzd.frida.windows.CallbackMessage;
import org.tzd.frida.windows.Frida;
import org.tzd.frida.windows.FridaRunnable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Main 类用于启动和执行 Frida 注入操作。
*
* <p>此类主要包含一个入口方法 <code>main</code>,用于加载必要的本地库并初始化 Frida 对象。</p>
* <p>它会通过调用 <code>getProcessPid</code> 方法获取指定进程的 PID并将 JavaScript 代码注入到目标进程中。</p>
*
* @author tzdwindows 7
*/
public class Main {
/**
* 程序入口方法。
*
* <p>此方法加载本地 DLL 库并创建一个 <code>Frida</code> 实例。接着通过 <code>run</code> 和 <code>execute</code> 方法执行指定的任务。</p>
* <p>执行期间,会将回调函数添加到 <code>Frida</code> 实例中,接收并打印消息。</p>
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 加载本地 DLL 文件
System.load("C:\\Users\\Administrator\\source\\repos\\FridaNative\\x64\\Release\\FridaNative.dll");
// 创建 Frida 实例并传入 JavaScript 代码及进程 PID
Frida frida = new Frida("console.log('Hello, Frida!');", getProcessPid("java.exe"));
// 执行 Frida 任务,注入代码并注册回调函数
frida.run(new Runnable() {
@Override
public void run() {
// 在此处添加要执行的代码
}
}).execute(new FridaRunnable() {
@Override
public void run(Frida frida) {
// 注册回调消息,接收到消息时打印
frida.addCallbackMessage(new CallbackMessage() {
@Override
public void onMessage(String message) {
System.out.println(message); // 打印收到的消息
}
});
}
}).start(); // 启动线程
}
/**
* 获取指定进程的 PID。
*
* <p>此方法通过运行 Windows 命令 <code>tasklist</code> 获取系统中所有正在运行的进程,并查找指定进程名。</p>
* <p>一旦找到匹配的进程,它将提取进程的 PID 并返回。</p>
*
* @param processName 要查找的进程名称。
* @return 目标进程的 PID如果未找到则返回 -1。
*/
public static long getProcessPid(String processName) {
long pid = -1;
try {
ProcessBuilder builder = new ProcessBuilder("tasklist");
builder.redirectErrorStream(true);
Process process = builder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains(processName)) {
String[] parts = line.split("\\s+");
pid = Long.parseLong(parts[1]);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return pid;
}
}

View File

@@ -0,0 +1,12 @@
package org.tzd.frida.windows;
/**
* @author tzdwindows 7
*/
public interface CallbackMessage {
/**
* 回调消息
* @param message 消息
*/
void onMessage(String message);
}

View File

@@ -0,0 +1,126 @@
package org.tzd.frida.windows;
/**
* @author tzdwindows 7
*/
public class Frida {
private final String jsCode;
private FridaThread thread;
boolean isRunning;
long pid;
/**
* 构造一个新的 <code>Frida</code> 实例。
*
* @param jsCode 需要注入的 JavaScript 代码。
* @param pid 目标进程的进程ID。
*
* <p>此构造函数用于初始化一个新的 <code>Frida</code> 对象,指定要注入的 JavaScript 代码及目标进程ID。</p>
*/
public Frida(String jsCode, long pid) {
this.jsCode = jsCode;
this.pid = pid;
isRunning = false;
}
/**
* 启动并返回一个新的线程用于执行JavaScript注入。
*
* @return 返回一个线程管理类 <code>FridaThread</code>,方便对线程进行统一管理。
*
* <p>该方法的工作流程如下:</p>
* <ol>
* <li<code>new FridaThread(() -> { ... })</code>: 创建一个新的线程,该线程执行 JavaScript 注入操作。线程内部会设置 <code>isRunning = true</code> 并调用 <code>Frida0.injection(jsCode, this)</code> 来注入 JavaScript 代码。</li>
* </ol>
*
* <p>示例用法:</p>
* <pre>
* FridaThread thread = frida.run();
* thread.setStart(true)
* thread.start(); // 启动线程
* </pre>
*/
public FridaThread run() {
thread = new FridaThread(() -> {
isRunning = true;
Frida0.injection(jsCode,this);
},this);
return thread;
}
/**
* 启动并返回一个新的线程用于执行JavaScript注入。
*
* @param callback 在循环中的回调函数
* @return 一个线程管理类,方便对线程进行统一管理
*
* <p>该方法的工作流程如下:</p>
* <ol>
* <li><code>run(Runnable... callback)</code>: 首先创建一个新的 <code>FridaThread</code>,并传入一个 <code>Runnable</code> 任务,任务会在新线程中执行。任务内会调用 <code>Frida0.injection(jsCode, this, callback)</code>,注入并执行 JavaScript 代码。</li>
* <li><code>execute(FridaRunnable runnable)</code>: <code>execute</code> 方法允许你定义在 <code>FridaThread</code> 中执行的额外任务。<code>FridaRunnable</code> 接口的 <code>run</code> 方法会被调用,允许你与 <code>Frida</code> 对象交互,添加回调消息或其他操作。</li>
* <li><code>start()</code>: 启动线程,执行上述所有任务。</li>
* </ol>
*
* <p>示例用法:</p>
* <pre>
* frida.run(new Runnable() {
* @Override
* public void run() {
* // 在此处添加需要执行的代码
* }
* }).execute(new FridaRunnable() {
* @Override
* public void run(Frida frida) {
* // 注册回调消息,接收信息
* frida.addCallbackMessage(new CallbackMessage() {
* @Override
* public void onMessage(String message) {
* System.out.println(message); // 打印收到的消息
* }
* });
* }
* }).start(); // 启动线程
* </pre>
*
* <p>在这个示例中,<code>run()</code> 方法首先创建并配置一个新的线程,<code>execute()</code> 方法为线程添加了一个回调函数,接收到消息时会触发该回调函数。最后,调用 <code>start()</code> 启动线程的执行。</p>
* <p>当然你如果非要在FridaThread中直接使用start而不经过execute的话我们会抛出异常 throw new RuntimeException("Basic information is not configured"); </p>
*/
public FridaThread run(Runnable... callback) {
thread = new FridaThread(() -> {
isRunning = true;
Frida0.injection(jsCode, this, callback);
}, this);
return thread;
}
/**
* 将回调消息添加到消息列表中。
*
* @param callbackMessage 要添加的回调消息对象。
*
* <p>此方法会将传入的 <code>callbackMessage</code> 对象添加到 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中。</p>
*/
public void addCallbackMessage(CallbackMessage callbackMessage) {
Frida0.CALLBACK_MESSAGE_LIST.add(callbackMessage);
}
/**
* 从消息列表中移除指定的回调消息。
*
* @param callbackMessage 要移除的回调消息对象。
*
* <p>此方法会将传入的 <code>callbackMessage</code> 对象从 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中移除。</p>
*/
public void clearCallbackMessage(CallbackMessage callbackMessage) {
Frida0.CALLBACK_MESSAGE_LIST.remove(callbackMessage);
}
/**
* 清空所有回调消息。
*
* <p>此方法会清空 <code>Frida0.CALLBACK_MESSAGE_LIST</code> 中的所有回调消息。</p>
*/
public void clearCallbackMessage() {
Frida0.CALLBACK_MESSAGE_LIST.clear();
}
}

View File

@@ -0,0 +1,85 @@
package org.tzd.frida.windows;
import java.util.ArrayList;
import java.util.List;
/**
* Frida0 类用于处理 Frida 注入相关的操作和消息传递。
*
* <p>此类包括注入 JavaScript 代码到目标进程、消息的发送与接收处理等功能。</p>
* <p>通过该类,用户可以与 Frida 注入的进程进行交互,并通过回调函数获取日志或错误信息。</p>
*
* @author tzdwindows 7
*/
public class Frida0 {
// 存储回调消息的列表
static final List<CallbackMessage> CALLBACK_MESSAGE_LIST = new ArrayList<>();
/**
* 注入 JavaScript 代码到指定的 Frida 实例,并执行回调任务。
*
* <p>该方法调用本地代码注入 JavaScript并执行传入的回调函数。在 Frida 进程运行期间,回调函数将不断被执行。</p>
* <p>方法会在 Frida 进程完成后释放资源,并设置 Frida 的运行状态为 `false`。</p>
*
* @param jsCode 注入的 JavaScript 代码。
* @param frida 当前的 Frida 实例,包含进程 PID 等信息。
* @param callback 运行中的回调任务列表,多个任务可以同时执行。
*/
static void injection(String jsCode, Frida frida, Runnable... callback) {
// 调用本地方法进行 JavaScript 注入
FridaNative.injection(frida.pid, jsCode);
// 如果有回调任务,循环执行回调
if (callback != null) {
while (FridaNative.isRunning()) {
FridaNative.update();
for (Runnable runnable : callback) {
runnable.run();
}
}
}
// 释放本地资源
FridaNative.release();
frida.isRunning = false;
}
/**
* 发送消息给所有已注册的回调消息对象。
*
* <p>此方法会遍历 <code>CALLBACK_MESSAGE_LIST</code> 列表,并触发每个回调对象的 <code>onMessage</code> 方法。</p>
*
* @param message 需要发送的消息内容。
*/
private static void sendMessage(String message) {
CALLBACK_MESSAGE_LIST.forEach(callbackMessage -> callbackMessage.onMessage(message));
}
/**
* 处理接收到的消息,并根据消息类型做出响应。
*
* <p>根据消息中的 `type` 字段,如果是 `error` 类型,抛出运行时异常;如果是 `log` 类型,打印日志。</p>
* <p>其他类型的消息直接通过回调发送。</p>
*
* @param message 接收到的消息内容。
*/
private static void onMessage(String message) {
// 获取消息类型
String type = FridaNative.getStringMember(message, "type");
// 处理错误类型的消息
if (!type.isEmpty()) {
if ("error".equals(type)) {
sendMessage(FridaNative.getStringMember(message, "payload"));
throw new RuntimeException(FridaNative.getStringMember(message, "description"));
} else if ("log".equals(type)) {
sendMessage(FridaNative.getStringMember(message, "payload"));
}
return;
}
// 处理普通消息
sendMessage(message);
}
}

View File

@@ -0,0 +1,71 @@
package org.tzd.frida.windows;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
/**
* FridaJsInjector 类负责通过 Frida 向目标进程注入 JavaScript 代码。
* <p>此类提供了一个方法,允许通过读取指定的 JS 文件,并将其中的代码注入到指定的进程中。</p>
* <p>如果注入过程中发生错误,类会抛出相应的异常。</p>
*
* @author tzdwindows 7
* @since 1.0
* @version 1.0
*/
public class FridaJsInjector {
private Frida frida;
/**
* 构造方法,通过传入 PID 和 JavaScript 文件路径来初始化 Frida 实例。
*
* @param pid 目标进程的 PID。
* @param jsFilePath JavaScript 文件的路径。
*/
public FridaJsInjector(long pid, String jsFilePath) {
String jsCode = readJsFile(jsFilePath);
this.frida = new Frida(jsCode, pid);
}
/**
* 读取指定路径的 JavaScript 文件内容。
*
* @param jsFilePath JavaScript 文件路径。
* @return 文件内容的字符串表示。
*/
private String readJsFile(String jsFilePath) {
String jsCode = null;
try {
jsCode = new String(Files.readAllBytes(Paths.get(jsFilePath)));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failed to read the JavaScript file: " + jsFilePath, e);
}
return jsCode;
}
/**
* 向目标进程注入 JavaScript 代码。
* <p>该方法会使用 Frida 将 JavaScript 代码注入到指定的目标进程,并执行相关操作。</p>
* <p>方法会启动一个线程,并在该线程中执行注入操作。可以通过提供回调函数来接收注入过程中的消息。</p>
* <p>此方法会检查 Frida 实例是否已经初始化,并在初始化完成后执行 JavaScript 注入。</p>
*
* @param callback 传入的回调消息,当接收到来自 Frida 的消息时,该回调会被触发。
* @param callbackMessage 可选的额外回调函数,用于处理 JavaScript 注入的过程中的操作。
* @return 返回一个线程对象,用于统一管理和控制线程执行。
*
* @throws RuntimeException 如果 Frida 实例未初始化,则抛出运行时异常。
*/
public Thread injectJs(CallbackMessage callback, Runnable... callbackMessage) {
if (frida == null) {
throw new RuntimeException("Frida instance is not initialized.");
}
return frida.run(callbackMessage).execute(new FridaRunnable() {
@Override
public void run(Frida frida) {
frida.addCallbackMessage(callback);
}
});
}
}

View File

@@ -0,0 +1,54 @@
package org.tzd.frida.windows;
/**
* FridaNative 类封装了与本地 Frida 库的交互方法。
* <p>该类提供了几个静态本地方法,用于将 JavaScript 代码注入到目标进程并进行管理。</p>
* <p>所有方法都通过 JNI 调用本地代码实现与 Frida 库的交互。</p>
*/
public class FridaNative {
/**
* 使用 Frida 将 JavaScript 代码注入到指定进程。
*
* <p>该方法通过 JNI 调用本地 Frida 函数,将 JavaScript 代码注入到指定的进程中。</p>
*
* @param pid 目标进程的 PID通常是目标程序的进程 ID例如QQ 进程)。
* @param jsCode 要注入的 JavaScript 代码字符串。
* @return 返回注入是否成功,成功返回 `true`,失败返回 `false`。
*/
native static boolean injection(long pid, String jsCode);
/**
* 更新 Frida 的状态,保持与注入进程的交互。
* <p>此方法调用本地 Frida 函数以保持与注入的进程进行通信和交互。</p>
*
* @return 返回更新是否成功,成功返回 `true`,失败返回 `false`。
*/
native static boolean update();
/**
* 判断 Frida 是否正在运行。
* <p>此方法用于检查 Frida 是否正在执行并保持与目标进程的交互。</p>
*
* @return 如果 Frida 正在运行,返回 `true`,否则返回 `false`。
*/
native static boolean isRunning();
/**
* 释放 Frida 的资源。
* <p>该方法调用本地函数释放与 Frida 进程的所有资源。</p>
*
* @return 如果资源释放成功,返回 `true`,否则返回 `false`。
*/
native static boolean release();
/**
* 从消息中提取指定的字符串成员。
* <p>该方法通过 JNI 调用本地函数获取消息中的指定成员,并返回其字符串值。</p>
*
* @param message 输入的消息字符串,通常是 Frida 的 JSON 格式的响应消息。
* @param member 要获取的成员名称。
* @return 返回指定成员的字符串值。
*/
native static String getStringMember(String message, String member);
}

View File

@@ -0,0 +1,8 @@
package org.tzd.frida.windows;
/**
* @author tzdwindows 7
*/
public interface FridaRunnable {
void run(Frida frida);
}

View File

@@ -0,0 +1,62 @@
package org.tzd.frida.windows;
/**
* FridaThread 类继承自 {@link Thread},用于封装与 Frida 相关的线程操作。
* <p>此类用于创建并启动线程,以便在新的线程中执行与 Frida 相关的任务。</p>
* <p>它允许在启动线程之前执行额外的操作,例如调用 `FridaRunnable` 的 `run` 方法来配置与 Frida 的交互。</p>
*
* @author tzdwindows 7
*/
public class FridaThread extends Thread {
private boolean isStart = false; // 用于标记线程是否已配置正确
private final Frida frida; // 与线程相关联的 Frida 实例
/**
* 构造一个新的 FridaThread 实例。
* <p>该构造函数接受一个任务和一个 Frida 实例,创建一个线程并传入任务。</p>
*
* @param task 线程执行的任务,类型为 {@link Runnable}。
* @param frida 与该线程关联的 {@link Frida} 实例。
*/
public FridaThread(Runnable task, Frida frida) {
super(task); // 调用父类构造器
this.frida = frida;
setName("Frida Thread"); // 设置线程名称
}
/**
* 执行与 Frida 相关的额外任务。
* <p>此方法会执行传入的 {@link FridaRunnable} 任务,并传入当前的 Frida 实例。</p>
*
* @param runnable 执行任务的 {@link FridaRunnable} 实例。
* @return 返回当前的 {@link FridaThread} 实例,以便链式调用。
*/
public FridaThread execute(FridaRunnable runnable) {
runnable.run(frida); // 执行任务
isStart = true; // 标记线程配置完成
return this; // 返回当前线程实例
}
/**
* 设置线程是否已经开始执行。
* <p>此方法可用于手动控制线程的启动配置。</p>
*
* @param start 设置线程是否已配置完成。
*/
public void setStart(boolean start) {
isStart = start;
}
/**
* 启动线程。
* <p>重写了 `Thread` 类的 `start()` 方法,首先检查线程是否已正确配置。</p>
* <p>如果未正确配置,则抛出一个运行时异常,避免线程未准备好就启动。</p>
*/
@Override
public void start() {
if (!isStart) {
throw new RuntimeException("Basic information is not configured");
}
super.start(); // 调用父类的 `start()` 方法启动线程
}
}

View File

@@ -0,0 +1,31 @@
package org.tzd.frida.windows;
/**
* 当 JavaScript 代码执行或语法出错时抛出此异常。
* <p>此异常用于处理与 JavaScript 代码相关的错误,例如代码执行失败或语法错误。</p>
* <p>通过该异常,程序能够捕获并处理 JavaScript 代码运行过程中可能出现的问题。</p>
*
* @author tzdwindows 7
* @since 1.0
* @version 1.0
*/
public class JsCodeError extends Exception {
/**
* 默认构造方法。
* <p>调用父类 {@link Exception} 的默认构造方法。</p>
*/
public JsCodeError() {
super();
}
/**
* 带有错误信息的构造方法。
* <p>使用传入的错误信息来初始化异常。</p>
*
* @param message 错误信息,用于描述异常的具体内容。
*/
public JsCodeError(String message) {
super(message); // 调用父类构造器,传入错误信息
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB