Deploy Sysmon with PowerShell Desired State Configuration

The technet page of sysmon 2.0 provided the following advanced configuration sample:

@'
<Sysmon schemaversion="1.0">
    <Configuration>
        <!-- Capture all hashes -->
        <Hashing>*</Hashing>
        <!-- Enable network logging -->
        <Network />
    </Configuration>
    <Rules>
        <!-- Log all drivers except if the signature -->
        <!-- contains Microsoft or Windows -->
        <DriverLoad default="include">
        <Signature condition="contains">microsoft</Signature>
        <Signature condition="contains">windows</Signature>
        </DriverLoad>
        <!-- Do not log process termination -->
        <ProcessTerminate />
        <!-- Log network connection if the destination port equal 443 -->
        <NetworkConnect>
        <DestinationPort>443</DestinationPort>
        </NetworkConnect>
    </Rules>
</Sysmon>
'@


If you want to do more advanced stuff, my fellow Windows PowerSell MVP Carlos Perez wrote an awesome module named Posh-Sysmon that would help you create XML configuration for Sysmon.

April 20, 2015, Sysmon 3.0 was published :-)
It delivers a version 2.0 of the XML schema which looks like this:

@'
<Sysmon schemaversion="2.0">
 <!-- Capture all hashes -->
 <HashAlgorithms>*</HashAlgorithms>
 <EventFiltering>
  <!-- Log all drivers except if the signature -->
  <!-- contains Microsoft or Windows -->
  <DriverLoad onmatch="include">
   <Signature condition="contains">microsoft</Signature>
   <Signature condition="contains">windows</Signature>
  </DriverLoad>
  <!-- Do not log process termination -->
  <ProcessTerminate onmatch="include"/>
  <!-- Log network connection if the destination port equal 443 -->
  <NetworkConnect onmatch="include">
   <DestinationPort>443</DestinationPort>
  </NetworkConnect>
 </EventFiltering>
</Sysmon>
'@

sysmon.v3.sample.config

In March 2015, I’ve asked the following question to Thomas Garnier who co-authored this awesome sysmon tool with Mark Russinovich.

Unfortunately, there’s no way currently in version 2.0 or 3.0 to dump the configuration directly to XML :-|
But, that’s not a huge problem for PowerShell ;-)
The only trick that made the reverse engineering experience consistent was to read the dumped rules from the bottom up 8-)

Let’s see a capture of the DSC configuration that deploys sysmon when it runs for the first time:
deploy-sysmon.1
If I run the same configuration a 2nd time, all the TEST phases performed are skipped (which is a good thing):
deploy-sysmon.2

Quick and dirty!
But Sysmon got deployed and configured through Desired State Configuration on a Windows Server 2012 R2 and its built-in PowerShell version 4.0

PS: If you check the different revisions of the gist file, you can get a DSC configuration that works against sysmon version 2.0 :D

Deploy and configure EMET 5.2 with PSDSC

I’ve been using EMET (The Enhanced Mitigation Experience Toolkit) and advocating for it since 2010…

Now with DSC (Desired State Configuration) and PowerShell, it can be fairly easy to deploy and configure it compared to my previous post about Applocker.

I’ve created two scripts, one to install EMET and one to remove it (because of continuous delivery of every product, right?) that can be run as of Windows 8.1 and Windows 2012 R2. Yes, DSC is built-in PowerShell version 4.0 that was released along with Windows 8.1 in August 2013.

The configuration of EMET 5.2 is based on XML files although EMET 5.2 can also get its configuration by GPO in a domain environment.
The XML configuration that you’ll find below is an export made with the EMET_Conf.exe after an import from the “Recommended Software.xml” profile provided under “C:\Program Files (x86)\EMET 5.2\Deployment\Protection Profiles\”.
Although I probably could, I chose to not handle Certificate Pinning rules because a new GUID for each rule is generated by the XML export made with EMET_conf.exe. If I did, it would have complicated the comparison made by the Test-TargetResource and probably slow it down.
I know that the built-in package DSC resource can download the file from the web if I specify a URL as a package source but I preferred to rely on my own custom script to download the file as it performs some additional steps such as checking the integrity of the file (is it the hash we expect) and whether the file is digitally signed (and recognized as such for the time being).


