exe2shellcode/Get-FunctionsHash.ps1

117 lines
4.2 KiB
PowerShell

function Get-FunctionHash
{
<#
.SYNOPSIS
Outputs a module and function hash that can be passed to the
GetProcAddressWithHash function.
PowerSploit Function: Get-FunctionHash
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Get-FunctionHash calculates a hash that can be passed to
GetProcAddressWithHash - a C function that is used to resolve Win32
library functions. Passing a hash to a function address resolver
prevents plaintext strings from being sent in the clear in shellcode.
A python implementation of this algorithm is present in Meatsploit
will perform hash collision detection.
.PARAMETER Module
Specifies the module to be hashed. Be sure to include the file extension.
The module name will be normalized to upper case.
.PARAMETER Function
Specifies the function to be hashed. The function name is case-sensitive.
.PARAMETER RorValue
Specifies the value by which the hashing algorithm rotates right. The
range of possibles values is 1-31.
.EXAMPLE
Get-FunctionHash kernel32.dll LoadLibraryA
.OUTPUTS
System.String
Outputs a hexadecimal representation of the function hash.
.LINK
http://www.exploit-monday.com/
https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/hash.py
#>
[CmdletBinding()] Param (
[Parameter(Position = 0, Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[String]
$Module,
[Parameter(Position = 1, Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[String]
$Function,
[Parameter(Position = 2)]
[ValidateRange(1, 31)]
[String]
$RorValue = 13
)
$MethodInfo = New-Object Reflection.Emit.DynamicMethod('Ror', [UInt32], @([UInt32], [UInt32]))
$ILGen = $MethodInfo.GetILGenerator(8)
# C# equivalent of: return x >> n | x << 32 - n;
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_0)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_1)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldc_I4_S, 31)
$ILGen.Emit([Reflection.Emit.OpCodes]::And)
$ILGen.Emit([Reflection.Emit.OpCodes]::Shr_Un)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_0)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldc_I4_S, 32)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_1)
$ILGen.Emit([Reflection.Emit.OpCodes]::Sub)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldc_I4_S, 31)
$ILGen.Emit([Reflection.Emit.OpCodes]::And)
$ILGen.Emit([Reflection.Emit.OpCodes]::Shl)
$ILGen.Emit([Reflection.Emit.OpCodes]::Or)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ret)
$Delegate = [Func``3[UInt32, UInt32, UInt32]]
$Ror = $MethodInfo.CreateDelegate($Delegate)
$MethodInfo = New-Object Reflection.Emit.DynamicMethod('Add', [UInt32], @([UInt32], [UInt32]))
$ILGen = $MethodInfo.GetILGenerator(2)
# C# equivalent of: return x + y;
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_0)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ldarg_1)
$ILGen.Emit([Reflection.Emit.OpCodes]::Add)
$ILGen.Emit([Reflection.Emit.OpCodes]::Ret)
$Add = $MethodInfo.CreateDelegate($Delegate)
$UnicodeEncoder = [Text.Encoding]::Unicode
$Module = $Module.ToUpper()
[Byte[]] $ModuleBytes = $UnicodeEncoder.GetBytes($Module) + [Byte[]] @(0, 0)
$ModuleHash = [UInt32] 0
# Iterate over each byte of the unicode module string including nulls
for ($i = 0; $i -lt $ModuleBytes.Length; $i++)
{
$ModuleHash = $Ror.Invoke($ModuleHash, 13)
$ModuleHash = $Add.Invoke($ModuleHash, $ModuleBytes[$i])
}
$AsciiEncoder = [Text.Encoding]::ASCII
[Byte[]] $FunctionBytes = $AsciiEncoder.GetBytes($Function) + @([Byte] 0)
$FunctionHash = [UInt32] 0
# Iterate over each byte of the function string including the null terminator
for ($i = 0; $i -lt $FunctionBytes.Length; $i++)
{
$FunctionHash = $Ror.Invoke($FunctionHash, $RorValue)
$FunctionHash = $Add.Invoke($FunctionHash, $FunctionBytes[$i])
}
# Add the function hash to the module hash
$FinalHash = $Add.Invoke($ModuleHash, $FunctionHash)
# Write out the hexadecimal representation of the hash
Write-Output "0x$($FinalHash.ToString('X8'))"
}