diff options
Diffstat (limited to 'PETools/Get-LibSymbols.ps1')
-rw-r--r-- | PETools/Get-LibSymbols.ps1 | 282 |
1 files changed, 0 insertions, 282 deletions
diff --git a/PETools/Get-LibSymbols.ps1 b/PETools/Get-LibSymbols.ps1 deleted file mode 100644 index 9864676..0000000 --- a/PETools/Get-LibSymbols.ps1 +++ /dev/null @@ -1,282 +0,0 @@ -function Get-LibSymbols -{ -<# -.SYNOPSIS - - Displays symbolic information from Windows lib files. - - PowerSploit Function: Get-LibSymbols - Author: Matthew Graeber (@mattifestation) - License: BSD 3-Clause - Required Dependencies: None - Optional Dependencies: None - -.DESCRIPTION - - Get-LibSymbols parses and returns symbols in Windows .lib files - in both decorated and undecorated form (for C++ functions). - -.PARAMETER Path - - Specifies a path to one or more lib file locations. - -.EXAMPLE - - C:\PS>Get-LibSymbols -Path msvcrt.lib - -.EXAMPLE - - C:\PS>ls *.lib | Get-LibSymbols - -.INPUTS - - System.String[] - - You can pipe a file system path (in quotation marks) to Get-LibSymbols. - -.OUTPUTS - - COFF.SymbolInfo - -.LINK - - http://www.exploit-monday.com/ -#> - [CmdletBinding()] Param ( - [Parameter(Position = 0, Mandatory = $True, ValueFromPipelineByPropertyName = $True)] - [ValidateScript({ Test-Path $_ })] - [Alias('FullName')] - [String[]] - $Path - ) - - BEGIN - { - $Code = @' - using System; - using System.IO; - using System.Text; - using System.Runtime.InteropServices; - - namespace COFF - { - public class HEADER - { - public ushort Machine; - public ushort NumberOfSections; - public DateTime TimeDateStamp; - public uint PointerToSymbolTable; - public uint NumberOfSymbols; - public ushort SizeOfOptionalHeader; - public ushort Characteristics; - - public HEADER(BinaryReader br) - { - this.Machine = br.ReadUInt16(); - this.NumberOfSections = br.ReadUInt16(); - this.TimeDateStamp = (new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(br.ReadUInt32()); - this.PointerToSymbolTable = br.ReadUInt32(); - this.NumberOfSymbols = br.ReadUInt32(); - this.SizeOfOptionalHeader = br.ReadUInt16(); - this.Characteristics = br.ReadUInt16(); - } - } - - public class IMAGE_ARCHIVE_MEMBER_HEADER - { - public string Name; - public DateTime Date; - public ulong Size; - public string EndHeader; - - public IMAGE_ARCHIVE_MEMBER_HEADER(BinaryReader br) - { - string tempName = Encoding.UTF8.GetString(br.ReadBytes(16)); - DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0); - this.Name = tempName.Substring(0, tempName.IndexOf((Char) 47)); - this.Date = dt.AddSeconds(Convert.ToDouble(Encoding.UTF8.GetString(br.ReadBytes(12)).Split((Char) 20)[0])); - br.ReadBytes(20); // Skip over UserID, GroupID, and Mode. They are useless fields. - this.Size = Convert.ToUInt64(Encoding.UTF8.GetString(br.ReadBytes(10)).Split((Char) 20)[0]); - this.EndHeader = Encoding.UTF8.GetString(br.ReadBytes(2)); - } - } - - public class Functions - { - [DllImport("dbghelp.dll", SetLastError=true, PreserveSig=true)] - public static extern int UnDecorateSymbolName( - [In] [MarshalAs(UnmanagedType.LPStr)] string DecoratedName, - [Out] StringBuilder UnDecoratedName, - [In] [MarshalAs(UnmanagedType.U4)] uint UndecoratedLength, - [In] [MarshalAs(UnmanagedType.U4)] uint Flags); - } - } -'@ - - Add-Type -TypeDefinition $Code - - function Dispose-Objects - { - $BinaryReader.Close() - $FileStream.Dispose() - } - } - - PROCESS - { - foreach ($File in $Path) - { - # Resolve the absolute path of the lib file. [IO.File]::OpenRead requires an absolute path. - $LibFilePath = Resolve-Path $File - - # Pull out just the file name - $LibFileName = Split-Path $LibFilePath -Leaf - - $IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR = 60 - $IMAGE_ARCHIVE_START = "!<arch>`n" # Magic used for lib files - $IMAGE_SIZEOF_LIB_HDR = $IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR + $IMAGE_ARCHIVE_START.Length - $IMAGE_ARCHIVE_END = "```n" # Footer of an archive header - $SizeofCOFFFileHeader = 20 - - # Open the object file for reading - $FileStream = [IO.File]::OpenRead($LibFilePath) - - $FileLength = $FileStream.Length - - # Validate lib header size - if ($FileLength -lt $IMAGE_SIZEOF_LIB_HDR) - { - # You cannot parse the lib header if the file is not big enough to contain a lib header. - Write-Error "$($LibFileName) is too small to store a lib header." - $FileStream.Dispose() - return - } - - # Open a BinaryReader object for the lib file - $BinaryReader = New-Object IO.BinaryReader($FileStream) - - $ArchiveStart = [Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes(8)) - - if ($ArchiveStart -ne $IMAGE_ARCHIVE_START) - { - Write-Error "$($LibFileName) does not contain a valid lib header." - Dispose-Objects - return - } - - # Parse the first archive header - $ArchiveHeader = New-Object COFF.IMAGE_ARCHIVE_MEMBER_HEADER($BinaryReader) - - if ($ArchiveHeader.EndHeader -ne $IMAGE_ARCHIVE_END) - { - Write-Error "$($LibFileName) does not contain a valid lib header." - Dispose-Objects - return - } - - # Check for the existence of symbols - if ($ArchiveHeader.Size -eq 0) - { - Write-Warning "$($LibFileName) contains no symbols." - Dispose-Objects - return - } - - $NumberOfSymbols = $BinaryReader.ReadBytes(4) - - # The offsets in the first archive header of a Microsoft lib file are stored in big-endian format - if ([BitConverter]::IsLittleEndian) - { - [Array]::Reverse($NumberOfSymbols) - } - - $NumberOfSymbols = [BitConverter]::ToUInt32($NumberOfSymbols, 0) - - $SymbolOffsets = New-Object UInt32[]($NumberOfSymbols) - - foreach ($Offset in 0..($SymbolOffsets.Length - 1)) - { - $SymbolOffset = $BinaryReader.ReadBytes(4) - - if ([BitConverter]::IsLittleEndian) - { - [Array]::Reverse($SymbolOffset) - } - - $SymbolOffsets[$Offset] = [BitConverter]::ToUInt32($SymbolOffset, 0) - } - - $SymbolStringLength = $ArchiveHeader.Size + $IMAGE_SIZEOF_LIB_HDR - $FileStream.Position - 1 - # $SymbolStrings = [Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes($SymbolStringLength)).Split([Char] 0) - - # Write-Output $SymbolStrings - - # There will be many duplicate offset entries. Remove them. - $SymbolOffsetsSorted = $SymbolOffsets | Sort-Object -Unique - - $SymbolOffsetsSorted | ForEach-Object { - # Seek to the each repective offset in the file - $FileStream.Seek($_, 'Begin') | Out-Null - - $ArchiveHeader = New-Object COFF.IMAGE_ARCHIVE_MEMBER_HEADER($BinaryReader) - - # This is not a true COFF header. It's the same size and mostly resembles a standard COFF header - # but Microsoft placed a marker (0xFFFF) in the first WORD to indicate that the 'object file' - # consists solely of the module name and symbol. - $CoffHeader = New-Object COFF.HEADER($BinaryReader) - - # Check for 0xFFFF flag value - if ($CoffHeader.NumberOfSections -eq [UInt16]::MaxValue) - { - # Get the total length of the module and symbol name - $SymbolStringLength = $CoffHeader.NumberOfSymbols - $Symbols = [Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes($SymbolStringLength)).Split([Char] 0) - - $DecoratedSymbol = $Symbols[0] - $UndecoratedSymbol = '' - - # Default to a 'C' type symbol unless it starts with a '?' - $SymbolType = 'C' - - # Is the symbol a C++ type? - if ($DecoratedSymbol.StartsWith('?')) - { - $StrBuilder = New-Object Text.Stringbuilder(512) - # Magically undecorated the convoluted C++ symbol into a proper C++ function definition - [COFF.Functions]::UnDecorateSymbolName($DecoratedSymbol, $StrBuilder, $StrBuilder.Capacity, 0) | Out-Null - $UndecoratedSymbol = $StrBuilder.ToString() - $SymbolType = 'C++' - } - else - { - if ($DecoratedSymbol[0] -eq '_' -or $DecoratedSymbol[0] -eq '@') - { - $UndecoratedSymbol = $DecoratedSymbol.Substring(1).Split('@')[0] - } - else - { - $UndecoratedSymbol = $DecoratedSymbol.Split('@')[0] - } - } - - $SymInfo = @{ - DecoratedName = $DecoratedSymbol - UndecoratedName = $UndecoratedSymbol - Module = $Symbols[1] - SymbolType = $SymbolType - } - - $ParsedSymbol = New-Object PSObject -Property $SymInfo - $ParsedSymbol.PSObject.TypeNames[0] = 'COFF.SymbolInfo' - - Write-Output $ParsedSymbol - } - } - - # Close file and binaryreader objects - Dispose-Objects - } - } - - END {} -} |