The initial download takes around 9 seconds.
DSC-Install-EMET52.download
Let’s see what output we get when I first push the configuration:
DSC-Install-EMET52.run1.Package
DSC-Install-EMET52.run1.Config

If I push the configuration as 2nd time, all TEST steps for each resource return false because they are in their expected state and all the SET operations are skipped:
DSC-Install-EMET52.run2

Here’s what happens when I remove EMET 5.2 for the first time if it’s present:
DSC-remove-EMET-1
If I run the removal a 2nd time, I get:
DSC-remove-EMET-2

About MS15-034

This month there was CVE-2015-1635 on the menu for the Patch Tuesday. Microsoft released the security bulletin MS15-034 (KB3042553) to address the vulnerability in HTTP.sys.
On the main TechNet page for April 2015, there’s the risk assessment for this vulnerability:

Bulletin ID: Vulnerability Title: CVE ID: Exploitability Assessment for
Latest Software Release:
Exploitability Assessment for
Older Software Release:
Denial of Service
Exploitability Assessment:
Key Notes:
MS15-034 HTTP.sys Remote Code Execution Vulnerability CVE-2015-1635 1 - Exploitation More Likely 1 - Exploitation More Likely Permanent (None)

Microsoft has its own Exploitability index and 1 means:

This rating means our analysis has shown that exploit code could be created in such a way that an attacker could consistently exploit this vulnerability. Moreover, Microsoft is aware of past instances of this type of vulnerability being exploited. This would make it an attractive target for attackers, and therefore more likely that exploits could be created. As such, customers who have reviewed the security bulletin and determined its applicability within their environment could treat this with a higher priority.

One of the key task when doing patch management is to review what the editor officially says, assess the risk of your assets in your own environment and monitor both the good and the bad guys on the Internet to prioritize your deployment and assess how easy and how fast the vulnerability is exploited, weaponized…

There’s a formula to assess the risk on Wikipedia

R (the Risk) can be function of four factors:
A = Value of the assets
T = the likelihood of the threat
V = the nature of vulnerability i.e. the likelihood that can be exploited (proportional to the potential benefit for the attacker and inversely proportional to the cost of exploitation)
I = the likely impact, the extent of the harm

That said, let’s dive into CVE-2015-1635.

The MS15-034 only mentions IIS in the workaround section of the bulletin and quickly states that disabling IIS kernel caching is a workaround. That was a very short statement.

The bulletin makes it clear that this is not a vulnerability of IIS, it’s a vulnerability of HTTP.sys. Let’s see the link between IIS and HTTP.sys:

Source: http://www.iis.net/learn/get-started/introduction-to-iis/introduction-to-iis-architecture

It’s not the first time HTTP.sys is vulnerable. We had formerly MS13-039, MS10-040
There’s even an obsolete knowledge base article that listed the hotfixes available for HTTP.sys but it wasn’t reviewed since November 9, 2011!

There are other components that are built on top of HTTP.sys like the WSMan protocol, so I posted the following message on twitter yesterday.
There was a buzz or panic about it. My tweet may have been misinterpreted and many probably wondered whether PSRemoting and WSMan were impacted by this vulnerability.

My goal with this tweet was:
Let’s pay attention to MS15-034 this month.
It will for sure require all your attention.
IIS and other components depend on http.sys. That’s why I joined the above image, I’ve got from this page about troubleshooting WinRM.
I didn’t say that PSRemoting or WSMan are proven to be vulnerable to the specific CVE-2015-1635 vulnerability.
Based on my tweet, if you thought that PSRemoting is vulnerable because of CVE-2015-1635, you’re wrong.
Lee Holmes from the Microsoft Windows PowerShell Team clearly said later on that:

This means that the vulnerable portion of code in https.sys that got fixed is directly linked to services that use the kernel mode caching feature.
WinRM and WSMan don’t rely/depend on this portion of code.

