Skip to content

Commit 891eed5

Browse files
committed
feat(burp): enhance context menu with command execution config support
- Add CommandExecConfig for configurable command execution - Add CommandExecConfigPanel UI for command execution settings - Add CommandExecHelpDialog for command execution help - Remove deprecated ClipboardConfigPanel - Update CommandExecutor to support new execution config - Update SqlCommandBuilder with enhanced command building - Update TitleExtractor for better title handling - Update ConfigManager and PresetConfigDatabase for new config types - Update SqlmapUITab and ContextMenuProvider integration - Apply changes to both legacy and montoya API plugins
1 parent 1d47505 commit 891eed5

25 files changed

Lines changed: 3981 additions & 744 deletions

src/burpEx/legacy-api/src/main/java/com/sqlmapwebui/burp/BurpExtender.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import com.sqlmapwebui.burp.dialogs.*;
66
import com.sqlmapwebui.burp.util.CommandExecutor;
77
import com.sqlmapwebui.burp.util.SqlCommandBuilder;
8-
import com.sqlmapwebui.burp.util.TitleConfig;
8+
import com.sqlmapwebui.burp.util.TitleRule;
99
import com.sqlmapwebui.burp.util.TitleExtractor;
1010

1111
import javax.swing.*;
@@ -521,9 +521,21 @@ private void handleExecuteSqlMap(IHttpRequestResponse message) {
521521
return;
522522
}
523523

524-
// 提取窗口标题
525-
TitleConfig titleConfig = configManager.getTitleConfig();
526-
String windowTitle = TitleExtractor.extract(message, helpers, titleConfig);
524+
// 提取窗口标题(使用多规则匹配)
525+
List<TitleRule> rules = configManager.getTitleRules();
526+
String fallback = configManager.getTitleFallback();
527+
int maxLength = configManager.getTitleMaxLength();
528+
529+
// 调试日志:打印规则列表
530+
uiTab.appendLog("[DEBUG] 标题规则数量: " + rules.size());
531+
for (TitleRule r : rules) {
532+
uiTab.appendLog("[DEBUG] - 规则: " + r.getName() + ", 类型: " + r.getSourceType() +
533+
", 启用: " + r.isEnabled() + ", 优先级: " + r.getPriority());
534+
}
535+
uiTab.appendLog("[DEBUG] Fallback: " + fallback + ", MaxLength: " + maxLength);
536+
537+
String windowTitle = TitleExtractor.extract(message, helpers, rules, fallback, maxLength);
538+
uiTab.appendLog("[DEBUG] 提取到的标题: " + windowTitle);
527539

