diff --git a/src/client/layout.ini b/src/client/layout.ini index 4de0de7..17a1c06 100644 --- a/src/client/layout.ini +++ b/src/client/layout.ini @@ -119,10 +119,14 @@ IsChild=1 Size=1363,540 [Window][Generate Payload] -Pos=704,337 -Size=500,325 +Pos=1071,500 +Size=717,677 Collapsed=0 +[Window][Generate Payload/0_B6B17D5F] +IsChild=1 +Size=326,310 + [Table][0x32886A44,8] Column 0 Weight=0.6465 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 DockNode ID=0x00000005 Parent=0x85940918 SizeRef=1888,474 Split=X 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 diff --git a/src/client/utils/colors.nim b/src/client/utils/colors.nim index 39e4e65..174eb83 100644 --- a/src/client/utils/colors.nim +++ b/src/client/utils/colors.nim @@ -2,6 +2,7 @@ import imguin/[cimgui, glfw_opengl, simple] import ../utils/appImGui # 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_INFO* = vec4(0.588f, 0.843f, 0.89f, 1.0f) const CONSOLE_SUCCESS* = vec4(0.176f, 0.569f, 0.075f, 1.0f) diff --git a/src/client/views/listeners.nim b/src/client/views/listeners.nim index da8f0dd..019f69c 100644 --- a/src/client/views/listeners.nim +++ b/src/client/views/listeners.nim @@ -59,9 +59,6 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, ws: WebS component.generatePayloadModal.draw() - - - #[ Listener table ]# diff --git a/src/client/views/modals/generatePayload.nim b/src/client/views/modals/generatePayload.nim index ff3f880..934449e 100644 --- a/src/client/views/modals/generatePayload.nim +++ b/src/client/views/modals/generatePayload.nim @@ -1,8 +1,8 @@ -import strutils +import strutils, sequtils import imguin/[cimgui, glfw_opengl, simple] -import ../../utils/appImGui +import ../../utils/[appImGui, colors] import ../../../common/[types, utils] - +import ../widgets/dualListSelection type AgentModalComponent* = ref object of RootObj @@ -12,6 +12,7 @@ type spoofStack: bool listeners: seq[string] sleepMaskTechniques: seq[string] + moduleSelection: DualListSelectionComponent proc AgentModal*(listeners: seq[Listener]): AgentModalComponent = result = new AgentModalComponent @@ -23,8 +24,16 @@ proc AgentModal*(listeners: seq[Listener]): AgentModalComponent = for l in listeners: result.listeners.add(l.listenerId) - for s in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high: - result.sleepMaskTechniques.add($s) + for technique in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high: + 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) = discard @@ -86,7 +95,7 @@ proc draw*(component: AgentModalComponent) = igText("Modules: ") - + component.moduleSelection.draw() igGetContentRegionAvail(addr availableSize) diff --git a/src/client/views/widgets/dualListSelection.nim b/src/client/views/widgets/dualListSelection.nim new file mode 100644 index 0000000..6ee40ae --- /dev/null +++ b/src/client/views/widgets/dualListSelection.nim @@ -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() \ No newline at end of file diff --git a/src/common/types.nim b/src/common/types.nim index 36cb746..6c11226 100644 --- a/src/common/types.nim +++ b/src/common/types.nim @@ -99,6 +99,18 @@ type ZILEAN = 2'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 type Uuid* = uint32 diff --git a/src/server/core/listener.nim b/src/server/core/listener.nim index fac261e..bcf8340 100644 --- a/src/server/core/listener.nim +++ b/src/server/core/listener.nim @@ -39,8 +39,6 @@ proc serve(listener: Listener) {.thread.} = discard proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protocol: Protocol) = - - # Validate arguments try: # Create new listener var router: Router @@ -98,7 +96,7 @@ proc restartListeners*(cq: Conquest) = # Restart all active listeners that are stored in the database for listener in listeners: try: - # Create new listener + # Create new listener let name: string = generateUUID() var router: Router router.notFoundHandler = routes.error404