Get-WinEvent cmdlet tip to filter noise

I’ve been using Windows 10 and Applocker in ‘Allow mode’ for some time and I need to filter the noise left by the Constrained Mode from the event log.

Windows 10 and PowerShell 5.x introduce a way to protect the interactive shell from copy/paste. If you configure Applocker in ‘Allow mode’ (don’t use default rules when proposed by the GUI), your interactive shell starts in a different LanguageMode named ‘Constrained mode’. Want to read more, start with PowerShell ♥ the Blue Team and about_Language_Modes.

Here’s a quick demo in a picture is worth a thousand words:

Although I’m running an interactive shell with administrative privileges, I cannot use the ToXML() method. I get the symptomatic error message Cannot invoke method. Method invocation is supported only on core types in this language mode.

What’s the challenge here?
It should work in constrained mode and I should figure out the correct XML query 🙄

In other words, I need to find 8007 events from the ‘Microsoft-Windows-AppLocker/MSI and Script’ event log but not those that have the filehash (SHA256) set to: 6B86B273FF34FCE19D6B804EFF5A3F5747ADA4EAA22F1D49C01E52DDB7875B4B
This hash is well known, it’s a file with only 1 as content.

Here’s the tip:

If you use the GUI, you can copy/paste the above XML query in the eventvwr


About CIM modules

Last week I made a private demo about how to discover CIM based modules.

At first, I did:

Get-Module -ListAvailable | 
Where ModuleType -eq 'CIM'

Based on what’s installed on a workstation or if it’s on a server, either there’s 0 result or the following:

…and that’s not what I really expected and wanted to illustrate.

I wanted actually to show how Microsoft has extended the number of cmdlets using CDXML (cmdlet definition XML).

If I do the following:

Get-NetAdapter | Get-Member

I can see the Get-NetAdapter cmldet returned a CIM instance of the ROOT/StandardCimv2/MSFT_NetAdapter class.

Now, if I query the type of module the Get-NetAdapter cmdlet comes from

Get-Command -Name Get-NetAdapter
Get-Module -Name NetAdapter

It’s clear that the NetAdapter module uses a manifest module type instead of CIM based type.

If I continue and show more properties of this NetAdapter module,

Get-Module -Name NetAdapter | Format-List

Nothing really relevant is shown except the fact that this module has nested modules.

Let’s investigate that NestedModules property:

Get-Module -Name NetAdapter | 
Select -Expand NestedModules

Using the ExpandProperty parameter reveals what I was looking for: the CIM module type.

Using a loop, I can now list the modules that have at least 1 CIM based nested module

