diff --git a/src/client/layout.ini b/src/client/layout.ini index d10c141..2710639 100644 --- a/src/client/layout.ini +++ b/src/client/layout.ini @@ -1,6 +1,6 @@ [Window][Dockspace] Pos=0,0 -Size=1908,999 +Size=2548,1359 Collapsed=0 [Window][Debug##Default] @@ -9,26 +9,26 @@ Size=449,261 Collapsed=0 [Window][Dear ImGui Demo] -Pos=10,43 -Size=1453,946 +Pos=1852,43 +Size=686,653 Collapsed=0 -DockId=0x00000001,1 +DockId=0x00000007,0 [Window][Agents [Table View]] Pos=10,43 Size=1187,946 Collapsed=0 -DockId=0x00000001,0 +DockId=0x00000006,0 [Window][Agents [Graph View]] Pos=10,43 Size=1888,473 Collapsed=0 -DockId=0x00000001,1 +DockId=0x00000006,1 [Window][Eventlog] -Pos=1465,43 -Size=433,946 +Pos=10,698 +Size=2528,651 Collapsed=0 DockId=0x00000004,0 @@ -48,9 +48,10 @@ Size=1150,550 Collapsed=0 [Window][Dear ImGui Debug Log] -Pos=60,60 -Size=1088,486 +Pos=10,698 +Size=2528,651 Collapsed=0 +DockId=0x00000004,1 [Window][Dear ImGui Metrics/Debugger] Pos=60,60 @@ -59,9 +60,9 @@ Collapsed=0 [Window][Sessions [Table View]] Pos=10,43 -Size=1453,946 +Size=1840,653 Collapsed=0 -DockId=0x00000001,0 +DockId=0x00000006,0 [Window][Dear ImGui Demo/ResizableChild_478B81A3] IsChild=1 @@ -93,6 +94,10 @@ Size=1453,471 Collapsed=0 DockId=0x00000002,0 +[Window][Dear ImGui Demo/##Basket_87771727] +IsChild=1 +Size=614,540 + [Table][0xB6880529,2] RefScale=27 Column 0 Sort=0v @@ -100,21 +105,21 @@ Column 0 Sort=0v [Table][0x951FCC8A,6] RefScale=27 Column 0 Width=48 -Column 1 Width=72 Sort=0v +Column 1 Width=112 Sort=0v Column 2 Width=108 -Column 3 Weight=0.5480 +Column 3 Width=136 Column 4 Weight=1.0000 -Column 5 Weight=-1.0000 +Column 5 Width=-1 [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 +Column 0 Weight=0.7126 +Column 1 Weight=1.0615 +Column 2 Weight=0.7126 +Column 3 Weight=1.2397 +Column 4 Weight=1.6776 +Column 5 Weight=1.2397 +Column 6 Weight=0.3563 +Column 7 Weight=1.5466 [Table][0x51D6F5EA,3] Column 0 Weight=1.0000 @@ -168,9 +173,9 @@ 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 +Column 0 Weight=1.0000 +Column 1 Width=839 Sort=0v +Column 2 Width=-1 [Table][0x3A20F3F3,3] RefScale=27 @@ -182,7 +187,7 @@ Column 2 Width=96 [Table][0x302651AD,14] RefScale=27 -Column 0 Width=96 Sort=0v +Column 0 Width=96 Column 1 Width=33 Column 2 Width=33 Column 3 Width=33 @@ -222,13 +227,13 @@ 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 +Column 0 Width=155 +Column 1 Width=155 +Column 2 Width=155 +Column 3 Width=156 +Column 4 Width=156 +Column 5 Width=156 +Column 6 Width=474 [Table][0x755BE644,3] RefScale=27 @@ -237,9 +242,10 @@ 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 +RefScale=27 +Column 0 Width=84 +Column 1 Width=84 +Column 2 Width=217 [Table][0xDE11CCC7,8] Column 0 Weight=0.7758 @@ -251,10 +257,18 @@ Column 5 Weight=1.1556 Column 6 Weight=0.3879 Column 7 Weight=1.8263 -[Docking][Data] -DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,946 Split=X - DockNode ID=0x00000003 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75 - 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 +[Table][0x61294EC1,3] +RefScale=27 +Column 0 Width=119 +Column 1 Width=119 +Column 2 Width=119 + +[Docking][Data] +DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2528,1306 Split=Y + DockNode ID=0x00000001 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75 + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=2528,653 Split=X Selected=0x61E02D75 + DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1840,653 CentralNode=1 Selected=0x61E02D75 + DockNode ID=0x00000007 Parent=0x00000003 SizeRef=686,653 Selected=0x5E5F7166 + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=2528,651 Selected=0x0FA43D88 + DockNode ID=0x00000002 Parent=0x85940918 SizeRef=1453,471 Selected=0x6D7E7D39 diff --git a/src/client/main.nim b/src/client/main.nim index 1e31195..b7d20bc 100644 --- a/src/client/main.nim +++ b/src/client/main.nim @@ -19,6 +19,15 @@ proc main() = views["Listeners"] = addr showListeners views["Eventlog"] = addr showEventlog + # Create components + var + dockspace = Dockspace() + sessionsTable = SessionsTable("Sessions [Table View]") + sessionsGraph = SessionsTable("Sessions [Graph View]") + listenersTable = ListenersTable("Listeners") + eventlog = Eventlog("Eventlog") + + let io = igGetIO() # main loop @@ -30,13 +39,11 @@ proc main() = continue newFrame() - # UI components/views - Dockspace().draw(addr showConquest, views) - - if showSessionsTable: SessionsTable("Sessions [Table View]").draw(addr showSessionsTable) - if showSessionsGraph: SessionsTable("Sessions [Graph View]").draw(addr showSessionsGraph) - if showListeners: ListenersTable("Listeners").draw(addr showListeners) - if showEventlog:Eventlog("Eventlog").draw(addr showEventlog) + # Draw/update UI components/views + dockspace.draw(addr showConquest, views) + if showSessionsTable: sessionsTable.draw(addr showSessionsTable) + if showListeners: listenersTable.draw(addr showListeners) + if showEventlog: eventlog.draw(addr showEventlog) igShowDemoWindow(nil) diff --git a/src/client/views/sessions.nim b/src/client/views/sessions.nim index df49a06..0061a20 100644 --- a/src/client/views/sessions.nim +++ b/src/client/views/sessions.nim @@ -1,13 +1,13 @@ import times import imguin/[cimgui, glfw_opengl, simple] import ../utils/appImGui -import ../../common/[types] +import ../../common/[types, utils] type SessionsTableComponent = ref object of RootObj title: string agents: seq[Agent] - + selection: ptr ImGuiSelectionBasicStorage let exampleAgents: seq[Agent] = @[ Agent( @@ -43,6 +43,40 @@ let exampleAgents: seq[Agent] = @[ 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] + ), + Agent( + agentId: "C9D8E7F6", + listenerId: "L2468135", + username: "charlie", + hostname: "SERVER-03", + domain: "IT", + ip: "172.16.0.20", + os: "Windows Server 2019", + process: "powershell.exe", + pid: 7890, + elevated: true, + sleep: 30, + tasks: @[], + firstCheckin: now() - initDuration(hours = 3, minutes = 15), + latestCheckin: now() - initDuration(minutes = 10), + sessionKey: [byte 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + ), + Agent( + agentId: "G1H2I3J4", + listenerId: "L1357924", + username: "diana", + hostname: "WORKSTATION-04", + domain: "HR", + ip: "192.168.2.15", + os: "Windows 10", + process: "chrome.exe", + pid: 3210, + elevated: false, + sleep: 90, + tasks: @[], + firstCheckin: now() - initDuration(hours = 4), + latestCheckin: now() - initDuration(minutes = 2), + sessionKey: [byte 5, 4, 3, 2, 1, 0, 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] ) ] @@ -50,6 +84,7 @@ proc SessionsTable*(title: string): SessionsTableComponent = result = new SessionsTableComponent result.title = title result.agents = exampleAgents + result.selection = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage() proc draw*(component: SessionsTableComponent, showComponent: ptr bool) = igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32) @@ -62,13 +97,12 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) = 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 + ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or ImGui_TableFlags_SizingStretchProp.int32 ) @@ -86,12 +120,20 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) = igTableSetupScrollFreeze(0, 1) igTableHeadersRow() + + var multiSelectIO = igBeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape.int32 or ImGuiMultiSelectFlags_BoxSelect1d.int32, component.selection[].Size, int32(component.agents.len())) + ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO) 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(0): + # Enable multi-select functionality + igSetNextItemSelectionUserData(row) + var isSelected = ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](row)) + discard igSelectable_Bool(agent.agentId, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32, vec2(0.0f, 0.0f)) if igTableSetColumnIndex(1): igText(agent.ip) if igTableSetColumnIndex(2): @@ -107,6 +149,23 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) = if igTableSetColumnIndex(7): igText(agent.latestCheckin.format("yyyy-MM-dd HH:mm:ss")) + # Handle right-click context menu + # Right-clicking the table header to hide/show columns or reset the layout is only possible when no sessions are selected + if component.selection[].Size > 0 and igBeginPopupContextWindow("TableContextMenu", ImGui_PopupFlags_MouseButtonRight.int32): + + if igMenuItem("Interact", "ENTER", false, true): + igCloseCurrentPopup() + + if igMenuItem("Remove", "DELETE", false, true): + igCloseCurrentPopup() + + igEndPopup() + + + multiSelectIO = igEndMultiSelect() + ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO) + igEndTable() + \ No newline at end of file