Skip to content

Commit 1fbc5e8

Browse files
committed
Release 0.101.57
2 parents b8ec080 + 506f1d0 commit 1fbc5e8

File tree

14 files changed

+1826
-25
lines changed

14 files changed

+1826
-25
lines changed

src/api/agents.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,134 @@ export async function wakeUpWOL(agent_id) {
265265
const { data } = await axios.post(`${baseUrl}/${agent_id}/wol/`);
266266
return data;
267267
}
268+
269+
export async function fetchAgentRegistry(
270+
agent_id,
271+
path,
272+
page = 1,
273+
hiveSearch = false,
274+
) {
275+
try {
276+
const { data } = await axios.get(`${baseUrl}/${agent_id}/registry/`, {
277+
params: { path: `${path}`, page, page_size: hiveSearch ? 100000 : 400 },
278+
});
279+
return data;
280+
} catch (e) {
281+
console.error(e);
282+
throw e;
283+
}
284+
}
285+
286+
export async function deleteRegistryKey(agent_id, path) {
287+
try {
288+
const { data } = await axios.delete(
289+
`${baseUrl}/${agent_id}/registry/delete-key/`,
290+
{
291+
params: { path: `${path}` },
292+
},
293+
);
294+
return data;
295+
} catch (e) {
296+
console.error(e);
297+
}
298+
}
299+
300+
export async function createRegistryKey(agent_id, path) {
301+
try {
302+
const { data } = await axios.post(
303+
`${baseUrl}/${agent_id}/registry/create-key/`,
304+
{ path },
305+
);
306+
return data;
307+
} catch (e) {
308+
console.error(e);
309+
throw e;
310+
}
311+
}
312+
313+
export async function renameRegistryKey(agent_id, old_path, new_path) {
314+
try {
315+
const { data } = await axios.post(
316+
`${baseUrl}/${agent_id}/registry/rename-key/`,
317+
{ old_path, new_path },
318+
);
319+
return data;
320+
} catch (e) {
321+
console.error(e);
322+
throw e;
323+
}
324+
}
325+
326+
export async function deleteRegistryValue(agent_id, path, name) {
327+
try {
328+
const { data } = await axios.delete(
329+
`${baseUrl}/${agent_id}/registry/delete-value/`,
330+
{
331+
params: { path, name },
332+
},
333+
);
334+
return data;
335+
} catch (e) {
336+
console.error("Failed to delete value:", e);
337+
throw e;
338+
}
339+
}
340+
341+
export async function renameRegistryValue(agentId, path, oldName, newName) {
342+
try {
343+
const { data } = await axios.post(
344+
`${baseUrl}/${agentId}/registry/rename-value/`,
345+
{
346+
path,
347+
old_name: oldName,
348+
new_name: newName,
349+
},
350+
);
351+
return data;
352+
} catch (e) {
353+
console.error("Failed to rename value:", e);
354+
throw e;
355+
}
356+
}
357+
358+
export async function modifyRegistryValue(
359+
agentId,
360+
path,
361+
name,
362+
type,
363+
dataValue,
364+
) {
365+
try {
366+
const { data } = await axios.post(
367+
`${baseUrl}/${agentId}/registry/modify-value/`,
368+
{
369+
path,
370+
name,
371+
type,
372+
data: dataValue,
373+
},
374+
);
375+
return data;
376+
} catch (e) {
377+
console.error("Failed to modify registry value:", e);
378+
throw e;
379+
}
380+
}
381+
382+
export async function createRegistryValue(agentId, path, name, type, data) {
383+
const formData = new FormData();
384+
formData.append("path", path);
385+
formData.append("name", name);
386+
formData.append("type", type);
387+
formData.append("data", data);
388+
try {
389+
const { data } = await axios.post(
390+
`${baseUrl}/${agentId}/registry/create-value/`,
391+
formData,
392+
);
393+
return data;
394+
} catch (e) {
395+
console.error("Failed to create registry value:", e);
396+
throw e;
397+
}
398+
}

src/assets/binary_type.png

8.24 KB
Loading