Get-Module -ListAvailable | 
ForEach-Object { 
 if ('CIM' -in $_.NestedModules.ModuleType) { 

After that I can do some calculation:

# How many modules have at least 1 CIM based nested module?
Get-Module -ListAvailable | 
ForEach-Object { 
 if ('CIM' -in $_.NestedModules.ModuleType) { 
} | Measure

# How many cmdlets were added using these "CIM" modules
Get-Module -ListAvailable |
ForEach-Object { 
 if ('CIM' -in $_.NestedModules.ModuleType) {
  Get-Command -Module $_.Name 
} | Measure

# Over a total of how many cmdlets, regardless modules types?
Get-Command | Measure

Heads up! CVE-2018-0875

The MSRC published the following details about CVE-2018-0875 | .NET Core Denial of Service Vulnerability

The .Net Core vulnerability is documented on Fine, no problem with that.

But, the version 1.0 of the advisory for CVE-2018-0875 is wrong about PowerShell Core because it just lists 6.0.0 as affected.

It appears actually that both PowerShell Core 6.0.0 and 6.0.1 are affected by CVE-2018-0875.
The CVE-2018-0875 vulneralbility is a Hash Collision issue that can cause a Denial of Service.

If you’ve got PowerShell Core, you need to update to version 6.0.2 using this link


PowerShell Core is a self contained application that has coreclr embedded as well as other assemblies.
PowerShell Core has been updated to target the updated .NET Core runtime, recompiled and released on this page.

MSRC security guidance: the dashboard

I’ve shown how to get the latest release note in the previous blog post

I’ll now show what can be done with the main “Security Updates” dashboard without the API key available on this page: Security Update Guide > Dashboard

I’ve published two functions: a private one named Get-MSRCDashBoardPage and a public one named Get-MSRCDashBoard

The first private function Get-MSRCDashBoardPage aims at downloading a specific dashboard page based on a time frame. By default, without giving parameters, if there are data published based on the current date, the function gets the first page. There are 3 parameters that can be passed to the function to get another page number and specify another After and Before date. It’s a private function because it’s used by its public counterpart where it’s called recursively for every page found in a specified time range.

As you can see, we get many properties back, much more than what’s displayed by the web interface. 🙄

The second public function Get-MSRCDashBoard aims at doing the same thing as its private counterpart. The difference is that there isn’t a “Page” parameter. It downloads the first page based on the time range specified, it then gets the total number of pages available and calls recursively its private counterpart to download each page.

Now, let’s see this function in action with some examples:

    • Here’s how to get all the pages on the Dashboard published in January 2018:
Get-MSRCDashBoard -After 01/01/2018 -Before 01/31/2018
    • Here’s how to export to CSV all the dashboard data about security updates published this month (after the second Tuesday)
# Save every page to a CSV file
Get-MSRCDashBoard |
Export-Csv -Path ~/Documents/MSRCDashBoard.$((Get-Date).ToString('yyyy-MM')).csv

# Read the CSV and use Out-GridView to look and filter data
Import-CSV ~/Documents/MSRCDashBoard.$((Get-Date).ToString('yyyy-MM')).csv | 

The first command saves every page to a CSV file and the second one reads the CSV file and sends the data to Out-GridView so that you can look and filter data.

    • Here’s how you can display the same properties as the web interface for February 2018:
Get-MSRCDashBoard -After 02/01/2018 -Before 02/28/2018  |
Select publishedDate,cveNumber,Name,Platform,articleTitle1,
downloadTitle1,articleTitle2,downloadTitle2,severity,impact | 

    • Here’s how you can display the same properties as the web interface for this month:
Get-MSRCDashBoard |
Select publishedDate,cveNumber,Name,Platform,articleTitle1,
downloadTitle1,articleTitle2,downloadTitle2,severity,impact | 

Let’s compare the Out-Gridview and the web interface:

PS: The two functions work in PowerShell Core but the “Out-Gridview” cmdlet used in examples isn’t available in PowerShell Core.

MSRC security guidance: about release notes

I’ve recently talked about a shortcoming of release notes published on the Security Update Guide > Dashboard in the following blog post

As you can see, there’s only the latest release note available. You cannot see previous ones.
If you want to read any release note ever published, you can.
I’ve kept a list of these on this page.

The same shortcoming also exists if you want to retrieve data using some automation.
Whatever date values you submit in a post request, you always get only the latest release note 😦

I’ve started a new project about the MSRC Microsoft Security Updates API in this github repository. I’ve documented why I started this project.
The last point is about to showcase some functions to get data from the portal without using an API key.

Here’s the first example with release notes:
I’ve published so far two functions: Get-MsrcReleaseNoteId and Get-MsrcReleaseNotePage

The first function Get-MsrcReleaseNoteId uses a post request to retrieve the latest release note available and doesn’t have any parameter.


It shows the release note Id (a GUID) that can be passed to the second function Get-MsrcReleaseNotePage by property name in order to retrieve the release note content as a json object.

Get-MSRCReleaseNoteId | Get-MSRCReleaseNotePage | fl

Notice that the note property is somehow html formatted and would need to be sanitized.

These are not the only functions I’ll showcase, stay tuned 🙂

You know what would be great about release notes:

  • It would be nice to be able to retrieve any release note using some datetime parameters (to addresss the above shortcoming).
  • It would be nice to retrieve any release note in either XML or JSON like the original MSRC Microsoft Security Updates API allows.
  • Instead of having a pseudo-html formatted string, I also would like to be able to get the Notes content as an object that has a title, a description, a list of affected software and the list of known issues.

Using the PowerShell MVP module

The renewal season is opened and it’s time to use the PowerShell module designed to interact with the Microsoft MVP website François-Xavier Cat and I released last year when the Microsoft MVP Rest API was made available.

François-Xavier already published some very useful posts and demoed how to use the MVP module for:

This year, I only used the module to insert and review my contributions.
To start using the module, you basically need to install the module, import it and set your subscription key with the Set-MVPConfiguration function. See first the following post from François-Xavier to achieve these steps.

Now I’d like to show you some code snippets I used along this contributions submission process.

First, I needed to find what contribution I submitted last year and filter out what PGI I attended.
To quickly do that I used:

Get-MVPContribution -Limit 100 | 
Where { $_.ContributionType.Name -notmatch 'PGI' } | 
Out-GridView -PassThru 

I first get the out-gridview window where I can list, search and select contribution(s):

If I select a previous one:

After I reviewed my old contribution, I gather updated numbers for the new period and prepare the following to submit an activity:

$splat = @{
 startdate ='2017/07/01'
 Title='Type your title here'
 Description = @'
Enter a full description about this activity
 AnnualReach = '1000'
 Visibility = (
  Get-MVPContributionVisibility | 
  Out-GridView -Title 'Select visibility' -PassThru
 ContributionType = (
  Get-MVPContributionType | 
  Out-GridView -Title 'Select Contribution Type' -PassThru
 ContributionTechnology = (
  Get-MVPContributionArea -All | 
  Out-GridView -Title 'Select Contribution Area' -PassThru

# Review one more time

# Submit activity
New-MVPContribution @splat

Note that a new contribution ID is returned when it’s submitted using the New-MVPContribution function.
I take a note of its ID and use the following to be able to query this activity later on when/if needed.

Get-MVPContribution -ID 547174

After I entered all the activities, I use this code snippet to see what I submitted:

Get-MVPContribution -Limit 100 | 
Where { $_.ContributionType.Name -notin @(
 'Product Group Interaction (PGI)',
 'Forum Participation (Microsoft Forums)') } | 
ForEach-Object {
 $_ | 
 Add-Member -MemberType NoteProperty -Name Date -Value (Get-Date $_.StartDate) -PassThru
} | Where { 
 $_.Date -ge (Get-Date '2017-07-01T00:00:00') 
} | 
Sort -Property Date | 

Tracking Office 365 versions

I’ve just started to work on Office 365 and I wondered how I could track the different versions, their release notes, what changed, when…
I’ve deployed a Semi-Annal Targeted version and got the following version.
I wondered where this info under Product Info come from when you click on File/Office Account:

I started to dig into the registry and the following key contains many info about the Office 365 branch that was installed.

Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" | 
Select AudienceId,UpdateChannel,*Version*,CDNBaseUrl | fl

Then I found these two links:

These are very nice and let you know what changed but I wanted to avoid parsing a web page to be able to track Office 365 versions, branches… and I’d like to get the same nice chart:

Then I found the github page about deploying Office 365 although I knew about the XML editor.
It appears that it contained all what I needed 😀

So, I wrote a function to help you and me achieve the following:

# See examples provided in the help of the function
Get-Help Get-O365UpdateChannelReleaseHistory -Examples

# Example 1: Displays all branches and releases
Get-O365UpdateChannelReleaseHistory  -Verbose |
ft -AutoSize

Note that there’s a 0 behind the version because it’s a real [version] object and not a [string]. Having real version objects will allow you to do a successful comparison between versions. Idem for release dates.
Notice also that there’s already a Long-Term Servicing Channel (2019) branch in the xml data. Who knew that?

# Example 2: Displays all branches and 
# only displays the latest version of every branch
Get-O365UpdateChannelReleaseHistory -Verbose| 
Where { $_.Latest} | ft -AutoSize

The next examples will display the same branch by calling the function by name, by id, by displayname and by global unique identifier (guid):
Note that every parameter (name, id, displayname and guid) have completion because valid sets have been declared in the parameters block. Just press TAB after a parameter:

# Example 3: Using the name
Get-O365UpdateChannelReleaseHistory -Name FirstReleaseDeferred -Verbose|
ft -AutoSize
# Example 4: using the Id
Get-O365UpdateChannelReleaseHistory -Id Targeted -Verbose|
ft -AutoSize
# Example 5: Using the displayname
Get-O365UpdateChannelReleaseHistory -DisplayName 'Semi-Annual Channel (Targeted)' -Verbose | ft -AutoSize
# Example 6: using a GUID
Get-O365UpdateChannelReleaseHistory -Guid b8f9b850-328d-4355-9145-c59439a0c4cf -Verbose | ft -AutoSize

If the function was able to download at least once a file but then fails, it will use the previous file that was previously downloaded. The verbose stream displays the published date found in the downloaded xml file:

Enjoy 😎