Implemented console input field.
This commit is contained in:
@@ -1,43 +1,43 @@
|
|||||||
[Window][Sessions [Table View]]
|
[Window][Sessions [Table View]]
|
||||||
Pos=10,43
|
Pos=10,43
|
||||||
Size=2117,381
|
Size=2117,223
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Listeners]
|
[Window][Listeners]
|
||||||
Pos=10,426
|
Pos=10,268
|
||||||
Size=2528,971
|
Size=2528,1081
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
[Window][Eventlog]
|
[Window][Eventlog]
|
||||||
Pos=2129,43
|
Pos=2129,43
|
||||||
Size=409,381
|
Size=409,223
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][Dear ImGui Demo]
|
[Window][Dear ImGui Demo]
|
||||||
Pos=2129,43
|
Pos=2129,43
|
||||||
Size=409,381
|
Size=409,223
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,1
|
DockId=0x00000004,1
|
||||||
|
|
||||||
[Window][Dockspace]
|
[Window][Dockspace]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=2548,1407
|
Size=2548,1359
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][[FACEDEAD] bob@LAPTOP-02]
|
[Window][[FACEDEAD] bob@LAPTOP-02]
|
||||||
Pos=10,426
|
Pos=10,268
|
||||||
Size=2528,971
|
Size=2528,1081
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,3
|
DockId=0x00000002,1
|
||||||
|
|
||||||
[Window][[C9D8E7F6] charlie@SERVER-03]
|
[Window][[C9D8E7F6] charlie@SERVER-03]
|
||||||
Pos=10,426
|
Pos=10,268
|
||||||
Size=2528,971
|
Size=2528,1081
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,2
|
DockId=0x00000002,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,426
|
Pos=10,268
|
||||||
Size=2528,971
|
Size=2528,1081
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,1
|
DockId=0x00000002,1
|
||||||
|
|
||||||
[Window][[DEADBEEF] alice@DESKTOP-01]
|
[Window][[DEADBEEF] alice@DESKTOP-01]
|
||||||
Pos=10,429
|
Pos=10,604
|
||||||
Size=1888,560
|
Size=2848,1081
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,1
|
DockId=0x00000002,2
|
||||||
|
|
||||||
[Window][Example: Console]
|
[Window][Example: Console]
|
||||||
Pos=10,466
|
Pos=10,466
|
||||||
@@ -80,8 +80,8 @@ Collapsed=0
|
|||||||
[Table][0x32886A44,8]
|
[Table][0x32886A44,8]
|
||||||
Column 0 Weight=0.6513
|
Column 0 Weight=0.6513
|
||||||
Column 1 Weight=0.9753
|
Column 1 Weight=0.9753
|
||||||
Column 2 Weight=0.5524
|
Column 2 Weight=0.3274
|
||||||
Column 3 Weight=1.0605
|
Column 3 Weight=1.2856
|
||||||
Column 4 Weight=1.7323
|
Column 4 Weight=1.7323
|
||||||
Column 5 Weight=1.1492
|
Column 5 Weight=1.1492
|
||||||
Column 6 Weight=0.4263
|
Column 6 Weight=0.4263
|
||||||
@@ -92,9 +92,9 @@ RefScale=27
|
|||||||
Column 0 Sort=0v
|
Column 0 Sort=0v
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2528,1354 Split=Y
|
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2528,1306 Split=Y
|
||||||
DockNode ID=0x00000001 Parent=0x85940918 SizeRef=1024,381 Split=X
|
DockNode ID=0x00000001 Parent=0x85940918 SizeRef=1024,559 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=613,159 CentralNode=1 Selected=0x61E02D75
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=613,159 CentralNode=1 Selected=0x61E02D75
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=409,159 Selected=0x5E5F7166
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=409,159 Selected=0x5E5F7166
|
||||||
DockNode ID=0x00000002 Parent=0x85940918 SizeRef=1024,971 Selected=0x8D780333
|
DockNode ID=0x00000002 Parent=0x85940918 SizeRef=1024,1081 Selected=0x65D642C0
|
||||||
|
|
||||||
|
|||||||
@@ -3,33 +3,30 @@ import imguin/[cimgui, glfw_opengl, simple]
|
|||||||
import ../utils/appImGui
|
import ../utils/appImGui
|
||||||
import ../../common/[types]
|
import ../../common/[types]
|
||||||
|
|
||||||
type
|
const MAX_INPUT_LENGTH = 512
|
||||||
ConsoleItem = ref object
|
type
|
||||||
timestamp: DateTime
|
|
||||||
logType: LogType
|
|
||||||
text: string
|
|
||||||
|
|
||||||
ConsoleItems = ref object
|
|
||||||
items: seq[string]
|
|
||||||
|
|
||||||
ConsoleComponent* = ref object of RootObj
|
ConsoleComponent* = ref object of RootObj
|
||||||
agent: Agent
|
agent: Agent
|
||||||
showConsole*: bool
|
showConsole*: bool
|
||||||
inputBuffer: string
|
inputBuffer: array[MAX_INPUT_LENGTH, char]
|
||||||
consoleItems: ConsoleItems
|
console: ConsoleItems
|
||||||
textSelect: ptr TextSelect
|
textSelect: ptr TextSelect
|
||||||
|
|
||||||
|
proc getItemText(item: ConsoleItem): cstring =
|
||||||
|
let timestamp = item.timestamp.format("dd-MM-yyyy HH:mm:ss")
|
||||||
|
return fmt"[{timestamp}] {$item.itemType} {item.text}".string
|
||||||
|
|
||||||
proc getNumLines(data: pointer): csize_t {.cdecl.} =
|
proc getNumLines(data: pointer): csize_t {.cdecl.} =
|
||||||
if data.isNil:
|
if data.isNil:
|
||||||
return 0
|
return 0
|
||||||
let consoleItems = cast[ConsoleItems](data)
|
let console = cast[ConsoleItems](data)
|
||||||
return consoleItems.items.len().csize_t
|
return console.items.len().csize_t
|
||||||
|
|
||||||
proc getLineAtIndex(i: csize_t, data: pointer, outLen: ptr csize_t): cstring {.cdecl.} =
|
proc getLineAtIndex(i: csize_t, data: pointer, outLen: ptr csize_t): cstring {.cdecl.} =
|
||||||
if data.isNil:
|
if data.isNil:
|
||||||
return nil
|
return nil
|
||||||
let consoleItems = cast[ConsoleItems](data)
|
let console = cast[ConsoleItems](data)
|
||||||
let line = consoleItems.items[i].cstring
|
let line = getItemText(console.items[i])
|
||||||
if not outLen.isNil:
|
if not outLen.isNil:
|
||||||
outLen[] = line.len.csize_t
|
outLen[] = line.len.csize_t
|
||||||
return line
|
return line
|
||||||
@@ -38,16 +35,18 @@ proc Console*(agent: Agent): ConsoleComponent =
|
|||||||
result = new ConsoleComponent
|
result = new ConsoleComponent
|
||||||
result.agent = agent
|
result.agent = agent
|
||||||
result.showConsole = true
|
result.showConsole = true
|
||||||
result.inputBuffer = ""
|
zeroMem(addr result.inputBuffer[0], MAX_INPUT_LENGTH)
|
||||||
|
|
||||||
result.consoleItems = new ConsoleItems
|
result.console = new ConsoleItems
|
||||||
result.consoleItems.items = @[]
|
result.console.items = @[]
|
||||||
result.textSelect = textselect_create(getLineAtIndex, getNumLines, cast[pointer](result.consoleItems), 0)
|
result.textSelect = textselect_create(getLineAtIndex, getNumLines, cast[pointer](result.console), 0)
|
||||||
|
|
||||||
proc draw*(component: ConsoleComponent) =
|
proc draw*(component: ConsoleComponent) =
|
||||||
igBegin(fmt"[{component.agent.agentId}] {component.agent.username}@{component.agent.hostname}", addr component.showConsole, 0)
|
igBegin(fmt"[{component.agent.agentId}] {component.agent.username}@{component.agent.hostname}", addr component.showConsole, 0)
|
||||||
defer: igEnd()
|
defer: igEnd()
|
||||||
|
|
||||||
|
var focusInput = false
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Console items/text section using ImGuiTextSelect in a child window
|
Console items/text section using ImGuiTextSelect in a child window
|
||||||
Supports:
|
Supports:
|
||||||
@@ -61,51 +60,74 @@ proc draw*(component: ConsoleComponent) =
|
|||||||
- https://github.com/ocornut/imgui/issues/950
|
- https://github.com/ocornut/imgui/issues/950
|
||||||
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 footerHeight = igGetStyle().ItemSpacing.y + igGetFrameHeightWithSpacing() * 2
|
let consolePadding: float = 10.0f
|
||||||
|
let footerHeight = (consolePadding * 2) + (igGetStyle().ItemSpacing.y + igGetFrameHeightWithSpacing())
|
||||||
if igBeginChild_Str("##Console", vec2(-1.0f, -footerHeight), ImGuiChildFlags_NavFlattened.int32, ImGuiWindowFlags_HorizontalScrollbar.int32):
|
let textSpacing = igGetStyle().ItemSpacing.x
|
||||||
|
|
||||||
# Display console items
|
|
||||||
for entry in component.consoleItems.items:
|
|
||||||
igTextColored(vec4(0.0f, 1.0f, 1.0f, 1.0f), entry.cstring)
|
|
||||||
|
|
||||||
component.textSelect.textselect_update()
|
|
||||||
|
|
||||||
# Auto-scroll to bottom if we're already at the bottom
|
|
||||||
if igGetScrollY() >= igGetScrollMaxY():
|
|
||||||
igSetScrollHereY(1.0f)
|
|
||||||
|
|
||||||
igEndChild()
|
|
||||||
|
|
||||||
# Buttons for testing the console
|
|
||||||
if igButton("Add Items", vec2(0.0f, 0.0f)):
|
|
||||||
for i in 1..10:
|
|
||||||
component.consoleItems.items.add("Hello world!")
|
|
||||||
|
|
||||||
igSameLine(0.0f, 5.0f)
|
# Padding
|
||||||
if igButton("Add Long Items", vec2(0.0f, 0.0f)):
|
igDummy(vec2(0.0f, consolePadding))
|
||||||
for i in 1..3:
|
try:
|
||||||
component.consoleItems.items.add("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.")
|
# Set styles of the console window
|
||||||
|
igPushStyleColor_Vec4(ImGui_Col_FrameBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
|
||||||
igSameLine(0.0f, 5.0f)
|
igPushStyleColor_Vec4(ImGui_Col_ScrollbarBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
|
||||||
if igButton("Clear", vec2(0.0f, 0.0f)):
|
igPushStyleColor_Vec4(ImGui_Col_Border.int32, vec4(0.2f, 0.2f, 0.2f, 1.0f))
|
||||||
component.consoleItems.items.setLen(0)
|
igPushStyleVar_Float(ImGui_StyleVar_FrameBorderSize .int32, 1.0f)
|
||||||
|
|
||||||
|
let childWindowFlags = ImGuiChildFlags_NavFlattened.int32 or ImGui_ChildFlags_Borders.int32 or ImGui_ChildFlags_AlwaysUseWindowPadding.int32 or ImGuiChildFlags_FrameStyle.int32
|
||||||
|
if igBeginChild_Str("##Console", vec2(-1.0f, -footerHeight), childWindowFlags, ImGuiWindowFlags_HorizontalScrollbar.int32):
|
||||||
|
# Display console items
|
||||||
|
for entry in component.console.items:
|
||||||
|
let timestamp = entry.timestamp.format("dd-MM-yyyy HH:mm:ss")
|
||||||
|
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), fmt"[{timestamp}]".cstring)
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
igTextColored(vec4(0.0f, 1.0f, 1.0f, 1.0f), $entry.itemType)
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
igTextUnformatted(entry.text.cstring, nil)
|
||||||
|
|
||||||
|
component.textSelect.textselect_update()
|
||||||
|
|
||||||
|
# Auto-scroll to bottom
|
||||||
|
if igGetScrollY() >= igGetScrollMaxY():
|
||||||
|
igSetScrollHereY(1.0f)
|
||||||
|
|
||||||
|
except IndexDefect:
|
||||||
|
# CTRL+A crashes when no items are in the console
|
||||||
|
discard
|
||||||
|
|
||||||
|
finally:
|
||||||
|
igPopStyleColor(3)
|
||||||
|
igPopStyleVar(1)
|
||||||
|
igEndChild()
|
||||||
|
|
||||||
|
# Padding
|
||||||
|
igDummy(vec2(0.0f, consolePadding))
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Input field with prompt indicator
|
Input field with prompt indicator
|
||||||
]#
|
]#
|
||||||
igText(fmt"[{component.agent.agentId}]")
|
igText(fmt"[{component.agent.agentId}]")
|
||||||
let spacing = igGetStyle().ItemSpacing.x
|
igSameLine(0.0f, textSpacing)
|
||||||
igSameLine(0.0f, spacing)
|
|
||||||
|
|
||||||
# Calculate available width for input
|
# Calculate available width for input
|
||||||
var availableWidth: ImVec2
|
var availableWidth: ImVec2
|
||||||
igGetContentRegionAvail(addr availableWidth)
|
igGetContentRegionAvail(addr availableWidth)
|
||||||
igSetNextItemWidth(availableWidth.x)
|
igSetNextItemWidth(availableWidth.x)
|
||||||
|
|
||||||
let inputFlags = ImGuiInputTextFlags_EnterReturnsTrue.int32 or ImGuiInputTextFlags_EscapeClearsAll.int32 or ImGuiInputTextFlags_CallbackCompletion.int32 or ImGuiInputTextFlags_CallbackHistory.int32
|
let inputFlags = ImGuiInputTextFlags_EnterReturnsTrue.int32 or ImGuiInputTextFlags_EscapeClearsAll.int32 # or ImGuiInputTextFlags_CallbackCompletion.int32 or ImGuiInputTextFlags_CallbackHistory.int32
|
||||||
if igInputText("##Input", component.inputBuffer, 256, inputFlags, nil, nil):
|
if igInputText("##Input", addr component.inputBuffer[0], MAX_INPUT_LENGTH, inputFlags, nil, nil):
|
||||||
discard
|
|
||||||
|
let command = $(addr component.inputBuffer[0]).cstring
|
||||||
|
let commandItem = ConsoleItem(
|
||||||
|
timestamp: now(),
|
||||||
|
itemType: LOG_COMMAND,
|
||||||
|
text: command
|
||||||
|
)
|
||||||
|
component.console.items.add(commandItem)
|
||||||
|
|
||||||
|
# TODO: Handle command execution
|
||||||
|
|
||||||
|
zeroMem(addr component.inputBuffer[0], MAX_INPUT_LENGTH)
|
||||||
|
focusInput = true
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Session information (optional footer)
|
Session information (optional footer)
|
||||||
@@ -115,3 +137,5 @@ proc draw*(component: ConsoleComponent) =
|
|||||||
# igText(sessionInfo)
|
# igText(sessionInfo)
|
||||||
|
|
||||||
igSetItemDefaultFocus()
|
igSetItemDefaultFocus()
|
||||||
|
if focusInput:
|
||||||
|
igSetKeyboardFocusHere(-1)
|
||||||
|
|||||||
@@ -73,10 +73,14 @@ type
|
|||||||
# LOG_ERROR = "[ - ] "
|
# LOG_ERROR = "[ - ] "
|
||||||
# LOG_SUCCESS = "[ + ] "
|
# LOG_SUCCESS = "[ + ] "
|
||||||
# LOG_WARNING = "[ ! ] "
|
# LOG_WARNING = "[ ! ] "
|
||||||
|
# LOG_COMMAND = "[ > ] "
|
||||||
|
# LOG_OUTPUT = ""
|
||||||
LOG_INFO = "[INFO] "
|
LOG_INFO = "[INFO] "
|
||||||
LOG_ERROR = "[FAIL] "
|
LOG_ERROR = "[FAIL] "
|
||||||
LOG_SUCCESS = "[DONE] "
|
LOG_SUCCESS = "[DONE] "
|
||||||
LOG_WARNING = "[WARN] "
|
LOG_WARNING = "[WARN] "
|
||||||
|
LOG_COMMAND = "[>>>>] "
|
||||||
|
LOG_OUTPUT = ""
|
||||||
|
|
||||||
SleepObfuscationTechnique* = enum
|
SleepObfuscationTechnique* = enum
|
||||||
NONE = 0'u8
|
NONE = 0'u8
|
||||||
@@ -233,3 +237,13 @@ type
|
|||||||
arguments*: seq[Argument]
|
arguments*: seq[Argument]
|
||||||
dispatchMessage*: string
|
dispatchMessage*: string
|
||||||
execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.}
|
execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.}
|
||||||
|
|
||||||
|
# Definitions for ImGui User interface
|
||||||
|
type
|
||||||
|
ConsoleItem* = ref object
|
||||||
|
timestamp*: DateTime
|
||||||
|
itemType*: LogType
|
||||||
|
text*: string
|
||||||
|
|
||||||
|
ConsoleItems* = ref object
|
||||||
|
items*: seq[ConsoleItem]
|
||||||
Reference in New Issue
Block a user