Loot (downloads/screenshots) is now sent by the teamserver either on client-connection or when new loot is added. For images, smaller thumbnails are used to reduce size of network packets.

This commit is contained in:
Jakob Friedl
2025-10-09 12:14:38 +02:00
parent bcf845288c
commit 4e0eae77b8
12 changed files with 230 additions and 97 deletions

View File

@@ -84,7 +84,7 @@ proc main(ip: string = "localhost", port: int = 37573) =
connection.sendPublicKey(clientKeyPair.publicKey)
of CLIENT_PROFILE:
profile = parsetoml.parseString(event.data["profile"].getStr())
profile = parsetoml.parseString(event.data["profile"].getStr())
of CLIENT_LISTENER_ADD:
let listener = event.data.to(UIListener)
@@ -152,9 +152,22 @@ proc main(ip: string = "localhost", port: int = 37573) =
event.data["message"].getStr(),
event.timestamp
)
of CLIENT_LOOT_ADD:
let lootItem = event.data.to(LootItem)
case lootItem.itemType:
of DOWNLOAD:
lootDownloads.items.add(lootItem)
of SCREENSHOT:
lootScreenshots.addItem(lootItem)
else: discard
of CLIENT_SYNC_LOOT:
discard
else: discard
# Draw/update UI components/views
if showSessionsTable: sessionsTable.draw(addr showSessionsTable)
if showListeners: listenersTable.draw(addr showListeners, connection)
@@ -175,6 +188,7 @@ proc main(ip: string = "localhost", port: int = 37573) =
# This is done to ensure that closed console windows can be opened again
consoles = newConsoleTable
igShowDemoWindow(nil)
# render
@@ -183,5 +197,6 @@ proc main(ip: string = "localhost", port: int = 37573) =
if not showConquest:
app.handle.setWindowShouldClose(true)
when isMainModule:
import cligen; dispatch main

View File

@@ -1,4 +1,4 @@
import strformat, strutils, times
import strformat, strutils, times, os
import imguin/[cimgui, glfw_opengl, simple]
import ../../utils/[appImGui, colors]
import ../../../common/[types, utils]
@@ -6,7 +6,7 @@ import ../../../common/[types, utils]
type
DownloadsComponent* = ref object of RootObj
title: string
items: seq[LootItem]
items*: seq[LootItem]
selectedIndex: int
@@ -16,24 +16,6 @@ proc LootDownloads*(title: string): DownloadsComponent =
result.items = @[]
result.selectedIndex = -1
result.items.add(@[LootItem(
agentId: "DEADBEEF",
path: "C:\\Software\\Conquest\\README.md",
timestamp: now().toTime().toUnix(),
size: 1000,
host: "WKS-1",
data: string.toBytes("README.md\nPreview\nHello world.")
),
LootItem(
agentId: "DEADBEEF",
path: "C:\\Software\\Conquest\\README.md",
timestamp: now().toTime().toUnix(),
size: 1000,
host: "WKS-1",
data: string.toBytes("README.md\nPreview\nHello world.")
)
])
proc draw*(component: DownloadsComponent, showComponent: ptr bool) =
igBegin(component.title, showComponent, 0)
defer: igEnd()
@@ -60,12 +42,14 @@ proc draw*(component: DownloadsComponent, showComponent: ptr bool) =
ImGui_TableFlags_SizingStretchSame.int32
)
let cols: int32 = 4
let cols: int32 = 6
if igBeginTable("##Items", cols, tableFlags, vec2(0.0f, 0.0f), 0.0f):
igTableSetupColumn("ID", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("AgentID", ImGuiTableColumnFlags_DefaultHide.int32, 0.0f, 0)
igTableSetupColumn("Host", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Path", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Creation Date", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Size", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Host", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupScrollFreeze(0, 1)
igTableHeadersRow()
@@ -75,19 +59,25 @@ proc draw*(component: DownloadsComponent, showComponent: ptr bool) =
if igTableSetColumnIndex(0):
igPushID_Int(i.int32)
let isSelected = component.selectedIndex == i
if igSelectable_Bool(item.path.cstring, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32 or ImGuiSelectableFlags_AllowOverlap.int32, vec2(0, 0)):
if igSelectable_Bool(item.lootId.cstring, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32 or ImGuiSelectableFlags_AllowOverlap.int32, vec2(0, 0)):
component.selectedIndex = i
igPopID()
if igTableSetColumnIndex(1):
igText(item.timestamp.fromUnix().local().format("dd-MM-yyyy HH:mm:ss"))
igText(item.agentId)
if igTableSetColumnIndex(2):
igText(item.host.cstring)
if igTableSetColumnIndex(3):
igText(item.path.extractFilename().replace("C_", "C:/").replace("_", "/"))
if igTableSetColumnIndex(4):
igText(item.timestamp.fromUnix().local().format("dd-MM-yyyy HH:mm:ss"))
if igTableSetColumnIndex(5):
igText($item.size)
if igTableSetColumnIndex(3):
igText(item.host.cstring)
igEndTable()
igEndChild()
@@ -99,7 +89,13 @@ proc draw*(component: DownloadsComponent, showComponent: ptr bool) =
if component.selectedIndex >= 0 and component.selectedIndex < component.items.len:
let item = component.items[component.selectedIndex]
igText(item.path)
igText(fmt("[{item.host}] "))
igSameLine(0.0f, 0.0f)
igText(item.path.extractFilename().replace("C_", "C:/").replace("_", "/"))
igSeparator()
igText(item.data)
else:
igText("Select item to preview contents")

View File

@@ -20,36 +20,18 @@ proc LootScreenshots*(title: string): ScreenshotsComponent =
result.title = title
result.items = @[]
result.selectedIndex = -1
result.items.add(@[LootItem(
agentId: "DEADBEEF",
timestamp: now().toTime().toUnix(),
size: 1000,
path: "/mnt/c/Users/jakob/Documents/Projects/conquest/data/loot/570DCB57/screenshot_1757769346.bmp",
host: "WKS-1",
data: string.toBytes(readFile("/mnt/c/Users/jakob/Documents/Projects/conquest/data/loot/570DCB57/screenshot_1757769346.bmp"))
),
LootItem(
agentId: "DEADBEEF",
timestamp: now().toTime().toUnix(),
path: "/mnt/c/Users/jakob/Documents/Projects/conquest/data/loot/C2468819/screenshot_1759238569.png",
size: 1000,
host: "WKS-1",
data: string.toBytes(readFile("/mnt/c/Users/jakob/Documents/Projects/conquest/data/loot/C2468819/screenshot_1759238569.png"))
)
])
result.textures = initTable[string, ScreenshotTexture]()
for item in result.items:
var textureId: GLuint
let (width, height) = loadTextureFromBytes(item.data, textureId)
result.textures[item.path] = ScreenshotTexture(
textureId: textureId,
width: width,
height: height
)
proc addItem*(component: ScreenshotsComponent, screenshot: LootItem) =
component.items.add(screenshot)
var textureId: GLuint
let (width, height) = loadTextureFromBytes(string.toBytes(screenshot.data), textureId)
component.textures[screenshot.path] = ScreenshotTexture(
textureId: textureId,
width: width,
height: height
)
proc draw*(component: ScreenshotsComponent, showComponent: ptr bool) =
igBegin(component.title, showComponent, 0)
@@ -77,12 +59,13 @@ proc draw*(component: ScreenshotsComponent, showComponent: ptr bool) =
ImGui_TableFlags_SizingStretchSame.int32
)
let cols: int32 = 4
let cols: int32 = 5
if igBeginTable("##Items", cols, tableFlags, vec2(0.0f, 0.0f), 0.0f):
igTableSetupColumn("Path", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Creation Date", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Size", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("ID", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("AgentID", ImGuiTableColumnFlags_DefaultHide.int32, 0.0f, 0)
igTableSetupColumn("Host", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Creation Date", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("File Size", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupScrollFreeze(0, 1)
igTableHeadersRow()
@@ -92,19 +75,22 @@ proc draw*(component: ScreenshotsComponent, showComponent: ptr bool) =
if igTableSetColumnIndex(0):
igPushID_Int(i.int32)
let isSelected = component.selectedIndex == i
if igSelectable_Bool(item.path.cstring, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32 or ImGuiSelectableFlags_AllowOverlap.int32, vec2(0, 0)):
if igSelectable_Bool(item.lootId.cstring, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32 or ImGuiSelectableFlags_AllowOverlap.int32, vec2(0, 0)):
component.selectedIndex = i
igPopID()
if igTableSetColumnIndex(1):
igText(item.timestamp.fromUnix().local().format("dd-MM-yyyy HH:mm:ss"))
igText(item.agentId)
if igTableSetColumnIndex(2):
igText($item.size)
if igTableSetColumnIndex(3):
igText(item.host.cstring)
if igTableSetColumnIndex(3):
igText(item.timestamp.fromUnix().local().format("dd-MM-yyyy HH:mm:ss"))
if igTableSetColumnIndex(4):
igText($item.size)
igEndTable()
igEndChild()