I was right about paying attention to MS15-034.
It’s actually easy to trigger a denial of service (DoS) against IIS computers that have kernel mode caching enabled.
Things are moving fast. In less than 48 hours after MS15-034 was published, there are already active exploits in the wild.
See https://isc.sans.edu/forums/diary/MS15034+HTTPsys+IIS+DoS+And+Possible+Remote+Code+Execution+PATCH+NOW/19583/ for more information.

List all cultures by extending the native Get-Culture cmdlet

I recently needed to list all possible cultures available on a Windows box.
I’ve looked for a native cmdlet that you’d do it by typing:

Get-command *culture*


After using the Get-Member cmdlet on the output of the Get-Culture cmdlet, I found a .Net way of achieving this by doing:

[System.Globalization.CultureInfo]::GetCultures(
[System.Globalization.CultureTypes]::AllCultures
)

It’s nice and I thought that it would be great to have a -All switch on the native Get-Culture cmdlet.
Lee Holmes from the Windows PowerShell Team at Microsoft recently demonstrated a mind-blowing way of extending cmdlets with a few lines of code on his blog.

After playing with what Lee Holmes presented and how that would apply for extending the native Get-Culture cmdlet, I came up with this:

I’ve tested the above code on PowerShell version 2.0. Guess what! It works 8-)

To get a sorted list of cultures that match the following pattern “en-US” for example, you can do (on PowerShell version 3.0):

Get-Culture -All | 
? Name -match "^[a-z]{2}-[A-Z]{2}$"  | 
Sort Parent

Configure Applocker with Desired State Configuration

I was working with Desired State Configuration and wondered why a custom DSC resources hasn’t been published yet for Applocker.
Bitlocker has already its experimental DSC resource. Why Applocker doesn’t have one?

I also wondered what it really takes to configure Applocker with PowerShell Desired State Configuration.

First a quick disclaimer is required:

  • Do not apply this on your servers/workstations if you don’t understand what Applocker does.
  • The deny rules are just examples. I don’t have anything against these software editors.
  • Yes, I know that’s not the most secure Applocker configuration as the example below mixes both a very permissive (default) whitelist and a very specific blacklist.

Let’s also quickly examine the Applocker requirements:

  • Applocker rules can be imported from/exported to a XML file using the GUI or using the cmdlets of the built-in Applocker module (it exists since PowerShell version 2.0 on Windows 7).
    XML seems to better way to go although the Applocker policy can be found in the registry under the HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2 key.
  • The applocker policy depends on the ‘Application Identity’ service to be enforced.

Based on the above light requirements, it seems that built-in DSC resources would actually make it and allow to deploy an Applocker policy locally.

To configure Applocker, I need first to export the Applocker policy to XML and dump its indented representation to a file.
To solve the indentation issue, I’ve used the Format-XML function written by Jeffrey Snover that you can find on this page.

# http://blogs.msdn.com/b/powershell/archive/2008/01/18/format-xml.aspx
function Format-XML ([xml]$xml, $indent=2)
{
    $StringWriter = New-Object System.IO.StringWriter
    $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
    $xmlWriter.Formatting = "indented"
    $xmlWriter.Indentation = $Indent
    $xml.WriteContentTo($XmlWriter)
    $XmlWriter.Flush()
    $StringWriter.Flush()
    Write-Output $StringWriter.ToString()
}
Format-XML ([xml](Get-AppLockerPolicy -Effective -Xml)) -indent 2 | 
Out-File -FilePath ~/Documents\Applocker-pol.xml -Encoding ascii

The second step consists in creating the file locally with the XML content thanks to the built-in File DSC resource.
To decide whether to apply the policy, I’ll export the current effective Applocker policy and compare it to the XML file.
Once the Applocker policy is applied, I’ll start the required service.

Here is what the DSC configuration looks like to deploy locally an Applocker policy.

It only takes a service, a file, a script resource and less than 5 seconds to deploy an Applocker policy locally. 8-)


If I apply it one more time, we can see that all the tests performed are skipped as my system is already in the desired state.


If I open the local group policy editor, we can see the following:

The above configuration was just for testing purposes, right ;-)
Here’s how to achieve the exact opposite, i.e., clear the local Applocker policy and stop the required service.

