Skip to content

Instantly share code, notes, and snippets.

@Trucido
Created February 28, 2019 23:48
Show Gist options
  • Save Trucido/2aa287d29f9d65f047549a3833e8f22d to your computer and use it in GitHub Desktop.
Save Trucido/2aa287d29f9d65f047549a3833e8f22d to your computer and use it in GitHub Desktop.
## Get-PECharacteristics.ps1
<#
.SYNOPSIS
Get the file characteristics of a PE Executable.
.EXAMPLE
PS > Get-PECharacteristics $env:WINDIR\notepad.exe
IMAGE_FILE_LOCAL_SYMS_STRIPPED
IMAGE_FILE_RELOCS_STRIPPED
IMAGE_FILE_EXECUTABLE_IMAGE
IMAGE_FILE_32BIT_MACHINE
IMAGE_FILE_LINE_NUMS_STRIPPED
#>
function Get-PECharacteristics
{
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string] $Path
)
Set-StrictMode -Version 'Latest'
# Define characteristics used in PE file headers.
# TODO: Many more characteristics; easier to parse as CSharp class.
$characteristics = @{
"IMAGE_FILE_RELOCS_STRIPPED" = 0x0001
"IMAGE_FILE_EXECUTABLE_IMAGE" = 0x0002
"IMAGE_FILE_LINE_NUMS_STRIPPED" = 0x0004
"IMAGE_FILE_LOCAL_SYMS_STRIPPED" = 0x0008
"IMAGE_FILE_AGGRESSIVE_WS_TRIM" = 0x0010
"IMAGE_FILE_LARGE_ADDRESS_AWARE" = 0x0020
"RESERVED" = 0x0040
"IMAGE_FILE_BYTES_REVERSED_LO" = 0x0080
"IMAGE_FILE_32BIT_MACHINE" = 0x0100
"IMAGE_FILE_DEBUG_STRIPPED" = 0x0200
"IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP" = 0x0400
"IMAGE_FILE_NET_RUN_FROM_SWAP" = 0x0800
"IMAGE_FILE_SYSTEM" = 0x1000
"IMAGE_FILE_DLL" = 0x2000
"IMAGE_FILE_UP_SYSTEM_ONLY" = 0x4000
"IMAGE_FILE_BYTES_REVERSED_HI" = 0x8000
}
# Get content of file as byte array
# TODO: Wildcarded [string[]]$Path
# [!NOTE] > In PowerShell 6.0, The `-Encoding` parameter type
# > was changed from `FileSystemCmdletProviderEncoding`
# > to `System.Text.Encoding` and Byte is no longer a valid option.
# > The `-AsByteStream` parameter should be used to indicate that
# > the content should be read and output as a byte stream.
if($PSVersionTable.PSVersion.Major -ge 6)
{
$fileBytes = Get-Content $path -ReadCount 0 -AsByteStream
}
else
{
$fileBytes = Get-Content $path -ReadCount 0 -Encoding byte
}
# Signature offset location is 0x3c.
$signatureOffset = $fileBytes[0x3c]
# Ensure file is PE
$signature = [char[]] $fileBytes[$signatureOffset..($signatureOffset + 3)]
if(($signature -join '') -ne "PE`0`0")
{
throw "This file does not conform to the PE specification."
}
# COFF header location is 4 bytes into signature
$coffHeader = $signatureOffset + 4
# Characteristics data are 18 bytes into COFF header.
# BitConverter class manages conversion of the 4 bytes into int.
$characteristicsData = [BitConverter]::ToInt32($fileBytes, $coffHeader + 18)
# Loop through each characteristic and output it if file contains the flag.
# TODO: Add characteristics as properties for object parsing/formatting.
foreach($key in $characteristics.Keys)
{
$flag = $characteristics[$key]
if(($characteristicsData -band $flag) -eq $flag)
{
$key
}
}
}
# If this script is invoked directly - as opposed to being dot-sourced in order
# to define the embedded function for later use - invoke the embedded function,
# relaying any arguments passed - but first detect ValueFromPipeLine $input
if ($MyInvocation.ExpectingInput)
{
$input | Get-PECharacteristics @args
}
elseif (-not ($MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq ''))
{
Get-PECharacteristics @args
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment