Skip to content

Commit f64533f

Browse files
committed
feat(c2): 添加 C2 场景支持及相关功能
1 parent c5dba6c commit f64533f

File tree

2 files changed

+67
-9
lines changed

2 files changed

+67
-9
lines changed

frontend/src/components/SpecialModules/SpecialModules.svelte

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
<script>
22
import { onMount } from 'svelte';
3-
import { loadUserdataTemplates, getTemplatesByCategory, getAIScenarios, getVulhubScenarios } from '../../lib/userdataTemplates.js';
3+
import { loadUserdataTemplates, getTemplatesByCategory, getAIScenarios, getVulhubScenarios, getC2Scenarios } from '../../lib/userdataTemplates.js';
44
55
let { t, onTabChange } = $props();
66
let specialModuleTab = $state('vulhub');
77
let selectedAIScenario = $state(null);
88
let selectedVulhubScenario = $state(null);
9+
let selectedC2Scenario = $state(null);
910
let copied = $state(false);
1011
let aiSearchQuery = $state('');
1112
let vulhubSearchQuery = $state('');
13+
let c2SearchQuery = $state('');
1214
let templates = $state([]);
1315
let templatesLoading = $state(true);
1416
@@ -42,6 +44,18 @@
4244
return scenarios;
4345
});
4446
47+
let c2Scenarios = $derived(() => {
48+
let scenarios = getC2Scenarios(templates);
49+
if (c2SearchQuery) {
50+
const query = c2SearchQuery.toLowerCase();
51+
scenarios = scenarios.filter(s =>
52+
(s.nameZh || s.name).toLowerCase().includes(query) ||
53+
s.name.toLowerCase().includes(query)
54+
);
55+
}
56+
return scenarios;
57+
});
58+
4559
function selectAIScenario(scenario) {
4660
selectedAIScenario = scenario;
4761
}
@@ -50,6 +64,10 @@
5064
selectedVulhubScenario = scenario;
5165
}
5266
67+
function selectC2Scenario(scenario) {
68+
selectedC2Scenario = scenario;
69+
}
70+
5371
async function copyToClipboard() {
5472
if (!selectedVulhubScenario) return;
5573
try {
@@ -197,7 +215,11 @@
197215
</div>
198216
{:else if specialModuleTab === 'c2'}
199217
<div class="bg-white rounded-xl border border-gray-100 p-4 sm:p-6 md:p-8">
200-
{#if templates.length === 0}
218+
{#if templatesLoading}
219+
<div class="flex items-center justify-center h-32">
220+
<div class="w-6 h-6 border-2 border-gray-100 border-t-orange-500 rounded-full animate-spin"></div>
221+
</div>
222+
{:else if templates.length === 0}
201223
<div class="bg-blue-50 border border-blue-100 rounded-xl p-5 mb-4">
202224
<div class="flex items-start gap-3">
203225
<svg class="w-5 h-5 text-blue-500 flex-shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
@@ -215,14 +237,44 @@
215237
</div>
216238
</div>
217239
{:else}
218-
<div class="text-center py-8">
219-
<p class="text-[13px] text-gray-500">暂无可用的 C2 场景</p>
220-
<p class="text-[12px] text-gray-400 mt-1">此模块功能开发中...</p>
221-
</div>
222-
<div class="bg-blue-50 rounded-lg p-4 sm:p-6 text-center">
223-
<p class="text-[13px] text-blue-800 mb-2">C2 场景管理模块</p>
224-
<p class="text-[12px] text-blue-600">此功能正在开发中,敬请期待</p>
240+
<div class="mb-4">
241+
<input
242+
type="text"
243+
placeholder={t.searchPlaceholder || '搜索...'}
244+
class="w-full h-10 px-3 text-[13px] bg-gray-50 border-0 rounded-lg text-gray-900 placeholder-gray-400 focus:ring-2 focus:ring-gray-900 focus:ring-offset-1 transition-shadow"
245+
bind:value={c2SearchQuery}
246+
/>
247+
{#if c2Scenarios().length > 0}
248+
<div class="flex flex-wrap gap-2 mt-3">
249+
{#each c2Scenarios() as scenario}
250+
<button
251+
class="px-3 py-2 text-[12px] font-medium rounded-lg transition-all {selectedC2Scenario?.name === scenario.name ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}"
252+
onclick={() => selectC2Scenario(scenario)}
253+
>
254+
{scenario.nameZh || scenario.name}
255+
</button>
256+
{/each}
257+
</div>
258+
{:else}
259+
<p class="text-[12px] text-gray-500 mt-3 text-center">未找到匹配的 C2 场景</p>
260+
{/if}
225261
</div>
262+
263+
{#if selectedC2Scenario}
264+
<div class="border-t border-gray-100 pt-4">
265+
{#if selectedC2Scenario.description}
266+
<p class="text-[13px] text-gray-700 mb-3">{selectedC2Scenario.description}</p>
267+
{/if}
268+
{#if selectedC2Scenario.script}
269+
<pre class="bg-gray-900 text-gray-100 text-[12px] p-4 rounded-lg overflow-x-auto max-h-96 overflow-y-auto font-mono">{selectedC2Scenario.script}</pre>
270+
{/if}
271+
</div>
272+
{:else}
273+
<div class="bg-blue-50 rounded-lg p-4 sm:p-6 text-center">
274+
<p class="text-[13px] text-blue-800 mb-2">选择一个 C2 场景查看部署脚本</p>
275+
<p class="text-[12px] text-blue-600">脚本将在云服务器上自动安装 C2 工具</p>
276+
</div>
277+
{/if}
226278
{/if}
227279
</div>
228280
{:else if specialModuleTab === 'ai'}

frontend/src/lib/userdataTemplates.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export function getVulhubScenarios(templates) {
3030
return templates.filter(t => t.category === 'vulhub');
3131
}
3232

33+
export function getC2Scenarios(templates) {
34+
if (!Array.isArray(templates)) return [];
35+
return templates.filter(t => t.category === 'c2');
36+
}
37+
3338
export function getGroupedTemplates(templates) {
3439
if (!Array.isArray(templates)) return {};
3540
const groups = {};
@@ -48,5 +53,6 @@ export const userdataCategoryNames = {
4853
ai: 'AI 应用',
4954
security: '安全工具',
5055
vulhub: '漏洞环境',
56+
c2: 'C2 场景',
5157
other: '其他'
5258
};

0 commit comments

Comments
 (0)