# encoding: ascii
# api: powershell
# title: Read-DllExportFunctions
# description: Prints DLL exported functions list.
# version: 0.1
# type: function
# author: greg zakharov
# license: CC0
# function: Read-DllExportFunctions
# x-poshcode-id: 5262
# x-archived: 2014-07-04T02:47:11
# x-published: 2014-06-25T17:24:00
#
#
#requires -version 2.0
if (!(Test-Path alias:dllexp)) { Set-Alias dllexp Read-DllExportFunctions }
function Read-DllExportFunctions {
<#
.NOTES
Author: greg zakharov
#>
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[ValidateScript({Test-Path $_})]
[String]$FileName
)
begin {
$cd = [AppDomain]::CurrentDomain
$attr = 'AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
if (!($cd.GetAssemblies() | ? {
$_.FullName.Contains('ExpBrowse')
})) {
$type = (($cd.DefineDynamicAssembly(
(New-Object Reflection.AssemblyName('ExpBrowse')), [Reflection.Emit.AssemblyBuilderAccess]::Run
)).DefineDynamicModule('ExpBrowse', $false)).DefineType('IMAGE_EXPORT_DIRECTORY', $attr)
[void]$type.DefineField('Characteristics', [UInt32], 'Public')
[void]$type.DefineField('TimeDateStamp', [UInt32], 'Public')
[void]$type.DefineField('MajorVersion', [UInt16], 'Public')
[void]$type.DefineField('MinorVersion', [UInt16], 'Public')
[void]$type.DefineField('Name', [UInt32], 'Public')
[void]$type.DefineField('Base', [UInt32], 'Public')
[void]$type.DefineField('NumberOfFunctions', [UInt32], 'Public')
[void]$type.DefineField('NumberOfNames', [UInt32], 'Public')
[void]$type.DefineField('AddressOfFunctions', [UInt32], 'Public')
[void]$type.DefineField('AddressOfNames', [UInt32], 'Public')
[void]$type.DefineField('AddressOfOrdinals', [UInt32], 'Public')
$global:IMAGE_EXPORT_DIRECTORY = $type.CreateType()
}
}
process {
try {
#read file
$fs = [IO.File]::OpenRead($FileName)
$buf = New-Object "Byte[]" $fs.Length
[void]$fs.Read($buf, 0, $buf.Length)
#validate that file is a PE
$e_magic = -join [Char[]]$buf[0..1]
$e_lfanew = 256 * $buf[0x3D] + $buf[0x3C]
$pe_sign = -join [Char[]]$buf[$e_lfanew..($e_lfanew + 3)]
if ($e_magic -ne 'MZ' -or $pe_sign -ne "PE`0`0") {
throw (New-Object FormatException('Invalid file format.'))
}
#get PE bit and check what it is a DLL
function Sync-Bytes([Int32]$offset) {
return [BitConverter]::ToInt32($buf, ($e_lfanew + $offset))
}
$is32bit = ((Sync-Bytes 0x16) -band 0x0100) -eq 0x0100
if (((Sync-Bytes 0x16) -band 0x2000) -eq 0x2000) {
$ImageBase = if ($is32bit) {
Sync-Bytes 0x34
} else {
[BitConverter]::ToInt64($buf, ($e_lfanew + 0x30))
}
}
#fill structure
$ied = [Activator]::CreateInstance($IMAGE_EXPORT_DIRECTORY)
[Runtime.InteropServices.Marshal]::PtrToStructure(
[IntPtr]($ImageBase + (Sync-Bytes 0x78)), $ied
)
0..($ied.NumberOfNames - 1) | % {
[Runtime.InteropServices.Marshal]::PtrToStringAnsi(
[IntPtr]($ImageBase + [Runtime.InteropServices.Marshal]::ReadInt32(
($ImageBase + $ied.AddressOfNames) + $_ * 4
))
)
}
}
catch { $e = [Boolean]$_ }
finally {
if ($fs -ne $null) { $fs.Close() }
if ($e) { return }
}
}
end {''}
}