Add goinfo and gosoft
This commit is contained in:
3
tools/go/goinfo/go.mod
Normal file
3
tools/go/goinfo/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.ktf.ninja/tabledevil/goinfo
|
||||||
|
|
||||||
|
go 1.22.5
|
||||||
52
tools/go/goinfo/goinfo.go
Normal file
52
tools/go/goinfo/goinfo.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getHostname() string {
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Could not retrieve Hostname")
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return hostname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUsernameDomain() string {
|
||||||
|
user, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIP(hostname string) string {
|
||||||
|
addrs, err := net.LookupIP(hostname)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return addrs[0].String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGroups() []int {
|
||||||
|
groups, err := os.Getgroups()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hostname: ", getHostname())
|
||||||
|
fmt.Println("username: ", getUsernameDomain())
|
||||||
|
fmt.Println("groups: ", getGroups())
|
||||||
|
fmt.Println("google: ", getIP("www.google.de"))
|
||||||
|
|
||||||
|
}
|
||||||
BIN
tools/go/gosoft/gosoft.exe
Executable file
BIN
tools/go/gosoft/gosoft.exe
Executable file
Binary file not shown.
502
tools/go/gosoft/gosoft.go
Normal file
502
tools/go/gosoft/gosoft.go
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user