Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Read windows appx packages on a FS scan. #4804

Merged
merged 2 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading