aboutsummaryrefslogtreecommitdiff
path: root/PETools/Get-LibSymbols.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'PETools/Get-LibSymbols.ps1')
-rw-r--r--PETools/Get-LibSymbols.ps1282
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 {}
-}