diff --git a/changes/23540-pe-sfx b/changes/23540-pe-sfx new file mode 100644 index 000000000000..63c241a8be83 --- /dev/null +++ b/changes/23540-pe-sfx @@ -0,0 +1 @@ +Fixed name/version parsing issue with PE (EXE) installer self-extracting archives such as Opera. diff --git a/go.mod b/go.mod index 822b953698bc..778e211419e0 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,7 @@ require ( github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/rs/zerolog v1.32.0 github.com/russellhaering/goxmldsig v1.2.0 - github.com/saferwall/pe v1.5.2 + github.com/saferwall/pe v1.5.5 github.com/sassoftware/relic/v8 v8.0.1 github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 github.com/sethvargo/go-password v0.3.0 @@ -292,6 +292,7 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect github.com/secure-systems-lab/go-securesystemslib v0.5.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect diff --git a/go.sum b/go.sum index 36ba36ea7db0..515f77b00eb9 100644 --- a/go.sum +++ b/go.sum @@ -1034,14 +1034,16 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/saferwall/pe v1.5.2 h1:h5lLtLsyxGHQ9dN6cd8EfeLEBEo5gdqJpkuw4o4vTMY= -github.com/saferwall/pe v1.5.2/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s= +github.com/saferwall/pe v1.5.5 h1:GGbzKjXDm7i+1K6riOgtgblyTdRmTbr3r11IzjovAK8= +github.com/saferwall/pe v1.5.5/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ= github.com/sassoftware/relic/v8 v8.0.1 h1:uYUoaoTQMs67up8/46NgrSxSftgfY4VWBusDVg56k7I= github.com/sassoftware/relic/v8 v8.0.1/go.mod h1:s/MwugRcovgYcNJNOyvLfqRHDX7iArHtFtUR9kEodz8= github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= +github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc= +github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA= github.com/secure-systems-lab/go-securesystemslib v0.5.0 h1:oTiNu0QnulMQgN/hLK124wJD/r2f9ZhIUuKIeBsCBT8= github.com/secure-systems-lab/go-securesystemslib v0.5.0/go.mod h1:uoCqUC0Ap7jrBSEanxT+SdACYJTVplRXWLkGMuDjXqk= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= diff --git a/pkg/file/pe.go b/pkg/file/pe.go index 27e872221d00..4516b5a25e15 100644 --- a/pkg/file/pe.go +++ b/pkg/file/pe.go @@ -48,21 +48,51 @@ func ExtractPEMetadata(tfr *fleet.TempFileReader) (*InstallerMetadata, error) { return nil, fmt.Errorf("error parsing PE file: %w", err) } - v, err := pep.ParseVersionResources() + resources, err := pep.ParseVersionResourcesForEntries() if err != nil { return nil, fmt.Errorf("error parsing PE version resources: %w", err) } - name := strings.TrimSpace(v["ProductName"]) + var name, version, sfxName, sfxVersion string + + for _, e := range resources { + productName, ok := e["ProductName"] + if !ok { + productName = e["productname"] // used by Opera SFX (self-extracting archive) + } + productVersion := strings.TrimSpace(e["ProductVersion"]) + if productName != "" { + productName = strings.TrimSpace(productName) + if productName == "7-Zip" { + // This may be a 7-Zip self-extracting archive. + sfxName = productName + sfxVersion = productVersion + continue + } + name = productName + } + if productVersion != "" { + version = productVersion + } + } + if name == "" && sfxName != "" { + // If we didn't find a ProductName, we may be + // dealing with an archive executable (e.g., if we're dealing with the 7-Zip executable itself rather than Opera) + name = sfxName + if sfxVersion != "" { + version = sfxVersion + } + } + return applySpecialCases(&InstallerMetadata{ Name: name, - Version: strings.TrimSpace(v["ProductVersion"]), + Version: version, PackageIDs: []string{name}, SHASum: h.Sum(nil), - }, v), nil + }, resources), nil } -var exeSpecialCases = map[string]func(*InstallerMetadata, map[string]string) *InstallerMetadata{ - "Notion": func(meta *InstallerMetadata, resources map[string]string) *InstallerMetadata { +var exeSpecialCases = map[string]func(*InstallerMetadata, []map[string]string) *InstallerMetadata{ + "Notion": func(meta *InstallerMetadata, _ []map[string]string) *InstallerMetadata { if meta.Version != "" { meta.Name = meta.Name + " " + meta.Version } @@ -82,7 +112,7 @@ var exeSpecialCases = map[string]func(*InstallerMetadata, map[string]string) *In // least for the most popular apps that use unusual naming. // // See https://github.com/fleetdm/fleet/issues/20440#issuecomment-2260500661 -func applySpecialCases(meta *InstallerMetadata, resources map[string]string) *InstallerMetadata { +func applySpecialCases(meta *InstallerMetadata, resources []map[string]string) *InstallerMetadata { if fn := exeSpecialCases[meta.Name]; fn != nil { return fn(meta, resources) }