Here is a script I wrote experimenting with resolving API Set function calls to on disk module/function/offset.
<#
.SYNOPSIS
This script resolves an API set and API name to a specific module and function name.
.DESCRIPTION
This script uses the NativeMethods class to call Windows API functions for resolving
a given API set and API name to the actual module and function name they correspond to.
.PARAMETER ApiSet
The API set string to be resolved. For example: "api-ms-win-devices-query-l1-1-0".
.PARAMETER Api
The API name string to be resolved. For example: "DevGetObjects".
.PARAMETER ShowOffset
Will show the offset of function instead of function name.
Use if symbols don't resolve.
.EXAMPLE
.\Resolve-ApiSet.ps1 -ApiSet "api-ms-win-devices-query-l1-1-0" -Api "DevGetObjects"
This command will resolve the given ApiSet and ApiName to their corresponding module and function name.
.\Resolve-ApiSet.ps1 -ApiSet "api-ms-win-devices-query-l1-1-0" -Api "DevGetObjects" -ShowOffSet
This command will resolve the given ApiSet and ApiName to their corresponding module and offset (based on the image base address on disk)
.NOTES
Run as 32-bit PowerShell for 32-bit modules
64-bit PowerShell for 64-bit modules.
If names are not resolving you may need to configure
Microsoft Symbol Server or place name of your desired
Symbol server in 2nd param to SymInitialize
#>
param(
[Parameter(Mandatory=$true)]
[string]$ApiSet,
[Parameter(Mandatory=$true)]
[string]$Api,
[switch]$ShowOffset
)
Add-Type -TypeDefinition @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
public class NativeMethods
{
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, bool fInvadeProcess);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SymFromAddr(IntPtr hProcess, ulong Address, out ulong Displacement, IntPtr Symbol);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SymCleanup(IntPtr hProcess);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
private const int MAX_SYM_NAME = 2000;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SYMBOL_INFO
{
public uint SizeOfStruct;
public uint TypeIndex;
public ulong Reserved1;
public ulong Reserved2;
public uint Index;
public uint Size;
public ulong ModBase;
public uint Flags;
public ulong Value;
public ulong Address;
public uint Register;
public uint Scope;
public uint Tag;
public uint NameLen;
public uint MaxNameLen;
public char Name;
}
public static void SymInitialize()
{
if (!SymInitialize(GetCurrentProcess(), "", true))
{
// ignore errors
// can only be called once per process instance
//Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
}
public static string GetSymbolName(IntPtr address)
{
ulong displacement = 0;
byte[] buffer = new byte[Marshal.SizeOf(typeof(SYMBOL_INFO)) + MAX_SYM_NAME * sizeof(char)];
GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr symbolPtr = bufferHandle.AddrOfPinnedObject();
SYMBOL_INFO symbol = (SYMBOL_INFO)Marshal.PtrToStructure(symbolPtr, typeof(SYMBOL_INFO));
symbol.SizeOfStruct = (uint)Marshal.SizeOf(typeof(SYMBOL_INFO));
symbol.MaxNameLen = MAX_SYM_NAME;
Marshal.StructureToPtr(symbol, symbolPtr, true);
if (SymFromAddr(GetCurrentProcess(), (ulong)address, out displacement, symbolPtr))
{
symbol = (SYMBOL_INFO)Marshal.PtrToStructure(symbolPtr, typeof(SYMBOL_INFO));
string functionName = Marshal.PtrToStringUni(symbolPtr + 84);
return functionName;
}
else
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
//SymCleanup(GetCurrentProcess());
bufferHandle.Free();
return String.Empty;
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint GetModuleFileName(
IntPtr hModule,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpFilename,
uint nSize
);
public static string GetModuleFileName(IntPtr hModule)
{
uint bufferSize = 1024;
StringBuilder fileNameBuilder = new StringBuilder((int)bufferSize);
uint result = GetModuleFileName(hModule, fileNameBuilder, bufferSize);
if (result == 0)
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
else if (result == bufferSize)
{
throw new InvalidOperationException("The file name is too long. Increase the buffer size and try again.");
}
return fileNameBuilder.ToString();
}
[DllImport("ntdll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int LdrLoadDll(
string DllPath,
uint[] DllCharacteristics,
ref UNICODE_STRING DllName,
out IntPtr DllHandle
);
[DllImport("ntdll.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int LdrUnloadDll(IntPtr ModuleHandle);
[DllImport("ntdll.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int LdrGetProcedureAddress(
IntPtr DllHandle,
ref ANSI_STRING ProcedureName,
uint ProcedureNumber,
out IntPtr ProcedureAddress
);
[StructLayout(LayoutKind.Sequential)]
public struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
public string Buffer;
}
[StructLayout(LayoutKind.Sequential)]
public struct ANSI_STRING
{
public ushort Length;
public ushort MaximumLength;
[MarshalAs(UnmanagedType.LPStr)]
public string Buffer;
}
public static UNICODE_STRING CreateUnicodeString(string str)
{
return new UNICODE_STRING
{
Length = (ushort)(str.Length * 2),
MaximumLength = (ushort)((str.Length * 2) + 2),
Buffer = str
};
}
public static ANSI_STRING CreateAnsiString(string str)
{
return new ANSI_STRING
{
Length = (ushort)str.Length,
MaximumLength = (ushort)(str.Length + 1),
Buffer = str
};
}
}
'@
[Uint16]$IMAGE_DOS_SIGNATURE = 0x5A4D
[Uint16]$IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b
[UInt16]$IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
[UInt16]$IMAGE_ROM_OPTIONAL_HDR_MAGIC = 0x107
[Uint16]$IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
[Uint16]$IMAGE_SIZEOF_SHORT_NAME = 8
[Uint16]$IMAGE_SIZEOF_SECTION_HEADER = 40
enum IMAGE_FILE_MACHINE {
IMAGE_FILE_RELOCS_STRIPPED = 0x0001 # Relocation info stripped from file.
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 # File is executable (i.e. no unresolved external references).
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 # Line nunbers stripped from file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 # Local symbols stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 # Aggressively trim working set
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 # App can handle >2gb addresses
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 # Bytes of machine word are reversed.
IMAGE_FILE_32BIT_MACHINE = 0x0100 # 32 bit word machine.
IMAGE_FILE_DEBUG_STRIPPED = 0x0200 # Debugging info stripped from file in .DBG file
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 # If Image is on removable media, copy and run from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 # If Image is on Net, copy and run from the swap file.
IMAGE_FILE_SYSTEM = 0x1000 # System File.
IMAGE_FILE_DLL = 0x2000 # File is a DLL.
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 # File should only be run on a UP machine
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 # Bytes of machine word are reversed.
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001 # Useful for indicating we want to interact with the host and not a WoW guest.
IMAGE_FILE_MACHINE_I386 = 0x014c # Intel 386.
IMAGE_FILE_MACHINE_R3000 = 0x0162 # MIPS little-endian, = 0x160 big-endian
IMAGE_FILE_MACHINE_R4000 = 0x0166 # MIPS little-endian
IMAGE_FILE_MACHINE_R10000 = 0x0168 # MIPS little-endian
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169 # MIPS little-endian WCE v2
IMAGE_FILE_MACHINE_ALPHA = 0x0184 # Alpha_AXP
IMAGE_FILE_MACHINE_SH3 = 0x01a2 # SH3 little-endian
IMAGE_FILE_MACHINE_SH3DSP = 0x01a3
IMAGE_FILE_MACHINE_SH3E = 0x01a4 # SH3E little-endian
IMAGE_FILE_MACHINE_SH4 = 0x01a6 # SH4 little-endian
IMAGE_FILE_MACHINE_SH5 = 0x01a8 # SH5
IMAGE_FILE_MACHINE_ARM = 0x01c0 # ARM Little-Endian
IMAGE_FILE_MACHINE_THUMB = 0x01c2 # ARM Thumb/Thumb-2 Little-Endian
IMAGE_FILE_MACHINE_ARMNT = 0x01c4 # ARM Thumb-2 Little-Endian
IMAGE_FILE_MACHINE_AM33 = 0x01d3
IMAGE_FILE_MACHINE_POWERPC = 0x01F0 # IBM PowerPC Little-Endian
IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1
IMAGE_FILE_MACHINE_IA64 = 0x0200 # Intel 64
IMAGE_FILE_MACHINE_MIPS16 = 0x0266 # MIPS
IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 # ALPHA64
IMAGE_FILE_MACHINE_MIPSFPU = 0x0366 # MIPS
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466 # MIPS
IMAGE_FILE_MACHINE_AXP64 = 0x0284 # IMAGE_FILE_MACHINE_ALPHA64
IMAGE_FILE_MACHINE_TRICORE = 0x0520 # Infineon
IMAGE_FILE_MACHINE_CEF = 0x0CEF
IMAGE_FILE_MACHINE_EBC = 0x0EBC # EFI Byte Code
IMAGE_FILE_MACHINE_AMD64 = 0x8664 # AMD64 (K8)
IMAGE_FILE_MACHINE_M32R = 0x9041 # M32R little-endian
IMAGE_FILE_MACHINE_ARM64 = 0xAA64 # ARM64 Little-Endian
IMAGE_FILE_MACHINE_CEE = 0xC0EE
}
[Flags()] enum IMAGE_SUBSYSTEM
{
IMAGE_SUBSYSTEM_UNKNOWN = 0 # Unknown subsystem.
IMAGE_SUBSYSTEM_NATIVE = 1 # Image doesnt require a subsystem.
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 # Image runs in the Windows GUI subsystem.
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 # Image runs in the Windows character subsystem.
IMAGE_SUBSYSTEM_OS2_CUI = 5 # image runs in the OS/2 character subsystem.
IMAGE_SUBSYSTEM_POSIX_CUI = 7 # image runs in the Posix character subsystem.
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8 # image is a native Win9x driver.
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9 # Image runs in the Windows CE subsystem.
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10 #
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11 #
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12 #
IMAGE_SUBSYSTEM_EFI_ROM = 13
IMAGE_SUBSYSTEM_XBOX = 14
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG = 17
}
[Flags()] enum IMAGE_DLLCHARACTERISTICS {
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 # Image can handle a high entropy 64-bit virtual address space.
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 # DLL can move.
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080 # Code Integrity Image
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100 # Image is NX compatible
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200 # Image understands isolation and doesn't want it
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 # Image does not use SEH. No SE handler may reside in this image
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800 # Do not bind this image.
IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000 # Image should execute in an AppContainer
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000 # Driver uses WDM model
IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000 # Image supports Control Flow Guard.
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
}
enum IMAGE_DIRECTORY_ENTRY
{
IMAGE_DIRECTORY_ENTRY_EXPORT = 0 # Export Directory
IMAGE_DIRECTORY_ENTRY_IMPORT = 1 # Import Directory
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 # Resource Directory
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 # Exception Directory
IMAGE_DIRECTORY_ENTRY_SECURITY = 4 # Security Directory
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 # Base Relocation Table
IMAGE_DIRECTORY_ENTRY_DEBUG = 6 # Debug Directory
# IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 # (X86 usage)
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 # Architecture Specific Data
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 # RVA of GP
IMAGE_DIRECTORY_ENTRY_TLS = 9 # TLS Directory
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 # Load Configuration Directory
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 # Bound Import Directory in headers
IMAGE_DIRECTORY_ENTRY_IAT = 12 # Import Address Table
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 # Delay Load Import Descriptors
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 # COM Runtime descriptor
}
[Flags()] enum IMAGE_SCN {
# IMAGE_SCN_TYPE_REG 0x00000000 # Reserved.
# IMAGE_SCN_TYPE_DSECT 0x00000001 # Reserved.
# IMAGE_SCN_TYPE_NOLOAD 0x00000002 # Reserved.
# IMAGE_SCN_TYPE_GROUP 0x00000004 # Reserved.
IMAGE_SCN_TYPE_NO_PAD = 0x00000008 # Reserved.
# IMAGE_SCN_TYPE_COPY 0x00000010 # Reserved.
IMAGE_SCN_CNT_CODE = 0x00000020 # Section contains code.
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 # Section contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 # Section contains uninitialized data.
IMAGE_SCN_LNK_OTHER = 0x00000100 # Reserved.
IMAGE_SCN_LNK_INFO = 0x00000200 # Section contains comments or some other type of information.
# IMAGE_SCN_TYPE_OVER 0x00000400 # Reserved.
IMAGE_SCN_LNK_REMOVE = 0x00000800 # Section contents will not become part of image.
IMAGE_SCN_LNK_COMDAT = 0x00001000 # Section contents comdat.
# 0x00002000 # Reserved.
# IMAGE_SCN_MEM_PROTECTED - Obsolete = 0x00004000
IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000 # Reset speculative exceptions handling bits in the TLB entries for this section.
IMAGE_SCN_GPREL = 0x00008000 # Section content can be accessed relative to GP
IMAGE_SCN_MEM_FARDATA = 0x00008000
# IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000
IMAGE_SCN_MEM_PURGEABLE = 0x00020000
IMAGE_SCN_MEM_16BIT = 0x00020000
IMAGE_SCN_MEM_LOCKED = 0x00040000
IMAGE_SCN_MEM_PRELOAD = 0x00080000
IMAGE_SCN_ALIGN_1BYTES = 0x00100000 #
IMAGE_SCN_ALIGN_2BYTES = 0x00200000 #
IMAGE_SCN_ALIGN_4BYTES = 0x00300000 #
IMAGE_SCN_ALIGN_8BYTES = 0x00400000 #
IMAGE_SCN_ALIGN_16BYTES = 0x00500000 # Default alignment if no others are specified.
IMAGE_SCN_ALIGN_32BYTES = 0x00600000 #
IMAGE_SCN_ALIGN_64BYTES = 0x00700000 #
IMAGE_SCN_ALIGN_128BYTES = 0x00800000 #
IMAGE_SCN_ALIGN_256BYTES = 0x00900000 #
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 #
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 #
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 #
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 #
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 #
# Unused 0x00F00000
IMAGE_SCN_ALIGN_MASK = 0x00F00000
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 # Section contains extended relocations.
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 # Section can be discarded.
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 # Section is not cachable.
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 # Section is not pageable.
IMAGE_SCN_MEM_SHARED = 0x10000000 # Section is shareable.
IMAGE_SCN_MEM_EXECUTE = 0x20000000 # Section is executable.
IMAGE_SCN_MEM_READ = 0x40000000 # Section is readable.
IMAGE_SCN_MEM_WRITE = 0x80000000 # Section is writeable.
#
# TLS Characteristic Flags
#
IMAGE_SCN_SCALE_INDEX = 0x00000001 # Tls index is scaled
}
Function Convert-EnumToString([Enum]$enum)
{
$type = [Type]$enum
}
$IMAGE_DOS_HEADER = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_DOS_HEADER.Add("e_magic",[Uint16]0) # magic number
$IMAGE_DOS_HEADER.Add("e_cblp",[UInt16]0) # Bytes on last page of file
$IMAGE_DOS_HEADER.Add("e_cp",[UInt16]0) # Pages in file
$IMAGE_DOS_HEADER.Add("e_crlc",[UInt16]0) # Relocations
$IMAGE_DOS_HEADER.Add("e_cparhdr",[UInt16]0) # Size of header in paragraphs
$IMAGE_DOS_HEADER.Add("e_minalloc",[UInt16]0) # Minimum extra paragraphs needed
$IMAGE_DOS_HEADER.Add("e_maxalloc",[UInt16]0) # Maximum extra paragraphs needed
$IMAGE_DOS_HEADER.Add("e_ss",[UInt16]0) # Initial (relative) SS value
$IMAGE_DOS_HEADER.Add("e_sp",[UInt16]0) # Initial SP value
$IMAGE_DOS_HEADER.Add("e_csum",[UInt16]0) # Checksum
$IMAGE_DOS_HEADER.Add("e_ip",[UInt16]0) # Initial IP value
$IMAGE_DOS_HEADER.Add("e_cs",[UInt16]0) # Initial (relative) CS value
$IMAGE_DOS_HEADER.Add("e_lfarlc",[UInt16]0) # File address of relocation table
$IMAGE_DOS_HEADER.Add("e_ovno",[UInt16]0) # Overlay number
$IMAGE_DOS_HEADER.Add("e_res",(New-Object UInt16[] 4)) # Reserved words
$IMAGE_DOS_HEADER.Add("e_oemid",[UInt16]0) # OEM identifier (for e_oeminfo)
$IMAGE_DOS_HEADER.Add("e_oeminfo",[UInt16]0) # OEM information,[UInt16]0) e_oemid specific
$IMAGE_DOS_HEADER.Add("e_res2[10]",(New-Object UInt16[] 10)) # Reserved words
$IMAGE_DOS_HEADER.Add("e_lfanew",[Uint32]0) # File address of new exe header
$IMAGE_FILE_HEADER = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_FILE_HEADER.Add("Machine",[UInt16]0)
$IMAGE_FILE_HEADER.Add("NumberOfSections",[UInt16]0)
$IMAGE_FILE_HEADER.Add("TimeDateStamp",[UInt32]0)
$IMAGE_FILE_HEADER.Add("PointerToSymbolTable",[UInt32]0)
$IMAGE_FILE_HEADER.Add("NumberOfSymbols",[UInt32]0)
$IMAGE_FILE_HEADER.Add("SizeOfOptionalHeader",[UInt16]0)
$IMAGE_FILE_HEADER.Add("Characteristics",[UInt16]0)
$IMAGE_OPTIONAL_HEADER = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_OPTIONAL_HEADER.Add("Magic",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MajorLinkerVersion",[Byte]0)
$IMAGE_OPTIONAL_HEADER.Add("MinorLinkerVersion",[Byte]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfCode",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfInitializedData",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfUninitializedData",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("AddressOfEntryPoint",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("BaseOfCode",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("BaseOfData",[Uint32]0)
# NT Additional Fields
$IMAGE_OPTIONAL_HEADER.Add("ImageBase",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SectionAlignment",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("FileAlignment",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("MajorOperatingSystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MinorOperatingSystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MajorImageVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MinorImageVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MajorSubsystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("MinorSubsystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("Win32VersionValue",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfImage",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfHeaders",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("CheckSum",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("Subsystem",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("DllCharacteristics",[Uint16]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfStackReserve",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfStackCommit",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfHeapReserve",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("SizeOfHeapCommit",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("LoaderFlags",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("NumberOfRvaAndSizes",[Uint32]0)
$IMAGE_OPTIONAL_HEADER.Add("DataDirectory",(New-Object System.Collections.Specialized.OrderedDictionary[] $IMAGE_NUMBEROF_DIRECTORY_ENTRIES))
For ($i = 0; $i -lt $IMAGE_OPTIONAL_HEADER["DataDirectory"].Count;$i++)
{
$IMAGE_OPTIONAL_HEADER["DataDirectory"][$i] = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_OPTIONAL_HEADER["DataDirectory"][$i].Add("VirtualAddress",[Uint32]0)
$IMAGE_OPTIONAL_HEADER["DataDirectory"][$i].Add("Size",[UINt32]0)
}
$IMAGE_OPTIONAL_HEADER64 = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_OPTIONAL_HEADER64.Add("Magic",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MajorLinkerVersion",[Byte]0)
$IMAGE_OPTIONAL_HEADER64.Add("MinorLinkerVersion",[Byte]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfCode",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfInitializedData",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfUninitializedData",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("AddressOfEntryPoint",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("BaseOfCode",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("ImageBase",[Uint64]0)
$IMAGE_OPTIONAL_HEADER64.Add("SectionAlignment",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("FileAlignment",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("MajorOperatingSystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MinorOperatingSystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MajorImageVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MinorImageVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MajorSubsystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("MinorSubsystemVersion",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("Win32VersionValue",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfImage",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfHeaders",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("CheckSum",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("Subsystem",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("DllCharacteristics",[Uint16]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfStackReserve",[Uint64]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfStackCommit",[Uint64]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfHeapReserve",[Uint64]0)
$IMAGE_OPTIONAL_HEADER64.Add("SizeOfHeapCommit",[Uint64]0)
$IMAGE_OPTIONAL_HEADER64.Add("LoaderFlags",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("NumberOfRvaAndSizes",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64.Add("DataDirectory",(New-Object System.Collections.Specialized.OrderedDictionary[] $IMAGE_NUMBEROF_DIRECTORY_ENTRIES))
For ($i = 0; $i -lt $IMAGE_OPTIONAL_HEADER64["DataDirectory"].Count;$i++)
{
$IMAGE_OPTIONAL_HEADER64["DataDirectory"][$i] = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_OPTIONAL_HEADER64["DataDirectory"][$i].Add("VirtualAddress",[Uint32]0)
$IMAGE_OPTIONAL_HEADER64["DataDirectory"][$i].Add("Size",[UINt32]0)
}
$IMAGE_SECTION_HEADER = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_SECTION_HEADER.Add("Name",(New-Object Byte[] $IMAGE_SIZEOF_SHORT_NAME))
$IMAGE_SECTION_HEADER.Add("Misc.PhysicalAddress",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("Misc.VirtualSize",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("VirtualAddress",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("SizeOfRawData",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("PointerToRawData",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("PointerToRelocations",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("PointerToLinenumbers",[Uint32]0)
$IMAGE_SECTION_HEADER.Add("NumberOfRelocations",[Uint16]0)
$IMAGE_SECTION_HEADER.Add("NumberOfLinenumbers",[Uint16]0)
$IMAGE_SECTION_HEADER.Add("Characteristics",[Uint32]0)
Function Convert-EnumToString
{
param($enum,$value)
$builder = New-Object System.Text.StringBuilder
$names = ($enum.DeclaredFields | Select-Object -Property Name | Where-Object { $_.Name -ne "value__" }).Name
ForEach ($name in $names)
{
if (!($value -ne 0 -and [Enum]::Parse($enum,$name).value__ -eq 0))
{
if ((([Enum]::Parse($enum,$name).value__) -band $value) -eq ([Enum]::Parse($enum,$name).value__))
{
if ($builder.Length -gt 0)
{
[void]$builder.Append(" | ")
}
[void]$builder.Append($name)
}
}
}
return $builder.ToString()
}
Function Read-BinaryFile
{
param(
[System.IO.BinaryReader][ref]$reader,
[System.Collections.Specialized.OrderedDictionary][ref]$items)
$keys = New-Object String[] $items.Count
$items.Keys.CopyTo($keys,0)
for ($i = 0;$i -lt $items.Count;$i++)
{
$item = $keys[$i]
if ($items[$item] -is [Array])
{
if ($items[$item][0] -is [System.Collections.Specialized.OrderedDictionary])
{
ForEach ($subItem in $items[$item])
{
Read-BinaryFile -reader ([ref]$reader) -items ([ref]$subItem)
}
}
else
{
$currentItem = $items[$item][0]
For ($j = 0;$j -lt $items[$item].Length;$j++)
{
switch($currentItem.GetType().Name)
{
"Byte"
{
$items[$item][$j] = $reader.ReadByte()
}
"Uint16"
{
$items[$item][$j] = $Reader.ReadUint16()
}
"Uint32"
{
$items[$item][$j] = $reader.ReadUInt32()
}
"Uint64"
{
$items[$item][$j] = $Reader.ReadUInt64()
}
default { "Unknown Type! $($currentItem.GetType().Name)" }
}
}
}
}
else
{
$currentItem = $items[$item]
if ($currentItem -is [System.Collections.Specialized.OrderedDictionary])
{
Read-BinaryFile -reader ([ref]$reader) -items ([ref]$items[$item])
}
else
{
switch($currentItem.GetType().Name)
{
"Byte"
{
$items[$item] = $reader.ReadByte()
}
"Uint16" {
$items[$item] = $reader.ReadUint16()
}
"Uint32"
{
$items[$item] = $reader.ReadUint32()
}
"Uint64"
{
$items[$item] = $reader.ReadUint64()
}
default { "Unknown Type! $($currentItem.GetType().Name)" }
}
}
}
}
}
[NativeMethods]::SymInitialize()
$apiSetName = [NativeMethods]::CreateUnicodeString($ApiSet)
$apiName = [NativeMethods]::CreateAnsiString($Api)
[IntPtr]$dllHandle = [IntPtr]::Zero
[IntPtr]$procAddress = [IntPtr]::Zero
if ([NativeMethods]::LdrLoadDll("",0,[ref]$apiSetName,[ref]$dllHandle) -eq 0)
{
if ([NativeMethods]::LdrGetProcedureAddress($dllHandle,[ref]$apiName,0,[ref]$procAddress) -eq 0)
{
if ($procAddress -ne [IntPtr]::Zero)
{
$filename = [NativeMethods]::GetModuleFileName($dllHandle)
if ($ShowOffset)
{
$FileStream = [System.IO.File]::Open($filename, [System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::Read)
$BinaryReader = New-Object System.IO.BinaryReader($FileStream)
[void]$BinaryReader.BaseStream.Seek(0,[System.IO.SeekOrigin]::Begin)
Read-BinaryFile -reader ([ref]$BinaryReader) -Items ([ref]$IMAGE_DOS_HEADER)
if ($IMAGE_DOS_HEADER["e_magic"] -eq $IMAGE_DOS_SIGNATURE)
{
[void]$BinaryReader.BaseStream.Seek($IMAGE_DOS_HEADER["e_lfanew"] + 24,[System.IO.SeekOrigin]::Begin)
$magic = $BinaryReader.ReadInt16()
[void]$BinaryReader.BaseStream.Seek($IMAGE_DOS_HEADER["e_lfanew"],[System.IO.SeekOrigin]::Begin)
$IMAGE_NT_HEADER = New-Object System.Collections.Specialized.OrderedDictionary
$IMAGE_NT_HEADER.Add("Signature",[Uint32]0)
$IMAGE_NT_HEADER.Add("FileHeader",$IMAGE_FILE_HEADER)
switch ($magic)
{
$IMAGE_NT_OPTIONAL_HDR32_MAGIC
{
$IMAGE_NT_HEADER.Add("OptionalHeader",$IMAGE_OPTIONAL_HEADER)
}
$IMAGE_NT_OPTIONAL_HDR64_MAGIC
{
$IMAGE_NT_HEADER.Add("OptionalHeader",$IMAGE_OPTIONAL_HEADER64)
}
$IMAGE_ROM_OPTIONAL_HDR_MAGIC { "ROM File, not supported!" }
default { "Unknown PE file type $($magic)!" }
}
Read-BinaryFile -reader ([ref]$BinaryReader) -Items ([ref]$IMAGE_NT_HEADER)
}
else
{
Write-Host "Not a valid PE file!"
}
$dllCharacteristics = Convert-EnumToString -enum ([IMAGE_DLLCHARACTERISTICS]) -value $IMAGE_NT_HEADER["OptionalHeader"]["DllCharacteristics"]
$subSystem = [Enum]::Parse([IMAGE_SUBSYSTEM],$IMAGE_NT_HEADER["OptionalHeader"]["Subsystem"])
$machine = [Enum]::Parse([IMAGE_FILE_MACHINE],$IMAGE_NT_HEADER["FileHeader"]["Machine"])
[UInt64]$originalAddress = ($procAddress.ToInt64() -$dllHandle) + $IMAGE_NT_HEADER.OptionalHeader.ImageBase
"$($filename)!0x{0:X}" -f $originalAddress
}
else
{
$symbolName = [NativeMethods]::GetSymbolName($procAddress)
[Void][NativeMethods]::LdrUnloadDll($dllHandle)
"$($filename)!$symbolName"
}
}
}
}