diff --git a/src/client/views/listeners.nim b/src/client/views/listeners.nim index b180ca6..4efc091 100644 --- a/src/client/views/listeners.nim +++ b/src/client/views/listeners.nim @@ -32,14 +32,16 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, ws: WebS if igButton("Start Listener", vec2(0.0f, 0.0f)): igOpenPopup_str("Start Listener", ImGui_PopupFlags_None.int32) igSameLine(0.0f, textSpacing) - # Payload generation modal + + # Payload generation modal (only enabled when at least one listener is active) + igBeginDisabled(component.listeners.len() <= 0) if igButton("Generate Payload", vec2(0.0f, 0.0f)): igOpenPopup_str("Generate Payload", ImGui_PopupFlags_None.int32) + igEndDisabled() let listener = component.startListenerModal.draw() if listener != nil: ws.sendStartListener(listener) - component.listeners.add(listener) component.generatePayloadModal.draw(component.listeners) diff --git a/src/client/views/modals/generatePayload.nim b/src/client/views/modals/generatePayload.nim index 6191188..333bb77 100644 --- a/src/client/views/modals/generatePayload.nim +++ b/src/client/views/modals/generatePayload.nim @@ -2,6 +2,7 @@ import strutils, sequtils import imguin/[cimgui, glfw_opengl, simple] import ../../utils/[appImGui, colors] import ../../../common/[types, profile, utils] +import ../../../modules/manager import ../widgets/dualListSelection type @@ -11,7 +12,7 @@ type sleepMask: int32 spoofStack: bool sleepMaskTechniques: seq[string] - moduleSelection: DualListSelectionComponent[ModuleType] + moduleSelection: DualListSelectionComponent[Module] proc AgentModal*(): AgentModalComponent = result = new AgentModalComponent @@ -23,14 +24,17 @@ proc AgentModal*(): AgentModalComponent = for technique in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high: result.sleepMaskTechniques.add($technique) - var modules: seq[ModuleType] - for module in ModuleType: - modules.add(module) + let modules = getModules() + proc moduleName(module: Module): string = + return module.name + proc moduleDesc(module: Module): string = + result = module.description & "\nModule commands:\n" + for cmd in module.commands: + result &= " - " & cmd.name & "\n" + proc compareModules(x, y: Module): int = + return cmp(x.name, y.name) - proc moduleName(module: ModuleType): string = - return ($module).split("_")[1..^1].mapIt(it.toLowerAscii().capitalizeAscii()).join("") - - result.moduleSelection = DualListSelection(modules, moduleName) + result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc) proc resetModalValues(component: AgentModalComponent) = component.listener = 0 @@ -119,7 +123,7 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]) = # Iterate over modules var module: uint32 = 0 for m in component.moduleSelection.items[1]: - module = module or uint32(m) + module = module or uint32(m.moduleType) echo module component.resetModalValues() diff --git a/src/client/views/widgets/dualListSelection.nim b/src/client/views/widgets/dualListSelection.nim index b3ad38f..9e6fe07 100644 --- a/src/client/views/widgets/dualListSelection.nim +++ b/src/client/views/widgets/dualListSelection.nim @@ -1,6 +1,6 @@ import strutils, sequtils, algorithm import imguin/[cimgui, glfw_opengl, simple] -import ../../utils/[appImGui, colors] +import ../../utils/[appImGui, colors, utils] import ../../../common/[types, utils] type @@ -8,36 +8,40 @@ type items*: array[2, seq[T]] selection: array[2, ptr ImGuiSelectionBasicStorage] display: proc(item: T): string + compare: proc(x, y: T): int + tooltip: proc(item: T): string proc defaultDisplay[T](item: T): string = return $item -proc DualListSelection*[T](items: seq[T], display: proc(item: T): string = defaultDisplay): DualListSelectionComponent[T] = +proc DualListSelection*[T](items: seq[T], display: proc(item: T): string = defaultDisplay, compare: proc(x, y: T): int, tooltip: proc(item: T): string = nil): DualListSelectionComponent[T] = result = new DualListSelectionComponent[T] result.items[0] = items result.items[1] = @[] result.selection[0] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage() result.selection[1] = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage() result.display = display + result.compare = compare + result.tooltip = tooltip proc moveAll[T](component: DualListSelectionComponent[T], src, dst: int) = for m in component.items[src]: component.items[dst].add(m) - component.items[dst].sort() + component.items[dst].sort(component.compare) component.items[src].setLen(0) ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst]) ImGuiSelectionBasicStorage_Clear(component.selection[src]) proc moveSelection[T](component: DualListSelectionComponent[T], src, dst: int) = - var keep: seq[ModuleType] + var keep: seq[T] for i in 0 ..< component.items[src].len(): let item = component.items[src][i] if not component.selection[src].ImGuiSelectionBasicStorage_Contains(cast[ImGuiID](i)): keep.add(item) continue component.items[dst].add(item) - component.items[dst].sort() + component.items[dst].sort(component.compare) component.items[src] = keep ImGuiSelectionBasicStorage_Swap(component.selection[src], component.selection[dst]) @@ -83,6 +87,9 @@ proc draw*[T](component: DualListSelectionComponent[T]) = var isSelected = ImGuiSelectionBasicStorage_Contains(selection, cast[ImGuiID](row)) igSetNextItemSelectionUserData(row) discard igSelectable_Bool(component.display(modules[row]), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f)) + + if not component.tooltip.isNil(): + setTooltip(component.tooltip(modules[row])) # Move on Enter and double-click if igIsItemFocused(): @@ -134,6 +141,9 @@ proc draw*[T](component: DualListSelectionComponent[T]) = igSetNextItemSelectionUserData(row) discard igSelectable_Bool(component.display(modules[row]), isSelected, ImGuiSelectableFlags_AllowDoubleClick.int32, vec2(0.0f, 0.0f)) + if not component.tooltip.isNil(): + setTooltip(component.tooltip(modules[row])) + # Move on Enter and double-click if igIsItemFocused(): if igIsKeyPressed_Bool(ImGuiKey_Enter, false) or igIsKeyPressed_Bool(ImGuiKey_KeypadEnter, false): diff --git a/src/common/types.nim b/src/common/types.nim index e55065c..a05fcb0 100644 --- a/src/common/types.nim +++ b/src/common/types.nim @@ -318,6 +318,7 @@ type Module* = object name*: string description*: string + moduleType*: ModuleType commands*: seq[Command] # Definitions for ImGui User interface diff --git a/src/modules/bof.nim b/src/modules/bof.nim index 97436d8..22ea85e 100644 --- a/src/modules/bof.nim +++ b/src/modules/bof.nim @@ -7,6 +7,7 @@ proc executeBof(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("bof"), description: protect("Load and execute BOF/COFF files in memory."), + moduleType: MODULE_BOF, commands: @[ Command( name: protect("bof"), @@ -23,7 +24,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeBof(ctx: AgentCtx, task: Task): TaskResult = nil when defined(agent): diff --git a/src/modules/dotnet.nim b/src/modules/dotnet.nim index 8ecbad3..f842409 100644 --- a/src/modules/dotnet.nim +++ b/src/modules/dotnet.nim @@ -7,6 +7,7 @@ proc executeAssembly(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("dotnet"), description: protect("Load and execute .NET assemblies in memory."), + moduleType: MODULE_DOTNET, commands: @[ Command( name: protect("dotnet"), @@ -23,7 +24,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeAssembly(ctx: AgentCtx, task: Task): TaskResult = nil when defined(agent): diff --git a/src/modules/filesystem.nim b/src/modules/filesystem.nim index faf3da5..bdb57a7 100644 --- a/src/modules/filesystem.nim +++ b/src/modules/filesystem.nim @@ -13,6 +13,7 @@ proc executeCopy(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("filesystem"), description: protect("Conduct simple filesystem operations via Windows API."), + moduleType: MODULE_DOTNET, commands: @[ Command( name: protect("pwd"), @@ -88,7 +89,7 @@ let module* = Module( ) # Implementation of the execution functions -when defined(server): +when not defined(agent): proc executePwd(ctx: AgentCtx, task: Task): TaskResult = nil proc executeCd(ctx: AgentCtx, task: Task): TaskResult = nil proc executeDir(ctx: AgentCtx, task: Task): TaskResult = nil diff --git a/src/modules/filetransfer.nim b/src/modules/filetransfer.nim index fb23a82..e4f6d9e 100644 --- a/src/modules/filetransfer.nim +++ b/src/modules/filetransfer.nim @@ -8,6 +8,7 @@ proc executeUpload(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("filetransfer"), description: protect("Upload/download files to/from the target system."), + moduleType: MODULE_FILESYSTEM, commands: @[ Command( name: protect("download"), @@ -33,7 +34,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeDownload(ctx: AgentCtx, task: Task): TaskResult = nil proc executeUpload(ctx: AgentCtx, task: Task): TaskResult = nil diff --git a/src/modules/manager.nim b/src/modules/manager.nim index 4b02782..7204a85 100644 --- a/src/modules/manager.nim +++ b/src/modules/manager.nim @@ -5,12 +5,14 @@ const MODULES {.intdefine.} = 0 type ModuleManager* = object + modules*: seq[Module] commandsByType*: Table[CommandType, Command] commandsByName*: Table[string, Command] var manager: ModuleManager proc registerModule(module: Module) {.discardable.} = + manager.modules.add(module) for cmd in module.commands: manager.commandsByType[cmd.commandType] = cmd manager.commandsByName[cmd.name] = cmd @@ -71,4 +73,7 @@ proc getCommandByName*(cmdName: string): Command = raise newException(ValueError, fmt"The command '{cmdName}' does not exist.") proc getAvailableCommands*(): Table[string, Command] = - return manager.commandsByName \ No newline at end of file + return manager.commandsByName + +proc getModules*(): seq[Module] = + return manager.modules \ No newline at end of file diff --git a/src/modules/screenshot.nim b/src/modules/screenshot.nim index 2823baf..4ee6aab 100644 --- a/src/modules/screenshot.nim +++ b/src/modules/screenshot.nim @@ -7,6 +7,7 @@ proc executeScreenshot(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("screenshot"), description: protect("Take and retrieve a screenshot of the target desktop."), + moduleType: MODULE_SCREENSHOT, commands: @[ Command( name: protect("screenshot"), @@ -20,7 +21,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeScreenshot(ctx: AgentCtx, task: Task): TaskResult = nil when defined(agent): diff --git a/src/modules/shell.nim b/src/modules/shell.nim index 1dcf48b..98016c8 100644 --- a/src/modules/shell.nim +++ b/src/modules/shell.nim @@ -7,6 +7,7 @@ proc executeShell(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("shell"), description: protect("Execute shell commands or programs."), + moduleType: MODULE_SHELL, commands: @[ Command( name: protect("shell"), @@ -23,7 +24,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeShell(ctx: AgentCtx, task: Task): TaskResult = nil when defined(agent): diff --git a/src/modules/situationalAwareness.nim b/src/modules/situationalAwareness.nim index 1a42d11..55d1461 100644 --- a/src/modules/situationalAwareness.nim +++ b/src/modules/situationalAwareness.nim @@ -9,6 +9,7 @@ proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("situational-awareness"), description: protect("Retrieve information about the target system and environment."), + moduleType: MODULE_SITUATIONAL_AWARENESS, commands: @[ Command( name: protect("ps"), @@ -38,7 +39,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executePs(ctx: AgentCtx, task: Task): TaskResult = nil proc executeEnv(ctx: AgentCtx, task: Task): TaskResult = nil proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult = nil diff --git a/src/modules/sleep.nim b/src/modules/sleep.nim index ef72472..1a68612 100644 --- a/src/modules/sleep.nim +++ b/src/modules/sleep.nim @@ -8,6 +8,7 @@ proc executeSleepmask(ctx: AgentCtx, task: Task): TaskResult let module* = Module( name: protect("sleep"), description: protect("Change sleep settings."), + moduleType: MODULE_SLEEP, commands: @[ Command( name: protect("sleep"), @@ -34,7 +35,7 @@ let module* = Module( ) # Implement execution functions -when defined(server): +when not defined(agent): proc executeSleep(ctx: AgentCtx, task: Task): TaskResult = nil proc executeSleepmask(ctx: AgentCtx, task: Task): TaskResult = nil