SHOW:
|
|
- or go back to the newest paste.
| 1 | <# | |
| 2 | ||
| 3 | ____ ______ ______ ____ __ __ | |
| 4 | /\ _`\ /\ _ \ /\__ _\/\ _`\ /\ \/\ \ | |
| 5 | \ \ \L\ \\ \ \L\ \\/_/\ \/\ \ \/\_\\ \ \_\ \ | |
| 6 | \ \ ,__/ \ \ __ \ \ \ \ \ \ \/_/_\ \ _ \ | |
| 7 | \ \ \/ \ \ \/\ \ \ \ \ \ \ \L\ \\ \ \ \ \ | |
| 8 | \ \_\ \ \_\ \_\ \ \_\ \ \____/ \ \_\ \_\ | |
| 9 | \/_/ \/_/\/_/ \/_/ \/___/ \/_/\/_/ | |
| 10 | ||
| 11 | ||
| 12 | ____ __ __ ______ ____ ______ ____ ______ | |
| 13 | /\ _`\ /\ \ /\ \ /\__ _\/\ _`\ /\ _ \ /\ _`\ /\__ _\ | |
| 14 | \ \ \L\_\\ `\`\/'/'\/_/\ \/\ \ \L\ \\ \ \L\ \\ \ \/\_\\/_/\ \/ | |
| 15 | \ \ _\L `\/ > < \ \ \ \ \ , / \ \ __ \\ \ \/_/_ \ \ \ | |
| 16 | \ \ \L\ \ \/'/\`\ \ \ \ \ \ \\ \ \ \ \/\ \\ \ \L\ \ \ \ \ | |
| 17 | \ \____/ /\_\\ \_\ \ \_\ \ \_\ \_\\ \_\ \_\\ \____/ \ \_\ | |
| 18 | \/___/ \/_/ \/_/ \/_/ \/_/\/ / \/_/\/_/ \/___/ \/_/ | |
| 19 | ||
| 20 | ||
| 21 | __ __ _ __ | |
| 22 | /\ \/\ \ /' \ /'__`\ | |
| 23 | \ \ \ \ \ /\_, \ /\_\L\ \ | |
| 24 | \ \ \ \ \\/_/\ \ \/_/_\_<_ | |
| 25 | \ \ \_/ \ \ \ \ __ /\ \L\ \ | |
| 26 | \ `\___/ \ \_\/\_\\ \____/ | |
| 27 | `\/__/ \/_/\/_/ \/___/ | |
| 28 | ||
| 29 | ||
| 30 | ================ | |
| 31 | PATCHEXTRACT.PS1 | |
| 32 | ================= | |
| 33 | Version 1.3 Microsoft MSU Patch Extraction and Patch Organization Utility by Greg Linares (@Laughing_Mantis) | |
| 34 | ||
| 35 | This Powershell script will extract a Microsoft MSU update file and then organize the output of extracted files and folders. | |
| 36 | ||
| 37 | Organization of the output files is based on the patch's files and will organize them based on their archicture (x86, x64, or wow64) | |
| 38 | 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 | |
| 39 | goto a PATCH folder. | |
| 40 | ||
| 41 | This script was developed in order to aid reverse engineers in quickly organizing patches so they can be binary diffed faster and easier. | |
| 42 | This was especially developed with the new bulk Microsoft Kernel patches in mind. | |
| 43 | ||
| 44 | Example output folder structure ouput would be similar to this: | |
| 45 | ||
| 46 | C:\PATCHES\MS15-XXX\PRE | |
| 47 | -x86 | |
| 48 | - x86 Binary patched files | |
| 49 | -x64 | |
| 50 | - x64 binary patched files | |
| 51 | -WOW64 | |
| 52 | - syswow64 binary patched files | |
| 53 | -JUNK | |
| 54 | - resource, catalog, mum, and other non-binary based patched files | |
| 55 | -PATCH | |
| 56 | - original patch, cabs and xml files from the extraction | |
| 57 | -MSIL | |
| 58 | - MSIL .NET binary patched files ***New in Version 1.1*** | |
| 59 | ||
| 60 | Directories will automagically be organized into filename-version to remove garbage filler folder names | |
| 61 | ||
| 62 | ||
| 63 | ============= | |
| 64 | REQUIREMENTS | |
| 65 | ============= | |
| 66 | 'expand.exe' to be present in %WINDIR%\SYSTEM32 (it is by default) - It will execute this file @ the current users permissions | |
| 67 | A valid Microsoft MSU patch file to extract (PATCH variable) | |
| 68 | Directory and File write/creation permissions to the PATH folder specified | |
| 69 | ||
| 70 | ||
| 71 | ======= | |
| 72 | USAGE | |
| 73 | ======= | |
| 74 | ||
| 75 | Powershell -ExecutionPolicy Bypass -File PatchExtract.ps1 -Patch C:\Patches\Windows6.1-KB3088195-x64.msu -Path C:\Patches\MS15-XXX\POST\ | |
| 76 | ||
| 77 | ||
| 78 | This would extract the patch file C:\Patches\Windows6.1-KB3088195-x64.msu to the folder C:\Patches\MS15-XXX\POST\. | |
| 79 | It will then create all the sub organization folders within C:\Patches\MS15-XXX\POST\ folder. | |
| 80 | ||
| 81 | (Note: the optional Powershell parameters '-ExecutionPolicy Bypass' is necessary in some environments to overcome Powershell execution restrictions) | |
| 82 | ||
| 83 | ========== | |
| 84 | ARGUMENTS | |
| 85 | ========== | |
| 86 | -PATCH <STRING:Filename> [REQUIRED] [NO DEFAULT] | |
| 87 | 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 | |
| 88 | Extract command will be "expand -F:* <PATCH> <PATH>" | |
| 89 | 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) | |
| 90 | the script assumes extraction failed. | |
| 91 | ||
| 92 | -PATH <STRING:FolderPath> [REQUIRED] [NO DEFAULT] | |
| 93 | Specified the folder that the PATCH file will be extracted and organized into | |
| 94 | If the specified folders does not exist yet, the user will be prompted if they want to create it. | |
| 95 | Relative paths '.\POST' can be used but it has not extensively been tested. | |
| 96 | ||
| 97 | ***New in Version 1.1*** | |
| 98 | The -PATH variable may be now omitted to expand to current directory | |
| 99 | ||
| 100 | ||
| 101 | -x86 <STRING:Foldername> [OPTIONAL] [DEFAULT='x86'] | |
| 102 | ||
| 103 | Specifies the folder name within $PATH to store x86 patch binaries | |
| 104 | example: -x86 32bit | |
| 105 | ||
| 106 | ||
| 107 | -x64 <STRING:Foldername> [OPTIONAL] [DEFAULT='x64'] | |
| 108 | ||
| 109 | Specifies the folder name within $PATH to store x64 patch binaries | |
| 110 | example: -x64 64bit | |
| 111 | ||
| 112 | -WOW <STRING:Foldername> [OPTIONAL] [DEFAULT='WOW64'] | |
| 113 | ||
| 114 | Specifies the folder name within $PATH to store wow64 type patch binaries | |
| 115 | example: -WOW sysWOW64 | |
| 116 | ||
| 117 | -MSIL <STRING:Foldername> [OPTIONAL] [DEFAULT='MSIL'] | |
| 118 | ||
| 119 | *** New in Version 1.1*** | |
| 120 | Specifies the folder name within $PATH to store .NET type patch binaries | |
| 121 | example: -MSIL DOTNET | |
| 122 | ||
| 123 | -JUNK <STRING:Foldername> [OPTIONAL] [DEFAULT='JUNK'] | |
| 124 | ||
| 125 | Specifies the folder name within $PATH to store resource, catalog, and other generally useless for diffing patch binaries | |
| 126 | example: -JUNK res | |
| 127 | ||
| 128 | ||
| 129 | -BIN <STRING:Foldername> [OPTIONAL] [DEFAULT='PATCH'] | |
| 130 | ||
| 131 | Specifies the folder name within $PATH to store extraction xml and original patch msu and cab files | |
| 132 | example: -BIN bin | |
| 133 | ||
| 134 | ||
| 135 | ================ | |
| 136 | VERSION HISTORY | |
| 137 | ================ | |
| 138 | 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 | |
| 139 | ||
| 140 | Oct 15, 2015 - Initial Public Release 1.0 | |
| 141 | Oct 20, 2016 - Version 1.1 Released | |
| 142 | * Bug fixes handling new naming format for patch .cab files | |
| 143 | * Added the ability to auto-extract to the same directory as current PATCH | |
| 144 | * filtered output directory name format to aid in bindiffing | |
| 145 | ||
| 146 | Oct 20, 2016 - Version 1.2 Released | |
| 147 | * Bug fixes handling MSIL renaming issues and collisions in renameing patch folders | |
| 148 | ||
| 149 | Nov 7, 2016 - Version 1.25 Released | |
| 150 | * Added hack to handle subsequent CAB files Microsoft Added in Windows 10 Cumulative Patches - will make a better way to handle this in 1.3 | |
| 151 | ||
| 152 | March 15, 2017 - Version 1.3 Released | |
| 153 | * Color Change to sweet vaporwave retro 80s colors | |
| 154 | * Cleaned up some awful code that I must have been on some amazing substances when I wrote | |
| 155 | * Spent several hours making a rad ASCII Logo | |
| 156 | * Most importantly fixed the Sub-cab auto-extraction method that Microsoft introduced late 2016 | |
| 157 | ||
| 158 | ||
| 159 | ||
| 160 | ========== | |
| 161 | LICENSING | |
| 162 | ========== | |
| 163 | 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. | |
| 164 | Feedback is encouraged and I will be likely releasing new scripts and tools and training in the future if it is welcome. | |
| 165 | ||
| 166 | ||
| 167 | -GLin | |
| 168 | ||
| 169 | #> | |
| 170 | ||
| 171 | ||
| 172 | ||
| 173 | ||
| 174 | Param | |
| 175 | ( | |
| 176 | ||
| 177 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 178 | [ValidateNotNullOrEmpty()] | |
| 179 | [string]$PATCH = "", | |
| 180 | ||
| 181 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 182 | [string]$PATH = "", | |
| 183 | ||
| 184 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 185 | [string]$x86 = "x86", | |
| 186 | ||
| 187 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 188 | [string]$x64 = "x64", | |
| 189 | ||
| 190 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 191 | [string]$WOW = "WOW64", | |
| 192 | ||
| 193 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 194 | [string]$MSIL = "MSIL", | |
| 195 | ||
| 196 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 197 | [string]$JUNK = "JUNK", | |
| 198 | ||
| 199 | [Parameter(ValueFromPipelineByPropertyName = $true)] | |
| 200 | [string]$BIN = "PATCH" | |
| 201 | ||
| 202 | ) | |
| 203 | ||
| 204 | Clear-Host | |
| 205 | $ASCIIART = @" | |
| 206 | ____ ______ ______ ____ __ __ | |
| 207 | /\ _`\ /\ _ \ /\__ _\/\ _`\ /\ \/\ \ | |
| 208 | \ \ \L\ \\ \ \L\ \\/_/\ \/\ \ \/\_\\ \ \_\ \ | |
| 209 | \ \ ,__/ \ \ __ \ \ \ \ \ \ \/_/_\ \ _ \ | |
| 210 | \ \ \/ \ \ \/\ \ \ \ \ \ \ \L\ \\ \ \ \ \ | |
| 211 | \ \_\ \ \_\ \_\ \ \_\ \ \____/ \ \_\ \_\ | |
| 212 | \/_/ \/_/\/_/ \/_/ \/___/ \/_/\/_/ | |
| 213 | ||
| 214 | ||
| 215 | ____ __ __ ______ ____ ______ ____ ______ | |
| 216 | /\ _`\ /\ \ /\ \ /\__ _\/\ _`\ /\ _ \ /\ _`\ /\__ _\ | |
| 217 | \ \ \L\_\\ `\`\/'/'\/_/\ \/\ \ \L\ \\ \ \L\ \\ \ \/\_\\/_/\ \/ | |
| 218 | \ \ _\L `\/ > < \ \ \ \ \ , / \ \ __ \\ \ \/_/_ \ \ \ | |
| 219 | \ \ \L\ \ \/'/\`\ \ \ \ \ \ \\ \ \ \ \/\ \\ \ \L\ \ \ \ \ | |
| 220 | \ \____/ /\_\\ \_\ \ \_\ \ \_\ \_\\ \_\ \_\\ \____/ \ \_\ | |
| 221 | \/___/ \/_/ \/_/ \/_/ \/_/\/ / \/_/\/_/ \/___/ \/_/ | |
| 222 | ||
| 223 | ||
| 224 | __ __ _ __ | |
| 225 | /\ \/\ \ /' \ /'__`\ | |
| 226 | \ \ \ \ \ /\_, \ /\_\L\ \ | |
| 227 | \ \ \ \ \\/_/\ \ \/_/_\_<_ | |
| 228 | \ \ \_/ \ \ \ \ __ /\ \L\ \ | |
| 229 | \ `\___/ \ \_\/\_\\ \____/ | |
| 230 | `\/__/ \/_/\/_/ \/___/ | |
| 231 | "@ | |
| 232 | ||
| 233 | Write-Host $ASCIIART -ForegroundColor Magenta | |
| 234 | Start-Sleep -s 3 | |
| 235 | ||
| 236 | ||
| 237 | if ($PATCH -eq "") | |
| 238 | {
| |
| 239 | Throw ("Error: No PATCH file specified. Specify a valid Microsoft MSU Patch with the -PATCH argument")
| |
| 240 | ||
| 241 | } | |
| 242 | ||
| 243 | if ((Split-Path $PATCH -Parent) -eq "") | |
| 244 | {
| |
| 245 | # First look in current working directory for the relative filename | |
| 246 | $CurrentDir = $(get-location).Path; | |
| 247 | $PATCH = $CurrentDir + "\" + $PATCH | |
| 248 | ||
| 249 | # if that doesnt work we look in the current script directory (less likely) | |
| 250 | # but hey we tried | |
| 251 | if (!(Test-Path $PATCH)) | |
| 252 | {
| |
| 253 | $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent | |
| 254 | $PATCH = $scriptDir + "\" + $PATCH | |
| 255 | } | |
| 256 | } | |
| 257 | ||
| 258 | if (!(Test-Path $PATCH)) | |
| 259 | {
| |
| 260 | Throw ("Error: Specified PATCH file ($PATCH) does not exist. Specify a valid Microsoft MSU Patch file with the -PATCH argument.")
| |
| 261 | } | |
| 262 | ||
| 263 | if ($PATH -eq "") | |
| 264 | {
| |
| 265 | $PATH = Split-Path $PATCH -Parent | |
| 266 | write-Host ("PATH = $PATH") -ForegroundColor White
| |
| 267 | Write-Host ("No PATH folder specified. Will extract to $PATH folder.") -ForegroundColor White
| |
| 268 | ||
| 269 | } | |
| 270 | ||
| 271 | #Bug Fix (Resolve-Path Error if invalid path was specified before the path was created) | |
| 272 | ||
| 273 | ||
| 274 | ||
| 275 | ||
| 276 | if (!($PATCH.ToUpper().EndsWith(".MSU")))
| |
| 277 | {
| |
| 278 | Do | |
| 279 | {
| |
| 280 | $Attempt = Read-Host ("Warning: Specified PATCH file ($PATCH) is not a MSU file type. Do you still want to attempt extraction? [Y] or [N]")
| |
| 281 | } | |
| 282 | Until ('Y', 'y', 'n', 'N' -ccontains $Attempt)
| |
| 283 | if ($Attempt.ToUpper() -eq 'N') | |
| 284 | {
| |
| 285 | Write-Host ("Exiting...") -ForegroundColor DarkMagenta
| |
| 286 | Exit | |
| 287 | } | |
| 288 | } | |
| 289 | ||
| 290 | if (!(Test-Path $PATH)) | |
| 291 | {
| |
| 292 | Do | |
| 293 | {
| |
| 294 | $Attempt = Read-Host ("Warning: Specified PATH folder ($PATH) does not exist. Do you want to create it? [Y] or [N]")
| |
| 295 | } | |
| 296 | Until ('Y', 'y', 'n', 'N' -ccontains $Attempt)
| |
| 297 | if ($Attempt.ToUpper() -eq 'N') | |
| 298 | {
| |
| 299 | Write-Host ("Exiting...") -ForegroundColor DarkMagenta
| |
| 300 | Exit | |
| 301 | } | |
| 302 | else | |
| 303 | {
| |
| 304 | New-Item $PATH -Force -ItemType Directory | |
| 305 | Write-Host "Created $PATH Folder" -ForegroundColor Cyan | |
| 306 | } | |
| 307 | } | |
| 308 | ||
| 309 | $PATCH = Resolve-Path $PATCH | |
| 310 | $PATH = Resolve-Path $PATH | |
| 311 | ||
| 312 | Write-Host "Patch to Extract: $PATCH" -ForegroundColor Magenta | |
| 313 | Write-Host "Extraction Path: $PATH" -ForegroundColor Magenta | |
| 314 | Write-Host "x86 File Storage Folder Name: $x86" -ForegroundColor Magenta | |
| 315 | Write-Host "x64 File Storage Folder Name: $x64" -ForegroundColor Magenta | |
| 316 | Write-Host "WOW64 File Storage Folder Name: $WOW" -ForegroundColor Magenta | |
| 317 | Write-Host "MSIL File Storage Folder Name: $MSIL" -ForegroundColor Magenta | |
| 318 | Write-Host "Junk File Storage Folder Name: $JUNK" -ForegroundColor Magenta | |
| 319 | Write-Host "Orignal Patch File Storage Folder Name: $BIN" -ForegroundColor Magenta | |
| 320 | ||
| 321 | ||
| 322 | ||
| 323 | $PATCHx86 = Join-Path -path $PATH -ChildPath $x86 | |
| 324 | $PATCHx64 = Join-Path -path $PATH -ChildPath $x64 | |
| 325 | $PATCHWOW = Join-Path -path $PATH -ChildPath $WOW | |
| 326 | $PATCHMSIL = Join-Path -path $PATH -ChildPath $MSIL | |
| 327 | $PATCHJUNK = Join-Path -path $PATH -ChildPath $JUNK | |
| 328 | $PATCHCAB = Join-Path -path $PATH -ChildPath $BIN | |
| 329 | ||
| 330 | ||
| 331 | if (!(Test-Path $PATCHx86 -pathType Container)) | |
| 332 | {
| |
| 333 | New-Item $PATCHx86 -Force -ItemType Directory | |
| 334 | Write-Host "Making $PATCHx86 Folder" -ForegroundColor Cyan | |
| 335 | } | |
| 336 | ||
| 337 | if (!(Test-Path $PATCHx64 -pathType Container)) | |
| 338 | {
| |
| 339 | New-Item $PATCHx64 -Force -ItemType Directory | |
| 340 | Write-Host "Making $PATCHx64 Folder" -ForegroundColor Cyan | |
| 341 | } | |
| 342 | ||
| 343 | if (!(Test-Path $PATCHWOW -pathType Container)) | |
| 344 | {
| |
| 345 | New-Item $PATCHWOW -Force -ItemType Directory | |
| 346 | Write-Host "Making $PATCHWOW Folder" -ForegroundColor Cyan | |
| 347 | } | |
| 348 | ||
| 349 | if (!(Test-Path $PATCHMSIL -pathType Container)) | |
| 350 | {
| |
| 351 | New-Item $PATCHMSIL -Force -ItemType Directory | |
| 352 | Write-Host "Making $PATCHMSIL Folder" -ForegroundColor Cyan | |
| 353 | } | |
| 354 | ||
| 355 | if (!(Test-Path $PATCHJUNK -pathType Container)) | |
| 356 | {
| |
| 357 | New-Item $PATCHJUNK -Force -ItemType Directory | |
| 358 | Write-Host "Making $PATCHJUNK Folder" -ForegroundColor Cyan | |
| 359 | } | |
| 360 | ||
| 361 | if (!(Test-Path $PATCHCAB -pathType Container)) | |
| 362 | {
| |
| 363 | New-Item $PATCHCAB -Force -ItemType Directory | |
| 364 | Write-Host "Making $PATCHCAB Folder" -ForegroundColor Cyan | |
| 365 | } | |
| 366 | ||
| 367 | ||
| 368 | $SYSPATH = Join-Path -path (get-item env:\windir).Value -ChildPath "system32" | |
| 369 | ||
| 370 | $EXPAND = Join-Path -path $SYSPATH -ChildPath "expand.exe" | |
| 371 | ||
| 372 | ||
| 373 | if (!(Test-Path $EXPAND)) | |
| 374 | {
| |
| 375 | Throw ("Error: Cannot find 'Expand.exe' in the $SYSPATH folder.")
| |
| 376 | } | |
| 377 | ||
| 378 | $ARG = '-F:* ' + '"' + $PATCH + '" ' + '"' + $PATH + '"' | |
| 379 | ||
| 380 | Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Cyan | |
| 381 | ||
| 382 | Start-Process -File $EXPAND -ArgumentList $ARG -Wait | |
| 383 | ||
| 384 | ||
| 385 | ||
| 386 | $CABS = Get-Childitem -Path $PATH -Filter *.cab | |
| 387 | foreach ($CAB in $CABS) | |
| 388 | {
| |
| 389 | Write-Host "CAB File: $CAB" -ForegroundColor White | |
| 390 | if (!($CAB.Name -eq "WSUSSCAN.cab")) | |
| 391 | {
| |
| 392 | $CAB = Join-Path -path $PATH -ChildPath $CAB | |
| 393 | Write-Host "Main-Cab: $CAB" -ForegroundColor Magenta | |
| 394 | if (Test-Path $CAB) | |
| 395 | {
| |
| 396 | $ARG = '-F:* ' + '"' + $CAB + '" ' + '"' + $PATH + '"' | |
| 397 | Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Cyan | |
| 398 | Start-Process -File $EXPAND -ArgumentList $ARG -Wait | |
| 399 | Write-Host "Moving $CAB to $PATCHCAB" -ForegroundColor Magenta | |
| 400 | Move-Item $CAB $PATCHCAB -Force -ErrorAction SilentlyContinue | |
| 401 | } | |
| 402 | else | |
| 403 | {
| |
| 404 | Throw "Error: Patch .CAB File [$CAB] could not be located. Patch Extraction failed - please send notification of this error to @Laughing_Mantis." | |
| 405 | } | |
| 406 | } | |
| 407 | else | |
| 408 | {
| |
| 409 | Write-Host "Moving $CAB to $PATCHCAB" -ForegroundColor Magenta | |
| 410 | Move-Item $CAB $PATCHCAB -Force -ErrorAction SilentlyContinue | |
| 411 | } | |
| 412 | } | |
| 413 | ||
| 414 | #Now for subcabs we do it again | |
| 415 | $CABS = Get-Childitem -Path $PATH -Filter *.cab | |
| 416 | foreach ($CAB in $CABS) | |
| 417 | {
| |
| 418 | if (!($CAB.Name -eq "WSUSSCAN.cab")) | |
| 419 | {
| |
| 420 | $CAB = Join-Path -path $PATH -ChildPath $CAB | |
| 421 | Write-Host "Sub-Cab: $CAB" -ForegroundColor Magenta | |
| 422 | if (Test-Path $CAB) | |
| 423 | {
| |
| 424 | $ARG = '-F:* ' + '"' + $CAB + '" ' + '"' + $PATH + '"' | |
| 425 | Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Cyan | |
| 426 | Start-Process -File $EXPAND -ArgumentList $ARG -Wait | |
| 427 | Write-Host "Moving $CAB to $PATCHCAB" -ForegroundColor Magenta | |
| 428 | Move-Item $CAB $PATCHCAB -Force -ErrorAction SilentlyContinue | |
| 429 | } | |
| 430 | else | |
| 431 | {
| |
| 432 | Throw "Error: Patch .CAB File [$CAB] could not be located. Patch Extraction failed - please send notification of this error to @Laughing_Mantis." | |
| 433 | } | |
| 434 | } | |
| 435 | } | |
| 436 | ||
| 437 | ||
| 438 | <# Microsoft newer patches do not follow this formula - likely an attempt to prevent | |
| 439 | auto extraction so we need to handle scenarios where patch cab does not have the same | |
| 440 | name as the container MSP #> | |
| 441 | ||
| 442 | ||
| 443 | ||
| 444 | ||
| 445 | ||
| 446 | <# Nov 7th, 2016 - Looks like Microsoft does not like my tool and added new sub-CABs to make automagic patch extraction not work. | |
| 447 | Adding an additional check to look for sub-CABs incase this becomes the new normal. | |
| 448 | This is an absolute hack that will likely be bypassed next month. | |
| 449 | #> | |
| 450 | ||
| 451 | ||
| 452 | ||
| 453 | <# 1.3 Fix - Microsoft likes to put multiple .Cabs in a single MSU now.... | |
| 454 | So we will look in the extracted contents and run extract on ALL cabs found | |
| 455 | except for WSUSSCAN.cab - I feel like Microsoft might put specific patches in | |
| 456 | sub cabs that might cause extracted files to overwrite each other - ie | |
| 457 | cab 1 might have binaries for specific build while cab 2 has same binary/folder name for | |
| 458 | different build...fingers crossed this doesnt happen | |
| 459 | Also Greetz to all the Microsoft Patch Team members | |
| 460 | #> | |
| 461 | ||
| 462 | ### I must have been on some amazing substances when i wrote this next part.....utterly ridiculous | |
| 463 | ### yeah this is garbage let me rewrite this for 1.3 | |
| 464 | ||
| 465 | <# GARBAGE CODE BELOW SAVED FOR SHAMING PURPOSES | |
| 466 | $patchCABID = "cab_" + $patchCAB + "_*.cab" | |
| 467 | $CAB = (Get-ChildItem -Path $PATH -Filter $PatchCABID | Select-Object -First 1) | |
| 468 | Write-Host "Debug CAB = $CAB" | |
| 469 | if (Test-Path $CAB) | |
| 470 | {
| |
| 471 | $flag = "1" | |
| 472 | } | |
| 473 | ||
| 474 | while ($flag -eq "1") | |
| 475 | {
| |
| 476 | Write-Host "Subsequent CAB $CAB detected - attempting beta extraction" -ForegroundColor Yellow | |
| 477 | $ARG = '-F:* ' + '"' + $CAB + '" ' + '"' + $PATH + '"' | |
| 478 | ||
| 479 | Write-Host "Executing the following command: $EXPAND $ARG" -ForegroundColor Cyan | |
| 480 | ||
| 481 | Start-Process -File $EXPAND -ArgumentList $ARG -Wait | |
| 482 | ||
| 483 | $patchCAB++ | |
| 484 | ||
| 485 | $patchCABID = "cab_" + $patchCAB + "_*.cab" | |
| 486 | try | |
| 487 | {
| |
| 488 | $CAB = (Get-ChildItem -Path $PATH -Filter $PatchCABID | Select-Object -First 1) | |
| 489 | if ((!(Test-Path $CAB)) -or ($CAB -eq "")) | |
| 490 | {
| |
| 491 | $flag = "0" | |
| 492 | } | |
| 493 | } | |
| 494 | catch | |
| 495 | {
| |
| 496 | $flag = "0" | |
| 497 | } | |
| 498 | ||
| 499 | } | |
| 500 | #> | |
| 501 | ||
| 502 | ||
| 503 | ||
| 504 | $PATCHFolders = Get-ChildItem -Path $PATH -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
| |
| 505 | ||
| 506 | foreach ($folder in $PATCHFolders) | |
| 507 | {
| |
| 508 | if ($folder.Name.Contains(".resources_"))
| |
| 509 | {
| |
| 510 | Move-Item $folder.FullName $PATCHJUNK -Force | |
| 511 | Write-Host "Moving $folder to $PATCHJUNK" -ForegroundColor Cyan | |
| 512 | Continue | |
| 513 | } | |
| 514 | else | |
| 515 | {
| |
| 516 | if ($folder.Name.StartsWith("x86_"))
| |
| 517 | {
| |
| 518 | Move-Item $folder.FullName $PATCHx86 -Force | |
| 519 | Write-Host "Moving $folder to $PATCHx86" -ForegroundColor Cyan | |
| 520 | Continue | |
| 521 | } | |
| 522 | ||
| 523 | if ($folder.Name.StartsWith("amd64_"))
| |
| 524 | {
| |
| 525 | Move-Item $folder.FullName $PATCHx64 -Force | |
| 526 | Write-Host "Moving $folder to $PATCHx64" -ForegroundColor Cyan | |
| 527 | Continue | |
| 528 | } | |
| 529 | ||
| 530 | if ($folder.Name.StartsWith("wow64_"))
| |
| 531 | {
| |
| 532 | Move-Item $folder.FullName $PATCHWOW -Force | |
| 533 | Write-Host "Moving $folder to $PATCHWOW" -ForegroundColor Cyan | |
| 534 | Continue | |
| 535 | } | |
| 536 | ||
| 537 | if ($folder.Name.StartsWith("msil_"))
| |
| 538 | {
| |
| 539 | Move-Item $folder.FullName $PATCHMSIL -Force | |
| 540 | Write-Host "Moving $folder to $PATCHMSIL" -ForegroundColor Cyan | |
| 541 | Continue | |
| 542 | } | |
| 543 | } | |
| 544 | } | |
| 545 | ||
| 546 | <# PRETTY BINDIFF OUTPUT - changes folder names from x86-microsoft-windows-filename-hash-version-garbage to filename-version #> | |
| 547 | ||
| 548 | $PATCHFolders = Get-ChildItem -Path $PATCHx86 -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
| |
| 549 | ||
| 550 | foreach ($folder in $PATCHFolders) | |
| 551 | {
| |
| 552 | if ($folder -like "x86_microsoft-windows-*") | |
| 553 | {
| |
| 554 | $newfolder = $folder.Name.Replace("x86_microsoft-windows-", "")
| |
| 555 | $newname = $newfolder.Split("_")[0]
| |
| 556 | $version = $newfolder.Split("_")[2]
| |
| 557 | $newname = $newname + "_" + $version | |
| 558 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Magenta
| |
| 559 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 560 | } | |
| 561 | elseif ($folder -like "x86_*") | |
| 562 | {
| |
| 563 | $newfolder = $folder.Name.Replace("x86_", "")
| |
| 564 | $newname = $newfolder.Split("_")[0]
| |
| 565 | $version = $newfolder.Split("_")[2]
| |
| 566 | $newname = $newname + "_" + $version | |
| 567 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Cyan
| |
| 568 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 569 | } | |
| 570 | } | |
| 571 | ||
| 572 | $PATCHFolders = Get-ChildItem -Path $PATCHx64 -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
| |
| 573 | ||
| 574 | foreach ($folder in $PATCHFolders) | |
| 575 | {
| |
| 576 | if ($folder -like "amd64_microsoft-windows-*") | |
| 577 | {
| |
| 578 | $newfolder = $folder.Name.Replace("amd64_microsoft-windows-", "")
| |
| 579 | $newname = $newfolder.Split("_")[0]
| |
| 580 | $version = $newfolder.Split("_")[2]
| |
| 581 | $newname = $newname + "_" + $version | |
| 582 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Magenta
| |
| 583 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 584 | } | |
| 585 | elseif ($folder -like "amd64_*") | |
| 586 | {
| |
| 587 | $newfolder = $folder.Name.Replace("amd64_", "")
| |
| 588 | $newname = $newfolder.Split("_")[0]
| |
| 589 | $version = $newfolder.Split("_")[2]
| |
| 590 | $newname = $newname + "_" + $version | |
| 591 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Cyan
| |
| 592 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 593 | } | |
| 594 | } | |
| 595 | ||
| 596 | $PATCHFolders = Get-ChildItem -Path $PATCHWOW -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
| |
| 597 | ||
| 598 | foreach ($folder in $PATCHFolders) | |
| 599 | {
| |
| 600 | if ($folder -like "wow64_microsoft-windows-*") | |
| 601 | {
| |
| 602 | $newfolder = $folder.Name.Replace("wow64_microsoft-windows-", "")
| |
| 603 | $newname = $newfolder.Split("_")[0]
| |
| 604 | $version = $newfolder.Split("_")[2]
| |
| 605 | $newname = $newname + "_" + $version | |
| 606 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Magenta
| |
| 607 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 608 | } | |
| 609 | elseif ($folder -like "wow64_*") | |
| 610 | {
| |
| 611 | $newfolder = $folder.Name.Replace("wow64_", "")
| |
| 612 | $newname = $newfolder.Split("_")[0]
| |
| 613 | $version = $newfolder.Split("_")[2]
| |
| 614 | $newname = $newname + "_" + $version | |
| 615 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Cyan
| |
| 616 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 617 | } | |
| 618 | } | |
| 619 | ||
| 620 | $PATCHFolders = Get-ChildItem -Path $PATCHMSIL -Force -ErrorAction SilentlyContinue | where {$_.Attributes -eq 'Directory'}
| |
| 621 | ||
| 622 | foreach ($folder in $PATCHFolders) | |
| 623 | {
| |
| 624 | if ($folder -like "msil_*") | |
| 625 | {
| |
| 626 | $newfolder = $folder.Name.Replace("msil_", "")
| |
| 627 | $newname = $newfolder.Split("_")[0]
| |
| 628 | $version = $newfolder.Split("_")[2]
| |
| 629 | $newname = $newname + "_" + $version | |
| 630 | Write-Host ("Renaming $folder to $newname") -ForegroundColor Cyan
| |
| 631 | Rename-Item -path $folder.FullName -newName ($newname) | |
| 632 | } | |
| 633 | ||
| 634 | } | |
| 635 | ||
| 636 | $Junkfiles = Get-ChildItem -Path $PATH -Force -ErrorAction SilentlyContinue | |
| 637 | ||
| 638 | ||
| 639 | foreach ($JunkFile in $Junkfiles) | |
| 640 | {
| |
| 641 | ||
| 642 | try | |
| 643 | {
| |
| 644 | if (($JunkFile.Name.EndsWith(".manifest")) -or ($JunkFile.Name.EndsWith(".cat")) -or ($JunkFile.Name.EndsWith(".mum")))
| |
| 645 | {
| |
| 646 | Move-Item $JunkFile.FullName $PATCHJUNK -Force -ErrorAction SilentlyContinue | |
| 647 | Write-Host "Moving $JunkFile to $PATCHJUNK" -ForegroundColor Magenta | |
| 648 | Continue | |
| 649 | } | |
| 650 | ||
| 651 | if (($JunkFile.Name.EndsWith(".cab")) -or ($JunkFile.Name.EndsWith(".xml")) -or ($JunkFile.Name.EndsWith(".msu")) -or ($JunkFile.Name.EndsWith("pkgProperties.txt")))
| |
| 652 | {
| |
| 653 | Move-Item $JunkFile.FullName $PATCHCAB -Force -ErrorAction SilentlyContinue | |
| 654 | Write-Host "Moving $JunkFile to $PATCHCAB" -ForegroundColor Cyan | |
| 655 | Continue | |
| 656 | } | |
| 657 | if ($JunkFile.Name -eq "patch") | |
| 658 | {
| |
| 659 | Move-Item $JunkFile.FullName $PATCHCAB -Force -ErrorAction SilentlyContinue | |
| 660 | Write-Host "Moving $JunkFile to $PATCHCAB" -ForegroundColor Magenta | |
| 661 | Continue | |
| 662 | } | |
| 663 | } | |
| 664 | catch | |
| 665 | {
| |
| 666 | Write-Host "Error Processing ($JunkFile.Fullname)" -ForegroundColor DarkMagenta | |
| 667 | } | |
| 668 | } |