Enhance detection logic to include process-based suspicious connection checks and refine firewall rule attributes in eliminate package. Add PID-to-process name mapping functionality.

This commit is contained in:
Evan Hosinski
2025-10-11 19:49:21 -04:00
parent a5d3623a72
commit bde1b23753
2 changed files with 92 additions and 15 deletions
@@ -40,16 +40,57 @@ func DetectOutboundConnections() []NetworkConnection {
func compareConnections(connections []NetworkConnection) []NetworkConnection {
var suspiciousConnections []NetworkConnection
for _, conn := range connections {
remote := conn.RemoteHost
// Get process names for all PIDs
pidToProcessName := getProcessNamesForPIDs(connections)
for _, conn := range connections {
isSuspicious := false
reason := ""
// Check 1: DNS pattern match (domain-based detection)
remote := conn.RemoteHost
for _, dns := range common.CommonDNS {
if matchesDNSPattern(remote, dns) {
fmt.Printf(" [?] Found %s\n", conn.RemoteHost)
suspiciousConnections = append(suspiciousConnections, conn)
isSuspicious = true
reason = fmt.Sprintf("DNS match: %s", conn.RemoteHost)
break
}
}
// Check 2: Process name match (catches RMMs using custom relay servers)
if !isSuspicious && conn.PID != "" {
if processName, exists := pidToProcessName[conn.PID]; exists {
processNameLower := strings.ToLower(processName)
// Check against known RMM names
for _, rmm := range common.CommonRMMs {
if strings.Contains(processNameLower, strings.ToLower(rmm)) {
isSuspicious = true
reason = fmt.Sprintf("RMM process: %s", processName)
break
}
}
// Check against known RMM executable patterns
if !isSuspicious {
for _, pattern := range common.CommonImageSuffixes {
patternLower := strings.ToLower(pattern)
// Remove leading backslash for matching
patternClean := strings.TrimPrefix(patternLower, "\\")
if strings.Contains(processNameLower, patternClean) {
isSuspicious = true
reason = fmt.Sprintf("RMM executable: %s", processName)
break
}
}
}
}
}
if isSuspicious {
fmt.Printf(" [?] Found %s (%s)\n", conn.RemoteHost, reason)
suspiciousConnections = append(suspiciousConnections, conn)
}
}
fmt.Printf("[+] Found %d Suspicious Outbound Connections\n", len(suspiciousConnections))
@@ -190,3 +231,39 @@ func GetHTTPHostnames() []string {
return hostnames
}
// getProcessNamesForPIDs returns a map of PID -> process name for all connections
func getProcessNamesForPIDs(connections []NetworkConnection) map[string]string {
pidMap := make(map[string]string)
// Collect unique PIDs
uniquePIDs := make(map[string]bool)
for _, conn := range connections {
if conn.PID != "" && conn.PID != "0" {
uniquePIDs[conn.PID] = true
}
}
// Query process names for each PID
for pid := range uniquePIDs {
processName := getProcessNameByPID(pid)
if processName != "" {
pidMap[pid] = processName
}
}
return pidMap
}
// getProcessNameByPID returns the process name for a given PID
func getProcessNameByPID(pid string) string {
cmd := exec.Command("powershell", "-Command",
fmt.Sprintf("(Get-Process -Id %s -ErrorAction SilentlyContinue).ProcessName", pid))
output, err := cmd.Output()
if err != nil {
return ""
}
processName := strings.TrimSpace(string(output))
return processName
}
+11 -11
View File
@@ -21,16 +21,16 @@ func EliminateConnection(dst string) error {
// Add a block rule for the destination
return fw.AddRule(firewall.FirewallRule{
Name: fmt.Sprintf("Block Outgoing %s", dst),
Direction: "outbound",
Protocol: "*",
LocalPort: "",
RemotePort: "",
LocalAddress: "",
RemoteAddress: "%s",
Action: "block",
Profile: "",
Destination: dst,
Source: "",
Name: fmt.Sprintf("Block Outgoing %s", dst),
Direction: "outbound",
Protocol: "*",
LocalPort: "",
RemotePort: "",
LocalAddress: "",
RemoteIPAddresses: "",
Action: "block",
Profile: "",
DestinationHostname: dst,
Source: "",
})
}