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) {}
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/axis/innovators/box/tools/FolderCreator.java b/src/main/java/com/axis/innovators/box/tools/FolderCreator.java
new file mode 100644
index 0000000..fed0a10
--- /dev/null
+++ b/src/main/java/com/axis/innovators/box/tools/FolderCreator.java
@@ -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();
+ }
+}
diff --git a/src/main/java/com/axis/innovators/box/tools/LibraryLoad.java b/src/main/java/com/axis/innovators/box/tools/LibraryLoad.java
new file mode 100644
index 0000000..ce3aab8
--- /dev/null
+++ b/src/main/java/com/axis/innovators/box/tools/LibraryLoad.java
@@ -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;
+ }
+ }
+}
diff --git a/src/main/java/org/tzd/frida/Main.java b/src/main/java/org/tzd/frida/Main.java
new file mode 100644
index 0000000..1c53626
--- /dev/null
+++ b/src/main/java/org/tzd/frida/Main.java
@@ -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 注入操作。
+ *
+ * 此类主要包含一个入口方法 main,用于加载必要的本地库并初始化 Frida 对象。
+ * 它会通过调用 getProcessPid 方法获取指定进程的 PID,并将 JavaScript 代码注入到目标进程中。
+ *
+ * @author tzdwindows 7
+ */
+public class Main {
+
+ /**
+ * 程序入口方法。
+ *
+ * 此方法加载本地 DLL 库并创建一个 Frida 实例。接着通过 run 和 execute 方法执行指定的任务。
+ * 执行期间,会将回调函数添加到 Frida 实例中,接收并打印消息。
+ *
+ * @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。
+ *
+ * 此方法通过运行 Windows 命令 tasklist 获取系统中所有正在运行的进程,并查找指定进程名。
+ * 一旦找到匹配的进程,它将提取进程的 PID 并返回。
+ *
+ * @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;
+ }
+}
diff --git a/src/main/java/org/tzd/frida/windows/CallbackMessage.java b/src/main/java/org/tzd/frida/windows/CallbackMessage.java
new file mode 100644
index 0000000..b10dd4b
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/CallbackMessage.java
@@ -0,0 +1,12 @@
+package org.tzd.frida.windows;
+
+/**
+ * @author tzdwindows 7
+ */
+public interface CallbackMessage {
+ /**
+ * 回调消息
+ * @param message 消息
+ */
+ void onMessage(String message);
+}
diff --git a/src/main/java/org/tzd/frida/windows/Frida.java b/src/main/java/org/tzd/frida/windows/Frida.java
new file mode 100644
index 0000000..2fccbfe
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/Frida.java
@@ -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;
+
+ /**
+ * 构造一个新的 Frida 实例。
+ *
+ * @param jsCode 需要注入的 JavaScript 代码。
+ * @param pid 目标进程的进程ID。
+ *
+ * 此构造函数用于初始化一个新的 Frida 对象,指定要注入的 JavaScript 代码及目标进程ID。
+ */
+ public Frida(String jsCode, long pid) {
+ this.jsCode = jsCode;
+ this.pid = pid;
+ isRunning = false;
+ }
+
+ /**
+ * 启动并返回一个新的线程,用于执行JavaScript注入。
+ *
+ * @return 返回一个线程管理类 FridaThread,方便对线程进行统一管理。
+ *
+ * 该方法的工作流程如下:
+ *
+ * - new FridaThread(() -> { ... }): 创建一个新的线程,该线程执行 JavaScript 注入操作。线程内部会设置
isRunning = true 并调用 Frida0.injection(jsCode, this) 来注入 JavaScript 代码。
+ *
+ *
+ * 示例用法:
+ *
+ * FridaThread thread = frida.run();
+ * thread.setStart(true)
+ * thread.start(); // 启动线程
+ *
+ */
+ public FridaThread run() {
+ thread = new FridaThread(() -> {
+ isRunning = true;
+ Frida0.injection(jsCode,this);
+ },this);
+ return thread;
+ }
+
+ /**
+ * 启动并返回一个新的线程,用于执行JavaScript注入。
+ *
+ * @param callback 在循环中的回调函数
+ * @return 一个线程管理类,方便对线程进行统一管理
+ *
+ * 该方法的工作流程如下:
+ *
+ * run(Runnable... callback): 首先创建一个新的 FridaThread,并传入一个 Runnable 任务,任务会在新线程中执行。任务内会调用 Frida0.injection(jsCode, this, callback),注入并执行 JavaScript 代码。
+ * execute(FridaRunnable runnable): execute 方法允许你定义在 FridaThread 中执行的额外任务。FridaRunnable 接口的 run 方法会被调用,允许你与 Frida 对象交互,添加回调消息或其他操作。
+ * start(): 启动线程,执行上述所有任务。
+ *
+ *
+ * 示例用法:
+ *
+ * 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(); // 启动线程
+ *
+ *
+ * 在这个示例中,run() 方法首先创建并配置一个新的线程,execute() 方法为线程添加了一个回调函数,接收到消息时会触发该回调函数。最后,调用 start() 启动线程的执行。
+ * 当然你如果非要在FridaThread中直接使用start,而不经过execute的话我们会抛出异常 throw new RuntimeException("Basic information is not configured");
+ */
+ public FridaThread run(Runnable... callback) {
+ thread = new FridaThread(() -> {
+ isRunning = true;
+ Frida0.injection(jsCode, this, callback);
+ }, this);
+ return thread;
+ }
+
+ /**
+ * 将回调消息添加到消息列表中。
+ *
+ * @param callbackMessage 要添加的回调消息对象。
+ *
+ * 此方法会将传入的 callbackMessage 对象添加到 Frida0.CALLBACK_MESSAGE_LIST 中。
+ */
+ public void addCallbackMessage(CallbackMessage callbackMessage) {
+ Frida0.CALLBACK_MESSAGE_LIST.add(callbackMessage);
+ }
+
+ /**
+ * 从消息列表中移除指定的回调消息。
+ *
+ * @param callbackMessage 要移除的回调消息对象。
+ *
+ * 此方法会将传入的 callbackMessage 对象从 Frida0.CALLBACK_MESSAGE_LIST 中移除。
+ */
+ public void clearCallbackMessage(CallbackMessage callbackMessage) {
+ Frida0.CALLBACK_MESSAGE_LIST.remove(callbackMessage);
+ }
+
+ /**
+ * 清空所有回调消息。
+ *
+ * 此方法会清空 Frida0.CALLBACK_MESSAGE_LIST 中的所有回调消息。
+ */
+ public void clearCallbackMessage() {
+ Frida0.CALLBACK_MESSAGE_LIST.clear();
+ }
+}
diff --git a/src/main/java/org/tzd/frida/windows/Frida0.java b/src/main/java/org/tzd/frida/windows/Frida0.java
new file mode 100644
index 0000000..cd4b551
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/Frida0.java
@@ -0,0 +1,85 @@
+package org.tzd.frida.windows;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Frida0 类用于处理 Frida 注入相关的操作和消息传递。
+ *
+ * 此类包括注入 JavaScript 代码到目标进程、消息的发送与接收处理等功能。
+ * 通过该类,用户可以与 Frida 注入的进程进行交互,并通过回调函数获取日志或错误信息。
+ *
+ * @author tzdwindows 7
+ */
+public class Frida0 {
+
+ // 存储回调消息的列表
+ static final List CALLBACK_MESSAGE_LIST = new ArrayList<>();
+
+ /**
+ * 注入 JavaScript 代码到指定的 Frida 实例,并执行回调任务。
+ *
+ * 该方法调用本地代码注入 JavaScript,并执行传入的回调函数。在 Frida 进程运行期间,回调函数将不断被执行。
+ * 方法会在 Frida 进程完成后释放资源,并设置 Frida 的运行状态为 `false`。
+ *
+ * @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;
+ }
+
+ /**
+ * 发送消息给所有已注册的回调消息对象。
+ *
+ * 此方法会遍历 CALLBACK_MESSAGE_LIST 列表,并触发每个回调对象的 onMessage 方法。
+ *
+ * @param message 需要发送的消息内容。
+ */
+ private static void sendMessage(String message) {
+ CALLBACK_MESSAGE_LIST.forEach(callbackMessage -> callbackMessage.onMessage(message));
+ }
+
+ /**
+ * 处理接收到的消息,并根据消息类型做出响应。
+ *
+ * 根据消息中的 `type` 字段,如果是 `error` 类型,抛出运行时异常;如果是 `log` 类型,打印日志。
+ * 其他类型的消息直接通过回调发送。
+ *
+ * @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);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/tzd/frida/windows/FridaJsInjector.java b/src/main/java/org/tzd/frida/windows/FridaJsInjector.java
new file mode 100644
index 0000000..7681d36
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/FridaJsInjector.java
@@ -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 代码。
+ * 此类提供了一个方法,允许通过读取指定的 JS 文件,并将其中的代码注入到指定的进程中。
+ * 如果注入过程中发生错误,类会抛出相应的异常。
+ *
+ * @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 代码。
+ * 该方法会使用 Frida 将 JavaScript 代码注入到指定的目标进程,并执行相关操作。
+ * 方法会启动一个线程,并在该线程中执行注入操作。可以通过提供回调函数来接收注入过程中的消息。
+ * 此方法会检查 Frida 实例是否已经初始化,并在初始化完成后执行 JavaScript 注入。
+ *
+ * @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);
+ }
+ });
+ }
+}
diff --git a/src/main/java/org/tzd/frida/windows/FridaNative.java b/src/main/java/org/tzd/frida/windows/FridaNative.java
new file mode 100644
index 0000000..96ed750
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/FridaNative.java
@@ -0,0 +1,54 @@
+package org.tzd.frida.windows;
+
+/**
+ * FridaNative 类封装了与本地 Frida 库的交互方法。
+ * 该类提供了几个静态本地方法,用于将 JavaScript 代码注入到目标进程并进行管理。
+ * 所有方法都通过 JNI 调用本地代码实现与 Frida 库的交互。
+ */
+public class FridaNative {
+
+ /**
+ * 使用 Frida 将 JavaScript 代码注入到指定进程。
+ *
+ * 该方法通过 JNI 调用本地 Frida 函数,将 JavaScript 代码注入到指定的进程中。
+ *
+ * @param pid 目标进程的 PID,通常是目标程序的进程 ID(例如,QQ 进程)。
+ * @param jsCode 要注入的 JavaScript 代码字符串。
+ * @return 返回注入是否成功,成功返回 `true`,失败返回 `false`。
+ */
+ native static boolean injection(long pid, String jsCode);
+
+ /**
+ * 更新 Frida 的状态,保持与注入进程的交互。
+ * 此方法调用本地 Frida 函数以保持与注入的进程进行通信和交互。
+ *
+ * @return 返回更新是否成功,成功返回 `true`,失败返回 `false`。
+ */
+ native static boolean update();
+
+ /**
+ * 判断 Frida 是否正在运行。
+ * 此方法用于检查 Frida 是否正在执行并保持与目标进程的交互。
+ *
+ * @return 如果 Frida 正在运行,返回 `true`,否则返回 `false`。
+ */
+ native static boolean isRunning();
+
+ /**
+ * 释放 Frida 的资源。
+ * 该方法调用本地函数释放与 Frida 进程的所有资源。
+ *
+ * @return 如果资源释放成功,返回 `true`,否则返回 `false`。
+ */
+ native static boolean release();
+
+ /**
+ * 从消息中提取指定的字符串成员。
+ * 该方法通过 JNI 调用本地函数获取消息中的指定成员,并返回其字符串值。
+ *
+ * @param message 输入的消息字符串,通常是 Frida 的 JSON 格式的响应消息。
+ * @param member 要获取的成员名称。
+ * @return 返回指定成员的字符串值。
+ */
+ native static String getStringMember(String message, String member);
+}
diff --git a/src/main/java/org/tzd/frida/windows/FridaRunnable.java b/src/main/java/org/tzd/frida/windows/FridaRunnable.java
new file mode 100644
index 0000000..c2142e2
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/FridaRunnable.java
@@ -0,0 +1,8 @@
+package org.tzd.frida.windows;
+
+/**
+ * @author tzdwindows 7
+ */
+public interface FridaRunnable {
+ void run(Frida frida);
+}
diff --git a/src/main/java/org/tzd/frida/windows/FridaThread.java b/src/main/java/org/tzd/frida/windows/FridaThread.java
new file mode 100644
index 0000000..18ec54c
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/FridaThread.java
@@ -0,0 +1,62 @@
+package org.tzd.frida.windows;
+
+/**
+ * FridaThread 类继承自 {@link Thread},用于封装与 Frida 相关的线程操作。
+ * 此类用于创建并启动线程,以便在新的线程中执行与 Frida 相关的任务。
+ * 它允许在启动线程之前执行额外的操作,例如调用 `FridaRunnable` 的 `run` 方法来配置与 Frida 的交互。
+ *
+ * @author tzdwindows 7
+ */
+public class FridaThread extends Thread {
+ private boolean isStart = false; // 用于标记线程是否已配置正确
+ private final Frida frida; // 与线程相关联的 Frida 实例
+
+ /**
+ * 构造一个新的 FridaThread 实例。
+ * 该构造函数接受一个任务和一个 Frida 实例,创建一个线程并传入任务。
+ *
+ * @param task 线程执行的任务,类型为 {@link Runnable}。
+ * @param frida 与该线程关联的 {@link Frida} 实例。
+ */
+ public FridaThread(Runnable task, Frida frida) {
+ super(task); // 调用父类构造器
+ this.frida = frida;
+ setName("Frida Thread"); // 设置线程名称
+ }
+
+ /**
+ * 执行与 Frida 相关的额外任务。
+ * 此方法会执行传入的 {@link FridaRunnable} 任务,并传入当前的 Frida 实例。
+ *
+ * @param runnable 执行任务的 {@link FridaRunnable} 实例。
+ * @return 返回当前的 {@link FridaThread} 实例,以便链式调用。
+ */
+ public FridaThread execute(FridaRunnable runnable) {
+ runnable.run(frida); // 执行任务
+ isStart = true; // 标记线程配置完成
+ return this; // 返回当前线程实例
+ }
+
+ /**
+ * 设置线程是否已经开始执行。
+ * 此方法可用于手动控制线程的启动配置。
+ *
+ * @param start 设置线程是否已配置完成。
+ */
+ public void setStart(boolean start) {
+ isStart = start;
+ }
+
+ /**
+ * 启动线程。
+ * 重写了 `Thread` 类的 `start()` 方法,首先检查线程是否已正确配置。
+ * 如果未正确配置,则抛出一个运行时异常,避免线程未准备好就启动。
+ */
+ @Override
+ public void start() {
+ if (!isStart) {
+ throw new RuntimeException("Basic information is not configured");
+ }
+ super.start(); // 调用父类的 `start()` 方法启动线程
+ }
+}
diff --git a/src/main/java/org/tzd/frida/windows/JsCodeError.java b/src/main/java/org/tzd/frida/windows/JsCodeError.java
new file mode 100644
index 0000000..6f14c84
--- /dev/null
+++ b/src/main/java/org/tzd/frida/windows/JsCodeError.java
@@ -0,0 +1,31 @@
+package org.tzd.frida.windows;
+
+/**
+ * 当 JavaScript 代码执行或语法出错时抛出此异常。
+ * 此异常用于处理与 JavaScript 代码相关的错误,例如代码执行失败或语法错误。
+ * 通过该异常,程序能够捕获并处理 JavaScript 代码运行过程中可能出现的问题。
+ *
+ * @author tzdwindows 7
+ * @since 1.0
+ * @version 1.0
+ */
+public class JsCodeError extends Exception {
+
+ /**
+ * 默认构造方法。
+ * 调用父类 {@link Exception} 的默认构造方法。
+ */
+ public JsCodeError() {
+ super();
+ }
+
+ /**
+ * 带有错误信息的构造方法。
+ * 使用传入的错误信息来初始化异常。
+ *
+ * @param message 错误信息,用于描述异常的具体内容。
+ */
+ public JsCodeError(String message) {
+ super(message); // 调用父类构造器,传入错误信息
+ }
+}
diff --git a/src/main/resources/icons/debug/debug.png b/src/main/resources/icons/debug/debug.png
new file mode 100644
index 0000000..f7f530f
Binary files /dev/null and b/src/main/resources/icons/debug/debug.png differ
diff --git a/src/main/resources/icons/debug/frida/frida_main.png b/src/main/resources/icons/debug/frida/frida_main.png
new file mode 100644
index 0000000..b64bc68
Binary files /dev/null and b/src/main/resources/icons/debug/frida/frida_main.png differ
diff --git a/src/main/resources/icons/logo.png b/src/main/resources/icons/logo.png
new file mode 100644
index 0000000..15d6b5d
Binary files /dev/null and b/src/main/resources/icons/logo.png differ
diff --git a/src/main/resources/icons/settings.png b/src/main/resources/icons/settings.png
new file mode 100644
index 0000000..cf964b3
Binary files /dev/null and b/src/main/resources/icons/settings.png differ
diff --git a/src/main/resources/icons/start_page.png b/src/main/resources/icons/start_page.png
new file mode 100644
index 0000000..80a8d1d
Binary files /dev/null and b/src/main/resources/icons/start_page.png differ