2222 * 5. 提交会话Header
2323 * 6. 提交Header规则
2424 *
25+ * 批量选择时自动过滤二进制内容的报文,只有纯文本请求才会被发送
26+ *
2527 * @author SQLMap WebUI Team
2628 * @version 1.0.0
2729 */
@@ -42,6 +44,47 @@ public class BurpExtender implements IBurpExtender, IContextMenuFactory, ITab {
4244 private static final String EXTENSION_NAME = "SQLMap WebUI" ;
4345 private static final String EXTENSION_VERSION = "1.0.0" ;
4446
47+ /**
48+ * 过滤结果类 - 存储过滤后的纯文本请求和过滤统计
49+ */
50+ private static class FilterResult {
51+ final List <IHttpRequestResponse > textMessages ;
52+ final List <IHttpRequestResponse > binaryMessages ;
53+
54+ FilterResult (List <IHttpRequestResponse > textMessages , List <IHttpRequestResponse > binaryMessages ) {
55+ this .textMessages = textMessages ;
56+ this .binaryMessages = binaryMessages ;
57+ }
58+
59+ int totalCount () {
60+ return textMessages .size () + binaryMessages .size ();
61+ }
62+
63+ int textCount () {
64+ return textMessages .size ();
65+ }
66+
67+ int binaryCount () {
68+ return binaryMessages .size ();
69+ }
70+
71+ boolean hasTextMessages () {
72+ return !textMessages .isEmpty ();
73+ }
74+
75+ boolean allBinary () {
76+ return textMessages .isEmpty () && !binaryMessages .isEmpty ();
77+ }
78+
79+ String getMenuSuffix () {
80+ if (totalCount () == 1 ) {
81+ return binaryMessages .isEmpty () ? "" : " (二进制报文)" ;
82+ } else {
83+ return String .format (" [%d/%d 可扫描]" , textCount (), totalCount ());
84+ }
85+ }
86+ }
87+
4588 @ Override
4689 public void registerExtenderCallbacks (IBurpExtenderCallbacks callbacks ) {
4790 this .callbacks = callbacks ;
@@ -118,68 +161,68 @@ public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
118161 return menuItems ;
119162 }
120163
121- // 检测请求是否为二进制内容
122- IHttpRequestResponse firstMessage = selectedMessages [0 ];
123- BinaryContentDetector .DetectionResult detectionResult =
124- BinaryContentDetector .detect (firstMessage , helpers );
125- boolean isBinary = detectionResult .isBinary ();
126- String binarySuffix = isBinary ? " (二进制报文)" : "" ;
164+ // 过滤二进制请求
165+ FilterResult filterResult = filterBinaryRequests (selectedMessages );
166+ String menuSuffix = filterResult .getMenuSuffix ();
127167
128168 // 使用默认配置发送
129- JMenuItem sendWithDefault = new JMenuItem ("Send to SQLMap WebUI" + binarySuffix );
130- if (isBinary ) {
169+ JMenuItem sendWithDefault = new JMenuItem ("Send to SQLMap WebUI" + menuSuffix );
170+ if (filterResult . allBinary () ) {
131171 sendWithDefault .setEnabled (false );
132- sendWithDefault .setToolTipText ("二进制报文无法发起扫描任务: " + detectionResult . getReason () );
172+ sendWithDefault .setToolTipText ("所有选中的报文都是二进制格式,无法发起扫描任务" );
133173 } else {
134174 sendWithDefault .addActionListener (e -> {
135- for (IHttpRequestResponse message : selectedMessages ) {
136- sendRequestToBackend (message , configManager .getDefaultConfig ());
137- }
175+ sendFilteredRequests (filterResult , configManager .getDefaultConfig ());
138176 });
139177 }
140178 menuItems .add (sendWithDefault );
141179
142180 // 选择配置发送
143- JMenuItem sendWithOptions = new JMenuItem ("Send to SQLMap WebUI (选择配置)..." + binarySuffix );
144- if (isBinary ) {
181+ JMenuItem sendWithOptions = new JMenuItem ("Send to SQLMap WebUI (选择配置)..." + menuSuffix );
182+ if (filterResult . allBinary () ) {
145183 sendWithOptions .setEnabled (false );
146- sendWithOptions .setToolTipText ("二进制报文无法发起扫描任务: " + detectionResult . getReason () );
184+ sendWithOptions .setToolTipText ("所有选中的报文都是二进制格式,无法发起扫描任务" );
147185 } else {
148186 sendWithOptions .addActionListener (e -> {
149- ConfigSelectionDialog dialog = new ConfigSelectionDialog (
150- callbacks , apiClient , configManager , uiTab );
151- dialog .show (selectedMessages [0 ]);
187+ if (filterResult .hasTextMessages ()) {
188+ ConfigSelectionDialog dialog = new ConfigSelectionDialog (
189+ callbacks , apiClient , configManager , uiTab );
190+ dialog .show (filterResult .textMessages .get (0 ));
191+ }
152192 });
153193 }
154194 menuItems .add (sendWithOptions );
155195
156196 // 标记注入点并扫描
157- JMenuItem markInjectionPoints = new JMenuItem ("标记注入点并扫描 (*)" + binarySuffix );
158- if (isBinary ) {
197+ JMenuItem markInjectionPoints = new JMenuItem ("标记注入点并扫描 (*)" +
198+ (filterResult .allBinary () ? " (二进制报文)" : "" ));
199+ if (filterResult .allBinary ()) {
159200 markInjectionPoints .setEnabled (false );
160- markInjectionPoints .setToolTipText ("二进制报文无法发起扫描任务: " + detectionResult . getReason () );
201+ markInjectionPoints .setToolTipText ("所有选中的报文都是二进制格式,无法发起扫描任务" );
161202 } else {
162203 markInjectionPoints .addActionListener (e -> {
163- InjectionPointDialog dialog = new InjectionPointDialog (
164- callbacks , apiClient , configManager , uiTab );
165- dialog .show (selectedMessages [0 ]);
204+ if (filterResult .hasTextMessages ()) {
205+ InjectionPointDialog dialog = new InjectionPointDialog (
206+ callbacks , apiClient , configManager , uiTab );
207+ dialog .show (filterResult .textMessages .get (0 ));
208+ }
166209 });
167210 }
168211 menuItems .add (markInjectionPoints );
169212
170213 // 提交会话Header 和 Header规则 - 仅在选中单条请求时显示
171- if (selectedMessages .length == 1 ) {
214+ if (selectedMessages .length == 1 && filterResult . hasTextMessages () ) {
172215 JMenuItem submitSessionHeaders = new JMenuItem ("提交会话Header" );
173216 submitSessionHeaders .addActionListener (e -> {
174217 SessionHeaderDialog dialog = new SessionHeaderDialog (callbacks , apiClient , uiTab );
175- dialog .show (selectedMessages [ 0 ] );
218+ dialog .show (filterResult . textMessages . get ( 0 ) );
176219 });
177220 menuItems .add (submitSessionHeaders );
178221
179222 JMenuItem submitHeaderRule = new JMenuItem ("提交Header规则" );
180223 submitHeaderRule .addActionListener (e -> {
181224 HeaderRuleDialog dialog = new HeaderRuleDialog (callbacks , apiClient , uiTab );
182- dialog .show (selectedMessages [ 0 ] );
225+ dialog .show (filterResult . textMessages . get ( 0 ) );
183226 });
184227 menuItems .add (submitHeaderRule );
185228 }
@@ -188,6 +231,48 @@ public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
188231 return menuItems ;
189232 }
190233
234+ /**
235+ * 过滤二进制请求,返回纯文本请求列表和统计信息
236+ */
237+ private FilterResult filterBinaryRequests (IHttpRequestResponse [] messages ) {
238+ List <IHttpRequestResponse > textMessages = new ArrayList <>();
239+ List <IHttpRequestResponse > binaryMessages = new ArrayList <>();
240+
241+ for (IHttpRequestResponse message : messages ) {
242+ if (BinaryContentDetector .isTextRequest (message , helpers )) {
243+ textMessages .add (message );
244+ } else {
245+ binaryMessages .add (message );
246+ }
247+ }
248+
249+ return new FilterResult (textMessages , binaryMessages );
250+ }
251+
252+ /**
253+ * 发送过滤后的纯文本请求,并记录被过滤的二进制请求日志
254+ */
255+ private void sendFilteredRequests (FilterResult filterResult , ScanConfig config ) {
256+ // 记录过滤统计
257+ if (filterResult .binaryCount () > 0 ) {
258+ uiTab .appendLog (String .format ("[*] 过滤统计: 共选中 %d 个请求,%d 个纯文本可扫描,%d 个二进制已过滤" ,
259+ filterResult .totalCount (), filterResult .textCount (), filterResult .binaryCount ()));
260+
261+ // 记录被过滤的二进制请求URL
262+ for (IHttpRequestResponse binaryMsg : filterResult .binaryMessages ) {
263+ IRequestInfo reqInfo = helpers .analyzeRequest (binaryMsg );
264+ String url = reqInfo .getUrl ().toString ();
265+ BinaryContentDetector .DetectionResult detection = BinaryContentDetector .detect (binaryMsg , helpers );
266+ uiTab .appendLog (String .format (" [跳过] %s (原因: %s)" , url , detection .getReason ()));
267+ }
268+ }
269+
270+ // 发送纯文本请求
271+ for (IHttpRequestResponse message : filterResult .textMessages ) {
272+ sendRequestToBackend (message , config );
273+ }
274+ }
275+
191276 /**
192277 * 发送请求到后端 - 使用默认配置发送
193278 */
0 commit comments