From d8d38a3a4e736c45f5c76e960e9489ffe2e940c6 Mon Sep 17 00:00:00 2001 From: Stran Dutton Date: Mon, 23 Feb 2026 16:04:31 -0600 Subject: [PATCH 1/6] BED-6446: Add winres tool to generate windows resources, tests --- .github/workflows/build.yml | 7 + .github/workflows/publish.yml | 7 + .../generate-windows-resources.go | 142 +++++++++++++++ .../generate-windows-resources_test.go | 171 ++++++++++++++++++ constants/misc.go | 1 + go.mod | 9 + go.sum | 20 ++ winres/favicon.ico | Bin 0 -> 4286 bytes 8 files changed, 357 insertions(+) create mode 100644 cmd/generate-windows-resources/generate-windows-resources.go create mode 100644 cmd/generate-windows-resources/generate-windows-resources_test.go create mode 100644 winres/favicon.ico diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8425f4cc..088eb245 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -189,6 +189,13 @@ jobs: check-latest: true cache: true + - name: Generate Windows Resources + if: matrix.os == 'windows' + continue-on-error: true + run: | + echo "Generating Windows resources..." + go run cmd/generate-windows-resources/generate-windows-resources.go "v0.0.0-rolling+${{ github.sha }}" || echo "Failed to generate Windows Resources. Skipping..." + - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=v0.0.0-rolling+${{ github.sha }}"' env: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dfaae6c2..7495ec45 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -32,6 +32,13 @@ jobs: check-latest: true cache: true + - name: Generate Windows Resources + if: matrix.os == 'windows' + continue-on-error: true + run: | + echo "Generating Windows resources..." + go run cmd/generate-windows-resources/generate-windows-resources.go "${{ env.AZUREHOUND_VERSION }}" || echo "Failed to generate Windows Resources. Skipping..." + - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=${{ env.AZUREHOUND_VERSION }}"' env: diff --git a/cmd/generate-windows-resources/generate-windows-resources.go b/cmd/generate-windows-resources/generate-windows-resources.go new file mode 100644 index 00000000..b8cbbe89 --- /dev/null +++ b/cmd/generate-windows-resources/generate-windows-resources.go @@ -0,0 +1,142 @@ +// Copyright (C) 2026 Specter Ops, Inc. +// +// This file is part of AzureHound. +// +// AzureHound is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// AzureHound is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package main + +import ( + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "time" + + "github.com/bloodhoundad/azurehound/v2/constants" +) + +const ( + winresDir = "winres" + winresJSONFile = "winres.json" + iconFile = "favicon.ico" + langCodeUSEn = "0409" // US English + fileVersion = "0.0.0.0" // Windows PE file version; we will update 'productVersion' field instead of this one +) + +func main() { + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} + +func run() error { + productVersion, err := parseProductVersion() + if err != nil { + return err + } + + config := buildWinresConfig(productVersion) + + if err := writeWinresConfig(config); err != nil { + return fmt.Errorf("failed to write winres config: %w", err) + } + + if err := runWinres(); err != nil { + return fmt.Errorf("failed to generate windows resources: %w", err) + } + + fmt.Printf("✓ Windows resources generated successfully!\n") + fmt.Printf(" Product Version: %s\n", productVersion) + return nil +} + +func parseProductVersion() (string, error) { + if len(os.Args) < 2 { + return "", fmt.Errorf("usage: %s ", filepath.Base(os.Args[0])) + } + version := os.Args[1] + if version == "" { + return "", fmt.Errorf("product version cannot be empty") + } + return version, nil +} + +func buildWinresConfig(productVersion string) map[string]interface{} { + return map[string]interface{}{ + // Icon resource + "RT_GROUP_ICON": map[string]interface{}{ + "APP": map[string]interface{}{ + "0000": iconFile, + }, + }, + // Version information + "RT_VERSION": map[string]interface{}{ + "#1": map[string]interface{}{ + "0000": map[string]interface{}{ + "fixed": map[string]interface{}{ + "file_version": fileVersion, + "product_version": fileVersion, + }, + "info": map[string]interface{}{ + langCodeUSEn: map[string]string{ + "FileDescription": constants.Description, + "ProductName": constants.DisplayName, + "CompanyName": constants.AuthorRef, + "LegalCopyright": fmt.Sprintf("Copyright (C) %d %s", time.Now().Year(), constants.Company), + "ProductVersion": productVersion, + "FileVersion": fileVersion, + "OriginalFilename": "azurehound.exe", + }, + }, + }, + }, + }, + } +} + +func writeWinresConfig(config map[string]interface{}) error { + if err := os.MkdirAll(winresDir, 0755); err != nil { + return fmt.Errorf("failed to create winres directory: %w", err) + } + + configPath := filepath.Join(winresDir, winresJSONFile) + f, err := os.Create(configPath) + if err != nil { + return fmt.Errorf("failed to create %s: %w", configPath, err) + } + defer f.Close() + + enc := json.NewEncoder(f) + enc.SetIndent("", " ") + if err := enc.Encode(config); err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + + return nil +} + +func runWinres() error { + cmd := exec.Command("go", "tool", "go-winres", "make") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + return fmt.Errorf("go-winres command failed: %w", err) + } + + return nil +} diff --git a/cmd/generate-windows-resources/generate-windows-resources_test.go b/cmd/generate-windows-resources/generate-windows-resources_test.go new file mode 100644 index 00000000..bb859a51 --- /dev/null +++ b/cmd/generate-windows-resources/generate-windows-resources_test.go @@ -0,0 +1,171 @@ +// Copyright (C) 2026 Specter Ops, Inc. +// +// This file is part of AzureHound. +// +// AzureHound is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// AzureHound is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package main + +import ( + "fmt" + "os" + "testing" + "time" + + "github.com/bloodhoundad/azurehound/v2/constants" +) + +func TestParseProductVersion(t *testing.T) { + tests := []struct { + name string + args []string + want string + wantErr bool + }{ + { + name: "valid version", + args: []string{"cmd", "v1.2.3"}, + want: "v1.2.3", + wantErr: false, + }, + { + name: "valid version with build metadata", + args: []string{"cmd", "v0.0.0-rolling+5f8807a4107f0b80debaf79b2d245bfa7078a54b"}, + want: "v0.0.0-rolling+5f8807a4107f0b80debaf79b2d245bfa7078a54b", + wantErr: false, + }, + { + name: "no version provided", + args: []string{"cmd"}, + want: "", + wantErr: true, + }, + { + name: "empty version string", + args: []string{"cmd", ""}, + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Save original os.Args and restore after test + oldArgs := os.Args + defer func() { os.Args = oldArgs }() + + os.Args = tt.args + + got, err := parseProductVersion() + if (err != nil) != tt.wantErr { + t.Errorf("parseProductVersion() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("parseProductVersion() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestBuildWinresConfig(t *testing.T) { + productVersion := "v2.9.0-test" + config := buildWinresConfig(productVersion) + + // Verify icon resource + rtGroupIcon, ok := config["RT_GROUP_ICON"].(map[string]interface{}) + if !ok { + t.Fatal("RT_GROUP_ICON not found or wrong type") + } + + app, ok := rtGroupIcon["APP"].(map[string]interface{}) + if !ok { + t.Fatal("APP icon not found or wrong type") + } + + iconPath, ok := app["0000"].(string) + if !ok { + t.Fatal("icon path not found or wrong type") + } + + if iconPath != iconFile { + t.Errorf("icon path = %v, want %v", iconPath, iconFile) + } + + // Verify top-level structure + rtVersion, ok := config["RT_VERSION"].(map[string]interface{}) + if !ok { + t.Fatal("RT_VERSION not found or wrong type") + } + + // Navigate to the version info + level1, ok := rtVersion["#1"].(map[string]interface{}) + if !ok { + t.Fatal("#1 not found or wrong type") + } + + level2, ok := level1["0000"].(map[string]interface{}) + if !ok { + t.Fatal("0000 not found or wrong type") + } + + // Test fixed section + fixed, ok := level2["fixed"].(map[string]interface{}) + if !ok { + t.Fatal("fixed section not found") + } + + if fixed["file_version"] != fileVersion { + t.Errorf("file_version = %v, want %v", fixed["file_version"], fileVersion) + } + + if fixed["product_version"] != fileVersion { + t.Errorf("product_version = %v, want %v", fixed["product_version"], fileVersion) + } + + // Test info section + info, ok := level2["info"].(map[string]interface{}) + if !ok { + t.Fatal("info section not found") + } + + langInfo, ok := info[langCodeUSEn].(map[string]string) + if !ok { + t.Fatal("language info not found") + } + + // Verify all required fields + requiredFields := map[string]string{ + "FileDescription": constants.Description, + "ProductName": constants.DisplayName, + "CompanyName": constants.AuthorRef, + "ProductVersion": productVersion, + "FileVersion": fileVersion, + "OriginalFilename": "azurehound.exe", + } + + for field, expected := range requiredFields { + if got := langInfo[field]; got != expected { + t.Errorf("%s = %v, want %v", field, got, expected) + } + } + + // Verify copyright contains current year and company + copyright := langInfo["LegalCopyright"] + currentYear := time.Now().Year() + expectedCopyright := fmt.Sprintf("Copyright (C) %d %s", currentYear, constants.Company) + if copyright != expectedCopyright { + t.Errorf("LegalCopyright = %v, want %v", copyright, expectedCopyright) + } +} diff --git a/constants/misc.go b/constants/misc.go index c90648d2..53704c52 100644 --- a/constants/misc.go +++ b/constants/misc.go @@ -27,6 +27,7 @@ var Version string = "v0.0.0" const ( Name string = "azurehound" DisplayName string = "AzureHound" + Company string = "Specter Ops, Inc." Description string = "The official tool for collecting Azure data for BloodHound and BloodHound Enterprise" AuthorRef string = "Created by the BloodHound Enterprise team - https://bloodhoundenterprise.io" AzPowerShellClientID string = "1950a258-227b-4e31-a9cf-717495945fc2" diff --git a/go.mod b/go.mod index dd8725d4..9529c55c 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/chzyer/readline v1.5.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect @@ -35,16 +36,24 @@ require ( github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.9.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.8.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/tc-hib/go-winres v0.3.1 // indirect + github.com/tc-hib/winres v0.1.6 // indirect + github.com/urfave/cli/v2 v2.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.40.0 // indirect + golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect golang.org/x/text v0.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +tool github.com/tc-hib/go-winres diff --git a/go.sum b/go.sum index 3ee7cd96..6b1a47ec 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,7 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -20,6 +21,9 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -61,6 +65,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -73,9 +79,12 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= @@ -92,6 +101,12 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tc-hib/go-winres v0.3.1 h1:9r67V7Ep34yyx8SL716BzcKePRvEBOjan47SmMnxEdE= +github.com/tc-hib/go-winres v0.3.1/go.mod h1:lTPf0MW3eu6rmvMyLrPXSy6xsSz4t5dRxB7dc5YFP6k= +github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= +github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= @@ -100,6 +115,9 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -111,10 +129,12 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/winres/favicon.ico b/winres/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8b38d16d15573b5fe52142e785310c0133b2125c GIT binary patch literal 4286 zcmeH~OH5Q(7{?EfiYPWJh>xO-3JL?vFatBpFu)AM@Dc40r7fly!bYtqGtC}?Fiqu5s-aCWZSBPEE-U0HyyI^xU&E0_6veJ}5J^zC(Z!6bZLMmlqHRJ+Ti+6xNQ zwX6@COp0aF{=MLxVUH7>H(FZmMBltQ7T(-EvJl$_V%ndU=3lPwmm~Hja4uI=1iJF` z)l*qnO0K@1lyv*M%F4ioq$K~3<>dh*eqG=m0pm6D?_=)8epYR5U^cpw)zyK_HEROJ z`1u^^LB6orl&00I{b$R|H5;|ug|A{A-)2+ifmvHrq`9f>E^2&)y=J-2T24uc*6sBM zGQqG%NBoJ*^~4@6>&jjq{yU_OURrZ`sU=|#xH=F$}^t_ySk5C_j)vC5qo2~G^HY3CT<VL=d`trB*4#(vNAP>7=7SbIS&P#tKs80nk#o@md zK5WJ=11@%fc@A3#vXmM%_4WM{lb5F@P~%qeI0~l=T3bh!rl#JS34W%-p*Z0{*};Q% zA|){U4>wxL9+O#}GEYafc5~eh9r$TNBa+MjG{d3ofjOL)rMxqQ4#F`L@%kIlxS& zFKOVv$z4~gL(z-F#M~+0Ik&6eVgvkfp)-;9KK#eYHSpyy{*Xs#4yTuZ*~$LKnwnr! zd;6U^a3YekmPPN5vA&aD+T>>Lg!$|%hBsBj7vI!0vXFHf^91KA%>{8Hi@gL}w$Wx#So+$JEw`@1sRU zfqK?GZnsv$nwc7!>FZaM-4zx-`g;an&E($!Ph!`v54!2wCa+gpk&tjJ3=Xc7IN(MS z&uZ?FSBY~Qye_6TuTzU7_*+PyBCcP*A4ToudTV_Ata^Bs2cNTUo?3NSv zAbjdADG8**EyJ2MTDmkkapDg_ekpLEpPq*9aX4#7jKr3A@#61c_*%~$eqMJ%UG?b$ zBef2_b6)u!>5q^v*tU^JH~kOwYr}>h{PurO&8zvgEXIeAy4b0696A&6rO=mTY0H|8 z`(y{P)yQ{Zki&mI@HP&+Eu7^+&e@0Xyl}EnSy|8r7oy<$C&adc-o(_7f!CB9e=Mp(BzrECP|c5BIb z2tJl_r^)Z_05+TORYiR3&~4*)!T4_l=?ZR4<8fk%To-W9pQ2vJkaqmPII%i0qxUJq z5l_ys_%k*(24_yJ>a(9jb@jwus%xhk$=OR@pK-63>HEk{pN2+qf8bqzAr^i5#3Q*k zP~&f#n}e|uggfhrv7W?`yzA)I2Tx-AG;HAZa?a^#iB(hc_x=Aga32?g-^1bXN&c7h znLgY%&(#03ay~ZIGaQpRd?iKoOu0|RRSNgeC!$sI#AqGap;)u~O r5j83diKCGsadd{E?>EoPvEgAc)-R%v#IdNWV`GW Date: Mon, 23 Feb 2026 16:19:01 -0600 Subject: [PATCH 2/6] BED-6446: update dependencies with vulnerabilities --- go.mod | 14 +++++++------- go.sum | 23 ++++++++++++----------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 9529c55c..b17322bb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/bloodhoundad/azurehound/v2 -go 1.23.0 +go 1.24.0 toolchain go1.24.2 @@ -19,8 +19,8 @@ require ( github.com/stretchr/testify v1.10.0 github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 go.uber.org/mock v0.5.2 - golang.org/x/net v0.42.0 - golang.org/x/sys v0.34.0 + golang.org/x/net v0.49.0 + golang.org/x/sys v0.41.0 ) require ( @@ -30,7 +30,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect @@ -50,9 +50,9 @@ require ( github.com/tc-hib/winres v0.1.6 // indirect github.com/urfave/cli/v2 v2.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/crypto v0.48.0 // indirect + golang.org/x/image v0.18.0 // indirect + golang.org/x/text v0.34.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6b1a47ec..60a36055 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -113,13 +113,14 @@ go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= +golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -127,11 +128,11 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 23d799fe842371c1e8f9421e3908667c1b638dfd Mon Sep 17 00:00:00 2001 From: Stran Dutton Date: Mon, 23 Feb 2026 16:24:26 -0600 Subject: [PATCH 3/6] BED-6446: complying with CodeRabbit nitpick to remove error fallback message --- .github/workflows/build.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 088eb245..7a218a7d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -194,7 +194,7 @@ jobs: continue-on-error: true run: | echo "Generating Windows resources..." - go run cmd/generate-windows-resources/generate-windows-resources.go "v0.0.0-rolling+${{ github.sha }}" || echo "Failed to generate Windows Resources. Skipping..." + go run cmd/generate-windows-resources/generate-windows-resources.go "v0.0.0-rolling+${{ github.sha }}" - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=v0.0.0-rolling+${{ github.sha }}"' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7495ec45..10fb8ef6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,7 +37,7 @@ jobs: continue-on-error: true run: | echo "Generating Windows resources..." - go run cmd/generate-windows-resources/generate-windows-resources.go "${{ env.AZUREHOUND_VERSION }}" || echo "Failed to generate Windows Resources. Skipping..." + go run cmd/generate-windows-resources/generate-windows-resources.go "${{ env.AZUREHOUND_VERSION }}" - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=${{ env.AZUREHOUND_VERSION }}"' From dca0bd5b83dd0a884b0cb873ba7886f419b706b2 Mon Sep 17 00:00:00 2001 From: Stran Dutton Date: Fri, 27 Feb 2026 10:50:18 -0600 Subject: [PATCH 4/6] BED-6446: refactor and update compName ref --- .../generate-windows-resources/generate-windows-resources.go | 2 +- .../generate-windows-resources_test.go | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {cmd => winres}/generate-windows-resources/generate-windows-resources.go (98%) rename {cmd => winres}/generate-windows-resources/generate-windows-resources_test.go (100%) diff --git a/cmd/generate-windows-resources/generate-windows-resources.go b/winres/generate-windows-resources/generate-windows-resources.go similarity index 98% rename from cmd/generate-windows-resources/generate-windows-resources.go rename to winres/generate-windows-resources/generate-windows-resources.go index b8cbbe89..b09f092c 100644 --- a/cmd/generate-windows-resources/generate-windows-resources.go +++ b/winres/generate-windows-resources/generate-windows-resources.go @@ -95,7 +95,7 @@ func buildWinresConfig(productVersion string) map[string]interface{} { langCodeUSEn: map[string]string{ "FileDescription": constants.Description, "ProductName": constants.DisplayName, - "CompanyName": constants.AuthorRef, + "CompanyName": constants.Company, "LegalCopyright": fmt.Sprintf("Copyright (C) %d %s", time.Now().Year(), constants.Company), "ProductVersion": productVersion, "FileVersion": fileVersion, diff --git a/cmd/generate-windows-resources/generate-windows-resources_test.go b/winres/generate-windows-resources/generate-windows-resources_test.go similarity index 100% rename from cmd/generate-windows-resources/generate-windows-resources_test.go rename to winres/generate-windows-resources/generate-windows-resources_test.go From 78b586b728cba7bdb14dfa1fdd63f9c03697101c Mon Sep 17 00:00:00 2001 From: Stran Dutton Date: Fri, 27 Feb 2026 10:51:55 -0600 Subject: [PATCH 5/6] BED-6446: update test --- .../generate-windows-resources_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winres/generate-windows-resources/generate-windows-resources_test.go b/winres/generate-windows-resources/generate-windows-resources_test.go index bb859a51..815729ed 100644 --- a/winres/generate-windows-resources/generate-windows-resources_test.go +++ b/winres/generate-windows-resources/generate-windows-resources_test.go @@ -149,7 +149,7 @@ func TestBuildWinresConfig(t *testing.T) { requiredFields := map[string]string{ "FileDescription": constants.Description, "ProductName": constants.DisplayName, - "CompanyName": constants.AuthorRef, + "CompanyName": constants.Company, "ProductVersion": productVersion, "FileVersion": fileVersion, "OriginalFilename": "azurehound.exe", From 9ddd02394f5e7fc496b8fc0b1aae2ce17591100a Mon Sep 17 00:00:00 2001 From: Stran Dutton Date: Fri, 27 Feb 2026 10:53:07 -0600 Subject: [PATCH 6/6] BED-6446: update workflows with updated file path --- .github/workflows/build.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a218a7d..35bddcf1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -194,7 +194,7 @@ jobs: continue-on-error: true run: | echo "Generating Windows resources..." - go run cmd/generate-windows-resources/generate-windows-resources.go "v0.0.0-rolling+${{ github.sha }}" + go run winres/generate-windows-resources/generate-windows-resources.go "v0.0.0-rolling+${{ github.sha }}" - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=v0.0.0-rolling+${{ github.sha }}"' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 10fb8ef6..3e50a46b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,7 +37,7 @@ jobs: continue-on-error: true run: | echo "Generating Windows resources..." - go run cmd/generate-windows-resources/generate-windows-resources.go "${{ env.AZUREHOUND_VERSION }}" + go run winres/generate-windows-resources/generate-windows-resources.go "${{ env.AZUREHOUND_VERSION }}" - name: Build run: 'go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=${{ env.AZUREHOUND_VERSION }}"'