Created
September 9, 2022 23:45
-
-
Save edyoung/bde6e5afbd69c10f9f079a5ca42923ea to your computer and use it in GitHub Desktop.
Extract a file from an MSI binary table and save it to disk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CmdletBinding()] | |
[OutputType( | |
[PSCustomObject] | |
)] | |
param ( | |
[Parameter( | |
Mandatory = $true | |
)] | |
[String] | |
$Path, | |
[String] | |
$BinaryName, | |
[String] | |
$OutFile | |
) | |
begin { | |
$windowsInstaller = New-Object -ComObject WindowsInstaller.Installer | |
} | |
process { | |
function Get-Property ($Object, $PropertyName, [object[]]$ArgumentList) { | |
return $Object.GetType().InvokeMember($PropertyName, 'Public, Instance, GetProperty', $null, $Object, $ArgumentList) | |
} | |
function Invoke-Method ($Object, $MethodName, $ArgumentList) { | |
return $Object.GetType().InvokeMember($MethodName, 'Public, Instance, InvokeMethod', $null, $Object, $ArgumentList) | |
} | |
$msiReadStreamAnsi = 2 | |
$pathValue = $path | |
try { | |
$item = Get-Item -Path $pathValue -ErrorAction Stop | |
$database = $windowsInstaller.GetType().InvokeMember( | |
"OpenDatabase", "InvokeMethod", $null, $windowsInstaller, ($item.FullName, 0) | |
) | |
Write-Verbose "Opened Database" | |
$ViewBinary = $database.GetType().InvokeMember( | |
"OpenView", "InvokeMethod", $null, $database, "SELECT Name, Data FROM Binary WHERE Name = '$binaryName'" | |
) | |
Write-Verbose "Opened view" | |
$ViewBinary.GetType().InvokeMember( | |
"Execute", "InvokeMethod", $null, $ViewBinary, @() | |
) | |
do { | |
$Binary = $ViewBinary.GetType().InvokeMember( | |
"Fetch", "InvokeMethod", $null, $ViewBinary, @() | |
) | |
if ($Binary) { | |
$Name = Get-Property $Binary StringData 1 | |
$DataSize = Get-Property $Binary DataSize 2 | |
Write-Output "Found Binary: $msiPath/$Name ($DataSize bytes)" | |
$BinaryData = Invoke-Method $Binary ReadStream @(2, $DataSize, $msiReadStreamAnsi) | |
$BinaryData | Set-Content -NoNewLine $outFile | |
} | |
} | |
while ($Binary) | |
Write-Output -InputObject $output | |
} | |
catch { | |
Write-Error $_ | |
continue | |
} | |
} | |
end { | |
Out-Null -InputObject ([System.Runtime.InteropServices.Marshal]::ReleaseComObject( | |
$windowsInstaller | |
)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment