Implemented dual list selection widgets for choosing modules.
This commit is contained in:
@@ -119,10 +119,14 @@ IsChild=1
|
|||||||
Size=1363,540
|
Size=1363,540
|
||||||
|
|
||||||
[Window][Generate Payload]
|
[Window][Generate Payload]
|
||||||
Pos=704,337
|
Pos=1071,500
|
||||||
Size=500,325
|
Size=717,677
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Generate Payload/0_B6B17D5F]
|
||||||
|
IsChild=1
|
||||||
|
Size=326,310
|
||||||
|
|
||||||
[Table][0x32886A44,8]
|
[Table][0x32886A44,8]
|
||||||
Column 0 Weight=0.6465
|
Column 0 Weight=0.6465
|
||||||
Column 1 Weight=0.9697
|
Column 1 Weight=0.9697
|
||||||
@@ -148,6 +152,6 @@ DockNode ID=0x00000009 Pos=100,200 Size=754,103 Selected=0x64D005CF
|
|||||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2848,1642 Split=Y
|
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2848,1642 Split=Y
|
||||||
DockNode ID=0x00000005 Parent=0x85940918 SizeRef=1888,474 Split=X
|
DockNode ID=0x00000005 Parent=0x85940918 SizeRef=1888,474 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=2101,159 CentralNode=1 Selected=0x61E02D75
|
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=2101,159 CentralNode=1 Selected=0x61E02D75
|
||||||
DockNode ID=0x00000004 Parent=0x00000005 SizeRef=745,159 Selected=0x0FA43D88
|
DockNode ID=0x00000004 Parent=0x00000005 SizeRef=745,159 Selected=0x5E5F7166
|
||||||
DockNode ID=0x00000006 Parent=0x85940918 SizeRef=1888,1166 Selected=0x6BE22050
|
DockNode ID=0x00000006 Parent=0x85940918 SizeRef=1888,1166 Selected=0x6BE22050
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import imguin/[cimgui, glfw_opengl, simple]
|
|||||||
import ../utils/appImGui
|
import ../utils/appImGui
|
||||||
|
|
||||||
# https://rgbcolorpicker.com/0-1
|
# https://rgbcolorpicker.com/0-1
|
||||||
|
const GRAY* = vec4(0.369f, 0.369f, 0.369f, 1.0f)
|
||||||
const CONSOLE_ERROR* = vec4(0.878f, 0.188f, 0.149f, 1.0f)
|
const CONSOLE_ERROR* = vec4(0.878f, 0.188f, 0.149f, 1.0f)
|
||||||
const CONSOLE_INFO* = vec4(0.588f, 0.843f, 0.89f, 1.0f)
|
const CONSOLE_INFO* = vec4(0.588f, 0.843f, 0.89f, 1.0f)
|
||||||
const CONSOLE_SUCCESS* = vec4(0.176f, 0.569f, 0.075f, 1.0f)
|
const CONSOLE_SUCCESS* = vec4(0.176f, 0.569f, 0.075f, 1.0f)
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, ws: WebS
|
|||||||
|
|
||||||
component.generatePayloadModal.draw()
|
component.generatePayloadModal.draw()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Listener table
|
Listener table
|
||||||
]#
|
]#
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import strutils
|
import strutils, sequtils
|
||||||
import imguin/[cimgui, glfw_opengl, simple]
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
import ../../utils/appImGui
|
import ../../utils/[appImGui, colors]
|
||||||
import ../../../common/[types, utils]
|
import ../../../common/[types, utils]
|
||||||
|
import ../widgets/dualListSelection
|
||||||
|
|
||||||
type
|
type
|
||||||
AgentModalComponent* = ref object of RootObj
|
AgentModalComponent* = ref object of RootObj
|
||||||
@@ -12,6 +12,7 @@ type
|
|||||||
spoofStack: bool
|
spoofStack: bool
|
||||||
listeners: seq[string]
|
listeners: seq[string]
|
||||||
sleepMaskTechniques: seq[string]
|
sleepMaskTechniques: seq[string]
|
||||||
|
moduleSelection: DualListSelectionComponent
|
||||||
|
|
||||||
proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
||||||
result = new AgentModalComponent
|
result = new AgentModalComponent
|
||||||
@@ -23,8 +24,16 @@ proc AgentModal*(listeners: seq[Listener]): AgentModalComponent =
|
|||||||
for l in listeners:
|
for l in listeners:
|
||||||
result.listeners.add(l.listenerId)
|
result.listeners.add(l.listenerId)
|
||||||
|
|
||||||
for s in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high:
|
for technique in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high:
|
||||||
result.sleepMaskTechniques.add($s)
|
result.sleepMaskTechniques.add($technique)
|
||||||
|
|
||||||
|
var modules: seq[string]
|
||||||
|
for module in ModuleType:
|
||||||
|
# Magic to convert MODULE_SITUATIONAL_AWARENESS into SituationalAwareness, etc.
|
||||||
|
var name = ($module).split("_")[1..^1].mapIt(it.toLowerAscii().capitalizeAscii()).join("")
|
||||||
|
modules.add(name)
|
||||||
|
|
||||||
|
result.moduleSelection = DualListSelection(modules)
|
||||||
|
|
||||||
proc resetModalValues(component: AgentModalComponent) =
|
proc resetModalValues(component: AgentModalComponent) =
|
||||||
discard
|
discard
|
||||||
@@ -86,7 +95,7 @@ proc draw*(component: AgentModalComponent) =
|
|||||||
|
|
||||||
igText("Modules: ")
|
igText("Modules: ")
|
||||||
|
|
||||||
|
component.moduleSelection.draw()
|
||||||
|
|
||||||
igGetContentRegionAvail(addr availableSize)
|
igGetContentRegionAvail(addr availableSize)
|
||||||
|
|
||||||
|
|||||||
159
src/client/views/widgets/dualListSelection.nim
Normal file
159
src/client/views/widgets/dualListSelection.nim
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
import strutils
|
||||||
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
|
import ../../utils/[appImGui, colors]
|
||||||
|
import ../../../common/[types, utils]
|
||||||
|
|
||||||
|
type
|
||||||
|
Direction = enum
|
||||||
|
Right = 0
|
||||||
|
Left = 1
|
||||||
|
|
||||||
|
DualListSelectionComponent* = ref object of RootObj
|
||||||
|
items: array[2, seq[string]]
|
||||||
|
selection: array[2, ptr ImGuiSelectionBasicStorage]
|
||||||
|
|
||||||
|
proc DualListSelection*(items: seq[string]): DualListSelectionComponent =
|
||||||
|
result = new DualListSelectionComponent
|
||||||
|
result.items[0] = items
|
||||||
|
result.items[1] = @[]
|
||||||
|
result.selection[0] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||||
|
result.selection[1] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||||
|
|
||||||
|
proc moveAll(component: DualListSelectionComponent, direction: Direction) =
|
||||||
|
|
||||||
|
if direction == Right:
|
||||||
|
for m in component.items[0]:
|
||||||
|
component.items[1].add(m)
|
||||||
|
component.items[0].setLen(0)
|
||||||
|
|
||||||
|
ImGuiSelectionBasicStorage_Swap(component.selection[0], component.selection[1])
|
||||||
|
ImGuiSelectionBasicStorage_Clear(component.selection[0])
|
||||||
|
|
||||||
|
else:
|
||||||
|
for m in component.items[1]:
|
||||||
|
component.items[0].add(m)
|
||||||
|
component.items[1].setLen(0)
|
||||||
|
|
||||||
|
ImGuiSelectionBasicStorage_Swap(component.selection[1], component.selection[0])
|
||||||
|
ImGuiSelectionBasicStorage_Clear(component.selection[1])
|
||||||
|
|
||||||
|
proc moveSelection(component: DualListSelectionComponent, direction: Direction) =
|
||||||
|
|
||||||
|
if direction == Right:
|
||||||
|
var
|
||||||
|
keep: seq[string]
|
||||||
|
|
||||||
|
for i in 0 ..< component.items[0].len():
|
||||||
|
let item = component.items[0][i]
|
||||||
|
if not component.selection[0].ImGuiSelectionBasicStorage_Contains(cast[ImGuiID](i)):
|
||||||
|
keep.add(item)
|
||||||
|
continue
|
||||||
|
component.items[1].add(item)
|
||||||
|
component.items[0] = keep
|
||||||
|
|
||||||
|
ImGuiSelectionBasicStorage_Swap(component.selection[0], component.selection[1])
|
||||||
|
ImGuiSelectionBasicStorage_Clear(component.selection[0])
|
||||||
|
|
||||||
|
else:
|
||||||
|
var
|
||||||
|
keep: seq[string]
|
||||||
|
|
||||||
|
for i in 0 ..< component.items[1].len():
|
||||||
|
let item = component.items[1][i]
|
||||||
|
if not component.selection[1].ImGuiSelectionBasicStorage_Contains(cast[ImGuiID](i)):
|
||||||
|
keep.add(item)
|
||||||
|
continue
|
||||||
|
component.items[0].add(item)
|
||||||
|
component.items[1] = keep
|
||||||
|
|
||||||
|
ImGuiSelectionBasicStorage_Swap(component.selection[1], component.selection[0])
|
||||||
|
ImGuiSelectionBasicStorage_Clear(component.selection[1])
|
||||||
|
|
||||||
|
proc draw*(component: DualListSelectionComponent) =
|
||||||
|
|
||||||
|
if igBeginTable("split", 3, ImGuiTableFlags_None.int32, vec2(0.0f, 0.0f), 0.0f):
|
||||||
|
|
||||||
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthStretch.int32, 0.0f, 0) # Left
|
||||||
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed.int32, 0.0f, 0) # Buttons
|
||||||
|
igTableSetupColumn("", ImGuiTableColumnFlags_WidthStretch.int32, 0.0f, 0) # Right
|
||||||
|
igTableNextRow(ImGuiTableRowFlags_None.int32, 0.0f)
|
||||||
|
|
||||||
|
var containerHeight: float
|
||||||
|
|
||||||
|
# Left selection container
|
||||||
|
igTableSetColumnIndex(0)
|
||||||
|
|
||||||
|
var modules = component.items[0]
|
||||||
|
var selection = component.selection[0]
|
||||||
|
|
||||||
|
# Header
|
||||||
|
var text = "Available"
|
||||||
|
var textSize: ImVec2
|
||||||
|
igCalcTextSize(addr textSize, text, nil, false, 0.0f)
|
||||||
|
igSetCursorPosX(igGetCursorPosX() + (igGetColumnWidth(0) - textSize.x) * 0.5f)
|
||||||
|
igTextColored(GRAY, text)
|
||||||
|
|
||||||
|
# Set the size of selection box to fit all modules
|
||||||
|
igSetNextWindowContentSize(vec2(0.0f, float(modules.len()) * igGetTextLineHeightWithSpacing()))
|
||||||
|
igSetNextWindowSizeConstraints(vec2(0.0f, igGetTextLineHeightWithSpacing() * 10.0f), vec2(igGET_FLT_MAX(), igGET_FLT_MAX()), nil, nil) # Set minimum container size
|
||||||
|
if igBeginChild_Str("0", vec2(0.0f, -1.0f), ImGuiChildFlags_FrameStyle.int32 or ImGuiChildFlags_ResizeY.int32, ImGuiWindowFlags_None.int32):
|
||||||
|
containerHeight = igGetWindowHeight()
|
||||||
|
|
||||||
|
var multiSelectIO = igBeginMultiSelect(ImGuiMultiSelectFlags_None.int32, selection[].Size, int32(modules.len()))
|
||||||
|
ImGuiSelectionBasicStorage_ApplyRequests(selection, multiSelectIO)
|
||||||
|
|
||||||
|
for row in 0 ..< modules.len().int32:
|
||||||
|
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
||||||
|
igSetNextItemSelectionUserData(row)
|
||||||
|
discard igSelectable_Bool(modules[row], isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
|
multiSelectIO = igEndMultiSelect()
|
||||||
|
ImGuiSelectionBasicStorage_ApplyRequests(selection, multiSelectIO)
|
||||||
|
|
||||||
|
igEndChild()
|
||||||
|
|
||||||
|
# Buttons column
|
||||||
|
igTableSetColumnIndex(1)
|
||||||
|
igNewLine()
|
||||||
|
|
||||||
|
let buttonSize = vec2(igGetFrameHeight(), igGetFrameHeight())
|
||||||
|
if igButton(">>", buttonSize):
|
||||||
|
component.moveAll(Right)
|
||||||
|
if igButton(">", buttonSize):
|
||||||
|
component.moveSelection(Right)
|
||||||
|
if igButton("<", buttonSize):
|
||||||
|
component.moveSelection(Left)
|
||||||
|
if igButton("<<", buttonSize):
|
||||||
|
component.moveAll(Left)
|
||||||
|
|
||||||
|
# Right selection container
|
||||||
|
igTableSetColumnIndex(2)
|
||||||
|
|
||||||
|
modules = component.items[1]
|
||||||
|
selection = component.selection[1]
|
||||||
|
|
||||||
|
# Header
|
||||||
|
text = "Selected"
|
||||||
|
igCalcTextSize(addr textSize, text, nil, false, 0.0f)
|
||||||
|
igSetCursorPosX(igGetCursorPosX() + (igGetColumnWidth(2) - textSize.x) * 0.5f)
|
||||||
|
igTextColored(GRAY, text)
|
||||||
|
|
||||||
|
# Set the size of selection box to fit all modules
|
||||||
|
igSetNextWindowContentSize(vec2(0.0f, float(modules.len()) * igGetTextLineHeightWithSpacing()))
|
||||||
|
if igBeginChild_Str("1", vec2(0.0f, containerHeight), ImGuiChildFlags_FrameStyle.int32, ImGuiWindowFlags_None.int32):
|
||||||
|
|
||||||
|
var multiSelectIO = igBeginMultiSelect(ImGuiMultiSelectFlags_None.int32, selection[].Size, int32(modules.len()))
|
||||||
|
ImGuiSelectionBasicStorage_ApplyRequests(selection, multiSelectIO)
|
||||||
|
|
||||||
|
for row in 0 ..< modules.len().int32:
|
||||||
|
var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row))
|
||||||
|
igSetNextItemSelectionUserData(row)
|
||||||
|
discard igSelectable_Bool(modules[row], isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
|
multiSelectIO = igEndMultiSelect()
|
||||||
|
ImGuiSelectionBasicStorage_ApplyRequests(selection, multiSelectIO)
|
||||||
|
|
||||||
|
igEndChild()
|
||||||
|
|
||||||
|
|
||||||
|
igEndTable()
|
||||||
@@ -99,6 +99,18 @@ type
|
|||||||
ZILEAN = 2'u8
|
ZILEAN = 2'u8
|
||||||
FOLIAGE = 3'u8
|
FOLIAGE = 3'u8
|
||||||
|
|
||||||
|
# Custom iterator for ModuleType, as it uses powers of 2 instead of standard increments
|
||||||
|
iterator items*(e: typedesc[ModuleType]): ModuleType =
|
||||||
|
# yield MODULE_ALL
|
||||||
|
yield MODULE_SLEEP
|
||||||
|
yield MODULE_SHELL
|
||||||
|
yield MODULE_BOF
|
||||||
|
yield MODULE_DOTNET
|
||||||
|
yield MODULE_FILESYSTEM
|
||||||
|
yield MODULE_FILETRANSFER
|
||||||
|
yield MODULE_SCREENSHOT
|
||||||
|
yield MODULE_SITUATIONAL_AWARENESS
|
||||||
|
|
||||||
# Encryption
|
# Encryption
|
||||||
type
|
type
|
||||||
Uuid* = uint32
|
Uuid* = uint32
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ proc serve(listener: Listener) {.thread.} =
|
|||||||
discard
|
discard
|
||||||
|
|
||||||
proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protocol: Protocol) =
|
proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protocol: Protocol) =
|
||||||
|
|
||||||
# Validate arguments
|
|
||||||
try:
|
try:
|
||||||
# Create new listener
|
# Create new listener
|
||||||
var router: Router
|
var router: Router
|
||||||
|
|||||||
Reference in New Issue
Block a user