diff --git a/web/static/css/c2.css b/web/static/css/c2.css index b6881b6c..0aedb3e2 100644 --- a/web/static/css/c2.css +++ b/web/static/css/c2.css @@ -772,6 +772,66 @@ border: 1px solid var(--c2-border); } +#c2-file-upload-btn.is-disabled, +#c2-file-upload-btn:disabled { + opacity: 0.5; + cursor: not-allowed; + color: var(--c2-text-dim, #94a3b8); + border-color: var(--c2-border, #e2e8f0); +} + +.c2-file-upload-hint { + font-size: 12px; + color: #b45309; + background: rgba(245, 158, 11, 0.08); + border: 1px solid rgba(245, 158, 11, 0.25); + border-radius: var(--c2-radius-xs, 4px); + padding: 8px 12px; + margin: -8px 0 12px; + line-height: 1.5; + word-break: break-word; +} + +.c2-file-upload-hint[hidden] { + display: none !important; +} + +.c2-file-upload-progress { + display: flex; + align-items: center; + gap: 10px; + margin: -8px 0 12px; + padding: 0 4px; +} + +.c2-file-upload-progress[hidden] { + display: none !important; +} + +.c2-file-upload-progress-track { + flex: 1; + height: 4px; + background: var(--c2-border); + border-radius: 2px; + overflow: hidden; +} + +.c2-file-upload-progress-fill { + height: 100%; + width: 0; + background: var(--c2-accent, #3b82f6); + transition: width 0.2s ease; +} + +.c2-file-upload-progress-label { + font-size: 11px; + color: var(--c2-text-dim); + white-space: nowrap; + max-width: 220px; + overflow: hidden; + text-overflow: ellipsis; +} + .c2-file-list { background: var(--c2-surface); border-radius: var(--c2-radius); diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json index d5194a5c..7241012a 100644 --- a/web/static/i18n/en-US.json +++ b/web/static/i18n/en-US.json @@ -2546,6 +2546,15 @@ "files": { "parent": "Parent", "refresh": "Refresh", + "upload": "Upload", + "uploading": "Uploading {{name}} · {{percent}}%", + "uploadOk": "Uploaded", + "uploadQueued": "Upload task queued", + "uploadPendingApproval": "Upload task pending HITL approval", + "uploadUnsupported": "Upload is not supported for this session", + "uploadCurlBeacon": "Curl beacons cannot upload files; use an HTTP Beacon", + "uploadTcpShell": "This is a TCP reverse shell (bash/nc): commands and download only. For upload, reconnect with: (1) a compiled CSB1 Beacon on the same listener, or (2) an HTTP/HTTPS Beacon.", + "uploadTcpReverse": "This is a TCP reverse shell (bash/nc): commands and download only. For upload, reconnect with: (1) a compiled CSB1 Beacon on the same listener, or (2) an HTTP/HTTPS Beacon.", "loading": "Loading…", "timeout": "Timed out loading files", "emptyDir": "Empty directory", @@ -2555,6 +2564,7 @@ "colActions": "Actions", "open": "Open", "download": "Download", + "downloadOk": "Downloaded", "failed": "Failed" }, "listeners": { diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json index c2dcd649..d7ee6d96 100644 --- a/web/static/i18n/zh-CN.json +++ b/web/static/i18n/zh-CN.json @@ -2535,6 +2535,15 @@ "files": { "parent": "上级目录", "refresh": "刷新", + "upload": "上传", + "uploading": "正在上传 {{name}} · {{percent}}%", + "uploadOk": "上传成功", + "uploadQueued": "上传任务已入队", + "uploadPendingApproval": "上传任务待人机协同审批", + "uploadUnsupported": "当前会话不支持上传", + "uploadCurlBeacon": "Curl 轻量信标不支持文件上传,请使用 HTTP Beacon", + "uploadTcpShell": "当前为 TCP 反弹 Shell(bash/nc),仅支持命令与下载。上传请改用:① 同一监听器下编译 CSB1 Beacon,或 ② HTTP/HTTPS Beacon 重新上线。", + "uploadTcpReverse": "当前为 TCP 反弹 Shell(bash/nc),仅支持命令与下载。上传请改用:① 同一监听器下编译 CSB1 Beacon,或 ② HTTP/HTTPS Beacon 重新上线。", "loading": "加载中…", "timeout": "加载文件超时", "emptyDir": "空目录", @@ -2544,6 +2553,7 @@ "colActions": "操作", "open": "打开", "download": "下载", + "downloadOk": "下载成功", "failed": "失败" }, "listeners": { diff --git a/web/static/js/c2.js b/web/static/js/c2.js index eec7da7d..a263a3d4 100644 --- a/web/static/js/c2.js +++ b/web/static/js/c2.js @@ -33,8 +33,10 @@ terminalBusy: false, terminalQueue: [], // 文件管理 - currentPath: '/', + currentPath: '.', + implantPwd: null, fileList: [], + fileUploadBusy: false, // 任务轮询 taskPollInterval: null, }; @@ -325,6 +327,7 @@ break; case 'c2-sessions': C2.loadSessions(); + C2.ensureListenersLoaded(); break; case 'c2-tasks': C2.loadTasks(); @@ -345,6 +348,16 @@ // 监听器管理 // ============================================================================ + C2.ensureListenersLoaded = function() { + if (C2.listeners && C2.listeners.length > 0) { + return Promise.resolve(C2.listeners); + } + return apiRequest('GET', `${API_BASE}/listeners`).then(function(data) { + C2.listeners = (data && data.listeners) || []; + return C2.listeners; + }); + }; + C2.loadListeners = function() { Promise.all([ apiRequest('GET', `${API_BASE}/listeners`), @@ -778,6 +791,8 @@ C2.selectSession = function(id) { C2.selectedSessionId = id; + C2.implantPwd = null; + C2.currentPath = '.'; C2.renderSessions(); C2.renderSessionDetail(id); }; @@ -822,10 +837,17 @@