Detouring Win32 API function calls is a more common practice than some may think. A long standing Microsoft research project has made this very easy in unmanaged code. The Detours project injects a hook in between a process and a Windows library (or any library for that matter). So when the process goes to call a function like StartProcess, the hook will instead be invoked and can execute its own version of the hooked function. This is very powerful and very dangerous. Serious system instability can be caused from using this the wrong way. That said, if you are only hooking the local process you only have to worry about crashing that.
An open source project exists called EasyHook. EasyHook is another implementation of a hooking mechanism like the one used in Detours. The difference with EasyHook is that is has a managed wrapper over the top of the unmanaged hooking code. This makes it consumable by PowerShell. Scary right! EasyHook makes hooking local process a snap. Here’s an example I cooked up in C# to hook GetSystemTimeByFileTime.
The hook redirects to my “Hooked” method and outputs a static time rather than actually looking up the system time. The result of this is the following output.
Whoa! Now the time changes all the way back to 1999. Since DateTime.Now just calls GetSystemTimeAsFileTime under the covers (thanks Reflector), the hooked method changes the behavior of that class as well. So any call to that Win32 API function will result in our 1999 time.
Hooking in PowerShell is a bit trickier. We need to still create a .NET class that we can define a delegate and method on and then call a script block that will execute within the hook. The first step is to collect the necessary information about the function we are hooking. We need the DLL it lives in, the function name and the signature to get this right. I created a New-Detour function that accepts these parameters. Then I load up EasyHook.
Notice that I didn’t include a parameter for the signature. To grab the signature I thought it would be cool if it was generated based on the parameters of the script block defined for the detour. Because we have access to the AST, this makes this much easier. Doing some careful iteration and using the new PSCustomObject class I put together some objects that represented the parameters in the param block of the ScriptBlock.
Next, I started to put together the C# code using the parameters. I have to initialize any out variables with the default value, fill out the delegate and function definition and actually execute the script block in the class. I’ll skip some of the parameter parsing (you can check out the full attached script). The C# class is pretty simple. It has a delegate, a hook and a script block execution.
The outVarSnippet is a bit interesting. Since [ref] variables aren’t reflected outside of the PowerShell engine, setting variables within like we did in the C# class in the first example won’t work. Instead I am returning variables based on position. So the first variable returned from the script block will be set to the first out variable and so forth (I don’t have support for returning anything from the detoured functions yet). This wasn’t ideal, is a bit of a hack and I don’t like it but it was the best thing I could think of to work around this.
Once we have generated the class we can compile it and use EasyHook to inject it into the current project.
Although all this looks kind of complicated, what we are left with is a pretty simple function to hook processes hosting Powershell. Here’s an example of hooking the same function as the C# project.
The result is even cooler.