Skip to content

Instantly share code, notes, and snippets.

@edyoung
Created September 9, 2022 23:45
Show Gist options
  • Save edyoung/bde6e5afbd69c10f9f079a5ca42923ea to your computer and use it in GitHub Desktop.
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
[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