etc/parser/test_richblock.ps1
function Test-PeRich { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateScript({!!($script:file = Convert-Path -Path $_ -ErrorAction 0)})] [ValidateNotNullOrEmpty()] [String]$Path ) end { $block = { [OutputType([Byte[]])] param([UInt16]$o, [UInt16]$c) end { (Format-Hex -Path ($Path = $file) -Offset $o -Count $c).Bytes } } try { if (($pe = [BitConverter]::ToUInt32($block.Invoke(0x3C, 0x04), 0)) -eq 0x80) { throw [InvalidOperationException]::new('Rich block has not been found.') } if (($fix = ($pe - 0x80) % 4)) { $pe -= 0x80 - $fix } $raw = ($block.Invoke(0x80, $pe - 0x80) | Group-Object { [Math]::Floor($script:i++ / 4) }).ForEach{[BitConverter]::ToUInt32($_.Group, 0)}.Where{$_} if ($raw[-2] -ne 0x68636952) { throw [InvalidOperationException]::new('Rich signature has not been found.') } $i, $fix, $raw = 0, $raw[-1], $raw[0..($raw.Count - 3)] $raw = $raw.ForEach{$_ -bxor $fix} if ($raw[0] -ne 0x536E6144) { throw [InvalidOperationException]::new('DanS signature has not been found.') } ($raw[4..$raw.Count] | Group-Object {[Math]::Floor($script:i++ / 2)}).ForEach{ [PSCustomObject][Ordered]@{ ProdId = ($_.Group[0] -shr 0x10) -band 0xFFFF Build = $_.Group[0] -band 0xFFFF Count = $_.Group[1] } } } catch { Write-Verbose $_ } } } |