Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- ================
- PATCHEXTRACT.PS1
- =================
- Microsoft MSU Patch Extraction and Patch OrganizationUtility by Greg Linares (@Laughing_Mantis)
- This Powershell script will extract a Microsoft MSU update file and then organize the output of extracted files and folders.
- Organization of the output files is based on the patch's files and will organize them based on their archicture (x86, x64, or wow64)
- as well as their content-type, ie: resource and catalog files will be moved to a JUNK subfolder and patch binaries and index files will
- goto a PATCH folder.
- This script was developed in order to aid reverse engineers in quickly organizing patches so they can be binary diffed faster and easier.
- This was especially developed with the new bulk Microsoft Kernel patches in mind.
- Example output folder structure ouput would be similar to this:
- C:\PATCHES\MS15-XXX\PRE
- -x86
- - x86 Binary patched files
- -x64
- - x64 binary patched files
- -WOW64
- - syswow64 binary patched files
- -JUNK
- - resource, catalog, mum, and other non-binary based patched files
- -PATCH
- - original patch, cabs and xml files from the extraction
- =============
- REQUIREMENTS
- =============
- 'expand.exe' to be present in %WINDIR%\SYSTEM32 (it is by default) - It will execute this file @ the current users permissions
- A valid Microsoft MSU patch file to extract (PATCH variable)
- Directory and File write/creation permissions to the PATH folder specified
- =======
- USAGE
- =======
- Powershell -ExecutionPolicy Bypass -File PatchExtract.ps1 -Patch C:\Patches\Windows6.1-KB3088195-x64.msu -Path C:\Patches\MS15-XXX\POST\
- This would extract the patch file C:\Patches\Windows6.1-KB3088195-x64.msu to the folder C:\Patches\MS15-XXX\POST\.
- It will then create all the sub organization folders within C:\Patches\MS15-XXX\POST\ folder.
- (Note: the optional Powershell parameters '-ExecutionPolicy Bypass' is necessary in some environments to overcome Powershell execution restrictions)
- ==========
- ARGUMENTS
- ==========
- -PATCH <STRING:Filename> [REQUIRED] [NO DEFAULT]
- Specifies the MSU file that will be extracted to the specified PATH folder and then organized into the x86, x64, WOW, JUNK, and BIN folders specified
- Extract command will be "expand -F:* <PATCH> <PATH>"
- Non MSU files have not been tested however if the extraction does not generate a CAB file of the same name (indicator of successful extraction of MSU files)
- the script assumes extraction failed.
- -PATH <STRING:FolderPath> [REQUIRED] [NO DEFAULT]
- Specified the folder that the PATCH file will be extracted and organized into
- If the specified folders does not exist yet, the user will be prompted if they want to create it.
- Relative paths '.\POST' can be used but it has not extensively been tested.
- -x86 <STRING:Foldername> [OPTIONAL] [DEFAULT='x86']
- Specifies the folder name within $PATH to store x86 patch binaries
- example: -x86 32bit
- -x64 <STRING:Foldername> [OPTIONAL] [DEFAULT='x64']
- Specifies the folder name within $PATH to store x64 patch binaries
- example: -x64 64bit
- -WOW <STRING:Foldername> [OPTIONAL] [DEFAULT='WOW64']
- Specifies the folder name within $PATH to store wow64 type patch binaries
- example: -WOW sysWOW64
- -JUNK <STRING:Foldername> [OPTIONAL] [DEFAULT='JUNK']
- Specifies the folder name within $PATH to store resource, catalog, and other generally useless for diffing patch binaries
- example: -JUNK res
- -BIN <STRING:Foldername> [OPTIONAL] [DEFAULT='PATCH']
- Specifies the folder name within $PATH to store extraction xml and original patch msu and cab files
- example: -BIN bin
- ================
- VERSION HISTORY
- ================
- I originally wrote this as an ugly batch file sometime between 2014 and 2015 as a way to organize folders but it was incomplete and buggy
- Oct 15, 2015 - Initial Public Release 1.0
- ==========
- LICENSING
- ==========
- This script is provided free as beer. It probably has some bugs and coding issues, however if you like it or find it useful please give me a shout out on twitter @Laughing_Mantis.
- Feedback is encouraged and I will be likely releasing new scripts and tools and training in the future if it is welcome.
- -GLin
- #>
- Param
- (
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [ValidateNotNullOrEmpty()]
- [string]$PATCH = "",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [ValidateNotNullOrEmpty()]
- [string]$PATH = "",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [string]$x86 = "x86",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [string]$x64 = "x64",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [string]$WOW = "WOW64",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [string]$JUNK = "JUNK",
- [Parameter(ValueFromPipelineByPropertyName = $true)]
- [string]$BIN = "PATCH"
- )
- Clear-Host
- if ($PATCH -eq "")
- {
- Throw ("Error: No PATCH file specified. Specify a valid Microsoft MSU Patch with the -PATCH argument")
- }
- if ($PATH -eq "")
- {
- Throw ("Error: No PATH folder specified. Specify a folder name to extract $PATCH to using the -PATH argument")
- }
- #Bug Fix (Resolve-Path Error if invalid path was specified before the path was created)
- if (!(Test-Path $PATCH))
- {
- Throw ("Error: Specified PATCH file ($PATCH) does not exist. Specify a valid Microsoft MSU Patch file with the -PATCH argument.")
- }
- if (!($PATCH.ToUpper().EndsWith(".MSU")))
- {
- Do
- {
- $Attempt = Read-Host ("Warning: Specified PATCH file ($PATCH) is not a MSU file type. Do you still want to attempt extraction? [Y] or [N]")
- }
- Until ('Y', 'y', 'n', 'N' -ccontains $Attempt)
- if ($Attempt.ToUpper() -eq 'N')
- {
- Write-Host ("Exiting...")
- Exit
- }
- }
- if (!(Test-Path $PATH))
- {
- Do
- {
- $Attempt = Read-Host ("Warning: Specified PATH folder ($PATH) does not exist. Do you want to create it? [Y] or [N]")
- }
- Until ('Y', 'y', 'n', 'N' -ccontains $Attempt)
- if ($Attempt.ToUpper() -eq 'N')
- {
- Write-Host ("Exiting...")
- Exit
- }
- else
- {
- New-Item $PATH -Force -ItemType Directory
- Write-Host "Created $PATH Folder" -ForegroundColor Green
- }
- }
- $PATCH = Resolve-Path $PATCH
- $PATH = Resolve-Path $PATH
- Write-Host "Patch to Extract: $PATCH"
- Write-Host "Extraction Path: $PATH"
- Write-Host "x86 File Storage Folder Name: $x86"
- Write-Host "x64 File Storage Folder Name: $x64"
- Write-Host "WOW64 File Storage Folder Name: $WOW"
- Write-Host "Junk File Storage Folder Name: $JUNK"
- Write-Host "Orignal Patch File Storage Folder Name: $BIN"
- $SYSPATH = Join-Path -path (get-item env:\windir).Value -ChildPath "system32"
- $EXPAND = Join-Path -path $SYSPATH -ChildPath "expand.exe"
- if (!(Test-Path $EXPAND))
- {
- Throw ("Error: Cannot find 'Expand.exe' in the $SYSPATH folder.")
- }
- $ARG = "-F:* " + $PATCH + " " + $PATH
- Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Green
- Start-Process -File $EXPAND -ArgumentList $ARG -Wait
- $CAB = Join-Path -path $PATH -ChildPath $((Get-ChildItem $PATCH).Basename + ".CAB")
- if (!(Test-Path $CAB))
- {
- Throw "Error: Patch .CAB File ($CAB) does not exist. Patch Extraction failed"
- }
- $ARG = " -F:* " + $CAB + " " + $PATH
- Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Green
- Start-Process -File $EXPAND -ArgumentList $ARG -Wait
- $PATCHx86 = Join-Path -path $PATH -ChildPath $x86
- $PATCHx64 = Join-Path -path $PATH -ChildPath $x64
- $PATCHWOW = Join-Path -path $PATH -ChildPath $WOW
- $PATCHJUNK = Join-Path -path $PATH -ChildPath $JUNK
- $PATCHCAB = Join-Path -path $PATH -ChildPath $BIN
- if (!(Test-Path $PATCHx86 -pathType Container))
- {
- New-Item $PATCHx86 -Force -ItemType Directory
- Write-Host "Making $PATCHx86 Folder" -ForegroundColor Green
- }
- if (!(Test-Path $PATCHx64 -pathType Container))
- {
- New-Item $PATCHx64 -Force -ItemType Directory
- Write-Host "Making $PATCHx64 Folder" -ForegroundColor Green
- }
- if (!(Test-Path $PATCHWOW -pathType Container))
- {
- New-Item $PATCHWOW -Force -ItemType Directory
- Write-Host "Making $PATCHWOW Folder" -ForegroundColor Green
- }
- if (!(Test-Path $PATCHJUNK -pathType Container))
- {
- New-Item $PATCHJUNK -Force -ItemType Directory
- Write-Host "Making $PATCHJUNK Folder" -ForegroundColor Green
- }
- if (!(Test-Path $PATCHCAB -pathType Container))
- {
- New-Item $PATCHCAB -Force -ItemType Directory
- Write-Host "Making $PATCHCAB Folder" -ForegroundColor Green
- }
- $PATCHFolders = Get-ChildItem -Path $PATH -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
- foreach ($folder in $PATCHFolders)
- {
- if ($folder.Name.Contains(".resources_"))
- {
- Move-Item $folder.FullName $PATCHJUNK -Force
- Write-Host "Moving $folder to $PATCHJUNK" -ForegroundColor Green
- Continue
- }
- else
- {
- if ($folder.Name.StartsWith("x86_"))
- {
- Move-Item $folder.FullName $PATCHx86 -Force
- Write-Host "Moving $folder to $PATCHx86" -ForegroundColor Green
- Continue
- }
- if ($folder.Name.StartsWith("amd64_"))
- {
- Move-Item $folder.FullName $PATCHx64 -Force
- Write-Host "Moving $folder to $PATCHx64" -ForegroundColor Green
- Continue
- }
- if ($folder.Name.StartsWith("wow64_"))
- {
- Move-Item $folder.FullName $PATCHWOW -Force
- Write-Host "Moving $folder to $PATCHWOW" -ForegroundColor Green
- Continue
- }
- }
- }
- $Junkfiles = Get-ChildItem -Path $PATH -Force -ErrorAction SilentlyContinue
- foreach ($JunkFile in $Junkfiles)
- {
- try
- {
- if (($JunkFile.Name.EndsWith(".manifest")) -or ($JunkFile.Name.EndsWith(".cat")) -or ($JunkFile.Name.EndsWith(".mum")))
- {
- Move-Item $JunkFile.FullName $PATCHJUNK -Force -ErrorAction SilentlyContinue
- Write-Host "Moving $JunkFile to $PATCHJUNK" -ForegroundColor Green
- Continue
- }
- if (($JunkFile.Name.EndsWith(".cab")) -or ($JunkFile.Name.EndsWith(".xml")) -or ($JunkFile.Name.EndsWith(".msu")) -or ($JunkFile.Name.EndsWith("pkgProperties.txt")))
- {
- Move-Item $JunkFile.FullName $PATCHCAB -Force -ErrorAction SilentlyContinue
- Write-Host "Moving $JunkFile to $PATCHCAB" -ForegroundColor Green
- Continue
- }
- if ($JunkFile.Name -eq "patch")
- {
- Move-Item $JunkFile.FullName $PATCHCAB -Force -ErrorAction SilentlyContinue
- Write-Host "Moving $JunkFile to $PATCHCAB" -ForegroundColor Green
- Continue
- }
- }
- catch
- {
- Write-Host "Error Processing ($JunkFile.Fullname)" -ForegroundColor Red
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement