Experimented with ImGUI tables for session view.

This commit is contained in:
Jakob Friedl
2025-09-07 17:18:50 +02:00
parent 87059ced4c
commit 2320b705d3
4 changed files with 323 additions and 78 deletions

View File

@@ -4,31 +4,31 @@ Size=1908,999
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
Pos=60,60 Pos=289,253
Size=400,400 Size=449,261
Collapsed=0 Collapsed=0
[Window][Dear ImGui Demo] [Window][Dear ImGui Demo]
Pos=10,43 Pos=10,43
Size=1187,946 Size=1453,946
Collapsed=0 Collapsed=0
DockId=0x00000003,1 DockId=0x00000001,1
[Window][Agents [Table View]] [Window][Agents [Table View]]
Pos=10,43 Pos=10,43
Size=1187,946 Size=1187,946
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000001,0
[Window][Agents [Graph View]] [Window][Agents [Graph View]]
Pos=10,43 Pos=10,43
Size=1888,473 Size=1888,473
Collapsed=0 Collapsed=0
DockId=0x00000003,1 DockId=0x00000001,1
[Window][Eventlog] [Window][Eventlog]
Pos=1199,43 Pos=1465,43
Size=699,946 Size=433,946
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@@ -57,12 +57,204 @@ Pos=60,60
Size=564,669 Size=564,669
Collapsed=0 Collapsed=0
[Window][Sessions [Table View]]
Pos=10,43
Size=1453,946
Collapsed=0
DockId=0x00000001,0
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
IsChild=1
Size=1136,248
[Window][Dear ImGui Demo/Red_BEEF922B]
IsChild=1
Size=200,100
[Window][Dear ImGui Demo/##Basket_956142B6]
IsChild=1
Size=1115,540
[Window][Dear ImGui Demo/##Basket_8B4CCC3E]
IsChild=1
Size=1115,540
[Window][Dear ImGui Demo/##Basket_10C9C799]
IsChild=1
Size=1115,540
[Window][Dear ImGui Demo/##Tree_EC99B1DE]
IsChild=1
Size=1115,540
[Window][Sessions [Graph View]]
Pos=10,518
Size=1453,471
Collapsed=0
DockId=0x00000002,0
[Table][0xB6880529,2] [Table][0xB6880529,2]
RefScale=27 RefScale=27
Column 0 Sort=0v Column 0 Sort=0v
[Table][0x951FCC8A,6]
RefScale=27
Column 0 Width=48
Column 1 Width=72 Sort=0v
Column 2 Width=108
Column 3 Weight=0.5480
Column 4 Weight=1.0000
Column 5 Weight=-1.0000
[Table][0x32886A44,8]
Column 0 Weight=0.7758
Column 1 Weight=1.1556
Column 2 Weight=0.7758
Column 3 Weight=0.9616
Column 4 Weight=0.9616
Column 5 Weight=1.1556
Column 6 Weight=0.3879
Column 7 Weight=1.8263
[Table][0x51D6F5EA,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
[Table][0xE102187A,3]
RefScale=27
Column 0 Width=134
Column 1 Width=108
Column 2 Width=108
[Table][0xF1421304,3]
RefScale=27
Column 0 Width=108
Column 1 Width=108
Column 2 Weight=1.0000
[Table][0xE212E0F0,6]
RefScale=27
Column 0 Width=108
Column 1 Width=108
Column 2 Width=-1
Column 3 Weight=1.0000
Column 4 Weight=1.0000
Column 5 Weight=-1.0000
[Table][0x86C9FC97,3]
Column 0 Weight=0.6856
Column 1 Weight=0.7387
Column 2 Weight=1.5757
[Table][0x95990F63,3]
RefScale=27
Column 0 Width=108
Column 1 Width=108
Column 2 Width=108
[Table][0xEB78AB2C,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
[Table][0x603C335E,2]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
[Table][0xA6C6558A,2]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
[Table][0xAED4F161,3]
RefScale=27
Column 0 Width=191 Visible=1
Column 1 Width=108 Visible=1 Sort=0v
Column 2 Width=-1 Visible=0
[Table][0x3A20F3F3,3]
RefScale=27
Column 0 Width=96
Column 1 Width=96
Column 2 Width=96
[Table][0x29CD9FF7,3]
[Table][0x302651AD,14]
RefScale=27
Column 0 Width=96 Sort=0v
Column 1 Width=33
Column 2 Width=33
Column 3 Width=33
Column 4 Width=33
Column 5 Width=33
Column 6 Width=33
Column 7 Width=33
Column 8 Width=33
Column 9 Width=33
Column 10 Width=33
Column 11 Width=33
Column 12 Width=33
Column 13 Width=33
[Table][0x369EB90F,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
[Table][0x2ACCE68A,3]
RefScale=27
Column 0 Width=136
Column 1 Width=136
Column 2 Width=136
[Table][0x6655AF53,4]
RefScale=27
Column 0 Width=48
Column 1 Width=72 Sort=0^
Column 2 Width=72
Column 3 Weight=1.0000
[Table][0x5145577A,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
[Table][0x127BEAD2,7]
RefScale=27
Column 0 Width=84
Column 1 Width=167
Column 2 Width=191
Column 3 Width=191
Column 4 Width=191
Column 5 Width=191
Column 6 Width=191
[Table][0x755BE644,3]
RefScale=27
Column 0 Width=84
Column 1 Width=83
Column 2 Width=84
[Table][0xBE0D9DE1,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
[Table][0xDE11CCC7,8]
Column 0 Weight=0.7758
Column 1 Weight=1.1556
Column 2 Weight=0.7758
Column 3 Weight=0.9616
Column 4 Weight=0.9616
Column 5 Weight=1.1556
Column 6 Weight=0.3879
Column 7 Weight=1.8263
[Docking][Data] [Docking][Data]
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,946 Split=X DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,946 Split=X
DockNode ID=0x00000003 Parent=0x85940918 SizeRef=1187,473 CentralNode=1 Selected=0x5E5F7166 DockNode ID=0x00000003 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75
DockNode ID=0x00000004 Parent=0x85940918 SizeRef=699,473 Selected=0x0FA43D88 DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1453,473 CentralNode=1 Selected=0x61E02D75
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1453,471 Selected=0x6D7E7D39
DockNode ID=0x00000004 Parent=0x85940918 SizeRef=433,473 Selected=0x0FA43D88

View File

@@ -1,6 +1,6 @@
import tables import tables
import ./utils/appImGui import ./utils/appImGui
import ./views/[dockspace, agents, listeners, eventlog] import ./views/[dockspace, sessions, listeners, eventlog]
proc main() = proc main() =
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true) var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
@@ -9,13 +9,13 @@ proc main() =
var var
views: Table[string, ptr bool] views: Table[string, ptr bool]
showConquest = true showConquest = true
showAgentsTable = true showSessionsTable = true
showAgentsGraph = false showSessionsGraph = false
showListeners = false showListeners = false
showEventlog = true showEventlog = true
views["Agents [Table View]"] = addr showAgentsTable views["Sessions [Table View]"] = addr showSessionsTable
views["Agents [Graph View]"] = addr showAgentsGraph views["Sessions [Graph View]"] = addr showSessionsGraph
views["Listeners"] = addr showListeners views["Listeners"] = addr showListeners
views["Eventlog"] = addr showEventlog views["Eventlog"] = addr showEventlog
@@ -33,8 +33,8 @@ proc main() =
# UI components/views # UI components/views
Dockspace().draw(addr showConquest, views) Dockspace().draw(addr showConquest, views)
if showAgentsTable: AgentsTable("Agents [Table View]").draw(addr showAgentsTable) if showSessionsTable: SessionsTable("Sessions [Table View]").draw(addr showSessionsTable)
if showAgentsGraph: AgentsTable("Agents [Graph View]").draw(addr showAgentsGraph) if showSessionsGraph: SessionsTable("Sessions [Graph View]").draw(addr showSessionsGraph)
if showListeners: ListenersTable("Listeners").draw(addr showListeners) if showListeners: ListenersTable("Listeners").draw(addr showListeners)
if showEventlog:Eventlog("Eventlog").draw(addr showEventlog) if showEventlog:Eventlog("Eventlog").draw(addr showEventlog)

View File

@@ -1,59 +0,0 @@
import times
import imguin/[cimgui, glfw_opengl, simple]
import ../utils/appImGui
import ../../common/[types]
type
AgentsTableComponent = ref object of RootObj
title: string
agents: seq[Agent]
let exampleAgents: seq[Agent] = @[
Agent(
agentId: "DEADBEEF",
listenerId: "L1234567",
username: "alice",
hostname: "DESKTOP-01",
domain: "CORP",
ip: "192.168.1.10",
os: "Windows 10",
process: "explorer.exe",
pid: 2340,
elevated: true,
sleep: 60,
tasks: @[],
firstCheckin: now() - initDuration(hours = 2),
latestCheckin: now(),
sessionKey: [byte 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
),
Agent(
agentId: "FACEDEAD",
listenerId: "L7654321",
username: "bob",
hostname: "LAPTOP-02",
domain: "SALES",
ip: "10.0.0.5",
os: "Windows 11",
process: "cmd.exe",
pid: 4567,
elevated: false,
sleep: 120,
tasks: @[],
firstCheckin: now() - initDuration(hours = 1, minutes = 30),
latestCheckin: now() - initDuration(minutes = 5),
sessionKey: [byte 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
)
]
proc AgentsTable*(title: string): AgentsTableComponent =
result = new AgentsTableComponent
result.title = title
result.agents = exampleAgents
proc draw*(component: AgentsTableComponent, showComponent: ptr bool) =
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
igBegin(component.title, showComponent, 0)
defer: igEnd()
igText("asd")

View File

@@ -0,0 +1,112 @@
import times
import imguin/[cimgui, glfw_opengl, simple]
import ../utils/appImGui
import ../../common/[types]
type
SessionsTableComponent = ref object of RootObj
title: string
agents: seq[Agent]
let exampleAgents: seq[Agent] = @[
Agent(
agentId: "DEADBEEF",
listenerId: "L1234567",
username: "alice",
hostname: "DESKTOP-01",
domain: "CORP",
ip: "192.168.1.10",
os: "Windows 10",
process: "explorer.exe",
pid: 2340,
elevated: true,
sleep: 60,
tasks: @[],
firstCheckin: now() - initDuration(hours = 2),
latestCheckin: now(),
sessionKey: [byte 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
),
Agent(
agentId: "FACEDEAD",
listenerId: "L7654321",
username: "bob",
hostname: "LAPTOP-02",
domain: "SALES",
ip: "10.0.0.5",
os: "Windows 11",
process: "cmd.exe",
pid: 4567,
elevated: false,
sleep: 120,
tasks: @[],
firstCheckin: now() - initDuration(hours = 1, minutes = 30),
latestCheckin: now() - initDuration(minutes = 5),
sessionKey: [byte 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
)
]
proc SessionsTable*(title: string): SessionsTableComponent =
result = new SessionsTableComponent
result.title = title
result.agents = exampleAgents
proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
igBegin(component.title, showComponent, 0)
defer: igEnd()
let tableFlags = (
ImGuiTableFlags_Resizable.int32 or
ImGuiTableFlags_Reorderable.int32 or
ImGuiTableFlags_Hideable.int32 or
ImGuiTableFlags_HighlightHoveredColumn.int32 or
ImGuiTableFlags_ContextMenuInBody.int32 or
ImGuiTableFlags_RowBg.int32 or
ImGuiTableFlags_BordersV.int32 or
ImGuiTableFlags_BordersH.int32 or
ImGuiTableFlags_ScrollY.int32 or
ImGuiTableFlags_ScrollX.int32 or
ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or
ImGui_TableFlags_SizingStretchProp.int32
)
let cols: int32 = 8
if igBeginTable("Sessions", cols, tableFlags, vec2(0.0f, 0.0f), 0.0f):
igTableSetupColumn("AgentID", ImGuiTableColumnFlags_NoReorder.int32 or ImGuiTableColumnFlags_NoHide.int32, 0.0f, 0)
igTableSetupColumn("Address", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Username", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Hostname", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("OS", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Process", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("PID", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupColumn("Activity", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
igTableSetupScrollFreeze(0, 1)
igTableHeadersRow()
for row in 0..< component.agents.len():
igTableNextRow(ImGuiTableRowFlags_None.int32, 0.0f)
let agent = component.agents[row]
if igTableSetColumnIndex(0):
igText(agent.agentId)
if igTableSetColumnIndex(1):
igText(agent.ip)
if igTableSetColumnIndex(2):
igText(agent.username)
if igTableSetColumnIndex(3):
igText(agent.hostname)
if igTableSetColumnIndex(4):
igText(agent.os)
if igTableSetColumnIndex(5):
igText(agent.process)
if igTableSetColumnIndex(6):
igText($agent.pid)
if igTableSetColumnIndex(7):
igText(agent.latestCheckin.format("yyyy-MM-dd HH:mm:ss"))
igEndTable()