diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/README.zh-CN.md b/plugins/burp-suite/cyberstrikeai-burp-extension/README.zh-CN.md index 575d55f7..90277e92 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/README.zh-CN.md +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/README.zh-CN.md @@ -2,16 +2,18 @@ ### 功能概述 -- 在 Burp 的 `CyberStrikeAI` 标签页中配置 **Host、端口、密码、单/多 Agent** +- 在 Burp 的 `CyberStrikeAI` 标签页中配置 **Host、端口、密码** - 点击 **Validate(验证)**: - 调用 `POST /api/auth/login` 用密码换取 Token - 调用 `GET /api/auth/validate` 校验 Token - 验证通过后 Token 会保存在插件内存中(本次 Burp 会话有效) - 右键任意 HTTP 请求包 → **Send to CyberStrikeAI (stream test)**: - - 将该 HTTP 请求(含 headers/body;若存在响应则附带截断片段)发送到 CyberStrikeAI - - 以 **SSE 流式**接收返回内容,并在标签页中实时展示 - - 单 Agent:`POST /api/eino-agent/stream` - - 多 Agent:`POST /api/multi-agent/stream`(需 `multi_agent.enabled: true`,请求体 `orchestration`) + - 弹出发送对话框,可针对**当前流量**选择: + - **项目**(`GET /api/projects`,新建对话时绑定 `projectId`) + - **角色**(`GET /api/roles`) + - **对话模式**(Eino 单代理 / Deep / Plan-Execute / Supervisor,按次选择并记住上次取值) + - **测试指令**(可编辑 prompt 前缀) + - 选择会记住上次取值,便于连续测同类流量 - **测试历史侧边栏(可搜索)**:每次发送都会新增一条记录,方便回看与对比 - **Output 分区**:`Progress`(可折叠)+ `Final Response`(主区域) - **Markdown 渲染**:最终输出可在 Output 主区域渲染为富文本(可开关) @@ -83,13 +85,13 @@ cd plugins/burp-suite/cyberstrikeai-burp-extension - **Port**:例如 `8080` - **HTTPS**:默认勾选(对接 `config.yaml` 中 `tls_enabled` / 自签证书);插件会自动信任本地自签证书,无需导入 - **Password**:你的 CyberStrikeAI 登录密码(对应服务端 `auth.password`) - - **Agent mode**:选择 `Single Agent` 或 `Multi Agent` 3) 点击 **Validate** - 成功:状态显示 `OK (token saved)` - 失败:状态会显示错误原因(例如密码错误、服务不可达、401/403 等) 4) 在 Burp 的 Proxy/HTTP history/Repeater 等列表中选中一条 HTTP 包 5) 右键 → **Send to CyberStrikeAI (stream test)** -6) 每次发送后会在 `CyberStrikeAI` 标签页左侧显示一个“测试记录”(请求标题 + 单/多 Agent + 状态);点击对应记录即可在右侧查看该次的流式输出结果 +6) 在弹出框中按需选择**项目、角色、对话模式**,并编辑测试指令后点确定 +7) 每次发送后会在 `CyberStrikeAI` 标签页左侧显示一个“测试记录”(请求标题 + 模式/角色 + 状态);点击对应记录即可在右侧查看该次的流式输出结果 ### 常见问题(排错) diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/dist/cyberstrikeai-burp-extension.jar b/plugins/burp-suite/cyberstrikeai-burp-extension/dist/cyberstrikeai-burp-extension.jar index 91323400..462329c4 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/dist/cyberstrikeai-burp-extension.jar and b/plugins/burp-suite/cyberstrikeai-burp-extension/dist/cyberstrikeai-burp-extension.jar differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java index f554bc27..f56205cf 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java @@ -1,7 +1,6 @@ package burp; import javax.swing.*; -import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -56,19 +55,26 @@ public class BurpExtender implements IBurpExtender, IContextMenuFactory { return; } - String instruction = showInstructionEditor(tab.getUiComponent(), lastInstruction); - if (instruction == null) { + SendOptionsDialog.Result options = SendOptionsDialog.show( + tab.getUiComponent(), client, cfg, token, lastInstruction); + if (options == null) { return; } - lastInstruction = instruction; + lastInstruction = options.instruction; - String prompt = HttpMessageFormatter.toPrompt(helpers, msg, instruction); + String prompt = HttpMessageFormatter.toPrompt(helpers, msg, options.instruction); String title = HttpMessageFormatter.getRequestTitle(helpers, msg); - String agentModeStr = cfg.agentMode.displayName; - String runId = tab.startNewRun(title, agentModeStr, msg); - tab.appendProgressToRun(runId, "\n[server] " + cfg.baseUrl + "\n\n"); + String agentModeStr = options.agentMode.displayName; + String roleLabel = options.role.isEmpty() ? "默认" : options.role; + String runId = tab.startNewRun(title, agentModeStr + " · " + roleLabel, msg); + tab.appendProgressToRun(runId, "\n[server] " + cfg.baseUrl); + if (!options.projectId.isEmpty()) { + tab.appendProgressToRun(runId, "\n[project] " + options.projectId); + } + tab.appendProgressToRun(runId, "\n\n"); - client.streamTest(cfg, token, prompt, new CyberStrikeAIClient.StreamListener() { + client.streamTest(cfg, token, prompt, options.role, options.projectId, options.agentMode, + new CyberStrikeAIClient.StreamListener() { @Override public void onEvent(String type, String message, String rawJson) { if (type == null) type = ""; @@ -190,38 +196,5 @@ public class BurpExtender implements IBurpExtender, IContextMenuFactory { } }); } - - private static String showInstructionEditor(Component parent, String initialValue) { - JTextArea editor = new JTextArea( - initialValue == null || initialValue.trim().isEmpty() - ? HttpMessageFormatter.defaultInstruction() - : initialValue, - 6, - 70 - ); - editor.setLineWrap(true); - editor.setWrapStyleWord(true); - editor.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 13)); - - JPanel panel = new JPanel(new BorderLayout(0, 8)); - panel.add(new JLabel("Edit instruction before sending:"), BorderLayout.NORTH); - panel.add(new JScrollPane(editor), BorderLayout.CENTER); - - int result = JOptionPane.showConfirmDialog( - parent, - panel, - "Customize Prompt Instruction", - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE - ); - if (result != JOptionPane.OK_OPTION) { - return null; - } - String value = editor.getText(); - if (value == null || value.trim().isEmpty()) { - return HttpMessageFormatter.defaultInstruction(); - } - return value.trim(); - } } diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java index b288b156..8fc5f819 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java @@ -10,7 +10,9 @@ import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -28,12 +30,10 @@ final class CyberStrikeAIClient { static final class Config { final String baseUrl; // e.g. http://127.0.0.1:8080 final String password; - final AgentMode agentMode; - Config(String baseUrl, String password, AgentMode agentMode) { + Config(String baseUrl, String password) { this.baseUrl = baseUrl; this.password = password; - this.agentMode = agentMode; } } @@ -54,6 +54,36 @@ final class CyberStrikeAIClient { } } + static final class ProjectOption { + final String id; + final String label; + + ProjectOption(String id, String label) { + this.id = id == null ? "" : id; + this.label = label == null || label.isEmpty() ? this.id : label; + } + + @Override + public String toString() { + return label.isEmpty() ? "(无)" : label; + } + } + + static final class RoleOption { + final String name; + final String label; + + RoleOption(String name, String label) { + this.name = name == null ? "" : name; + this.label = label == null || label.isEmpty() ? (this.name.isEmpty() ? "默认" : this.name) : label; + } + + @Override + public String toString() { + return label; + } + } + interface StreamListener { void onEvent(String type, String message, String rawJson); void onError(String message, Exception e); @@ -207,15 +237,75 @@ final class CyberStrikeAIClient { } } + List fetchProjects(Config cfg, String token) throws IOException { + String resp = authorizedGet(cfg.baseUrl, token, "/api/projects?limit=500"); + List out = new ArrayList<>(); + out.add(new ProjectOption("", "(无)")); + for (String obj : SimpleJson.extractObjectArray(resp, "projects")) { + String id = SimpleJson.extractStringField(obj, "id"); + if (id.isEmpty()) continue; + String name = SimpleJson.extractStringField(obj, "name"); + String status = SimpleJson.extractStringField(obj, "status"); + String label = name.isEmpty() ? id : name; + if ("archived".equalsIgnoreCase(status)) { + label = label + " [已归档]"; + } + out.add(new ProjectOption(id, label)); + } + return out; + } + + List fetchRoles(Config cfg, String token) throws IOException { + String resp = authorizedGet(cfg.baseUrl, token, "/api/roles"); + List out = new ArrayList<>(); + out.add(new RoleOption("", "默认")); + for (String obj : SimpleJson.extractObjectArray(resp, "roles")) { + if (!SimpleJson.extractBooleanField(obj, "enabled", true)) { + continue; + } + String name = SimpleJson.extractStringField(obj, "name"); + if (name.isEmpty()) continue; + out.add(new RoleOption(name, name)); + } + return out; + } + + private String authorizedGet(String baseUrl, String token, String path) throws IOException { + URL url = new URL(baseUrl + path); + HttpURLConnection conn = SslTrustAll.open(url, AUTH_CONNECT_TIMEOUT_MS, AUTH_READ_TIMEOUT_MS); + try { + conn.setRequestMethod("GET"); + conn.setRequestProperty("Accept", "application/json"); + conn.setRequestProperty("Authorization", "Bearer " + token); + int code = conn.getResponseCode(); + String resp = readAll(code >= 200 && code < 300 ? conn.getInputStream() : conn.getErrorStream()); + if (code < 200 || code >= 300) { + throw new IOException("GET " + path + " failed (" + code + "): " + resp); + } + return resp; + } finally { + conn.disconnect(); + } + } + void streamTest(Config cfg, String token, String message, StreamListener listener) { - String urlStr = cfg.baseUrl + cfg.agentMode.streamPath; + streamTest(cfg, token, message, "", "", AgentMode.EINO_SINGLE, listener); + } + + void streamTest(Config cfg, String token, String message, String role, String projectId, + AgentMode agentMode, StreamListener listener) { + AgentMode mode = agentMode != null ? agentMode : AgentMode.EINO_SINGLE; + String urlStr = cfg.baseUrl + mode.streamPath; Map payload = new HashMap<>(); payload.put("message", message); payload.put("conversationId", ""); - payload.put("role", ""); - if (cfg.agentMode.orchestration != null) { - payload.put("orchestration", cfg.agentMode.orchestration); + payload.put("role", role == null ? "" : role); + if (projectId != null && !projectId.trim().isEmpty()) { + payload.put("projectId", projectId.trim()); + } + if (mode.orchestration != null) { + payload.put("orchestration", mode.orchestration); } Thread worker = new Thread(() -> { @@ -319,6 +409,9 @@ final class CyberStrikeAIClient { sb.append("\"message\":\"").append(escapeJson(message)).append("\","); sb.append("\"conversationId\":\"").append(escapeJson(conversationId)).append("\","); sb.append("\"role\":\"").append(escapeJson(role)).append("\""); + if (payload.containsKey("projectId") && payload.get("projectId") != null) { + sb.append(",\"projectId\":\"").append(escapeJson(String.valueOf(payload.get("projectId")))).append("\""); + } if (payload.containsKey("orchestration") && payload.get("orchestration") != null) { sb.append(",\"orchestration\":\"").append(escapeJson(String.valueOf(payload.get("orchestration")))).append("\""); } diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java index baad02c1..05f54cad 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java @@ -16,16 +16,6 @@ final class CyberStrikeAITab implements ITab { private final JTextField portField = new JTextField("8080"); private final JCheckBox useHttpsBox = new JCheckBox("HTTPS", true); private final JPasswordField passwordField = new JPasswordField(); - private final JComboBox agentModeBox = new JComboBox<>(agentModeLabels()); - private static String[] agentModeLabels() { - CyberStrikeAIClient.AgentMode[] modes = CyberStrikeAIClient.AgentMode.values(); - String[] labels = new String[modes.length]; - for (int i = 0; i < modes.length; i++) { - labels[i] = modes[i].displayName; - } - return labels; - } - private final JButton validateButton = new JButton("Validate"); private final JButton clearButton = new JButton("Clear Output"); private final JButton stopButton = new JButton("Stop"); @@ -113,7 +103,6 @@ final class CyberStrikeAITab implements ITab { hostField.setColumns(14); portField.setColumns(6); passwordField.setColumns(12); - agentModeBox.setPreferredSize(new Dimension(200, agentModeBox.getPreferredSize().height)); JPanel row1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 2)); row1.add(new JLabel("Host")); @@ -128,8 +117,6 @@ final class CyberStrikeAITab implements ITab { row1.add(statusLabel); JPanel row2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 2)); - row2.add(new JLabel("Agent")); - row2.add(agentModeBox); row2.add(stopButton); row2.add(copyButton); row2.add(clearButton); @@ -550,19 +537,13 @@ final class CyberStrikeAITab implements ITab { renderMarkdownBox.addActionListener(e -> refreshOutputView()); } - private static final CyberStrikeAIClient.AgentMode[] AGENT_MODES = CyberStrikeAIClient.AgentMode.values(); - CyberStrikeAIClient.Config currentConfig() { String host = hostField.getText().trim(); String port = portField.getText().trim(); String password = new String(passwordField.getPassword()); String scheme = useHttpsBox.isSelected() ? "https" : "http"; String baseUrl = scheme + "://" + host + ":" + port; - int idx = agentModeBox.getSelectedIndex(); - CyberStrikeAIClient.AgentMode mode = (idx >= 0 && idx < AGENT_MODES.length) - ? AGENT_MODES[idx] - : CyberStrikeAIClient.AgentMode.EINO_SINGLE; - return new CyberStrikeAIClient.Config(baseUrl, password, mode); + return new CyberStrikeAIClient.Config(baseUrl, password); } String getToken() { diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SendOptionsDialog.java b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SendOptionsDialog.java new file mode 100644 index 00000000..4088cd74 --- /dev/null +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SendOptionsDialog.java @@ -0,0 +1,210 @@ +package burp; + +import javax.swing.*; +import java.awt.*; +import java.util.List; + +/** + * Per-request send dialog: project, role, agent mode, and custom instruction. + */ +final class SendOptionsDialog { + private SendOptionsDialog() {} + + static final class Result { + final String instruction; + final String projectId; + final String role; + final CyberStrikeAIClient.AgentMode agentMode; + + Result(String instruction, String projectId, String role, CyberStrikeAIClient.AgentMode agentMode) { + this.instruction = instruction; + this.projectId = projectId == null ? "" : projectId; + this.role = role == null ? "" : role; + this.agentMode = agentMode; + } + } + + private static String lastProjectId = ""; + private static String lastRole = ""; + private static CyberStrikeAIClient.AgentMode lastAgentMode = null; + + static Result show( + Component parent, + CyberStrikeAIClient client, + CyberStrikeAIClient.Config cfg, + String token, + String defaultInstruction + ) { + CyberStrikeAIClient.AgentMode defaultMode = lastAgentMode != null + ? lastAgentMode + : CyberStrikeAIClient.AgentMode.EINO_SINGLE; + + JPanel panel = new JPanel(new BorderLayout(0, 10)); + panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4)); + + JPanel selectors = new JPanel(new GridBagLayout()); + GridBagConstraints gc = new GridBagConstraints(); + gc.insets = new Insets(4, 6, 4, 6); + gc.fill = GridBagConstraints.HORIZONTAL; + gc.weighty = 0; + + JComboBox projectBox = new JComboBox<>(); + projectBox.addItem(new CyberStrikeAIClient.ProjectOption("", "加载中...")); + projectBox.setEnabled(false); + + JComboBox roleBox = new JComboBox<>(); + roleBox.addItem(new CyberStrikeAIClient.RoleOption("", "加载中...")); + roleBox.setEnabled(false); + + JComboBox agentBox = new JComboBox<>(CyberStrikeAIClient.AgentMode.values()); + agentBox.setSelectedItem(defaultMode); + agentBox.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof CyberStrikeAIClient.AgentMode) { + setText(((CyberStrikeAIClient.AgentMode) value).displayName); + } + return this; + } + }); + + // Row 0: labels — 项目 | 角色 | 对话 + gc.gridy = 0; + gc.weightx = 1.0; + + gc.gridx = 0; + selectors.add(new JLabel("项目"), gc); + gc.gridx = 1; + selectors.add(new JLabel("角色"), gc); + gc.gridx = 2; + selectors.add(new JLabel("对话"), gc); + + // Row 1: dropdowns + gc.gridy = 1; + + gc.gridx = 0; + selectors.add(projectBox, gc); + gc.gridx = 1; + selectors.add(roleBox, gc); + gc.gridx = 2; + selectors.add(agentBox, gc); + + JTextArea editor = new JTextArea( + defaultInstruction == null || defaultInstruction.trim().isEmpty() + ? HttpMessageFormatter.defaultInstruction() + : defaultInstruction, + 7, + 70 + ); + editor.setLineWrap(true); + editor.setWrapStyleWord(true); + editor.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 13)); + + JPanel instructionPanel = new JPanel(new BorderLayout(0, 6)); + instructionPanel.add(new JLabel("测试指令(可针对当前流量修改):"), BorderLayout.NORTH); + instructionPanel.add(new JScrollPane(editor), BorderLayout.CENTER); + + panel.add(selectors, BorderLayout.NORTH); + panel.add(instructionPanel, BorderLayout.CENTER); + + Thread loader = new Thread(() -> { + try { + List projects = client.fetchProjects(cfg, token); + List roles = client.fetchRoles(cfg, token); + SwingUtilities.invokeLater(() -> populateProjects(projectBox, projects, lastProjectId)); + SwingUtilities.invokeLater(() -> populateRoles(roleBox, roles, lastRole)); + } catch (Exception ex) { + SwingUtilities.invokeLater(() -> { + projectBox.removeAllItems(); + projectBox.addItem(new CyberStrikeAIClient.ProjectOption("", "(加载失败)")); + projectBox.setEnabled(true); + roleBox.removeAllItems(); + roleBox.addItem(new CyberStrikeAIClient.RoleOption("", "默认")); + roleBox.setEnabled(true); + JOptionPane.showMessageDialog(parent, + "加载项目/角色失败: " + ex.getMessage(), + "CyberStrikeAI", JOptionPane.WARNING_MESSAGE); + }); + } + }, "CyberStrikeAI-LoadCatalog"); + loader.start(); + + int result = JOptionPane.showConfirmDialog( + parent, + panel, + "发送到 CyberStrikeAI", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE + ); + if (result != JOptionPane.OK_OPTION) { + return null; + } + + CyberStrikeAIClient.ProjectOption project = (CyberStrikeAIClient.ProjectOption) projectBox.getSelectedItem(); + CyberStrikeAIClient.RoleOption role = (CyberStrikeAIClient.RoleOption) roleBox.getSelectedItem(); + CyberStrikeAIClient.AgentMode agentMode = (CyberStrikeAIClient.AgentMode) agentBox.getSelectedItem(); + if (agentMode == null) { + agentMode = defaultMode; + } + + String instruction = editor.getText(); + if (instruction == null || instruction.trim().isEmpty()) { + instruction = HttpMessageFormatter.defaultInstruction(); + } else { + instruction = instruction.trim(); + } + + lastProjectId = project != null ? project.id : ""; + lastRole = role != null ? role.name : ""; + lastAgentMode = agentMode; + + return new Result(instruction, lastProjectId, lastRole, agentMode); + } + + private static void populateProjects(JComboBox box, + List items, + String selectId) { + box.removeAllItems(); + for (CyberStrikeAIClient.ProjectOption item : items) { + box.addItem(item); + } + selectComboById(box, selectId); + box.setEnabled(true); + } + + private static void populateRoles(JComboBox box, + List items, + String selectName) { + box.removeAllItems(); + for (CyberStrikeAIClient.RoleOption item : items) { + box.addItem(item); + } + selectComboByName(box, selectName); + box.setEnabled(true); + } + + private static void selectComboById(JComboBox box, String id) { + if (id == null) id = ""; + for (int i = 0; i < box.getItemCount(); i++) { + CyberStrikeAIClient.ProjectOption item = box.getItemAt(i); + if (item != null && id.equals(item.id)) { + box.setSelectedIndex(i); + return; + } + } + box.setSelectedIndex(0); + } + + private static void selectComboByName(JComboBox box, String name) { + if (name == null) name = ""; + for (int i = 0; i < box.getItemCount(); i++) { + CyberStrikeAIClient.RoleOption item = box.getItemAt(i); + if (item != null && name.equals(item.name)) { + box.setSelectedIndex(i); + return; + } + } + box.setSelectedIndex(0); + } +} diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java index e798fb52..15571b4a 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java @@ -1,6 +1,8 @@ package burp; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -76,5 +78,70 @@ final class SimpleJson { } return sb.toString(); } + + static boolean extractBooleanField(String json, String key, boolean defaultValue) { + if (json == null || key == null) return defaultValue; + String needle = "\"" + key + "\""; + int k = json.indexOf(needle); + if (k < 0) return defaultValue; + int colon = json.indexOf(':', k + needle.length()); + if (colon < 0) return defaultValue; + int i = colon + 1; + while (i < json.length() && Character.isWhitespace(json.charAt(i))) i++; + if (i >= json.length()) return defaultValue; + if (json.startsWith("true", i)) return true; + if (json.startsWith("false", i)) return false; + return defaultValue; + } + + /** Extracts each top-level object inside a JSON array field, e.g. projects / roles. */ + static List extractObjectArray(String json, String arrayKey) { + List out = new ArrayList<>(); + if (json == null || arrayKey == null) return out; + String needle = "\"" + arrayKey + "\""; + int k = json.indexOf(needle); + if (k < 0) return out; + int bracket = json.indexOf('[', k); + if (bracket < 0) return out; + int i = bracket + 1; + while (i < json.length()) { + while (i < json.length() && Character.isWhitespace(json.charAt(i))) i++; + if (i >= json.length()) break; + char c = json.charAt(i); + if (c == ']') break; + if (c == ',') { + i++; + continue; + } + if (c != '{') { + i++; + continue; + } + int start = i; + int depth = 0; + boolean inStr = false; + boolean esc = false; + for (; i < json.length(); i++) { + char ch = json.charAt(i); + if (inStr) { + if (esc) esc = false; + else if (ch == '\\') esc = true; + else if (ch == '"') inStr = false; + continue; + } + if (ch == '"') inStr = true; + else if (ch == '{') depth++; + else if (ch == '}') { + depth--; + if (depth == 0) { + out.add(json.substring(start, i + 1)); + i++; + break; + } + } + } + } + return out; + } } diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender$1.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender$1.class index bf57e524..3c215c35 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender$1.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender$1.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender.class index 086353b5..33d0ce2d 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/BurpExtender.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$1.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$1.class index ccf18337..412f4262 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$1.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$1.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$AgentMode.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$AgentMode.class index fa12cc28..49294259 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$AgentMode.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$AgentMode.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$Config.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$Config.class index 1fb54851..9c97e5dd 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$Config.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$Config.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$ProjectOption.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$ProjectOption.class new file mode 100644 index 00000000..e2a8be7c Binary files /dev/null and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$ProjectOption.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$RoleOption.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$RoleOption.class new file mode 100644 index 00000000..05f4f020 Binary files /dev/null and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient$RoleOption.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient.class index 20fed65b..7ca69f71 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAIClient.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$1.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$1.class index 72341617..70713bff 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$1.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$1.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$DotIcon.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$DotIcon.class index 5871502d..3c27ab31 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$DotIcon.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$DotIcon.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRun.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRun.class index 9af5bf90..0198fd95 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRun.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRun.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRunCellRenderer.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRunCellRenderer.class index 14160571..3c8b5086 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRunCellRenderer.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab$TestRunCellRenderer.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab.class index 7faa98c8..b97130e6 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/CyberStrikeAITab.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/HttpMessageFormatter.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/HttpMessageFormatter.class index 0ace303f..09eeb291 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/HttpMessageFormatter.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/HttpMessageFormatter.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$1.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$1.class new file mode 100644 index 00000000..1edebad4 Binary files /dev/null and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$1.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$Result.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$Result.class new file mode 100644 index 00000000..ece220d0 Binary files /dev/null and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog$Result.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog.class new file mode 100644 index 00000000..6ffa317d Binary files /dev/null and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SendOptionsDialog.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SimpleJson.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SimpleJson.class index c155627a..341f6acc 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SimpleJson.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SimpleJson.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SslTrustAll.class b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SslTrustAll.class index 568264d8..7067e6b5 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SslTrustAll.class and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/classes/burp/SslTrustAll.class differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/cyberstrikeai-burp-extension-1.0.0.jar b/plugins/burp-suite/cyberstrikeai-burp-extension/target/cyberstrikeai-burp-extension-1.0.0.jar index 91323400..462329c4 100644 Binary files a/plugins/burp-suite/cyberstrikeai-burp-extension/target/cyberstrikeai-burp-extension-1.0.0.jar and b/plugins/burp-suite/cyberstrikeai-burp-extension/target/cyberstrikeai-burp-extension-1.0.0.jar differ diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index e2b64ee9..669be075 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,11 +1,15 @@ burp/SslTrustAll.class +burp/CyberStrikeAIClient$ProjectOption.class +burp/CyberStrikeAIClient$RoleOption.class burp/SslTrustAll$TimeoutSslSocketFactory.class burp/CyberStrikeAIClient$StreamListener.class burp/CyberStrikeAIClient$Config.class burp/CyberStrikeAIClient$AgentMode.class burp/MarkdownRenderer.class burp/SimpleJson.class +burp/SendOptionsDialog.class burp/CyberStrikeAIClient.class +burp/SendOptionsDialog$1.class burp/CyberStrikeAIClient$1.class burp/CyberStrikeAITab$DotIcon.class burp/CyberStrikeAITab.class @@ -13,6 +17,7 @@ burp/CyberStrikeAITab$1.class burp/SslTrustAll$1.class burp/BurpExtender$1.class burp/BurpExtender.class +burp/SendOptionsDialog$Result.class burp/CyberStrikeAITab$TestRun.class burp/CyberStrikeAITab$TestRunCellRenderer.class burp/HttpMessageFormatter.class diff --git a/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index 00fabca4..f1ba1dbc 100644 --- a/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/plugins/burp-suite/cyberstrikeai-burp-extension/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,7 +1,8 @@ -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/HttpMessageFormatter.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/MarkdownRenderer.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java -/Users/temp/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SslTrustAll.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SimpleJson.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAITab.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/MarkdownRenderer.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SendOptionsDialog.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/SslTrustAll.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/HttpMessageFormatter.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/CyberStrikeAIClient.java +/Users/yifan.zhao/Downloads/CyberStrikeAI-main/plugins/burp-suite/cyberstrikeai-burp-extension/src/main/java/burp/BurpExtender.java