528540
// 生成HTTP请求字符串
529541
String httpRequest = buildHttpRequest(message);
@@ -553,19 +565,23 @@ private void handleExecuteSqlMap(IHttpRequestResponse message) {
553565
uiTab.appendLog("[+] 正在启动SQLMap扫描...");
554566
uiTab.appendLog(" 窗口标题: " + windowTitle);
555567
uiTab.appendLog(" 请求文件: " + requestFilePath);
568+
uiTab.appendLog(" 脚本目录: " + (configManager.getScriptTempDir().isEmpty() ? "(使用临时目录)" : configManager.getScriptTempDir()));
556569

557570
// 执行命令
558571
CommandExecutor.ExecutionResult result = CommandExecutor.executeInTerminal(
559572
sqlmapCommand,
560573
configManager.getDirectTerminalType(),
561574
configManager.isDirectKeepTerminal(),
562-
windowTitle
575+
windowTitle,
576+
configManager.getScriptTempDir()
563577
);
564578

565579
if (result.isSuccess()) {
566580
uiTab.appendLog("[+] SQLMap扫描已在终端中启动");
581+
uiTab.appendLog(" " + result.getMessage());
567582
JOptionPane.showMessageDialog(uiTab,
568583
"SQLMap扫描已在终端中启动!\n\n" +
584+
result.getMessage() + "\n\n" +
569585
"终端窗口会独立运行,您可以继续使用Burp。",
570586
"执行成功", JOptionPane.INFORMATION_MESSAGE);
571587
} else {
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package com.sqlmapwebui.burp;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.GsonBuilder;
5+
import com.google.gson.reflect.TypeToken;
6+
import com.sqlmapwebui.burp.util.TitleRule;
7+
8+
import java.lang.reflect.Type;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
12+
/**
13+
* 命令行执行配置数据模型
14+
* 存储剪贴板复制和直接执行的共用配置
15+
*/
16+
public class CommandExecConfig {
17+
18+
private boolean autoCopy = true; // 自动复制到剪贴板
19+
private String tempDir = ""; // HTTP请求临时存储目录
20+
private String scriptTempDir = ""; // 临时执行脚本存储目录
21+
private String pythonPath = ""; // Python解释器路径
22+
private String sqlmapPath = ""; // SQLMap脚本路径
23+
private String terminalType = "AUTO"; // 终端类型
24+
private boolean keepTerminal = true; // 执行后保持终端打开
25+
private List<TitleRule> titleRules = new ArrayList<>(); // 标题提取规则
26+
private String titleFallback = "SQLMap"; // 回退标题
27+
private int titleMaxLength = 50; // 标题最大长度
28+
29+
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
30+
31+
/**
32+
* 创建默认配置
33+
*/
34+
public static CommandExecConfig createDefault() {
35+
CommandExecConfig config = new CommandExecConfig();
36+
config.setAutoCopy(true);
37+
config.setTempDir("");
38+
config.setScriptTempDir("");
39+
config.setPythonPath("");
40+
config.setSqlmapPath("");
41+
config.setTerminalType("AUTO");
42+
config.setKeepTerminal(true);
43+
config.setTitleRules(new ArrayList<>());
44+
config.setTitleFallback("SQLMap");
45+
config.setTitleMaxLength(50);
46+
return config;
47+
}
48+
49+
/**
50+
* 从JSON字符串解析配置
51+
*/
52+
public static CommandExecConfig fromJson(String json) {
53+
if (json == null || json.trim().isEmpty()) {
54+
return createDefault();
55+
}
56+
try {
57+
CommandExecConfig config = GSON.fromJson(json, CommandExecConfig.class);
58+
if (config == null) {
59+
return createDefault();
60+
}
61+
// 确保 titleRules 不为 null
62+
if (config.getTitleRules() == null) {
63+
config.setTitleRules(new ArrayList<>());
64+
}
65+
return config;
66+
} catch (Exception e) {
67+
return createDefault();
68+
}
69+
}
70+
71+
/**
72+
* 转换为JSON字符串
73+
*/
74+
public String toJson() {
75+
return GSON.toJson(this);
76+
}
77+
78+
/**
79+
* 从标题规则JSON解析
80+
*/
81+
public static List<TitleRule> parseTitleRules(String json) {
82+
if (json == null || json.trim().isEmpty()) {
83+
return new ArrayList<>();
84+
}
85+
try {
86+
Type listType = new TypeToken<ArrayList<TitleRule>>(){}.getType();
87+
List<TitleRule> rules = GSON.fromJson(json, listType);
88+
return rules != null ? rules : new ArrayList<>();
89+
} catch (Exception e) {
90+
return new ArrayList<>();
91+
}
92+
}
93+
94+
/**
95+
* 将标题规则转换为JSON
96+
*/
97+
public static String titleRulesToJson(List<TitleRule> rules) {
98+
if (rules == null) {
99+
return "[]";
100+
}
101+
return GSON.toJson(rules);
102+
}
103+
104+
// ==================== Getters and Setters ====================
105+
106+
public boolean isAutoCopy() {
107+
return autoCopy;
108+
}
109+
110+
public void setAutoCopy(boolean autoCopy) {
111+
this.autoCopy = autoCopy;
112+
}
113+
114+
public String getTempDir() {
115+
return tempDir != null ? tempDir : "";
116+
}
117+
118+
public void setTempDir(String tempDir) {
119+
this.tempDir = tempDir != null ? tempDir : "";
120+
}
121+
122+
public String getScriptTempDir() {
123+
return scriptTempDir != null ? scriptTempDir : "";
124+
}
125+
126+
public void setScriptTempDir(String scriptTempDir) {
127+
this.scriptTempDir = scriptTempDir != null ? scriptTempDir : "";
128+
}
129+
130+
public String getPythonPath() {
131+
return pythonPath != null ? pythonPath : "";
132+
}
133+
134+
public void setPythonPath(String pythonPath) {
135+
this.pythonPath = pythonPath != null ? pythonPath : "";
136+
}
137+
138+
public String getSqlmapPath() {
139+
return sqlmapPath != null ? sqlmapPath : "";
140+
}
141+
142+
public void setSqlmapPath(String sqlmapPath) {
143+
this.sqlmapPath = sqlmapPath != null ? sqlmapPath : "";
144+
}
145+
146+
public String getTerminalType() {
147+
return terminalType != null ? terminalType : "AUTO";
148+
}
149+
150+
public void setTerminalType(String terminalType) {
151+
this.terminalType = terminalType != null ? terminalType : "AUTO";
152+
}
153+
154+
public boolean isKeepTerminal() {
155+
return keepTerminal;
156+
}
157+
158+
public void setKeepTerminal(boolean keepTerminal) {
159+
this.keepTerminal = keepTerminal;
160+
}
161+
162+
public List<TitleRule> getTitleRules() {
163+
return titleRules != null ? titleRules : new ArrayList<>();
164+
}
165+
166+
public void setTitleRules(List<TitleRule> titleRules) {
167+
this.titleRules = titleRules != null ? titleRules : new ArrayList<>();
168+
}
169+
170+
public String getTitleFallback() {
171+
return titleFallback != null ? titleFallback : "SQLMap";
172+
}
173+
174+
public void setTitleFallback(String titleFallback) {
175+
this.titleFallback = titleFallback != null ? titleFallback : "SQLMap";
176+
}
177+
178+
public int getTitleMaxLength() {
179+
return titleMaxLength > 0 ? titleMaxLength : 50;
180+
}
181+
182+
public void setTitleMaxLength(int titleMaxLength) {
183+
this.titleMaxLength = titleMaxLength > 0 ? titleMaxLength : 50;
184+
}
185+
186+
@Override
187+
public String toString() {
188+
return "CommandExecConfig{" +
189+
"autoCopy=" + autoCopy +
190+
", tempDir='" + tempDir + '\'' +
191+
", pythonPath='" + pythonPath + '\'' +
192+
", sqlmapPath='" + sqlmapPath + '\'' +
193+
", terminalType='" + terminalType + '\'' +
194+
", keepTerminal=" + keepTerminal +
195+
", titleRulesCount=" + (titleRules != null ? titleRules.size() : 0) +
196+
", titleFallback='" + titleFallback + '\'' +
197+
", titleMaxLength=" + titleMaxLength +
198+
'}';
199+
}
200+
}

src/burpEx/legacy-api/src/main/java/com/sqlmapwebui/burp/ConfigManager.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class ConfigManager {
3939
private static final String KEY_DIRECT_SQLMAP_PATH = "directSqlmapPath"; // SQLMap路径
4040
private static final String KEY_DIRECT_TERMINAL_TYPE = "directTerminalType"; // 终端类型
4141
private static final String KEY_DIRECT_KEEP_TERMINAL = "directKeepTerminal"; // 保持终端打开
42+
private static final String KEY_SCRIPT_TEMP_DIR = "scriptTempDir"; // 执行脚本临时目录
4243

4344
// ==================== 标题配置 ====================
4445
private static final String KEY_TITLE_SOURCE_TYPE = "titleSourceType";
@@ -83,6 +84,9 @@ public class ConfigManager {
8384

8485
// 常用配置数据库引用
8586
private PresetConfigDatabase presetDatabase;
87+
88+
// 命令行执行配置(从数据库加载)
89+
private CommandExecConfig commandExecConfig;
8690

8791
// 连接状态
8892
private boolean connected = false;
@@ -96,6 +100,7 @@ public class ConfigManager {
96100
private String directSqlmapPath = ""; // SQLMap脚本路径
97101
private TerminalType directTerminalType = TerminalType.AUTO; // 终端类型
98102
private boolean directKeepTerminal = true; // 执行后保持终端打开
103+
private String scriptTempDir = ""; // 执行脚本临时目录
99104

100105
// ==================== 标题配置 ====================
101106
private TitleSourceType titleSourceType = TitleSourceType.URL_PATH;
@@ -447,9 +452,11 @@ public void setSelectedPresetName(String name) {
447452

448453
/**
449454
* 设置常用配置数据库引用
455+
* 同时从数据库加载命令行执行配置
450456
*/
451457
public void setPresetDatabase(PresetConfigDatabase database) {
452458
this.presetDatabase = database;
459+
loadCommandExecConfig();
453460
}
454461

455462
/**
@@ -785,6 +792,20 @@ public void setDirectKeepTerminal(boolean keepTerminal) {
785792
this.directKeepTerminal = keepTerminal;
786793
callbacks.saveExtensionSetting(KEY_DIRECT_KEEP_TERMINAL, String.valueOf(keepTerminal));
787794
}
795+
796+
/**
797+
* 获取执行脚本临时目录
798+
*/
799+
public String getScriptTempDir() {
800+
return scriptTempDir;
801+
}
802+
803+
/**
804+
* 设置执行脚本临时目录
805+
*/
806+
public void setScriptTempDir(String scriptTempDir) {
807+
this.scriptTempDir = scriptTempDir != null ? scriptTempDir : "";
808+
}
788809

789810
// ============ 标题配置管理 ============
790811

@@ -1094,4 +1115,65 @@ private void saveTitleRulesInternal() {
10941115
String json = gson.toJson(titleRules);
10951116
callbacks.saveExtensionSetting(KEY_TITLE_RULES, json);
10961117
}
1118+
1119+
/**
1120+
* 从数据库加载命令行执行配置
1121+
*/
1122+
public void loadCommandExecConfig() {
1123+
if (presetDatabase == null) {
1124+
return;
1125+
}
1126+
1127+
CommandExecConfig config = presetDatabase.getCommandExecConfig();
1128+
if (config != null) {
1129+
this.commandExecConfig = config;
1130+
1131+
// 同步到内存字段
1132+
this.clipboardAutoCopy = config.isAutoCopy();
1133+
this.clipboardTempDir = config.getTempDir();
1134+
this.directPythonPath = config.getPythonPath();
1135+
this.directSqlmapPath = config.getSqlmapPath();
1136+
try {
1137+
this.directTerminalType = TerminalType.valueOf(config.getTerminalType());
1138+
} catch (IllegalArgumentException e) {
1139+
this.directTerminalType = TerminalType.AUTO;
1140+
}
1141+
this.directKeepTerminal = config.isKeepTerminal();
1142+
this.scriptTempDir = config.getScriptTempDir();
1143+
this.titleFallback = config.getTitleFallback();
1144+
this.titleMaxLength = config.getTitleMaxLength();
1145+
1146+
// 加载标题规则
1147+
List<TitleRule> rules = config.getTitleRules();
1148+
if (rules != null && !rules.isEmpty()) {
1149+
this.titleRules = new ArrayList<>(rules);
1150+
}
1151+
}
1152+
}
1153+
1154+
/**
1155+
* 保存命令行执行配置到数据库
1156+
*/
1157+
public void saveCommandExecConfig() {
1158+
if (presetDatabase == null) {
1159+
return;
1160+
}
1161+
1162+
CommandExecConfig config = new CommandExecConfig();
1163+
config.setAutoCopy(clipboardAutoCopy);
1164+
config.setTempDir(clipboardTempDir);
1165+
config.setScriptTempDir(scriptTempDir);
1166+
config.setPythonPath(directPythonPath);
1167+
config.setSqlmapPath(directSqlmapPath);
1168+
config.setTerminalType(directTerminalType.name());
1169+
config.setKeepTerminal(directKeepTerminal);
1170+
config.setTitleFallback(titleFallback);
1171+
config.setTitleMaxLength(titleMaxLength);
1172+
if (titleRules != null) {
1173+
config.setTitleRules(new ArrayList<>(titleRules));
1174+
}
1175+
1176+
presetDatabase.saveCommandExecConfig(config);
1177+
this.commandExecConfig = config;
1178+
}
10971179
}

0 commit comments

Comments
 (0)