Scripts for extracting specific binaries from Windows update packages (MSUs) before and after a patch, for use with BinDiff, Diaphora, or similar tools. The pipeline handles both complete and forward-delta PSFX formats using the native msdelta.dll API.
| Script | Purpose |
|---|---|
ExtractMSU.ps1 |
Unpack a .msu into its inner payload, .psf, and CIX XML. |
ExtractFiles.ps1 |
Pull specific binaries out of the unpacked MSU. |
ExtractUUP.ps1 |
Extract specific files from UUP dump ESD/CAB packages (for RTM bases). |
GetChangedFiles.ps1 |
Inventory all files in an unpacked MSU to a CSV (filename, arch, version). |
CompareChangedFiles.ps1 |
Compare two inventory CSVs and report which files were updated, added, or removed. |
FindFileVersionHistory.ps1 |
Search all indexed patches for every known version of a specific file, sorted oldest to newest. |
- 7-Zip (
7z.exein PATH or installed to%ProgramFiles%\7-Zip\). Required for WIM-based MSUs and UUP ESDs. - Administrator access is required if the MSU uses WIM format (newer cumulative updates). Cabinet-based MSUs do not need elevation.
- Windows - these scripts rely on Windows specific features.
Modern Windows cumulative updates use the PSFX v2 (Progressive Servicing Format eXtended) format.
KB5082052.msu
Windows11.0-KB5082052-x64.wim <- inner payload (WIM or CAB)
Windows11.0-KB5082052-x64.psf <- binary blob store
Windows11.0-KB5082052-x64\
express.psf.cix.xml <- index: maps file paths to offsets in .psfThe CIX XML lists every file in the patch. Each entry is one of two types.
\n\(neutral/complete) entries store the full binary raw in the PSF. No base file is needed to extract them.\f\(forward delta) entries store a PA30 delta compressed against the RTM (.1) binary. You need the original base file to reconstruct the target version.
All \f\ blobs in the PSF carry a 4-byte container prefix before the PA30 magic. The scripts strip this automatically before calling ApplyDeltaB.
Clone this repository and setup the directory structure like this.
This is just a recommended structure, not mandatory.
New-Item -ItemType Directory -Path "KBXXXXXXX"
New-Item -ItemType Directory -Path "KBYYYYYYY"
New-Item -ItemType Directory -Path "RTMFiles"Cumulative updates are available from the Microsoft Update Catalog at https://catalog.update.microsoft.com. Search by KB number (e.g., KB5082052) and download the x64 .msu file.
I like to put these files in their respective KB* folders.
.\ExtractMSU.ps1 -MsuPath .\KB5082052\kb5082052.msu -OutputFolder .\KB5082052\unpackedThe script reads the first four bytes to detect the format automatically.
- WIM-based (
MSWIMheader, newer CUs) usesdism /Apply-Imageand requires elevation. - Cabinet-based (
MSCFheader, older) usesexpand.exeand does not need elevation.
The output folder will contain the inner payload (.wim or .cab), the .psf, and the CIX XML at <PayloadBaseName>\express.psf.cix.xml.
.\ExtractFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFolder .\KB5082052\dlls -Filter target.dll.\ExtractFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFolder .\KB5082052\dlls -BaseFolder .\RTMFiles -Filter target.dllThe script reports how many \f\ vs \n\ entries it found before doing any work. If -BaseFolder is omitted, \f\ files are skipped with a warning.
-Filter is matched against the full component path in the CIX XML:
-Filter "*.exe" # all EXEs
-Filter "installservice.dll" # exact filename
-Filter "*.dll" # all DLLsMUI files are always excluded. When a filename appears under multiple architectures, the script prefixes the output file with amd64_, wow64_, etc. to avoid collisions.
Forward-delta patches are always applied against the RTM build (10.0.XXXXX.1), not the previous patch.
UUP dump captures Windows Update delivery packages, including component ESDs that contain files at specific build versions.
- Go to
https://uupdump.netand find the RTM build (e.g.,22621.1for Windows 11 22H2). - Select your language and edition, then download the UUP download script.
- Run the download script. It creates a folder of ESD/CAB files.
- Use
ExtractUUP.ps1to pull the specific files.
.\ExtractUUP.ps1 -UupFolder .\UUPDump\UUPs -OutputFolder .\RTMFiles -Files installservice.dll, msi.dllThen pass the RTMFiles folder as -BaseFolder to ExtractFiles.ps1:
.\ExtractFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFolder .\KB5082052\dlls -BaseFolder .\RTMFiles -Filter installservice.dllMicrosoft's publicly distributed ISOs, whether via the Media Creation Tool or microsoft.com/software-download, are generally not RTM. However, if you have an RTM ISO, mount it with DISM and copy the file from there.
You can either mount the ISO and refer to sources\install.wim in the mounted drive, or you can extract sources\install.wim using 7zip. Either way, mount the file as shown below.
dism /Mount-Image /ImageFile:D:\sources\install.wim /Index:1 /MountDir:mnt /ReadOnlyFind the file you want, and copy it out. Then you can unmount as seen below.
dism /Unmount-Image /MountDir:C:\mnt /DiscardI would not recommend using 7zip to browse the indexes directly, as the format uses links so you may have to search each index (there are usually 11).
https://winbindex.m417z.com indexes PE files by filename and build number. It is useful for quick lookups and cross-referencing hashes, but it has flaws.
- The version metadata shown on the site can be wrong. Always verify the actual PE version after downloading.
- The hash displayed on the site may not match the downloaded file. Verify with
Get-FileHash. - Not all builds are indexed, and RTM binaries for some components may be missing entirely.
I tend to give WinBindex a shot first, and always verify the hashes as well as the version presented in the properties window. If that doesn't work, I use these scripts.
# 1. Unpack both patches
.\ExtractMSU.ps1 -MsuPath .\KB5040442\kb5040442.msu -OutputFolder .\KB5040442\unpacked
.\ExtractMSU.ps1 -MsuPath .\KB5082052\kb5082052.msu -OutputFolder .\KB5082052\unpacked
# 2. Get RTM base from UUP component ESDs
.\ExtractUUP.ps1 -UupFolder .\UUPDump\UUPs -OutputFolder .\RTMFiles -Files installservice.dll, msi.dll
# 3. Extract "before" versions (KB5040442 = August 2024 CU)
.\ExtractFiles.ps1 -MsuFolder .\KB5040442\unpacked -OutputFolder .\KB5040442\dlls -BaseFolder .\RTMFiles -Filter installservice.dll
.\ExtractFiles.ps1 -MsuFolder .\KB5040442\unpacked -OutputFolder .\KB5040442\dlls -BaseFolder .\RTMFiles -Filter msi.dll
# 4. Extract "after" versions (KB5082052 = April 2026 CU)
.\ExtractFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFolder .\KB5082052\dlls -BaseFolder .\RTMFiles -Filter installservice.dll
.\ExtractFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFolder .\KB5082052\dlls -BaseFolder .\RTMFiles -Filter msi.dll
# 5. BinDiff
# Before: .\KB5040442\dlls\installservice.dll
# After: .\KB5082052\dlls\installservice.dllSometimes you have a general idea of what service or subsystem you want to patch diff, but you don't know exactly what file to look for. Provided are a couple of scripts to help with this. One lists the files in a given patch. The other compares the list of files in two patches.
This script will show you what files were changed in this patch. Note, this may contain files from prior patches.
.\GetChangedFiles.ps1 -MsuFolder .\KB5082052\unpacked
# Writes .\KB5082052\unpacked\files.csvThe CSV has these columns: FileName, Arch, Version, IsForward, IsMui, FullPath. Search it directly from PowerShell:
Import-Csv .\KB5082052\unpacked\files.csv | Where-Object { $_.FileName -match 'msi' } | Select-Object FileName, Arch, VersionPass -OutputFile to write the CSV somewhere else:
.\GetChangedFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFile .\KB5082052\files.csvThis script shows you what files have changed between patches.
.\GetChangedFiles.ps1 -MsuFolder .\KB5040442\unpacked -OutputFile .\KB5040442\files.csv
.\GetChangedFiles.ps1 -MsuFolder .\KB5082052\unpacked -OutputFile .\KB5082052\files.csv
.\CompareChangedFiles.ps1 -BeforeCsv .\KB5040442\files.csv -AfterCsv .\KB5082052\files.csvOutput is a table of files with Status (Updated, Added, or Removed), the before version, and the after version. MUI files are excluded by default; pass -IncludeMui to include them.
Save the diff to a CSV for further filtering:
.\CompareChangedFiles.ps1 -BeforeCsv .\KB5040442\files.csv -AfterCsv .\KB5082052\files.csv -OutputFile .\diff.csv
Import-Csv .\diff.csv | Where-Object Status -eq 'Updated' | Select-Object FileName, Arch, BeforeVersion, AfterVersionFindFileVersionHistory.ps1 scans all files.csv files under a root folder and shows every known version of a specific file across all indexed patches, sorted from oldest to newest. If you're patch diffing you likely don't need this, since the only files you're interested in are the recently updated ones.
The script expects files.csv files to already exist under the root. Run GetChangedFiles.ps1 on each unpacked MSU first if they don't. It finds CSVs recursively, so it doesn't matter whether they sit at the KB root or inside an unpacked\ subfolder.
.\FindFileVersionHistory.ps1 -RootFolder . -FileName ntoskrnl.exeOutput looks like this:
3 result(s) for 'ntoskrnl.exe'
KB Arch Version IsForward SourceCsv
-- ---- ------- --------- ---------
KB5040442 amd64 10.0.26100.1 True C:\...\KB5040442\files.csv
KB5078132 amd64 10.0.26100.3194 True C:\...\KB5078132\extracted\files.csv
KB5082052 amd64 10.0.26100.3775 True C:\...\KB5082052\files.csv
The BeforeVersion from CompareChangedFiles.ps1 tells you what version you need. The last row before that version in this output is the KB to pull from.
# Filter to a specific architecture
.\FindFileVersionHistory.ps1 -RootFolder . -FileName ntoskrnl.exe -Arch amd64
# Save results to a CSV for further filtering
.\FindFileVersionHistory.ps1 -RootFolder . -FileName ntoskrnl.exe -OutputFile .\ntoskrnl-history.csvMUI files are excluded by default. Pass -IncludeMui to include them.
You can find the security releases here: https://msrc.microsoft.com/update-guide/. Using that site will show you the various bugs, their related CVEs, and articles. The articles will mention the appropriate KB, however, there are different ones for different versions of Windows.
My preferred method is to go to the support page with the list of releases. You can find it by searching for "site:support.microsoft.com Windows 11 KB". On the left of this site will be a bunch of versions, chose the one you want. For example, https://support.microsoft.com/en-us/topic/january-24-2026-kb5078132-os-build-22631-6495-out-of-band-ae8525fd-a0a8-4b9b-bba9-c647ea5dc8dd. This will list the exact KB for the desired version of Windows.
Once you identify the KB, grab it from the catalog here: https://catalog.update.microsoft.com/. Click the download button on the right, making sure you download the correct architecture.
ApplyDelta failed likely means the base binary is wrong. Verify that the base file is the RTM version (XXX.1 build), not a later version. Check with (Get-Item .\RTMFiles\target.dll).VersionInfo.FileVersion.
WIM-based MSU requires elevation because dism /Apply-Image needs an elevated prompt. Run PowerShell as Administrator.