Skip to content

Instantly share code, notes, and snippets.

@adamdriscoll
Created July 28, 2016 17:45
Show Gist options
  • Save adamdriscoll/40124e4283a68559882ca5cc5b1a8d40 to your computer and use it in GitHub Desktop.
Save adamdriscoll/40124e4283a68559882ca5cc5b1a8d40 to your computer and use it in GitHub Desktop.
Example of how to use EasyHook with powershell to override GetSystemTimeAsFileTime
function New-Detour
{
param(
$Library,
$FunctionName,
[ScriptBlock]$Detour,
[String[]]$ReferencedAssemblies
)
#Download from easyhook.codeplex.com
$EasyHook = Join-Path $PSScriptRoot 'EasyHook.dll'
[Reflection.Assembly]::LoadFile($EasyHook)
$ReferencedAssemblies += $EasyHook
$psParameters = @()
foreach($parameter in $Detour.Ast.ParamBlock.Parameters)
{
$psParameter = [PSCustomObject]@{Name=$parameter.Name.ToString().Replace("$", "");TypeName="";IsOut=$false}
foreach($attribute in $parameter.Attributes)
{
if ($attribute.TypeName.Name -eq "ref")
{
$psParameter.IsOut = $true
}
else
{
$psParameter.TypeName = $attribute.TypeName.FullName
}
}
$psParameters += $psParameter
}
$parameters = ""
$outParameters = @()
$psParameters | % {
$parameters = ""
if ($_.IsOut)
{
$parameters += "out "
$outParameters += $_
}
$parameters += "$($_.TypeName) $($_.Name),"
$parameterNames += "$($_.Name),"
}
$parameters = $parameters.Substring(0, $parameters.Length - 1)
$parameterNames = $parameterNames.Substring(0, $parameterNames.Length - 1)
$initializeSnippet = ""
$outVarSnippet = ""
$i = 0
foreach($outParam in $outParameters)
{
$initializeSnippet += "$($outParam.Name) = default($($outParam.TypeName));`n"
$outVarSnippet += "$($outParam.Name) = ($($outParam.TypeName))outVars[$i].ImmediateBaseObject;`n"
$i++
}
$random = Get-Random
$Class = "
namespace Detoured
{
using System.Runtime.InteropServices;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using EasyHook;
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true)]
public delegate void $($FunctionName)_Delegate$random($parameters);
public class Detour$random : IEntryPoint {
private static ScriptBlock _sb;
private static Runspace _rp;
public Detour$random(ScriptBlock sb, Runspace rp)
{
_sb = sb;
_rp = rp;
}
public static void $($FunctionName)_Hooked($parameters)
{
$initializeSnippet
try
{
Runspace.DefaultRunspace = _rp;
var outVars = _sb.Invoke($parameterNames);
$outVarSnippet
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
}
"
$TempFile = [IO.Path]::GetTempPath()
$TempFile = Join-Path $TempFile "Detoured$random.dll"
Add-Type -TypeDefinition $Class -ReferencedAssemblies $ReferencedAssemblies -OutputAssembly $TempFile
Add-Type -Path $TempFile
$DetourObject = New-Object -TypeName "Detoured.Detour$random" -ArgumentList $Detour,([System.Management.Automation.Runspaces.Runspace]::DefaultRunspace)
$Delegate = $DetourObject.GetType().GetMember("$($FunctionName)_Hooked").CreateDelegate([Type]"Detoured.$($FunctionName)_Delegate$random")
$CreateFileHook = [EasyHook.LocalHook]::Create([EasyHook.LocalHook]::GetProcAddress($library, $FunctionName), $delegate, $DetourObject);
$CreateFileHook.ThreadACL.SetExclusiveACL(@())
$CreateFileHook
}
$Detour = New-Detour -Library "Kernel32.dll" -FunctionName GetSystemTimeAsFileTime -Detour { param([ref][System.Int64]$time)
125911583990000000
}
Get-Date
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment