Updated directory structure.
This commit is contained in:
@@ -1,17 +0,0 @@
|
|||||||
import nanoid, sequtils, strutils, strformat, terminal, times, json
|
|
||||||
import ../types
|
|
||||||
import ../db/database
|
|
||||||
|
|
||||||
# Generic task creation procedure
|
|
||||||
proc createTask*(cq: Conquest, command: CommandType, args: string, message: string) =
|
|
||||||
let
|
|
||||||
date = now().format("dd-MM-yyyy HH:mm:ss")
|
|
||||||
task = Task(
|
|
||||||
id: generate(alphabet=join(toSeq('A'..'Z'), ""), size=8),
|
|
||||||
agent: cq.interactAgent.name,
|
|
||||||
command: command,
|
|
||||||
args: args,
|
|
||||||
)
|
|
||||||
|
|
||||||
cq.interactAgent.tasks.add(task)
|
|
||||||
cq.writeLine(fgBlack, styleBright, fmt"[{date}] [*] ", resetStyle, message)
|
|
||||||
@@ -11,8 +11,8 @@ Basic API-only Commands
|
|||||||
- [x] ls/dir : List all files in directory (including hidden ones)
|
- [x] ls/dir : List all files in directory (including hidden ones)
|
||||||
- [x] rm : Remove a file
|
- [x] rm : Remove a file
|
||||||
- [x] rmdir : Remove a empty directory
|
- [x] rmdir : Remove a empty directory
|
||||||
- [ ] mv : Move a file
|
- [x] mv : Move a file
|
||||||
- [ ] cp : Copy a file
|
- [x] cp : Copy a file
|
||||||
- [ ] cat/type : Display contents of a file
|
- [ ] cat/type : Display contents of a file
|
||||||
- [ ] env : Display environment variables
|
- [ ] env : Display environment variables
|
||||||
- [ ] ps : List processes
|
- [ ] ps : List processes
|
||||||
@@ -26,7 +26,7 @@ Basic API-only Commands
|
|||||||
|
|
||||||
Execution Commands
|
Execution Commands
|
||||||
------------------
|
------------------
|
||||||
- [~] shell : Execute shell command (to be implemented using Windows APIs instead of execCmdEx)
|
- [x] shell : Execute shell command (to be implemented using Windows APIs instead of execCmdEx)
|
||||||
- [ ] bof : Execute Beacon Object File in memory and retrieve output (bof /local/path/file.o)
|
- [ ] bof : Execute Beacon Object File in memory and retrieve output (bof /local/path/file.o)
|
||||||
- Read from listener endpoint directly to memory
|
- Read from listener endpoint directly to memory
|
||||||
- Base for all kinds of BOFs (Situational Awareness, ...)
|
- Base for all kinds of BOFs (Situational Awareness, ...)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
CONQUEST_ROOT="/mnt/c/Users/jakob/Documents/Projects/conquest"
|
CONQUEST_ROOT="/mnt/c/Users/jakob/Documents/Projects/conquest"
|
||||||
nim --os:windows --cpu:amd64 --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc -d:release --outdir:"$CONQUEST_ROOT/bin" -o:"monarch.x64.exe" c $CONQUEST_ROOT/agents/monarch/monarch.nim
|
nim --os:windows --cpu:amd64 --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc -d:release --outdir:"$CONQUEST_ROOT/bin" -o:"monarch.x64.exe" c $CONQUEST_ROOT/src/agents/monarch/monarch.nim
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import winim, tables
|
import winim, tables
|
||||||
import ../../server/types
|
import ../../types
|
||||||
export Task, CommandType, TaskResult, TaskStatus
|
export Task, CommandType, TaskResult, TaskStatus
|
||||||
|
|
||||||
type
|
type
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import terminal, strformat, strutils, sequtils, tables, json, times, base64, system, osproc, streams
|
import terminal, strformat, strutils, sequtils, tables, json, times, base64, system, osproc, streams
|
||||||
import ./interact
|
|
||||||
import ../[types, globals, utils]
|
|
||||||
import ../db/database
|
|
||||||
|
|
||||||
|
import ./taskDispatcher
|
||||||
|
import ../utils
|
||||||
|
import ../db/database
|
||||||
|
import ../../types
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent management mode
|
Agent management mode
|
||||||
@@ -121,7 +122,7 @@ proc agentBuild*(cq: Conquest, listener, sleep, payload: string) =
|
|||||||
let listener = cq.listeners[listener.toUpperAscii]
|
let listener = cq.listeners[listener.toUpperAscii]
|
||||||
|
|
||||||
# Create/overwrite nim.cfg file to set agent configuration
|
# Create/overwrite nim.cfg file to set agent configuration
|
||||||
let agentConfigFile = fmt"../agents/{payload}/nim.cfg"
|
let agentConfigFile = fmt"../src/agents/{payload}/nim.cfg"
|
||||||
|
|
||||||
# Parse IP Address and store as compile-time integer to hide hardcoded-strings in binary from `strings` command
|
# Parse IP Address and store as compile-time integer to hide hardcoded-strings in binary from `strings` command
|
||||||
let (first, second, third, fourth) = parseOctets(listener.address)
|
let (first, second, third, fourth) = parseOctets(listener.address)
|
||||||
@@ -142,7 +143,7 @@ proc agentBuild*(cq: Conquest, listener, sleep, payload: string) =
|
|||||||
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Configuration file created.")
|
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Configuration file created.")
|
||||||
|
|
||||||
# Build agent by executing the ./build.sh script on the system.
|
# Build agent by executing the ./build.sh script on the system.
|
||||||
let agentBuildScript = fmt"../agents/{payload}/build.sh"
|
let agentBuildScript = fmt"../src/agents/{payload}/build.sh"
|
||||||
|
|
||||||
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Building agent...")
|
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Building agent...")
|
||||||
|
|
||||||
@@ -166,87 +167,3 @@ proc agentBuild*(cq: Conquest, listener, sleep, payload: string) =
|
|||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
cq.writeLine(fgRed, styleBright, "[-] ", resetStyle, "An error occurred: ", err.msg)
|
cq.writeLine(fgRed, styleBright, "[-] ", resetStyle, "An error occurred: ", err.msg)
|
||||||
|
|
||||||
#[
|
|
||||||
Agent API
|
|
||||||
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results
|
|
||||||
]#
|
|
||||||
proc register*(agent: Agent): bool =
|
|
||||||
|
|
||||||
# The following line is required to be able to use the `cq` global variable for console output
|
|
||||||
{.cast(gcsafe).}:
|
|
||||||
|
|
||||||
# Check if listener that is requested exists
|
|
||||||
# TODO: Verify that the listener accessed is also the listener specified in the URL
|
|
||||||
# This can be achieved by extracting the port number from the `Host` header and matching it to the one queried from the database
|
|
||||||
if not cq.dbListenerExists(agent.listener.toUpperAscii):
|
|
||||||
cq.writeLine(fgRed, styleBright, fmt"[-] {agent.ip} attempted to register to non-existent listener: {agent.listener}.", "\n")
|
|
||||||
return false
|
|
||||||
|
|
||||||
# Store agent in database
|
|
||||||
if not cq.dbStoreAgent(agent):
|
|
||||||
cq.writeLine(fgRed, styleBright, fmt"[-] Failed to insert agent {agent.name} into database.", "\n")
|
|
||||||
return false
|
|
||||||
|
|
||||||
cq.add(agent)
|
|
||||||
|
|
||||||
let date = agent.firstCheckin.format("dd-MM-yyyy HH:mm:ss")
|
|
||||||
cq.writeLine(fgYellow, styleBright, fmt"[{date}] ", resetStyle, "Agent ", fgYellow, styleBright, agent.name, resetStyle, " connected to listener ", fgGreen, styleBright, agent.listener, resetStyle, ": ", fgYellow, styleBright, fmt"{agent.username}@{agent.hostname}", "\n")
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
proc getTasks*(listener, agent: string): JsonNode =
|
|
||||||
|
|
||||||
{.cast(gcsafe).}:
|
|
||||||
|
|
||||||
# Check if listener exists
|
|
||||||
if not cq.dbListenerExists(listener.toUpperAscii):
|
|
||||||
cq.writeLine(fgRed, styleBright, fmt"[-] Task-retrieval request made to non-existent listener: {listener}.", "\n")
|
|
||||||
return nil
|
|
||||||
|
|
||||||
# Check if agent exists
|
|
||||||
if not cq.dbAgentExists(agent.toUpperAscii):
|
|
||||||
cq.writeLine(fgRed, styleBright, fmt"[-] Task-retrieval request made to non-existent agent: {agent}.", "\n")
|
|
||||||
return nil
|
|
||||||
|
|
||||||
# Update the last check-in date for the accessed agent
|
|
||||||
cq.agents[agent.toUpperAscii].latestCheckin = now()
|
|
||||||
# if not cq.dbUpdateCheckin(agent.toUpperAscii, now().format("dd-MM-yyyy HH:mm:ss")):
|
|
||||||
# return nil
|
|
||||||
|
|
||||||
# Return tasks in JSON format
|
|
||||||
return %cq.agents[agent.toUpperAscii].tasks
|
|
||||||
|
|
||||||
proc handleResult*(listener, agent, task: string, taskResult: TaskResult) =
|
|
||||||
|
|
||||||
{.cast(gcsafe).}:
|
|
||||||
|
|
||||||
let date: string = now().format("dd-MM-yyyy HH:mm:ss")
|
|
||||||
|
|
||||||
if taskResult.status == Failed:
|
|
||||||
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgRed, styleBright, " [-] ", resetStyle, fmt"Task {task} failed.")
|
|
||||||
|
|
||||||
if taskResult.data != "":
|
|
||||||
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgRed, styleBright, " [-] ", resetStyle, "Output:")
|
|
||||||
|
|
||||||
# Split result string on newline to keep formatting
|
|
||||||
for line in decode(taskResult.data).split("\n"):
|
|
||||||
cq.writeLine(line)
|
|
||||||
else:
|
|
||||||
cq.writeLine()
|
|
||||||
|
|
||||||
else:
|
|
||||||
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgGreen, " [+] ", resetStyle, fmt"Task {task} finished.")
|
|
||||||
|
|
||||||
if taskResult.data != "":
|
|
||||||
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgGreen, " [+] ", resetStyle, "Output:")
|
|
||||||
|
|
||||||
# Split result string on newline to keep formatting
|
|
||||||
for line in decode(taskResult.data).split("\n"):
|
|
||||||
cq.writeLine(line)
|
|
||||||
else:
|
|
||||||
cq.writeLine()
|
|
||||||
|
|
||||||
# Update task queue to include all tasks, except the one that was just completed
|
|
||||||
cq.agents[agent].tasks = cq.agents[agent].tasks.filterIt(it.id != task)
|
|
||||||
|
|
||||||
return
|
|
||||||
90
src/server/core/agentApi.nim
Normal file
90
src/server/core/agentApi.nim
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import terminal, strformat, strutils, sequtils, tables, json, times, base64, system, osproc, streams
|
||||||
|
|
||||||
|
import ../globals
|
||||||
|
import ../db/database
|
||||||
|
import ../../types
|
||||||
|
|
||||||
|
#[
|
||||||
|
Agent API
|
||||||
|
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results
|
||||||
|
]#
|
||||||
|
proc register*(agent: Agent): bool =
|
||||||
|
|
||||||
|
# The following line is required to be able to use the `cq` global variable for console output
|
||||||
|
{.cast(gcsafe).}:
|
||||||
|
|
||||||
|
# Check if listener that is requested exists
|
||||||
|
# TODO: Verify that the listener accessed is also the listener specified in the URL
|
||||||
|
# This can be achieved by extracting the port number from the `Host` header and matching it to the one queried from the database
|
||||||
|
if not cq.dbListenerExists(agent.listener.toUpperAscii):
|
||||||
|
cq.writeLine(fgRed, styleBright, fmt"[-] {agent.ip} attempted to register to non-existent listener: {agent.listener}.", "\n")
|
||||||
|
return false
|
||||||
|
|
||||||
|
# Store agent in database
|
||||||
|
if not cq.dbStoreAgent(agent):
|
||||||
|
cq.writeLine(fgRed, styleBright, fmt"[-] Failed to insert agent {agent.name} into database.", "\n")
|
||||||
|
return false
|
||||||
|
|
||||||
|
cq.add(agent)
|
||||||
|
|
||||||
|
let date = agent.firstCheckin.format("dd-MM-yyyy HH:mm:ss")
|
||||||
|
cq.writeLine(fgYellow, styleBright, fmt"[{date}] ", resetStyle, "Agent ", fgYellow, styleBright, agent.name, resetStyle, " connected to listener ", fgGreen, styleBright, agent.listener, resetStyle, ": ", fgYellow, styleBright, fmt"{agent.username}@{agent.hostname}", "\n")
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc getTasks*(listener, agent: string): JsonNode =
|
||||||
|
|
||||||
|
{.cast(gcsafe).}:
|
||||||
|
|
||||||
|
# Check if listener exists
|
||||||
|
if not cq.dbListenerExists(listener.toUpperAscii):
|
||||||
|
cq.writeLine(fgRed, styleBright, fmt"[-] Task-retrieval request made to non-existent listener: {listener}.", "\n")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
# Check if agent exists
|
||||||
|
if not cq.dbAgentExists(agent.toUpperAscii):
|
||||||
|
cq.writeLine(fgRed, styleBright, fmt"[-] Task-retrieval request made to non-existent agent: {agent}.", "\n")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
# Update the last check-in date for the accessed agent
|
||||||
|
cq.agents[agent.toUpperAscii].latestCheckin = now()
|
||||||
|
# if not cq.dbUpdateCheckin(agent.toUpperAscii, now().format("dd-MM-yyyy HH:mm:ss")):
|
||||||
|
# return nil
|
||||||
|
|
||||||
|
# Return tasks in JSON format
|
||||||
|
return %cq.agents[agent.toUpperAscii].tasks
|
||||||
|
|
||||||
|
proc handleResult*(listener, agent, task: string, taskResult: TaskResult) =
|
||||||
|
|
||||||
|
{.cast(gcsafe).}:
|
||||||
|
|
||||||
|
let date: string = now().format("dd-MM-yyyy HH:mm:ss")
|
||||||
|
|
||||||
|
if taskResult.status == Failed:
|
||||||
|
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgRed, styleBright, " [-] ", resetStyle, fmt"Task {task} failed.")
|
||||||
|
|
||||||
|
if taskResult.data != "":
|
||||||
|
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgRed, styleBright, " [-] ", resetStyle, "Output:")
|
||||||
|
|
||||||
|
# Split result string on newline to keep formatting
|
||||||
|
for line in decode(taskResult.data).split("\n"):
|
||||||
|
cq.writeLine(line)
|
||||||
|
else:
|
||||||
|
cq.writeLine()
|
||||||
|
|
||||||
|
else:
|
||||||
|
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgGreen, " [+] ", resetStyle, fmt"Task {task} finished.")
|
||||||
|
|
||||||
|
if taskResult.data != "":
|
||||||
|
cq.writeLine(fgBlack, styleBright, fmt"[{date}]", fgGreen, " [+] ", resetStyle, "Output:")
|
||||||
|
|
||||||
|
# Split result string on newline to keep formatting
|
||||||
|
for line in decode(taskResult.data).split("\n"):
|
||||||
|
cq.writeLine(line)
|
||||||
|
else:
|
||||||
|
cq.writeLine()
|
||||||
|
|
||||||
|
# Update task queue to include all tasks, except the one that was just completed
|
||||||
|
cq.agents[agent].tasks = cq.agents[agent].tasks.filterIt(it.id != task)
|
||||||
|
|
||||||
|
return
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import prologue, nanoid, json
|
import prologue, nanoid, json
|
||||||
import sequtils, strutils, times
|
import sequtils, strutils, times
|
||||||
|
|
||||||
import ../[types]
|
import ./agentApi
|
||||||
import ../agent/agent
|
import ../../types
|
||||||
|
|
||||||
proc error404*(ctx: Context) {.async.} =
|
proc error404*(ctx: Context) {.async.} =
|
||||||
resp "", Http404
|
resp "", Http404
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import strformat, strutils, sequtils, nanoid, terminal
|
import strformat, strutils, sequtils, nanoid, terminal
|
||||||
import prologue
|
import prologue
|
||||||
|
|
||||||
import ./api
|
import ./endpoints
|
||||||
import ../[types, utils]
|
import ../utils
|
||||||
import ../db/database
|
import ../db/database
|
||||||
|
import ../../types
|
||||||
|
|
||||||
proc listenerUsage*(cq: Conquest) =
|
proc listenerUsage*(cq: Conquest) =
|
||||||
cq.writeLine("""Manage, start and stop listeners.
|
cq.writeLine("""Manage, start and stop listeners.
|
||||||
@@ -46,10 +47,10 @@ proc listenerStart*(cq: Conquest, host: string, portStr: string) =
|
|||||||
var listener = newApp(settings = listenerSettings)
|
var listener = newApp(settings = listenerSettings)
|
||||||
|
|
||||||
# Define API endpoints
|
# Define API endpoints
|
||||||
listener.post("{listener}/register", api.register)
|
listener.post("{listener}/register", endpoints.register)
|
||||||
listener.get("{listener}/{agent}/tasks", api.getTasks)
|
listener.get("{listener}/{agent}/tasks", endpoints.getTasks)
|
||||||
listener.post("{listener}/{agent}/{task}/results", api.postResults)
|
listener.post("{listener}/{agent}/{task}/results", endpoints.postResults)
|
||||||
listener.registerErrorHandler(Http404, api.error404)
|
listener.registerErrorHandler(Http404, endpoints.error404)
|
||||||
|
|
||||||
# Store listener in database
|
# Store listener in database
|
||||||
var listenerInstance = newListener(name, host, port)
|
var listenerInstance = newListener(name, host, port)
|
||||||
@@ -79,10 +80,10 @@ proc restartListeners*(cq: Conquest) =
|
|||||||
listener = newApp(settings = settings)
|
listener = newApp(settings = settings)
|
||||||
|
|
||||||
# Define API endpoints
|
# Define API endpoints
|
||||||
listener.post("{listener}/register", api.register)
|
listener.post("{listener}/register", endpoints.register)
|
||||||
listener.get("{listener}/{agent}/tasks", api.getTasks)
|
listener.get("{listener}/{agent}/tasks", endpoints.getTasks)
|
||||||
listener.post("{listener}/{agent}/{task}/results", api.postResults)
|
listener.post("{listener}/{agent}/{task}/results", endpoints.postResults)
|
||||||
listener.registerErrorHandler(Http404, api.error404)
|
listener.registerErrorHandler(Http404, endpoints.error404)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
discard listener.runAsync()
|
discard listener.runAsync()
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import argparse, times, strformat, terminal, nanoid, tables, json, sequtils
|
import argparse, times, strformat, terminal, nanoid, tables, json, sequtils
|
||||||
import ./taskDispatcher
|
import ../../types
|
||||||
import ../types
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent Argument parsing
|
Agent Argument parsing
|
||||||
@@ -224,6 +223,19 @@ proc packageArguments(cq: Conquest, command: Command, arguments: seq[string]): J
|
|||||||
else:
|
else:
|
||||||
result[argument.name] = %""
|
result[argument.name] = %""
|
||||||
|
|
||||||
|
proc createTask*(cq: Conquest, command: CommandType, args: string, message: string) =
|
||||||
|
let
|
||||||
|
date = now().format("dd-MM-yyyy HH:mm:ss")
|
||||||
|
task = Task(
|
||||||
|
id: generate(alphabet=join(toSeq('A'..'Z'), ""), size=8),
|
||||||
|
agent: cq.interactAgent.name,
|
||||||
|
command: command,
|
||||||
|
args: args,
|
||||||
|
)
|
||||||
|
|
||||||
|
cq.interactAgent.tasks.add(task)
|
||||||
|
cq.writeLine(fgBlack, styleBright, fmt"[{date}] [*] ", resetStyle, message)
|
||||||
|
|
||||||
proc handleAgentCommand*(cq: Conquest, input: string) =
|
proc handleAgentCommand*(cq: Conquest, input: string) =
|
||||||
# Return if no command (or just whitespace) is entered
|
# Return if no command (or just whitespace) is entered
|
||||||
if input.replace(" ", "").len == 0: return
|
if input.replace(" ", "").len == 0: return
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import system, terminal, tiny_sqlite
|
import system, terminal, tiny_sqlite
|
||||||
import ../types
|
|
||||||
import ./[dbAgent, dbListener]
|
import ./[dbAgent, dbListener]
|
||||||
|
import ../../types
|
||||||
|
|
||||||
# Export functions so that only ./db/database is required to be imported
|
# Export functions so that only ./db/database is required to be imported
|
||||||
export dbAgent, dbListener
|
export dbAgent, dbListener
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import system, terminal, tiny_sqlite, times
|
import system, terminal, tiny_sqlite, times
|
||||||
import ../types
|
import ../../types
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent database functions
|
Agent database functions
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import system, terminal, tiny_sqlite
|
import system, terminal, tiny_sqlite
|
||||||
import ../types
|
import ../../types
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Listener database functions
|
Listener database functions
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import ./types
|
import ../types
|
||||||
|
|
||||||
# Global variable for handling listeners, agents and console output
|
# Global variable for handling listeners, agents and console output
|
||||||
var cq*: Conquest
|
var cq*: Conquest
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import prompt, terminal, argparse
|
import prompt, terminal, argparse
|
||||||
import strutils, strformat, times, system, tables
|
import strutils, strformat, times, system, tables
|
||||||
|
|
||||||
import ./[types, globals]
|
import ./globals
|
||||||
import agent/agent, listener/listener, db/database
|
import core/agent, core/listener, db/database
|
||||||
|
import ../types
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Argument parsing
|
Argument parsing
|
||||||
@@ -136,7 +137,7 @@ proc main() =
|
|||||||
setControlCHook(exit)
|
setControlCHook(exit)
|
||||||
|
|
||||||
# Initialize framework
|
# Initialize framework
|
||||||
let dbPath: string = "../server/db/conquest.db"
|
let dbPath: string = "../src/server/db/conquest.db"
|
||||||
cq = initConquest(dbPath)
|
cq = initConquest(dbPath)
|
||||||
|
|
||||||
# Print header
|
# Print header
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import strutils, terminal, tables, sequtils, times, strformat
|
import strutils, terminal, tables, sequtils, times, strformat
|
||||||
import std/wordwrap
|
import std/wordwrap
|
||||||
|
|
||||||
import ./[types]
|
import ../types
|
||||||
|
|
||||||
proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] =
|
proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] =
|
||||||
# TODO: Verify that address is in correct, expected format
|
# TODO: Verify that address is in correct, expected format
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import prompt
|
import prompt
|
||||||
import prologue
|
import prologue
|
||||||
import tables, sequtils
|
import tables
|
||||||
import times
|
import times
|
||||||
import terminal
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent types & procs
|
Agent types & procs
|
||||||
@@ -140,7 +139,6 @@ proc stringToProtocol*(protocol: string): Protocol =
|
|||||||
return HTTP
|
return HTTP
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Conquest framework types & procs
|
Conquest framework types & procs
|
||||||
]#
|
]#
|
||||||
Reference in New Issue
Block a user