//go:build windows package deploy import ( "encoding/json" "net" "strings" ) const dnsClientCacheScript = ` $rows = Get-DnsClientCache -ErrorAction SilentlyContinue | Where-Object { $_.Entry -ne '' -and $_.Data -ne '' } | Select-Object -First 64 Entry, Data, Type $rows | ConvertTo-Json -Compress ` const codeSignCertScript = ` $eku = '1.3.6.1.5.5.7.3.3' $cert = Get-ChildItem Cert:\CurrentUser\My, Cert:\LocalMachine\My -ErrorAction SilentlyContinue | Where-Object { $_.HasPrivateKey -and ( ($_.EnhancedKeyUsageList | Where-Object { $_.ObjectId -eq $eku }) -or ($_.EnhancedKeyUsageList.FriendlyName -contains 'Code Signing') ) } | Select-Object -First 1 Subject if ($cert) { $cert.Subject } else { '' } ` func probeEnterpriseCodeSignCert() (present bool, subject string) { out, err := HiddenOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", codeSignCertScript) if err != nil { return false, "" } subject = strings.TrimSpace(string(out)) return subject != "", subject } func probeMulticastNameCache(max int) (llmnr, mdns []NameHost) { if max <= 0 { return nil, nil } out, err := HiddenOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", dnsClientCacheScript) if err != nil { return nil, nil } raw := strings.TrimSpace(string(out)) if raw == "" { return nil, nil } if idx := strings.LastIndex(raw, "{"); idx >= 0 && !strings.HasPrefix(raw, "[") { raw = "[" + raw[idx:] if !strings.HasSuffix(raw, "]") { raw += "]" } } var rows []struct { Entry string `json:"Entry"` Data string `json:"Data"` Type int `json:"Type"` } if err := json.Unmarshal([]byte(raw), &rows); err != nil { var one struct { Entry string `json:"Entry"` Data string `json:"Data"` Type int `json:"Type"` } if err2 := json.Unmarshal([]byte(raw), &one); err2 != nil || one.Entry == "" { return nil, nil } rows = []struct { Entry string `json:"Entry"` Data string `json:"Data"` Type int `json:"Type"` }{one} } seenLLMNR := make(map[string]bool) seenMDNS := make(map[string]bool) for _, row := range rows { name := strings.TrimSpace(strings.TrimSuffix(row.Entry, ".")) ip := strings.TrimSpace(row.Data) if name == "" { continue } if ip != "" { if parsed := net.ParseIP(ip); parsed != nil && parsed.To4() != nil { ip = parsed.To4().String() } } entry := NameHost{Name: name, IP: ip} lower := strings.ToLower(name) switch { case strings.HasSuffix(lower, ".local"): if len(mdns) >= max || seenMDNS[name] { continue } seenMDNS[name] = true mdns = append(mdns, entry) case !strings.Contains(name, "."): if len(llmnr) >= max || seenLLMNR[name] { continue } seenLLMNR[name] = true llmnr = append(llmnr, entry) } if len(llmnr)+len(mdns) >= max { break } } return llmnr, mdns }