src/assets/string_type.png

7.3 KB
Loading

src/assets/windows-registry.png

1.5 KB
Loading

src/components/accounts/RolesForm.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@
129129
v-model="localRole.can_recover_agents"
130130
label="Recover Agents"
131131
/>
132+
<q-checkbox
133+
v-model="localRole.can_use_registry"
134+
label="Use Registry"
135+
/>
132136
</div>
133137
</q-card-section>
134138
<div class="text-subtitle2">Core</div>
@@ -552,6 +556,7 @@ export default {
552556
// reporting perms
553557
can_view_reports: false,
554558
can_manage_reports: false,
559+
can_use_registry: false,
555560
});
556561
557562
const loading = ref(false);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<template>
2+
<q-card-section class="q-px-xs q-pb-md q-pt-xs" v-if="hasText">
3+
<script-output-copy-clip label="Live Output" :data="outputText" />
4+
<q-separator class="q-my-sm" />
5+
</q-card-section>
6+
<div class="command-stream" ref="streamContainer" v-if="hasText">
7+
<div class="terminal">
8+
<pre class="mt-0">{{ outputText }}</pre>
9+
</div>
10+
</div>
11+
</template>
12+
13+
<script setup lang="ts">
14+
import {
15+
ref,
16+
onMounted,
17+
onUnmounted,
18+
watchEffect,
19+
nextTick,
20+
computed,
21+
} from "vue";
22+
import { useTemplateRef } from "vue";
23+
import { useAgentCmdWSConnection } from "@/websocket/agent";
24+
import ScriptOutputCopyClip from "@/components/scripts/ScriptOutputCopyClip.vue";
25+
import { uid } from "quasar";
26+
27+
const props = defineProps({
28+
agentId: { type: String, required: true },
29+
cmd: { type: String, required: true },
30+
shell: { type: String, required: true },
31+
custom_shell: { type: String, required: false },
32+
timeout: { type: Number, default: 10 },
33+
});
34+
35+
// emits
36+
const emit = defineEmits(["updateOutput", "streamLoaded", "streamClosed"]);
37+
38+
const cmdId = uid();
39+
const { send, data, reset, close, status } = useAgentCmdWSConnection(
40+
props.agentId,
41+
cmdId,
42+
);
43+
44+
const outputText = ref("");
45+
const streamContainer = useTemplateRef<HTMLElement>("streamContainer");
46+
let firstChunk = false;
47+
48+
const hasText = computed(() => outputText.value.trim() !== "");
49+
50+
watchEffect(() => {
51+
if (data.value.length) {
52+
outputText.value = data.value.map((msg) => msg.output).join("\n");
53+
emit("updateOutput", outputText.value);
54+
55+
if (!firstChunk && data.value.length > 0) {
56+
firstChunk = true;
57+
emit("streamLoaded");
58+
}
59+
60+
nextTick(() => {
61+
if (streamContainer.value) {
62+
streamContainer.value.scrollTop = streamContainer.value.scrollHeight;
63+
}
64+
});
65+
}
66+
});
67+
68+
watchEffect(() => {
69+
if (status.value === "CLOSED") emit("streamClosed");
70+
});
71+
72+
onMounted(() => {
73+
outputText.value = "";
74+
reset();
75+
send(
76+
JSON.stringify({
77+
shell: props.shell,
78+
cmd: props.cmd,
79+
timeout: props.timeout,
80+
run_as_user: false,
81+
custom_shell: props.custom_shell,
82+
stream: true,
83+
cmd_id: cmdId,
84+
}),
85+
);
86+
});
87+
88+
onUnmounted(close);
89+
</script>
90+
91+
<style scoped>
92+
.command-stream {
93+
font-family: monospace;
94+
background: #191818;
95+
color: #fff;
96+
padding: 0 10px;
97+
height: 30vh;
98+
overflow-y: auto;
99+
border: 1px solid #ccc;
100+
border-radius: 4px;
101+
}
102+
.terminal {
103+
white-space: pre-wrap;
104+
}
105+
</style>

0 commit comments

Comments
 (0)