Let’s remove the existing Applocker local policy for the 1rst time:

Again, applied one more time, we can see that all the tests performed are skipped as my system is already in the desired state.


Nice, isn’t it? DSC and PowerShell bring more than just automation! I love it :-D

Troubleshooting Windows Store and PC Settings not accessible

We offered a Surface RT to my mother for her birthday but after more than 18 months, she brought the tablet back to me because all her apps have disappeared and she couldn’t launch the Windows Store or PC settings.

I’ve created another account and I noticed that this account could launch the Windows Store and PC settings.
I’ve also queried the main Windows components store health state with the following DSIM cmdlet:

Repair-WindowsImage -Online -ScanHealth -Verbose


It was Ok. In other words, only her user profile had a problem.

I ran the Apps troubleshooter. It found 3 problems but was able to fix only 2 of them.

I’ve also checked the ACLs on various parts of the filesystem and registry using the following support article: KB2798317.
I added back manually the “All Application Packages” group (“tous les packages d’application” in French) full control NTFS permission onto the user profile.
The Windows store and PC settings still didn’t launch.

Then I reset the Windows Store cache.

& "c:\windows\system32\WSReset.exe"
Add-AppxPackage -DisableDevelopmentMode `
-Register C:\Windows\ImmersiveControlPanel\AppxManifest.xml

Now, I was able to launch the Windows Store but not the PC Settings.

And I had still events ID 5973 in the Application log

The latest command made me realize that all the other modern apps not working might only need to be registered.
So, I ended up doing:

dir C:\ -include AppxManifest.xml -ea 0 -rec -for | 
select -expand FullName | 
? { $_ -notmatch "C:\\Windows\\WinSxS\\" } |
% {
 $p=$_
 try {
  Add-AppxPackage -DisableDevelopmentMode -Register $_ -ErrorAction Stop
  Write-Verbose "Successfully registered $_"
 } catch {
  Write-Warning "Failed to registered $p because $($_.Exception.Message)"
 }
}

Boom! After 8 minutes about 50 modern apps where registered and appeared back in the Start menu.
I was able to launch the PC settings and Windows Store as well :-D
I added back the Microsoft Account in the Windows Store.
When I switched to the “my applications” view in the Store, it reported that “all the available applications are installed on this PC”.

Windows Assessment and Deployment Kit (Windows ADK) Preview

With the recent Windows 10 Technical Preview version 10.0.10041, developer tools were published as well as hardware tools. At the bottom of the hardware tools page, you can find the preview version of the Windows Assessment and Deployment Kit (Windows ADK).

Here’s the PowerShell script to download the files required by ADK (~3GB) that uses the cmdlets from the BITS module.

#Requires -Version 4
#Requires -RunAsAdministrator

Function Get-ADKFiles {
[CmdletBinding()]
param(
    [parameter(Mandatory)]
    [system.string]$TargetFolder
)
Begin {
    $HT = @{}
    $HT += @{ ErrorAction = 'Stop'}
    # Validate target folder
    try {
        Get-Item $TargetFolder @HT | Out-Null
    } catch {
        Write-Warning -Message "The target folder specified as parameter does not exist"
        break
    }
 
    # March 24, 2015
    $PatchLevel = "10.0.10041"
 
}
    
Process {
    
    $adkGenericURL = (Invoke-WebRequest -Uri http://go.microsoft.com/fwlink/?LinkID=525592  -MaximumRedirection 0 -ErrorAction SilentlyContinue)
    
    # 302 = redirect as moved temporarily
    if ($adkGenericURL.StatusCode -eq 302) {

        # Currently set to http://download.microsoft.com/download/2/E/7/2E74CA3D-858C-4401-B6FF-3E1C2D1D5F0C/adk/
        # Resolving download root for: http://go.microsoft.com/fwlink/?LinkID=525592
        $MainURL = $adkGenericURL.Headers.Location
    
        $InstallerURLs = DATA {
            ConvertFrom-StringData @'
                0=0302dc615b0a5fd4810430b2cdacb5e3.cab
                1=036c618de505eeb40cca35afad6264f5.cab
                2=0708be5ffbe332f6a1571c929c1322a5.cab
                3=0a3a39d2f8a258e1dea4e76da0ec31b8.cab
                4=0b63b7c537782729483bff2d64a620fa.cab
                5=0c48c56ca00155f992c30167beb8f23d.cab
                6=0ce2876e9da7f82aac8755701aecfa64.cab
                7=0d981f062236baed075df3f42b1747db.cab
                8=11bdc4a4637c4d7ab86107fd13dcb9c6.cab
                9=125b1c8c81e36ec9dbe5abf370ff9919.cab
                10=1439dbcbd472f531c37a149237b300fc.cab
                11=14f4df8a2a7fc82a4f415cf6a341415d.cab
                12=1616336d1700fbea038fd3dc4c6c917b.cab
                13=186c4aa0cae637da0996e87ababf5b71.cab
                14=18e5e442fc73caa309725c0a69394a46.cab
                15=1bd4f044e271b42b110fe533720c10e9.cab
                16=1f90b0f7321fab8dcdedaba3b30415f3.cab
                17=23ca402f61cda3f672b3081da79dab63.cab
                18=24b9e5f1f97c2f05aa95ee1f671fd3cc.cab
                19=2517aec0259281507bfb693d7d136f30.cab
                20=268b1a41f6bd2906449944b964bf7393.cab
                21=27c0562eb1efb3ad282cf987ae40e873.cab
                22=2e134b026e871c5e8e547b6711578fb3.cab
                23=2e82f679c8709f838e7c839f7864ac84.cab
                24=3585b51691616d290315769bec85eb6f.cab
                25=3611bd81544efa3deb061718f15aee0c.cab
                26=36e3c2de16bbebad20daec133c22acb1.cab
                27=377a2b6b26ea305c924c25cf942400d6.cab
                28=3814eaa1d4e897c02ac4ca93e7e7796a.cab
                29=388dee738d7d1c99d6fe776a85ee32f8.cab
                30=38d93b8047d5efb04cf01ab7ec66d090.cab
                31=3b71855dfae6a44ab353293c119908b8.cab
                32=3d610ba2a5a333717eea5f9db277718c.cab
                33=3dc1ed76e5648b575ed559e37a1052f0.cab
                34=3e602662e913edefa58e52e04e900bf8.cab
                35=3eaef6a740a72a55f4a0ac3039d05419.cab
                36=413a073d16688e177d7536cd2a64eb43.cab
                37=450f8c76ee138b1d53befd91b735652b.cab
                38=45c632fb53b95fe3bd58a6242325afa6.cab
                39=4d2878f43060bacefdd6379f2dae89b0.cab
                40=4defb086385752d8cd0d1432900fb4ca.cab
                41=4e56c6c11e546d4265da4e9ff7686b67.cab
                42=4fc82a5cedaab58e43b487c17f6ef6f3.cab
                43=500e0afd7cc09e1e1d6daca01bc67430.cab
                44=527b957c06e68ebb115b41004f8e3ad0.cab
                45=56dd07dea070851064af5d29cadfac56.cab
                46=56e5d88e2c299be31ce4fc4a604cede4.cab
                47=57007192b3b38fcd019eb88b021e21cc.cab
                48=5775a15b7f297f3e705a74609cb21bbc.cab
                49=5ac1863798809c64e85c2535a27a3da6.cab
                50=5d984200acbde182fd99cbfbe9bad133.cab
                51=5eea85046f0c2112e2fcd0bac2c2cfc8.cab
                52=625aa8d1c0d2b6e8cf41c50b53868ecd.cab
                53=630e2d20d5f2abcc3403b1d7783db037.cab
                54=662ea66cc7061f8b841891eae8e3a67c.cab
                55=6894c1e1e549c4ab533078e3ff2e92af.cab
                56=690b8ac88bc08254d351654d56805aea.cab
                57=69f8595b00cf4081c2ecc89420610cbd.cab
                58=6a68bedadf2564eeef76c19379aae5ef.cab
                59=6bdcd388323175da70d836a25654aa92.cab
                60=6cc7aebd21947dbd8ea4884662780188.cab
                61=6d2cfb2c5343c33c8d9e54e7d1f613f9.cab
                62=6d3c63e785ac9ac618ae3f1416062098.cab
                63=6da2af86cb1227e66cf9bc85f2786782.cab
                64=6dc62760f8235e462db8f91f6eaa1d90.cab
                65=6e142759ce3a6e36e52e089caffaffe1.cab
                66=7011bf2f8f7f2df2fdd2ed7c82053d7f.cab
                67=732eefaf52275b7a708311a31c82c814.cab
                68=7608a6c73562800dd82c513d6d2dcd94.cab
                69=77adc85e5c49bbd36a91bb751dc55b39.cab
                70=781e7c95c1b6b277057c9b53b7b5a044.cab
                71=791b388183dc99f779aa6adadab92e9a.cab
                72=7a8eaeba46cc44d02a9a46fcbb641a12.cab
                73=7c11b295fb7f25c6d684b1957e96a226.cab
                74=7c195d91008a0a6ad16e535ac228467d.cab
                75=83bd1072721871ea0bdc4fab780d9382.cab
                76=84cf100ee76440117226cfb9af196ba3.cab
                77=8624feeaa6661d6216b5f27da0e30f65.cab
                78=870d7f92116bc55f7f72e7a9f5d5d6e1.cab
                79=8bc062474f7e4aa85efdc73d3fe8b442.cab
                80=8c9919a5e8638dd2b352b0a218939370.cab
                81=8d25d56b34194978403f6bba33f419c5.cab
                82=8f264641cdc436354282a744033e7850.cab
                83=9050f238beb90c3f2db4a387654fec4b.cab
                84=93ed81ef8cf2e77c6ebc8aba5d95b9cf.cab
                85=94cae441bc5628e21814208a973bbb9d.cab
                86=9722214af0ab8aa9dffb6cfdafd937b7.cab
                87=97b6e3671e2e5d03ea25df25a8056e70.cab
                88=9d2b092478d6cca70d5ac957368c00ba.cab
                89=9f0be655144a0c68c7f087465e1ad4f9.cab
                90=9f8944e2cc69646284cd07010e7eee99.cab
                91=a011a13d3157dae2dbdaa7090daa6acb.cab
                92=a03686381bcfa98a14e9c579f7784def.cab
                93=a1d26d38d4197f7873a8da3a26fc351c.cab
                94=a22d6a2483a921a887070cd800030e47.cab
                95=a29a0c716f903f42aca181dca250f681.cab
                96=a30d7a714f70ca6aa1a76302010d7914.cab
                97=a32918368eba6a062aaaaf73e3618131.cab
                98=a565f18707816c0d052281154b768ac0.cab
                99=a7eb3390a15bcd2c80a978c75f2dcc4f.cab
                100=aa25d18a5fcce134b0b89fb003ec99ff.cab
                101=aa4db181ead2227e76a3d291da71a672.cab
                102=abbeaf25720d61b6b6339ada72bdd038.cab
                103=Application Compatibility Toolkit-x64_en-us.msi
                104=Application Compatibility Toolkit-x86_en-us.msi
                105=Assessments on Client-x86_en-us.msi
                106=Assessments on Server-x86_en-us.msi
                107=b0189bdfbad208b3ac765f88f21a89df.cab
                108=b3892d561b571a5b8c81d33fbe2d6d24.cab
                109=b4687bc42d465256ad1a68aec6886f83.cab
                110=b5227bb68c3d4641d71b769e3ac606a1.cab
                111=b6758178d78e2a03e1d692660ec642bd.cab
                112=bbf55224a0290f00676ddc410f004498.cab
                113=bd00e61b3056a8aa44b48303f6fa1e62.cab
                114=be7ebc1ac434ead4ab1cf36e3921b70e.cab
                115=c300c91a497ea70c80a6d0efc9454c35.cab
                116=c6babfeb2e1e6f814e70cacb52a0f923.cab
                117=c98a0a5b63e591b7568b5f66d64dc335.cab
                118=cd23bfdfd9e3dfa8475bf59c2c5d6901.cab
                119=cfb8342932e6752026b63046a8d93845.cab
                120=d2611745022d67cf9a7703eb131ca487.cab
                121=d344672ad340db2b98b706ff06350843.cab
                122=d519967dbb262c80060d9efb5079aa23.cab
                123=d562ae79e25b943d03fc6aa7a65f9b81.cab
                124=dotNetFx45_Full_x86_x64.exe
                125=e0509d502dcdae109023403fc3bc8ac4.cab
                126=e5f4f4dc519b35948be4500a7dfeab14.cab
                127=e65f08c56c86f4e6d7e9358fa99c4c97.cab
                128=ea9c0c38594fd7df374ddfc620f4a1fd.cab
                129=eacac0698d5fa03569c86b25f90113b5.cab
                130=eb90890d25e1dee03cf79844d9f823f4.cab
                131=ec093852a41cbd9d167b714e4f4a2648.cab
                132=ed711e0a0102f1716cc073671804eb4c.cab
                133=eea40dab42b1052e4d55a25291e91ccd.cab
                134=eebe1a56de59fd5a57e26205ff825f33.cab
                135=f051f100a86ad4c94057a1d5280d9283.cab
                136=f2a850bce4500b85f37a8aaa71cbb674.cab
                137=f480ed0b7d2f1676b4c1d5fc82dd7420.cab
                138=f4e72c453e36ce0795c8c9fcaae2b190.cab
                139=f6aa96e71953e06cb7a3f69e76804b6d.cab
                140=f7699e5a82dcf6476e5ed2d8a3507ace.cab
                141=f8f7800500b180b8a2103c40ce94f56a.cab
                142=fa7c072a4c8f9cf0f901146213ebbce7.cab
                143=fbcf182748fd71a49becc8bb8d87ba92.cab
                144=fcc051e0d61320c78cac9fe4ad56a2a2.cab
                145=fd5778f772c39c09c3dd8cd99e7f0543.cab
                146=fe2c9602686dc1bcbf80a0f18bd54b49.cab
                147=fe43ba83b8d1e88cc4f4bfeac0850c6c.cab
                148=Flashing Tools-x86_en-us.msi
                149=Imaging And Configuration Designer-x86_en-us.msi
                150=InstallRegHiveRecoveryDriverAmd64.exe
                151=InstallRegHiveRecoveryDriverX86.exe
                152=Kits Configuration Installer-x86_en-us.msi
                153=Microsoft Compatibility Monitor-x86_en-us.msi
                154=SQLEXPR_x86_ENU.exe
                155=Toolkit Documentation-x86_en-us.msi
                156=User State Migration Tool-x86_en-us.msi
                157=Volume Activation Management Tool-x86_en-us.msi
                158=wasinstaller.exe
                159=WimMountAdkSetupAmd64.exe
                160=WimMountAdkSetupArm.exe
                161=WimMountAdkSetupX86.exe
                162=Windows Assessment Services - Client (AMD64 Architecture Specific, Client SKU)-x86_en-us.msi
                163=Windows Assessment Services - Client (AMD64 Architecture Specific, Server SKU)-x86_en-us.msi
                164=Windows Assessment Services - Client (Client SKU)-x86_en-us.msi
                165=Windows Assessment Services - Client (Server SKU)-x86_en-us.msi
                166=Windows Assessment Services - Client (X86 Architecture Specific, Client SKU)-x86_en-us.msi
                167=Windows Assessment Services-x86_en-us.msi
                168=Windows Assessment Toolkit (AMD64 Architecture Specific)-x86_en-us.msi
                169=Windows Assessment Toolkit (X86 Architecture Specific)-x86_en-us.msi
                170=Windows Assessment Toolkit-x86_en-us.msi
                171=Windows Deployment Customizations-x86_en-us.msi
                172=Windows Deployment Tools-x86_en-us.msi
                173=Windows PE x86 x64 wims-x86_en-us.msi
                174=Windows PE x86 x64-x86_en-us.msi
                175=Windows System Image Manager on amd64-x86_en-us.msi
                176=Windows System Image Manager on x86-x86_en-us.msi
                177=WPT Redistributables-x86_en-us.msi
                178=WPTarm-arm_en-us.msi
                179=WPTx64-x86_en-us.msi
                180=WPTx86-x86_en-us.msi
'@
        }
    
        $PatchesURLs = DATA {
            ConvertFrom-StringData @'
'@
        }
   
        "Installers","Patches\$PatchLevel" | ForEach-Object -Process {
            # Create target folders if required as BIT doesn't accept missing folders
            If (-not(Test-Path (Join-Path -Path $TargetFolder -ChildPath $_))) {
                try {
                    New-Item -Path (Join-Path -Path $TargetFolder -ChildPath $_) -ItemType Directory -Force @HT
                } catch {
                    Write-Warning -Message "Failed to create folder $($TargetFolder)/$_"
                    break
                }
            }
        }
        # Get adksetup.exe
        try {
            Invoke-WebRequest -Uri "$($MainURL)adksetup.exe" -OutFile  "$($TargetFolder)\adksetup.exe" @HT
        } catch {
            Write-Warning -Message "Failed to download adksetup.exe because $($_.Exception.Message)"
        }
    
        # Create a job that will downlad our first file
        $job = Start-BitsTransfer -Suspended -Source "$($MainURL)Installers/$($InstallerURLs['0'])" -Asynchronous -Destination (Join-Path -Path $TargetFolder -ChildPath ("Installers/$($InstallerURLs['0'])")) 
            
        # Downlod installers
        For ($i = 1 ; $i -lt $InstallerURLs.Count ; $i++) {
            $URL = $Destination = $null
            $URL = "$($MainURL)Installers/$($InstallerURLs[$i.ToString()])"
            $Destination = Join-Path -Path (Join-Path -Path $TargetFolder -ChildPath Installers) -ChildPath (([URI]$URL).Segments[-1] -replace '%20'," ")
            # Add-BitsFile http://technet.microsoft.com/en-us/library/dd819411.aspx
            $newjob = Add-BitsFile -BitsJob $job -Source  $URL -Destination $Destination
            Write-Progress -Activity "Adding file $($newjob.FilesTotal)" -Status "Percent completed: " -PercentComplete (($newjob.FilesTotal)*100/($InstallerURLs.Count))
        }
   
        # Donwload Patches
        For ($i = 0 ; $i -lt $PatchesURLs.Count ; $i++) {
            $URL = $Destination = $null
            $URL = "$($MainURL)Patches/$PatchLevel/$($PatchesURLs[$i.ToString()])"
            $Destination = Join-Path -Path (Join-Path -Path $TargetFolder -ChildPath "Patches/$PatchLevel") -ChildPath (([URI]$URL).Segments[-1] -replace '%20'," ")
            # Add-BitsFile http://technet.microsoft.com/en-us/library/dd819411.aspx
            $newjob = Add-BitsFile -BitsJob $job -Source  $URL -Destination $Destination
        }
    
        # Begin the download and show us the job
        Resume-BitsTransfer  -BitsJob $job -Asynchronous
    
        # http://msdn.microsoft.com/en-us/library/windows/desktop/ee663885%28v=vs.85%29.aspx
        while ($job.JobState -in @('Connecting','Transferring','Queued')) {
            Write-Progress -activity "Downloading ADK files" -Status "Percent completed: " -PercentComplete ($job.BytesTransferred*100/$job.BytesTotal)
        } 
        Switch($job.JobState) {
             "Transferred" {
                Complete-BitsTransfer -BitsJob $job
                break
            }
             "Error" {
                # List the errors.
                $job | Format-List
            } 
            default {
                # Perform corrective action.
            } 
        }
    } else {
        Write-Warning -Message "Guessing the ADK location returned the status code $($adkGenericURL.StatusCode)"
    }
}
End {}
}

Let’s see how to use the above script:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force
.  ~/documents\get-ADKFiles.ps1
mkdir ~/Downloads\ADK.10.0.10041 -Force
Get-ADKFiles -TargetFolder ~/Downloads\ADK.10.0.10041

Now you’ve got the tools to build WinPE (Windows Preinstallation Environment) with PowerShell 5.0 8-)