Skip to content

Commit

Permalink
✨ Read windows appx packages on a FS scan. (#4804)
Browse files Browse the repository at this point in the history
  • Loading branch information
preslavgerchev authored Nov 1, 2024
1 parent 5868c23 commit a9cc1bf
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 63 deletions.
File renamed without changes.
5 changes: 3 additions & 2 deletions providers/os/fs/find_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ func FindFiles(iofs fs.FS, from string, r *regexp.Regexp, typ string, perm *uint
if err != nil {
return err
}

if skip {
return nil
}

if matcher.Match(p, d.Type()) {
matchedPaths = append(matchedPaths, p)
}
Expand Down Expand Up @@ -54,7 +54,8 @@ func (m findFilesMatcher) matchesRegex(path string) bool {
// We don't use r.Match because we need the entire path to match
// if we want to be compatible with find. It would probably be
// more efficient add anchors to the regular expression
return m.r.FindString(path) == path
match := m.r.FindString(path)
return match == path
}

func (m findFilesMatcher) matchesType(entryType fs.FileMode) bool {
Expand Down
4 changes: 4 additions & 0 deletions providers/os/fs/find_files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ func TestFindFiles(t *testing.T) {
require.NoError(t, err)
assert.ElementsMatch(t, rootBFiles, []string{"root/b/file1"})

file1Files, err := FindFiles(afero.NewIOFS(fs), "root", regexp.MustCompile(".*/file1"), "f", nil)
require.NoError(t, err)
assert.ElementsMatch(t, file1Files, []string{"root/b/file1", "root/a/file1"})

perm := uint32(0o002)
permFiles, err := FindFiles(afero.NewIOFS(fs), "root", nil, "f", &perm)
require.NoError(t, err)
Expand Down
69 changes: 69 additions & 0 deletions providers/os/resources/packages/windows_appx_manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package packages

import "encoding/xml"

// AppxManifest represents the structure of an AppxManifest.xml file
type AppxManifest struct {
XMLName xml.Name `xml:"Package"`
Text string `xml:",chardata"`
Xmlns string `xml:"xmlns,attr"`
Uap string `xml:"uap,attr"`
Build string `xml:"build,attr"`
Mp string `xml:"mp,attr"`
IgnorableNamespaces string `xml:"IgnorableNamespaces,attr"`
Identity struct {
Text string `xml:",chardata"`
Name string `xml:"Name,attr"`
ProcessorArchitecture string `xml:"ProcessorArchitecture,attr"`
Publisher string `xml:"Publisher,attr"`
Version string `xml:"Version,attr"`
} `xml:"Identity"`
Properties struct {
Text string `xml:",chardata"`
Framework string `xml:"Framework"`
DisplayName string `xml:"DisplayName"`
PublisherDisplayName string `xml:"PublisherDisplayName"`
Description string `xml:"Description"`
Logo string `xml:"Logo"`
} `xml:"Properties"`
Resources struct {
Text string `xml:",chardata"`
Resource struct {
Text string `xml:",chardata"`
Language string `xml:"Language,attr"`
} `xml:"Resource"`
} `xml:"Resources"`
Dependencies struct {
Text string `xml:",chardata"`
TargetDeviceFamily struct {
Text string `xml:",chardata"`
Name string `xml:"Name,attr"`
MinVersion string `xml:"MinVersion,attr"`
MaxVersionTested string `xml:"MaxVersionTested,attr"`
} `xml:"TargetDeviceFamily"`
} `xml:"Dependencies"`
PhoneIdentity struct {
Text string `xml:",chardata"`
PhoneProductId string `xml:"PhoneProductId,attr"`
PhonePublisherId string `xml:"PhonePublisherId,attr"`
} `xml:"PhoneIdentity"`
Extensions struct {
Text string `xml:",chardata"`
Extension []struct {
Text string `xml:",chardata"`
Category string `xml:"Category,attr"`
InProcessServer struct {
Text string `xml:",chardata"`
Path string `xml:"Path"`
ActivatableClass []struct {
Text string `xml:",chardata"`
ActivatableClassId string `xml:"ActivatableClassId,attr"`
ThreadingModel string `xml:"ThreadingModel,attr"`
} `xml:"ActivatableClass"`
} `xml:"InProcessServer"`
} `xml:"Extension"`
} `xml:"Extensions"`
}
100 changes: 100 additions & 0 deletions providers/os/resources/packages/windows_appx_manifest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package packages

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestParseWindowsAppxManifest(t *testing.T) {
manifest := `<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:wincap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/windowscapabilities"
IgnorableNamespaces="uap rescap wincap">
<!--
Manual versioning is used for this app.
Appx version should be in sync with version used for the app name in microsoft-windows-diagnosticcomposerhost.appxsetup.man
See https://osgwiki.com/wiki/System_Apps#Servicing
-->
<Identity Name="Microsoft.AAD.BrokerPlugin"
Publisher="CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
ProcessorArchitecture="neutral"
ResourceId="neutral"
Version="1000.19580.1000.0" />
<Properties>
<DisplayName>ms-resource:PackageDisplayName</DisplayName>
<PublisherDisplayName>ms-resource:PublisherDisplayName</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Resources>
<Resource Language="en-us" />
</Resources>
<Applications>
<Application Id="App" Executable="Microsoft.AAD.BrokerPlugin.exe" EntryPoint="BrokerPlugin.App">
<uap:VisualElements DisplayName="ms-resource:PackageDisplayName" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="ms-resource:PackageDescription" BackgroundColor="#ffffff" AppListEntry="none">
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.webAccountProvider">
<uap:WebAccountProvider Url="https://login.windows.net" BackgroundEntryPoint="AAD.Core.TokenBackground" />
</uap:Extension>
<uap:Extension Category="windows.appService" EntryPoint="AAD.Core.AppService">
<uap:AppService Name="TBAuthAppService" />
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ms-aad-brokerplugin">
<uap:DisplayName>ms-resource:PackageDisplayName</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.10587.0"/>
</Dependencies>
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="enterpriseAuthentication" />
<Capability Name="privateNetworkClientServer" />
<uap:Capability Name="sharedUserCertificates" />
<rescap:Capability Name="deviceManagementAdministrator" />
<rescap:Capability Name="deviceManagementRegistration" />
<rescap:Capability Name="remotePassportAuthentication" />
<rescap:Capability Name="userPrincipalName" />
<rescap:Capability Name="windowsHelloCredentialAccess" />
<!-- needed for detection of Visitor accounts using Windows::System::Internal::UserManager::GetProfileForUser -->
<wincap:Capability Name="userSigninSupport" />
</Capabilities>
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>AAD.Core.dll</Path>
<!-- Value of ActivatableClassId should be the same as BackgroundEntryPoint
value in WebAccountProvider extension.
-->
<ActivatableClass ActivatableClassId="AAD.Core.TokenBackground" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="AAD.Core.AppService" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="AAD.Core.WebAccountProcessor" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
</Package>`

man, err := parseAppxManifest([]byte(manifest))
require.NoError(t, err)

require.Equal(t, "neutral", man.arch)
require.Equal(t, "Microsoft.AAD.BrokerPlugin", man.Name)
require.Equal(t, "CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", man.Publisher)
require.Equal(t, "1000.19580.1000.0", man.Version)
}
Loading

0 comments on commit a9cc1bf

Please sign in to comment.