feat(gui): 重构 FridaWindow 界面并添加新功能- 重新设计了 FridaWindow 的布局和样式,增加了菜单栏和更多控件
- 添加了进程列表和搜索功能,支持双击注入进程 - 实现了暗黑主题和自定义样式,提升了用户体验 - 优化了代码结构,增加了可读性和可维护性
This commit is contained in:
@@ -31,7 +31,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
// mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -69,11 +69,12 @@ dependencies {
|
|||||||
implementation 'org.bitbucket.mstrobel:procyon-compilertools:0.5.36'
|
implementation 'org.bitbucket.mstrobel:procyon-compilertools:0.5.36'
|
||||||
|
|
||||||
// 必须的核心依赖
|
// 必须的核心依赖
|
||||||
implementation 'com.fifesoft:rsyntaxtextarea:3.3.1'
|
implementation 'com.fifesoft:rsyntaxtextarea:3.5.4'
|
||||||
implementation 'com.fifesoft:autocomplete:3.3.1'
|
|
||||||
|
|
||||||
// 可选UI增强
|
// 可选UI增强
|
||||||
implementation 'com.fifesoft:rstaui:3.3.1'
|
implementation 'com.fifesoft:rstaui:3.3.1'
|
||||||
|
implementation 'com.fifesoft:languagesupport:3.3.0'
|
||||||
|
implementation 'com.fifesoft:autocomplete:3.3.2'
|
||||||
|
|
||||||
implementation 'org.apache.commons:commons-compress:1.23.0'
|
implementation 'org.apache.commons:commons-compress:1.23.0'
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
|
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
|
||||||
|
|||||||
@@ -252,6 +252,12 @@ public class AxisInnovatorsBox {
|
|||||||
*/
|
*/
|
||||||
private void setTopic() {
|
private void setTopic() {
|
||||||
try {
|
try {
|
||||||
|
main.registrationTopic.addTopic(new com.formdev.flatlaf.FlatDarculaLaf(),
|
||||||
|
"Darcula主题",
|
||||||
|
"Darcula主题",
|
||||||
|
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||||
|
"system:darcula_theme");
|
||||||
|
|
||||||
main.registrationTopic.addTopic(UIManager.getSystemLookAndFeelClassName(),
|
main.registrationTopic.addTopic(UIManager.getSystemLookAndFeelClassName(),
|
||||||
LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"),
|
LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"),
|
||||||
LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"),
|
LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"),
|
||||||
@@ -277,13 +283,7 @@ public class AxisInnovatorsBox {
|
|||||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||||
"system:flatLightLaf_theme");
|
"system:flatLightLaf_theme");
|
||||||
|
|
||||||
main.registrationTopic.addTopic(new com.formdev.flatlaf.FlatDarculaLaf(),
|
UIManager.setLookAndFeel(new com.formdev.flatlaf.FlatDarculaLaf());
|
||||||
"Darcula主题",
|
|
||||||
"Darcula主题",
|
|
||||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
|
||||||
"system:darcula_theme");
|
|
||||||
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Failed to load the system facade class", e);
|
logger.warn("Failed to load the system facade class", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class FridaSyntax {
|
|||||||
|
|
||||||
public static void addBasicCompletions(DefaultCompletionProvider provider) {
|
public static void addBasicCompletions(DefaultCompletionProvider provider) {
|
||||||
String[] jsKeywords = {"function", "var", "let", "const", "if", "else",
|
String[] jsKeywords = {"function", "var", "let", "const", "if", "else",
|
||||||
"for", "while(/* logic */)", "try", "catch", "true", "false","()", "for (int i = 0; i < ; i++) {\n" +
|
"for", "while(/* logic */)", "try", "catch", "true", "false","()", "for (var i = 0; i < ; i++) {\n" +
|
||||||
" \n" +
|
" \n" +
|
||||||
"}"};
|
"}"};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ package com.axis.innovators.box.gui;
|
|||||||
import com.axis.innovators.box.gui.renderer.DarculaCompletionCellRenderer;
|
import com.axis.innovators.box.gui.renderer.DarculaCompletionCellRenderer;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.fife.rsta.ac.LanguageSupport;
|
||||||
|
import org.fife.rsta.ac.LanguageSupportFactory;
|
||||||
|
import org.fife.rsta.ac.perl.PerlLanguageSupport;
|
||||||
import org.fife.ui.autocomplete.*;
|
import org.fife.ui.autocomplete.*;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.folding.CurlyFoldParser;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
|
||||||
import org.tzd.frida.windows.Frida;
|
import org.tzd.frida.windows.Frida;
|
||||||
|
|
||||||
import org.fife.ui.rsyntaxtextarea.*;
|
import org.fife.ui.rsyntaxtextarea.*;
|
||||||
@@ -11,14 +16,12 @@ import org.fife.ui.rtextarea.RTextScrollPane;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
import javax.swing.event.DocumentListener;
|
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -32,12 +35,11 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
private static final Logger logger = LogManager.getLogger(FridaWindow.class);
|
private static final Logger logger = LogManager.getLogger(FridaWindow.class);
|
||||||
private RSyntaxTextArea scriptArea;
|
private RSyntaxTextArea scriptArea;
|
||||||
private JTextArea logArea;
|
private JTextArea logArea;
|
||||||
private JTextField pidField;
|
|
||||||
private boolean isRepetition = false;
|
private boolean isRepetition = false;
|
||||||
|
private JComboBox<ProcessInfo> processCombo;
|
||||||
|
private JTextField pidField;
|
||||||
// IDEA风格配色
|
// IDEA风格配色
|
||||||
private static final Color BACKGROUND = new Color(0x2B2B2B);
|
private static final Color BACKGROUND = new Color(0x2B2B2B);
|
||||||
private static final Color FOREGROUND = new Color(0xBBBBBB);
|
|
||||||
private static final Color SELECTION_COLOR = new Color(0x214283);
|
private static final Color SELECTION_COLOR = new Color(0x214283);
|
||||||
|
|
||||||
public FridaWindow(Window owner) {
|
public FridaWindow(Window owner) {
|
||||||
@@ -45,6 +47,14 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
initUI();
|
initUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
Font chineseFont = new Font("Microsoft YaHei", Font.PLAIN, 13);
|
||||||
|
UIManager.put("Menu.font", chineseFont);
|
||||||
|
UIManager.put("MenuItem.font", chineseFont);
|
||||||
|
UIManager.put("Button.font", chineseFont);
|
||||||
|
UIManager.put("ComboBox.font", chineseFont);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initUI() {
|
public void initUI() {
|
||||||
super.initUI();
|
super.initUI();
|
||||||
@@ -56,6 +66,10 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
mainPanel.setBackground(BACKGROUND);
|
mainPanel.setBackground(BACKGROUND);
|
||||||
|
|
||||||
|
pidField = new JTextField();
|
||||||
|
styleTextField(pidField, "输入PID或进程名");
|
||||||
|
mainPanel.add(pidField, BorderLayout.CENTER);
|
||||||
|
|
||||||
// 输入面板
|
// 输入面板
|
||||||
JPanel inputPanel = createInputPanel();
|
JPanel inputPanel = createInputPanel();
|
||||||
mainPanel.add(inputPanel, BorderLayout.NORTH);
|
mainPanel.add(inputPanel, BorderLayout.NORTH);
|
||||||
@@ -74,7 +88,7 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
centerSplit.setBottomComponent(logPanel);
|
centerSplit.setBottomComponent(logPanel);
|
||||||
|
|
||||||
mainPanel.add(centerSplit, BorderLayout.CENTER);
|
mainPanel.add(centerSplit, BorderLayout.CENTER);
|
||||||
|
createMenuBar();
|
||||||
setContentPane(mainPanel);
|
setContentPane(mainPanel);
|
||||||
|
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
@@ -85,41 +99,186 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void styleTextField(JTextField field, String placeholder) {
|
||||||
|
field.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||||
|
field.setBackground(new Color(0x3C3F41));
|
||||||
|
field.setForeground(Color.WHITE);
|
||||||
|
field.setBorder(BorderFactory.createCompoundBorder(
|
||||||
|
BorderFactory.createLineBorder(new Color(0x515658)),
|
||||||
|
BorderFactory.createEmptyBorder(5, 8, 5, 8)
|
||||||
|
));
|
||||||
|
field.putClientProperty("JTextField.placeholderText", placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
private JPanel createInputPanel() {
|
private JPanel createInputPanel() {
|
||||||
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
|
JPanel panel = new JPanel(new BorderLayout(10, 0));
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||||
panel.setOpaque(false);
|
panel.setOpaque(false);
|
||||||
|
|
||||||
pidField = new JTextField(20);
|
// 进程组合框
|
||||||
styleTextField(pidField, "输入进程ID或选择进程...");
|
processCombo = new JComboBox<>();
|
||||||
|
styleComboBox(processCombo);
|
||||||
|
|
||||||
JButton browseButton = new JButton("选择进程");
|
// 操作工具栏
|
||||||
styleButton(browseButton, new Color(65, 131, 215));
|
JPanel controlPanel = new JPanel(new GridLayout(1, 2, 8, 0));
|
||||||
browseButton.addActionListener(this::openProcessSelectionWindow);
|
controlPanel.setOpaque(false);
|
||||||
|
|
||||||
JButton injectButton = new JButton("注入脚本");
|
JButton injectBtn = createModernButton(language.getText("fridaWindow.button.inject"), 0x6897BB);
|
||||||
styleButton(injectButton, new Color(215, 65, 65));
|
JButton stopBtn = createModernButton(language.getText("fridaWindow.button.inject.pid"), 0xD25252);
|
||||||
injectButton.addActionListener(this::handleInject);
|
|
||||||
|
|
||||||
panel.add(new JLabel("目标进程:"));
|
injectBtn.addActionListener(this::handleInject);
|
||||||
panel.add(pidField);
|
stopBtn.addActionListener(this::openProcessSelectionWindow);
|
||||||
panel.add(browseButton);
|
|
||||||
panel.add(injectButton);
|
controlPanel.add(injectBtn);
|
||||||
|
controlPanel.add(stopBtn);
|
||||||
|
|
||||||
|
panel.add(processCombo, BorderLayout.CENTER);
|
||||||
|
panel.add(controlPanel, BorderLayout.EAST);
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JButton createModernButton(String text, int color) {
|
||||||
|
JButton btn = new JButton(text);
|
||||||
|
btn.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||||
|
btn.setFocusPainted(false);
|
||||||
|
btn.setBackground(new Color(color));
|
||||||
|
btn.setForeground(Color.WHITE);
|
||||||
|
btn.setBorder(BorderFactory.createCompoundBorder(
|
||||||
|
BorderFactory.createLineBorder(new Color(color).darker(), 1),
|
||||||
|
BorderFactory.createEmptyBorder(6, 15, 6, 15)
|
||||||
|
));
|
||||||
|
|
||||||
|
// 悬停效果
|
||||||
|
btn.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseEntered(MouseEvent e) {
|
||||||
|
btn.setBackground(new Color(color).brighter());
|
||||||
|
}
|
||||||
|
public void mouseExited(MouseEvent e) {
|
||||||
|
btn.setBackground(new Color(color));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleComboBox(JComboBox<?> combo) {
|
||||||
|
combo.setRenderer(new DefaultListCellRenderer() {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList<?> list, Object value,
|
||||||
|
int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
|
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
setBackground(isSelected ? new Color(0x214283) : new Color(0x3C3F41));
|
||||||
|
setForeground(Color.WHITE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMenuBar() {
|
||||||
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
// 菜单栏深色背景
|
||||||
|
menuBar.setBackground(new Color(0x3C3F41));
|
||||||
|
menuBar.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0));
|
||||||
|
|
||||||
|
// 统一设置菜单UI属性
|
||||||
|
UIManager.put("Menu.background", new Color(0x3C3F41));
|
||||||
|
UIManager.put("Menu.foreground", new Color(0xBBBBBB));
|
||||||
|
UIManager.put("MenuItem.background", new Color(0x3C3F41));
|
||||||
|
UIManager.put("MenuItem.foreground", new Color(0xBBBBBB));
|
||||||
|
UIManager.put("MenuItem.selectionBackground", new Color(0x214283));
|
||||||
|
|
||||||
|
// 文件菜单
|
||||||
|
JMenu fileMenu = new JMenu(language.getText("fridaWindow.menu"));
|
||||||
|
styleMenu(fileMenu);
|
||||||
|
|
||||||
|
// 退出菜单项
|
||||||
|
JMenuItem exitItem = new JMenuItem(language.getText("fridaWindow.menu.exit"));
|
||||||
|
styleMenuItem(exitItem);
|
||||||
|
exitItem.addActionListener(e -> dispose());
|
||||||
|
|
||||||
|
// 帮助菜单
|
||||||
|
JMenu helpMenu = new JMenu(language.getText("fridaWindow.menu.help"));
|
||||||
|
styleMenu(helpMenu);
|
||||||
|
|
||||||
|
// 关于菜单项
|
||||||
|
JMenuItem aboutItem = new JMenuItem(language.getText("fridaWindow.menu.help.about"));
|
||||||
|
styleMenuItem(aboutItem);
|
||||||
|
aboutItem.addActionListener(e -> showAboutDialog());
|
||||||
|
|
||||||
|
menuBar.add(fileMenu);
|
||||||
|
menuBar.add(helpMenu);
|
||||||
|
setJMenuBar(menuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleMenu(JMenu menu) {
|
||||||
|
menu.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||||
|
menu.setForeground(new Color(0xBBBBBB));
|
||||||
|
menu.setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
|
||||||
|
menu.setOpaque(true);
|
||||||
|
menu.setBackground(new Color(0x3C3F41));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleMenuItem(JMenuItem item) {
|
||||||
|
item.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||||
|
item.setForeground(new Color(0xBBBBBB));
|
||||||
|
item.setBackground(new Color(0x3C3F41));
|
||||||
|
item.setBorder(BorderFactory.createEmptyBorder(5, 20, 5, 10)); // 增加左侧间距
|
||||||
|
item.setOpaque(true);
|
||||||
|
|
||||||
|
// 鼠标悬停效果
|
||||||
|
item.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseEntered(MouseEvent e) {
|
||||||
|
item.setBackground(new Color(0x515658));
|
||||||
|
}
|
||||||
|
public void mouseExited(MouseEvent e) {
|
||||||
|
item.setBackground(new Color(0x3C3F41));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAboutDialog() {
|
||||||
|
JDialog aboutDialog = new JDialog(this, "关于", true);
|
||||||
|
aboutDialog.setSize(300, 200);
|
||||||
|
aboutDialog.setLocationRelativeTo(this);
|
||||||
|
|
||||||
|
JPanel content = new JPanel(new BorderLayout());
|
||||||
|
content.setBorder(new EmptyBorder(20, 20, 20, 20));
|
||||||
|
|
||||||
|
JLabel title = new JLabel("Frida Injector v2.0");
|
||||||
|
title.setFont(new Font("Segoe UI", Font.BOLD, 16));
|
||||||
|
|
||||||
|
JTextArea info = new JTextArea("基于Frida的现代注入工具\n\nCopyright ? 2024");
|
||||||
|
info.setEditable(false);
|
||||||
|
|
||||||
|
content.add(title, BorderLayout.NORTH);
|
||||||
|
content.add(info, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
aboutDialog.setContentPane(content);
|
||||||
|
aboutDialog.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
private JPanel createScriptPanel() {
|
private JPanel createScriptPanel() {
|
||||||
JPanel panel = new JPanel(new BorderLayout());
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
panel.setBorder(BorderFactory.createTitledBorder("Frida脚本编辑器"));
|
panel.setBorder(BorderFactory.createTitledBorder("Frida脚本编辑器"));
|
||||||
|
|
||||||
scriptArea = new RSyntaxTextArea();
|
scriptArea = new RSyntaxTextArea();
|
||||||
scriptArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
|
LanguageSupportFactory lsf = LanguageSupportFactory.get();
|
||||||
|
LanguageSupport support = lsf.
|
||||||
|
getSupportFor(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
|
||||||
|
support.install(scriptArea);
|
||||||
|
|
||||||
scriptArea.setCodeFoldingEnabled(true);
|
scriptArea.setCodeFoldingEnabled(true);
|
||||||
|
FoldParserManager.get().addFoldParserMapping("text/javascript", new CurlyFoldParser());
|
||||||
|
|
||||||
|
scriptArea.setFractionalFontMetricsEnabled(true);
|
||||||
|
scriptArea.setAutoIndentEnabled(true);
|
||||||
|
|
||||||
|
scriptArea.setCodeFoldingEnabled(true);
|
||||||
|
scriptArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
|
||||||
scriptArea.setAntiAliasingEnabled(true);
|
scriptArea.setAntiAliasingEnabled(true);
|
||||||
scriptArea.setTabSize(4);
|
scriptArea.setTabSize(4);
|
||||||
scriptArea.setCaretPosition(0);
|
scriptArea.setCaretPosition(0);
|
||||||
scriptArea.setSelectionColor(SELECTION_COLOR);
|
scriptArea.setSelectionColor(SELECTION_COLOR);
|
||||||
scriptArea.setCurrentLineHighlightColor(new Color(0x323232));
|
|
||||||
scriptArea.setMarkOccurrences(true);
|
scriptArea.setMarkOccurrences(true);
|
||||||
scriptArea.setBracketMatchingEnabled(true);
|
scriptArea.setBracketMatchingEnabled(true);
|
||||||
setupAutoCompletion();
|
setupAutoCompletion();
|
||||||
@@ -131,7 +290,6 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
scriptArea.setFont(ideaFont);
|
scriptArea.setFont(ideaFont);
|
||||||
|
|
||||||
scriptArea.setBackground(new Color(0x1E1F22));
|
scriptArea.setBackground(new Color(0x1E1F22));
|
||||||
//codeArea.setForeground(new Color(0xBBBBBB));
|
|
||||||
scriptArea.setSelectionColor(new Color(0x214283));
|
scriptArea.setSelectionColor(new Color(0x214283));
|
||||||
scriptArea.setCurrentLineHighlightColor(new Color(0x323232));
|
scriptArea.setCurrentLineHighlightColor(new Color(0x323232));
|
||||||
|
|
||||||
@@ -158,6 +316,11 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
defaultStyle.foreground = foreground;
|
defaultStyle.foreground = foreground;
|
||||||
defaultStyle.background = background;
|
defaultStyle.background = background;
|
||||||
|
|
||||||
|
// ======== JavaScript 标准库配置 ========
|
||||||
|
// console 相关 API
|
||||||
|
setTokenStyle(scheme, Token.RESERVED_WORD_2, 0xCC7832); // 橙色
|
||||||
|
setTokenStyle(scheme, Token.FUNCTION, 0xFFC66D); // 黄色
|
||||||
|
|
||||||
// ======== Frida 关键字和 API 配置 ========
|
// ======== Frida 关键字和 API 配置 ========
|
||||||
// Frida 关键字(如 Java.perform, Interceptor.attach 等)
|
// Frida 关键字(如 Java.perform, Interceptor.attach 等)
|
||||||
setTokenStyle(scheme, Token.RESERVED_WORD, 0xCC7832); // 橙色
|
setTokenStyle(scheme, Token.RESERVED_WORD, 0xCC7832); // 橙色
|
||||||
@@ -188,16 +351,6 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
// 正则表达式
|
// 正则表达式
|
||||||
setTokenStyle(scheme, Token.REGEX, 0xD25252); // 红色
|
setTokenStyle(scheme, Token.REGEX, 0xD25252); // 红色
|
||||||
|
|
||||||
// ======== Frida 特有 API 配置 ========
|
|
||||||
// Java 相关 API
|
|
||||||
setTokenStyle(scheme, Token.RESERVED_WORD_2, 0xCC7832); // 橙色
|
|
||||||
|
|
||||||
// 内存操作 API
|
|
||||||
setTokenStyle(scheme, Token.DATA_TYPE, 0xE8BF6A); // 浅黄色
|
|
||||||
|
|
||||||
// 拦截器相关 API
|
|
||||||
setTokenStyle(scheme, Token.ANNOTATION, 0xBBB529); // 黄色
|
|
||||||
|
|
||||||
// ======== 跨语言通用配置 ========
|
// ======== 跨语言通用配置 ========
|
||||||
// XML/HTML 标签(如果有需要)
|
// XML/HTML 标签(如果有需要)
|
||||||
setTokenStyle(scheme, Token.MARKUP_TAG_NAME, 0xE8BF6A); // 浅黄色
|
setTokenStyle(scheme, Token.MARKUP_TAG_NAME, 0xE8BF6A); // 浅黄色
|
||||||
@@ -211,6 +364,7 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
return scheme;
|
return scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setTokenStyle(SyntaxScheme scheme, int tokenType, int rgb) {
|
private void setTokenStyle(SyntaxScheme scheme, int tokenType, int rgb) {
|
||||||
Style style = scheme.getStyle(tokenType);
|
Style style = scheme.getStyle(tokenType);
|
||||||
style.foreground = new Color(rgb);
|
style.foreground = new Color(rgb);
|
||||||
@@ -238,7 +392,6 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
CompletionProvider provider = createCompletionProvider();
|
CompletionProvider provider = createCompletionProvider();
|
||||||
AutoCompletion ac = new AutoCompletion(provider);
|
AutoCompletion ac = new AutoCompletion(provider);
|
||||||
|
|
||||||
// 关键配置
|
|
||||||
ac.setAutoActivationEnabled(true);
|
ac.setAutoActivationEnabled(true);
|
||||||
ac.setParameterAssistanceEnabled(true);
|
ac.setParameterAssistanceEnabled(true);
|
||||||
ac.setShowDescWindow(true);
|
ac.setShowDescWindow(true);
|
||||||
@@ -246,7 +399,6 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
|
|
||||||
ac.install(scriptArea);
|
ac.install(scriptArea);
|
||||||
ac.setDescriptionWindowColor(new Color(0x323232));
|
ac.setDescriptionWindowColor(new Color(0x323232));
|
||||||
//ac.setChoicesWindowSize(386,200);
|
|
||||||
scriptArea.addKeyListener(new KeyAdapter() {
|
scriptArea.addKeyListener(new KeyAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void keyTyped(KeyEvent e) {
|
public void keyTyped(KeyEvent e) {
|
||||||
@@ -268,33 +420,10 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void styleTextField(JTextField field, String placeholder) {
|
|
||||||
field.setFont(new Font("JetBrains Mono", Font.PLAIN, 14));
|
|
||||||
field.setBackground(new Color(0x3C3F41));
|
|
||||||
field.setForeground(Color.WHITE);
|
|
||||||
field.setBorder(BorderFactory.createCompoundBorder(
|
|
||||||
BorderFactory.createLineBorder(new Color(0x515658)),
|
|
||||||
BorderFactory.createEmptyBorder(5, 8, 5, 8)
|
|
||||||
));
|
|
||||||
field.putClientProperty("JTextField.placeholderText", placeholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void styleButton(JButton button, Color bgColor) {
|
|
||||||
button.setFont(new Font("Segoe UI", Font.PLAIN, 13));
|
|
||||||
button.setFocusPainted(false);
|
|
||||||
button.setBackground(bgColor);
|
|
||||||
button.setForeground(Color.WHITE);
|
|
||||||
button.setBorder(BorderFactory.createCompoundBorder(
|
|
||||||
BorderFactory.createLineBorder(bgColor.darker()),
|
|
||||||
BorderFactory.createEmptyBorder(5, 15, 5, 15)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleInject(ActionEvent e) {
|
private void handleInject(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
long pid = Long.parseLong(pidField.getText());
|
long pid = Long.parseLong(pidField.getText());
|
||||||
String script = scriptArea.getText();
|
String script = scriptArea.getText();
|
||||||
|
|
||||||
Frida frida = new Frida(script, pid);
|
Frida frida = new Frida(script, pid);
|
||||||
if (!isRepetition) {
|
if (!isRepetition) {
|
||||||
try {
|
try {
|
||||||
@@ -341,67 +470,93 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeUI() {
|
private void initializeUI() {
|
||||||
JPanel panel = new JPanel();
|
JPanel panel = new JPanel(new BorderLayout(5, 5));
|
||||||
panel.setLayout(new BorderLayout());
|
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
panel.setBackground(new Color(0x2B2B2B));
|
||||||
|
|
||||||
// 获取所有进程信息
|
JTextField searchField = new JTextField(20);
|
||||||
processList = getProcesses();
|
styleSearchField(searchField);
|
||||||
|
|
||||||
// 创建搜索框
|
table = new JTable();
|
||||||
JPanel searchPanel = new JPanel();
|
table.setModel(createTableModel());
|
||||||
searchPanel.setLayout(new BorderLayout());
|
styleTable(table);
|
||||||
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(language.getText("fridaWindow.processSelectionWindow.search")), BorderLayout.WEST);
|
|
||||||
searchPanel.add(searchField, BorderLayout.CENTER);
|
|
||||||
panel.add(searchPanel, BorderLayout.NORTH);
|
|
||||||
|
|
||||||
String[] columns = {language.getText("fridaWindow.processSelectionWindow.columns.1"),
|
|
||||||
language.getText("fridaWindow.processSelectionWindow.columns.2")};
|
|
||||||
Object[][] data = getTableData(processList);
|
|
||||||
table = new JTable(data, columns);
|
|
||||||
JScrollPane scrollPane = new JScrollPane(table);
|
JScrollPane scrollPane = new JScrollPane(table);
|
||||||
panel.add(scrollPane, BorderLayout.CENTER);
|
scrollPane.setBorder(BorderFactory.createLineBorder(new Color(0x3C3F41)));
|
||||||
|
|
||||||
JButton selectButton = new JButton(language.getText("fridaWindow.processSelectionWindow.selectButton"));
|
JPopupMenu contextMenu = createContextMenu();
|
||||||
selectButton.addActionListener(e -> {
|
table.addMouseListener(new MouseAdapter() {
|
||||||
int selectedRow = table.getSelectedRow();
|
public void mouseClicked(MouseEvent e) {
|
||||||
if (selectedRow >= 0) {
|
if (SwingUtilities.isRightMouseButton(e)) {
|
||||||
long selectedPid = (Long) table.getValueAt(selectedRow, 1);
|
contextMenu.show(table, e.getX(), e.getY());
|
||||||
((FridaWindow) getOwner()).pidField.setText(String.valueOf(selectedPid));
|
}
|
||||||
dispose();
|
else if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
|
||||||
|
injectSelectedProcess();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panel.add(selectButton, BorderLayout.SOUTH);
|
|
||||||
|
|
||||||
|
panel.add(searchField, BorderLayout.NORTH);
|
||||||
|
panel.add(scrollPane, BorderLayout.CENTER);
|
||||||
setContentPane(panel);
|
setContentPane(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterProcesses(String query) {
|
private DefaultTableModel createTableModel() {
|
||||||
List<ProcessInfo> filteredList = new ArrayList<>();
|
processList = getProcesses();
|
||||||
for (ProcessInfo process : processList) {
|
String[] columns = { "进程名称", "进程ID" };
|
||||||
if (process.name().toLowerCase().contains(query.toLowerCase())) {
|
Object[][] data = getTableData(processList);
|
||||||
filteredList.add(process);
|
return new DefaultTableModel(data, columns) {
|
||||||
|
@Override
|
||||||
|
public boolean isCellEditable(int row, int column) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Object[][] filteredData = getTableData(filteredList);
|
private void injectSelectedProcess() {
|
||||||
table.setModel(new DefaultTableModel(filteredData, new String[]{"进程名称", "进程ID"}));
|
int selectedRow = table.getSelectedRow();
|
||||||
|
if (selectedRow != -1) {
|
||||||
|
long pid = (Long) table.getModel().getValueAt(selectedRow, 1);
|
||||||
|
((FridaWindow) getOwner()).pidField.setText(String.valueOf(pid));
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleSearchField(JTextField field) {
|
||||||
|
field.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||||
|
field.putClientProperty("JTextField.placeholderText", "输入进程名搜索...");
|
||||||
|
field.setBorder(BorderFactory.createCompoundBorder(
|
||||||
|
BorderFactory.createLineBorder(new Color(0x515658)),
|
||||||
|
BorderFactory.createEmptyBorder(5, 8, 5, 8)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleTable(JTable table) {
|
||||||
|
table.setRowHeight(28);
|
||||||
|
table.setIntercellSpacing(new Dimension(0, 0));
|
||||||
|
table.setShowGrid(false);
|
||||||
|
table.setSelectionBackground(new Color(0x214283));
|
||||||
|
|
||||||
|
// 自定义渲染器
|
||||||
|
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||||
|
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
|
Component c = super.getTableCellRendererComponent(table, value,
|
||||||
|
isSelected, hasFocus, row, column);
|
||||||
|
c.setBackground(row % 2 == 0 ? new Color(0x323232) : new Color(0x2B2B2B));
|
||||||
|
c.setForeground(Color.WHITE);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPopupMenu createContextMenu() {
|
||||||
|
JPopupMenu menu = new JPopupMenu();
|
||||||
|
JMenuItem injectItem = new JMenuItem("注入选中进程");
|
||||||
|
injectItem.addActionListener(e -> injectSelectedProcess());
|
||||||
|
menu.add(injectItem);
|
||||||
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object[][] getTableData(List<ProcessInfo> processes) {
|
private Object[][] getTableData(List<ProcessInfo> processes) {
|
||||||
@@ -441,4 +596,8 @@ public class FridaWindow extends WindowsJDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private record ProcessInfo(long pid, String name) {}
|
private record ProcessInfo(long pid, String name) {}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ public class MainWindow extends JFrame {
|
|||||||
private final ToolItem tool;
|
private final ToolItem tool;
|
||||||
private Timer pressTimer;
|
private Timer pressTimer;
|
||||||
private Timer releaseTimer;
|
private Timer releaseTimer;
|
||||||
|
private static int delay = 0;
|
||||||
public CardMouseAdapter(JPanel card, ToolItem tool) {
|
public CardMouseAdapter(JPanel card, ToolItem tool) {
|
||||||
this.card = card;
|
this.card = card;
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
@@ -639,9 +639,14 @@ public class MainWindow extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
startReleaseAnimation(() -> tool.getAction().actionPerformed(
|
if (delay == 0) {
|
||||||
new ActionEvent(card, ActionEvent.ACTION_PERFORMED, "")
|
delay++;
|
||||||
));
|
startReleaseAnimation(() -> tool.getAction().actionPerformed(
|
||||||
|
new ActionEvent(card, ActionEvent.ACTION_PERFORMED, "")
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
delay--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user