package main import ( "encoding/json" "fmt" "log" "os/exec" "regexp" "runtime" "strings" "time" ) // Software holds information about installed software type Software struct { Source string `json:"source"` Name string `json:"name"` Version string `json:"version"` InstallDate string `json:"install_date"` } func main() { var softwareList []Software if runtime.GOOS == "windows" { softwareList = append(softwareList, enumerateWindows()...) } else if runtime.GOOS == "linux" { softwareList = append(softwareList, enumerateLinux()...) } output, err := json.MarshalIndent(softwareList, "", " ") if err != nil { log.Println("Error marshalling software list:", err) return } fmt.Println(string(output)) } // Add to the enumerateWindows function func enumerateWindows() []Software { var softwareList []Software // Winget softwareList = append(softwareList, enumerateWinget()...) // Chocolatey softwareList = append(softwareList, enumerateChocolatey()...) // Scoop softwareList = append(softwareList, enumerateScoop()...) // Common Windows Installations softwareList = append(softwareList, enumerateCommonWindows()...) // NuGet softwareList = append(softwareList, enumerateNuGet()...) // Microsoft Store softwareList = append(softwareList, enumerateMicrosoftStore()...) return softwareList } // Add to the enumerateLinux function func enumerateLinux() []Software { var softwareList []Software // APT softwareList = append(softwareList, enumerateApt()...) // Snap softwareList = append(softwareList, enumerateSnap()...) // Pip softwareList = append(softwareList, enumeratePip()...) // NPM softwareList = append(softwareList, enumerateNpm()...) // Flatpak softwareList = append(softwareList, enumerateFlatpak()...) // RPM softwareList = append(softwareList, enumerateRpm()...) // Pacman softwareList = append(softwareList, enumeratePacman()...) // Homebrew softwareList = append(softwareList, enumerateHomebrew()...) // Conda softwareList = append(softwareList, enumerateConda()...) return softwareList } func enumerateNuGet() []Software { var softwareList []Software output, err := runCommand("nuget", "list", "-AllVersions") if err != nil { log.Println("Error enumerating NuGet packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "nuget", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateMicrosoftStore() []Software { var softwareList []Software output, err := runCommand("powershell", "Get-AppxPackage", "|", "Select-Object", "Name,PackageFullName,InstallDate") if err != nil { log.Println("Error enumerating Microsoft Store packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 3 { continue } softwareList = append(softwareList, Software{ Source: "microsoft store", Name: parts[0], Version: parts[1], InstallDate: parseInstallDate(parts[2]), }) } return softwareList } func enumerateFlatpak() []Software { var softwareList []Software output, err := runCommand("flatpak", "list") if err != nil { log.Println("Error enumerating Flatpak packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "flatpak", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateRpm() []Software { var softwareList []Software output, err := runCommand("rpm", "-qa", "--queryformat", "%{NAME} %{VERSION}\n") if err != nil { log.Println("Error enumerating RPM packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "rpm", Name: parts[0], Version: parts[1], }) } return softwareList } func enumeratePacman() []Software { var softwareList []Software output, err := runCommand("pacman", "-Q") if err != nil { log.Println("Error enumerating Pacman packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "pacman", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateHomebrew() []Software { var softwareList []Software output, err := runCommand("brew", "list", "--versions") if err != nil { log.Println("Error enumerating Homebrew packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "homebrew", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateConda() []Software { var softwareList []Software output, err := runCommand("conda", "list", "--json") if err != nil { log.Println("Error enumerating Conda packages:", err) return softwareList } var condaPackages []map[string]interface{} err = json.Unmarshal([]byte(output), &condaPackages) if err != nil { log.Println("Error parsing Conda JSON output:", err) return softwareList } for _, pkg := range condaPackages { softwareList = append(softwareList, Software{ Source: "conda", Name: pkg["name"].(string), Version: pkg["version"].(string), }) } return softwareList } func runCommand(cmd string, args ...string) (string, error) { out, err := exec.Command(cmd, args...).Output() if err != nil { return "", err } return string(out), nil } func parseInstallDate(dateString string) string { layout := "2006-01-02" date, err := time.Parse(layout, dateString) if err != nil { return "" } return date.Format(layout) } func enumerateWinget() []Software { var softwareList []Software output, err := runCommand("winget", "list", "--source", "winget") if err != nil { log.Println("Error enumerating Winget packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := regexp.MustCompile(`\s+`).Split(line, -1) if len(parts) < 4 { continue } softwareList = append(softwareList, Software{ Source: "winget", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateChocolatey() []Software { var softwareList []Software output, err := runCommand("choco", "list", "--local-only") if err != nil { log.Println("Error enumerating Chocolatey packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Split(line, "|") if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "chocolatey", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateScoop() []Software { var softwareList []Software output, err := runCommand("scoop", "list") if err != nil { log.Println("Error enumerating Scoop packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { if strings.HasPrefix(line, "Installed apps") { continue } parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "scoop", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateCommonWindows() []Software { var softwareList []Software output, err := runCommand("powershell", "Get-WmiObject", "-Class", "Win32_Product", "|", "Select-Object", "Name,Version,InstallDate") if err != nil { log.Println("Error enumerating common Windows installations:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 3 { continue } softwareList = append(softwareList, Software{ Source: "common windows installation", Name: parts[0], Version: parts[1], InstallDate: parseInstallDate(parts[2]), }) } return softwareList } func enumerateApt() []Software { var softwareList []Software output, err := runCommand("dpkg-query", "-W", "-f=${binary:Package} ${Version} ${Installed-Size}\n") if err != nil { log.Println("Error enumerating APT packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 2 { continue } softwareList = append(softwareList, Software{ Source: "apt", Name: parts[0], Version: parts[1], }) } return softwareList } func enumerateSnap() []Software { var softwareList []Software output, err := runCommand("snap", "list") if err != nil { log.Println("Error enumerating Snap packages:", err) return softwareList } lines := strings.Split(output, "\n") for _, line := range lines { parts := strings.Fields(line) if len(parts) < 3 { continue } softwareList = append(softwareList, Software{ Source: "snap", Name: parts[0], Version: parts[1], }) } return softwareList } func enumeratePip() []Software { var softwareList []Software output, err := runCommand("pip", "list", "--format=json") if err != nil { log.Println("Error enumerating Pip packages:", err) return softwareList } var pipPackages []map[string]string err = json.Unmarshal([]byte(output), &pipPackages) if err != nil { log.Println("Error parsing Pip JSON output:", err) return softwareList } for _, pkg := range pipPackages { softwareList = append(softwareList, Software{ Source: "pip", Name: pkg["name"], Version: pkg["version"], }) } return softwareList } func enumerateNpm() []Software { var softwareList []Software output, err := runCommand("npm", "list", "-g", "--depth=0", "--json") if err != nil { log.Println("Error enumerating NPM packages:", err) return softwareList } var npmPackages map[string]interface{} err = json.Unmarshal([]byte(output), &npmPackages) if err != nil { log.Println("Error parsing NPM JSON output:", err) return softwareList } dependencies := npmPackages["dependencies"].(map[string]interface{}) for name, info := range dependencies { infoMap := info.(map[string]interface{}) version := infoMap["version"].(string) softwareList = append(softwareList, Software{ Source: "npm", Name: name, Version: version, }) } return softwareList }