Made dual list selection widget generic.
This commit is contained in:
@@ -1,43 +1,43 @@
|
|||||||
[Window][Sessions [Table View]]
|
[Window][Sessions [Table View]]
|
||||||
Pos=10,43
|
Pos=10,43
|
||||||
Size=1141,338
|
Size=1310,279
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Listeners]
|
[Window][Listeners]
|
||||||
Pos=10,383
|
Pos=10,324
|
||||||
Size=1888,654
|
Size=1888,665
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Eventlog]
|
[Window][Eventlog]
|
||||||
Pos=1153,43
|
Pos=1322,43
|
||||||
Size=745,338
|
Size=576,279
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][Dear ImGui Demo]
|
[Window][Dear ImGui Demo]
|
||||||
Pos=1153,43
|
Pos=1322,43
|
||||||
Size=745,338
|
Size=576,279
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,1
|
DockId=0x00000004,1
|
||||||
|
|
||||||
[Window][Dockspace]
|
[Window][Dockspace]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=1908,1047
|
Size=1908,999
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][[FACEDEAD] bob@LAPTOP-02]
|
[Window][[FACEDEAD] bob@LAPTOP-02]
|
||||||
Pos=10,661
|
Pos=10,395
|
||||||
Size=2848,1024
|
Size=1888,594
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,3
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Window][[C9D8E7F6] charlie@SERVER-03]
|
[Window][[C9D8E7F6] charlie@SERVER-03]
|
||||||
Pos=10,661
|
Pos=10,324
|
||||||
Size=2848,1024
|
Size=1888,665
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,4
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
Pos=60,60
|
Pos=60,60
|
||||||
@@ -45,16 +45,16 @@ Size=400,400
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][[G1H2I3J5] diana@WORKSTATION-04]
|
[Window][[G1H2I3J5] diana@WORKSTATION-04]
|
||||||
Pos=10,372
|
Pos=10,125
|
||||||
Size=1888,617
|
Size=784,665
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,1
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Window][[DEADBEEF] alice@DESKTOP-01]
|
[Window][[DEADBEEF] alice@DESKTOP-01]
|
||||||
Pos=10,661
|
Pos=10,324
|
||||||
Size=2848,1024
|
Size=1888,665
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,2
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Window][Example: Console]
|
[Window][Example: Console]
|
||||||
Pos=10,661
|
Pos=10,661
|
||||||
@@ -119,23 +119,23 @@ IsChild=1
|
|||||||
Size=1363,540
|
Size=1363,540
|
||||||
|
|
||||||
[Window][Generate Payload]
|
[Window][Generate Payload]
|
||||||
Pos=704,185
|
Pos=1075,509
|
||||||
Size=500,677
|
Size=717,677
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Generate Payload/0_B6B17D5F]
|
[Window][Generate Payload/0_B6B17D5F]
|
||||||
IsChild=1
|
IsChild=1
|
||||||
Size=217,310
|
Size=326,310
|
||||||
|
|
||||||
[Table][0x32886A44,8]
|
[Table][0x32886A44,8]
|
||||||
Column 0 Weight=0.6465
|
Column 0 Weight=0.6432
|
||||||
Column 1 Weight=0.9697
|
Column 1 Weight=0.9647
|
||||||
Column 2 Weight=0.6696
|
Column 2 Weight=0.6694
|
||||||
Column 3 Weight=0.9639
|
Column 3 Weight=1.0960
|
||||||
Column 4 Weight=1.7143
|
Column 4 Weight=1.5816
|
||||||
Column 5 Weight=1.1544
|
Column 5 Weight=1.1551
|
||||||
Column 6 Weight=0.4271
|
Column 6 Weight=0.4331
|
||||||
Column 7 Weight=1.4546
|
Column 7 Weight=1.4570
|
||||||
|
|
||||||
[Table][0xB6880529,2]
|
[Table][0xB6880529,2]
|
||||||
RefScale=27
|
RefScale=27
|
||||||
@@ -149,9 +149,9 @@ Column 3 Weight=0.9746
|
|||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockNode ID=0x00000009 Pos=100,200 Size=754,103 Selected=0x64D005CF
|
DockNode ID=0x00000009 Pos=100,200 Size=754,103 Selected=0x64D005CF
|
||||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,994 Split=Y
|
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=1888,946 Split=Y
|
||||||
DockNode ID=0x00000005 Parent=0x85940918 SizeRef=1888,338 Split=X
|
DockNode ID=0x00000005 Parent=0x85940918 SizeRef=1888,279 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=2101,159 CentralNode=1 Selected=0x61E02D75
|
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=1310,159 CentralNode=1 Selected=0x61E02D75
|
||||||
DockNode ID=0x00000004 Parent=0x00000005 SizeRef=745,159 Selected=0x5E5F7166
|
DockNode ID=0x00000004 Parent=0x00000005 SizeRef=576,159 Selected=0x5E5F7166
|
||||||
DockNode ID=0x00000006 Parent=0x85940918 SizeRef=1888,654 Selected=0x6BE22050
|
DockNode ID=0x00000006 Parent=0x85940918 SizeRef=1888,665 Selected=0x65D642C0
|
||||||
|
|
||||||
|
|||||||
@@ -172,20 +172,33 @@ proc draw*(component: ConsoleComponent, ws: WebSocket) =
|
|||||||
Huge thanks to @dinau for implementing ImGuiTextSelect into imguin very rapidly after I requested it.
|
Huge thanks to @dinau for implementing ImGuiTextSelect into imguin very rapidly after I requested it.
|
||||||
]#
|
]#
|
||||||
let consolePadding: float = 10.0f
|
let consolePadding: float = 10.0f
|
||||||
let footerHeight = (consolePadding * 2) + (igGetStyle().ItemSpacing.y + igGetFrameHeightWithSpacing()) * 1.5f
|
let footerHeight = (consolePadding * 2) + (igGetStyle().ItemSpacing.y + igGetFrameHeightWithSpacing()) * 0.75f
|
||||||
let textSpacing = igGetStyle().ItemSpacing.x
|
let textSpacing = igGetStyle().ItemSpacing.x
|
||||||
|
|
||||||
# Padding
|
# Padding
|
||||||
igDummy(vec2(0.0f, consolePadding))
|
igDummy(vec2(0.0f, consolePadding))
|
||||||
|
|
||||||
|
#[
|
||||||
|
Session information
|
||||||
|
]#
|
||||||
|
let domain = if component.agent.domain.isEmptyOrWhitespace(): "" else: fmt".{component.agent.domain}"
|
||||||
|
let sessionInfo = fmt"{component.agent.username}@{component.agent.hostname}{domain} | {component.agent.ip} | {$component.agent.pid}/{component.agent.process}"
|
||||||
|
igTextColored(GRAY, sessionInfo)
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Filter & Options
|
Filter & Options
|
||||||
]#
|
]#
|
||||||
|
|
||||||
|
var availableSize: ImVec2
|
||||||
|
igGetContentRegionAvail(addr availableSize)
|
||||||
var labelSize: ImVec2
|
var labelSize: ImVec2
|
||||||
igCalcTextSize(addr labelSize, ICON_FA_MAGNIFYING_GLASS, nil, false, 0.0f)
|
igCalcTextSize(addr labelSize, ICON_FA_MAGNIFYING_GLASS, nil, false, 0.0f)
|
||||||
igSameLine(0.0f, igGetWindowWidth() - 200.0f - (labelSize.x + textSpacing) - (igGetStyle().WindowPadding.x * 2))
|
|
||||||
|
|
||||||
# SHow tooltip when hovering the search icon
|
let searchBoxWidth: float32 = 200.0f
|
||||||
|
igSameLine(0.0f, availableSize.x - (labelSize.x + textSpacing) - searchBoxWidth)
|
||||||
|
|
||||||
|
# Show tooltip when hovering the search icon
|
||||||
igTextUnformatted(ICON_FA_MAGNIFYING_GLASS.cstring, nil)
|
igTextUnformatted(ICON_FA_MAGNIFYING_GLASS.cstring, nil)
|
||||||
if igIsItemHovered(ImGuiHoveredFlags_None.int32):
|
if igIsItemHovered(ImGuiHoveredFlags_None.int32):
|
||||||
igBeginTooltip()
|
igBeginTooltip()
|
||||||
@@ -199,7 +212,7 @@ proc draw*(component: ConsoleComponent, ws: WebSocket) =
|
|||||||
igSetKeyboardFocusHere(0)
|
igSetKeyboardFocusHere(0)
|
||||||
|
|
||||||
igSameLine(0.0f, textSpacing)
|
igSameLine(0.0f, textSpacing)
|
||||||
component.filter.ImGuiTextFilter_Draw("##ConsoleSearch", 200.0f)
|
component.filter.ImGuiTextFilter_Draw("##ConsoleSearch", searchBoxWidth)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Set styles of the console window
|
# Set styles of the console window
|
||||||
@@ -245,9 +258,8 @@ proc draw*(component: ConsoleComponent, ws: WebSocket) =
|
|||||||
igSameLine(0.0f, textSpacing)
|
igSameLine(0.0f, textSpacing)
|
||||||
|
|
||||||
# Calculate available width for input
|
# Calculate available width for input
|
||||||
var availableWidth: ImVec2
|
igGetContentRegionAvail(addr availableSize)
|
||||||
igGetContentRegionAvail(addr availableWidth)
|
igSetNextItemWidth(availableSize.x)
|
||||||
igSetNextItemWidth(availableWidth.x)
|
|
||||||
|
|
||||||
let inputFlags = ImGuiInputTextFlags_EnterReturnsTrue.int32 or ImGuiInputTextFlags_EscapeClearsAll.int32 or ImGuiInputTextFlags_CallbackHistory.int32 or ImGuiInputTextFlags_CallbackCompletion.int32
|
let inputFlags = ImGuiInputTextFlags_EnterReturnsTrue.int32 or ImGuiInputTextFlags_EscapeClearsAll.int32 or ImGuiInputTextFlags_CallbackHistory.int32 or ImGuiInputTextFlags_CallbackCompletion.int32
|
||||||
if igInputText("##Input", addr component.inputBuffer[0], MAX_INPUT_LENGTH, inputFlags, callback, cast[pointer](component)):
|
if igInputText("##Input", addr component.inputBuffer[0], MAX_INPUT_LENGTH, inputFlags, callback, cast[pointer](component)):
|
||||||
@@ -277,11 +289,4 @@ proc draw*(component: ConsoleComponent, ws: WebSocket) =
|
|||||||
|
|
||||||
igSetItemDefaultFocus()
|
igSetItemDefaultFocus()
|
||||||
if focusInput:
|
if focusInput:
|
||||||
igSetKeyboardFocusHere(-1)
|
igSetKeyboardFocusHere(-1)
|
||||||
|
|
||||||
#[
|
|
||||||
Session information
|
|
||||||
]#
|
|
||||||
let sessionInfo = fmt"{component.agent.username}@{component.agent.hostname}.{component.agent.domain} [{component.agent.ip}] [{component.agent.process}/{$component.agent.pid}]"
|
|
||||||
igTextColored(vec4(0.75f, 0.75f, 0.75f, 1.0f), sessionInfo)
|
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ type
|
|||||||
spoofStack: bool
|
spoofStack: bool
|
||||||
listeners: seq[string]
|
listeners: seq[string]
|
||||||
sleepMaskTechniques: seq[string]
|
sleepMaskTechniques: seq[string]
|
||||||
moduleSelection: DualListSelectionComponent
|
moduleSelection: DualListSelectionComponent[ModuleType]
|
||||||
|
|
||||||
proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
||||||
result = new AgentModalComponent
|
result = new AgentModalComponent
|
||||||
@@ -30,7 +30,11 @@ proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
|||||||
var modules: seq[ModuleType]
|
var modules: seq[ModuleType]
|
||||||
for module in ModuleType:
|
for module in ModuleType:
|
||||||
modules.add(module)
|
modules.add(module)
|
||||||
result.moduleSelection = DualListSelection(modules)
|
|
||||||
|
proc moduleName(module: ModuleType): string =
|
||||||
|
return ($module).split("_")[1..^1].mapIt(it.toLowerAscii().capitalizeAscii()).join("")
|
||||||
|
|
||||||
|
result.moduleSelection = DualListSelection(modules, moduleName)
|
||||||
|
|
||||||
proc resetModalValues(component: AgentModalComponent) =
|
proc resetModalValues(component: AgentModalComponent) =
|
||||||
discard
|
discard
|
||||||
|
|||||||
@@ -4,18 +4,23 @@ import ../../utils/[appImGui, colors]
|
|||||||
import ../../../common/[types, utils]
|
import ../../../common/[types, utils]
|
||||||
|
|
||||||
type
|
type
|
||||||
DualListSelectionComponent* = ref object of RootObj
|
DualListSelectionComponent*[T] = ref object of RootObj
|
||||||
items*: array[2, seq[ModuleType]]
|
items*: array[2, seq[T]]
|
||||||
selection: array[2, ptr ImGuiSelectionBasicStorage]
|
selection: array[2, ptr ImGuiSelectionBasicStorage]
|
||||||
|
display: proc(item: T): string
|
||||||
|
|
||||||
proc DualListSelection*(items: seq[ModuleType]): DualListSelectionComponent =
|
proc defaultDisplay[T](item: T): string =
|
||||||
result = new DualListSelectionComponent
|
return $item
|
||||||
|
|
||||||
|
proc DualListSelection*[T](items: seq[T], display: proc(item: T): string = defaultDisplay): DualListSelectionComponent[T] =
|
||||||
|
result = new DualListSelectionComponent[T]
|
||||||
result.items[0] = items
|
result.items[0] = items
|
||||||
result.items[1] = @[]
|
result.items[1] = @[]
|
||||||
result.selection[0] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
result.selection[0] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||||
result.selection[1] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
result.selection[1] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||||
|
result.display = display
|
||||||
|
|
||||||
proc moveAll(component: DualListSelectionComponent, src, dst: int) =
|
proc moveAll[T](component: DualListSelectionComponent[T], src, dst: int) =
|
||||||
for m in component.items[src]:
|
for m in component.items[src]:
|
||||||
component.items[dst].add(m)
|
component.items[dst].add(m)
|
||||||
component.items[dst].sort()
|
component.items[dst].sort()
|
||||||
@@ -24,7 +29,7 @@ proc moveAll(component: DualListSelectionComponent, src, dst: int) =
|
|||||||
ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst])
|
ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst])
|
||||||
ImGuiSelectionBasicStorage_Clear(component.selection[src])
|
ImGuiSelectionBasicStorage_Clear(component.selection[src])
|
||||||
|
|
||||||
proc moveSelection(component: DualListSelectionComponent, src, dst: int) =
|
proc moveSelection[T](component: DualListSelectionComponent[T], src, dst: int) =
|
||||||
var keep: seq[ModuleType]
|
var keep: seq[ModuleType]
|
||||||
for i in 0 ..< component.items[src].len():
|
for i in 0 ..< component.items[src].len():
|
||||||
let item = component.items[src][i]
|
let item = component.items[src][i]
|
||||||
@@ -38,10 +43,7 @@ proc moveSelection(component: DualListSelectionComponent, src, dst: int) =
|
|||||||
ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst])
|
ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst])
|
||||||
ImGuiSelectionBasicStorage_Clear(component.selection[src])
|
ImGuiSelectionBasicStorage_Clear(component.selection[src])
|
||||||
|
|
||||||
proc moduleName(module: ModuleType): string =
|
proc draw*[T](component: DualListSelectionComponent[T]) =
|
||||||
return ($module).split("_")[1..^1].mapIt(it.toLowerAscii().capitalizeAscii()).join("")
|
|
||||||
|
|
||||||
proc draw*(component: DualListSelectionComponent) =
|
|
||||||
|
|
||||||
if igBeginTable("split", 3, ImGuiTableFlags_None.int32, vec2(0.0f, 0.0f), 0.0f):
|
if igBeginTable("split", 3, ImGuiTableFlags_None.int32, vec2(0.0f, 0.0f), 0.0f):
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ proc draw*(component: DualListSelectionComponent) =
|
|||||||
for row in 0 ..< modules.len().int32:
|
for row in 0 ..< modules.len().int32:
|
||||||
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
||||||
igSetNextItemSelectionUserData(row)
|
igSetNextItemSelectionUserData(row)
|
||||||
discard igSelectable_Bool(modules[row].moduleName(), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
discard igSelectable_Bool(component.display(modules[row]), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
# Move on Enter and double-click
|
# Move on Enter and double-click
|
||||||
if igIsItemFocused():
|
if igIsItemFocused():
|
||||||
@@ -127,7 +129,7 @@ proc draw*(component: DualListSelectionComponent) =
|
|||||||
for row in 0 ..< modules.len().int32:
|
for row in 0 ..< modules.len().int32:
|
||||||
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
||||||
igSetNextItemSelectionUserData(row)
|
igSetNextItemSelectionUserData(row)
|
||||||
discard igSelectable_Bool(modules[row].moduleName(), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
discard igSelectable_Bool(component.display(modules[row]), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
# Move on Enter and double-click
|
# Move on Enter and double-click
|
||||||
if igIsItemFocused():
|
if igIsItemFocused():
|
||||||
|
|||||||
Reference in New Issue
Block a user