Saturday, May 19, 2012

Accessing the Windows API in PowerShell via internal .NET methods and reflection

tl:dr version

It is possible to invoke Windows API function calls via internal .NET native method wrappers in PowerShell without requiring P/Invoke or C# compilation. How is this useful for an attacker? You can call any Windows API function (exported or non-exported) entirely in memory. For those familiar with Metasploit internals, think of this as an analogue to railgun.

This journey started for me upon releasing my PowerShell shellcode execution scripts and noticing that even if I issued C# compiler parameters to compile in memory, csc.exe would still write temporary files to disk. This is unacceptible for any attacker. The venerable Lee Holmes mentioned to me that the only way to achieve true memory-residence in .NET is through the System.Reflection namespace. Reflection is an extremely powerful technique used to generate dynamic code. In .NET, you can achieve fine-tuned control over generated code even to the MSIL bytecode level. Before I get too deep in the weeds, let me tell you a story about rifiling through .NET assemblies.

At one point, I was interested in auditing .NET methods that manipulated data/memory in a possibly unsafe fashion. To find some potential targets in Powershell I enumerated the exported types of every loaded .NET assembly via the following commands:

This search yielded some very interesting methods. The ones that were of the most immediate value to me were those contained within Microsoft.Win32.UnsafeNativeMethods:

Microsoft.Win32.UnsafeNativeMethods is an internal class that cannot be referenced through any direct means. If you try to reference the class, you will get an error stating that its module is not loaded. Microsoft.Win32.UnsafeNativeMethods is implemented within System.dll in the GAC.

Of the methods listed above, GetModuleHandle and GetProcAddress were the most interesting to me since these two methods form the basis for calling any other function in the Windows API. How do you access these methods you ask? I wrote the following PowerShell function to demonstrate:

The function first gets a list of all loaded assemblies in PowerShell. It then gets a reference to System.dll, which contains Microsoft.Win32.UnsafeNativeMethods. I then call the GetMethod method on 'GetModuleHandle' and 'GetProcAddress'. I then invoke GetModuleHandle. Normally, in PowerShell, you would invoke this .NET method like this: 


That syntax would generate an error though because it is not a public class. I then get a reference to the returned handle. This is necessary because the managed version of GetProcAddress requires it. Finally, I call GetProcAddress on the function I'm interested in. As an example, the following command will return the address for VirtualAlloc:

Get-ProcAddress kernel32.dll VirtualAlloc

Now, having the address to VirtualAlloc is great and all, but what can be done with it? Conveniently, the System.Runtime.InteropServices.Marshal class contains a very handy method called GetDelegateForFunctionPointer. For those unfamiliar with delegates, think of them as function pointers. GetDelegateForFunctionPointer takes two parameters: a pointer (what was returned from Get-ProcAddress) and a type (a method signature). In C#, defining a method signature is trivial. You just use the delegate keyword. Therefore if you wanted to create a method signature for VirtualAlloc in C#, you could write something like the following:

IntPtr delegate VirtualAllocSig(IntPtr lpAddress, UInt32 dwSize, UInt32 flAllocationType, UInt32 flProtect);

Unfortunately, PowerShell has no equivalent to the 'delegate' keyword. This is where reflection and a handy article circa 2004 come into play. Using reflection, you can do the equivalent of compiling the C# code snippet above. This process is far from straightforward but can be accomplished via the function below:

So to create the equivalent of the C# code that creates a delegate type, you can issue the following command now:

$VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])

Note that if a function passes a parameter by reference, you can still get a proper delegate type by using the MakeByRefType method:

$ByRefDelegate = Get-DelegateType @([String].MakeByRefType()) ([Void])

Coming back full-circle now, we now have everything GetDelegateForFunctionPointer needs to get a 'managed function pointer' to any Windows API function. So lets say you wanted to allocate some RWX memory. This can now be achieved:

Last but not least, it is worth noting that this method will only execute functions that use the StdCall calling convention. Also, if anyone is familiar with Lee Holmes' awesome Invoke-WindowsApi script, you might have noticed that these techniques offer similar functionality to his script. The main difference is that this technique does not use P/Invoke and because you're calling a function from an address, you not just limited to exported functions. You can call non-exported StdCall functions.

Now, you're limited only by your imagination as to what you can achieve in Powershell and all without touching the disk! For example, soon I'll be modifying PowerSyringe to take advantage of these techniques. Also, expect more features to be added to PowerSyringe in the near future...

Monday, May 14, 2012

Extracting hard-coded credentials using managed code debugging techniques in Windbg

tl;dr version

Using some simple managed code debugging techniques, you can easily pull out hard-coded credentials from a binary claiming to protect them.

A friend of mine (@Obscuresec) referred me to a blog post from a software vendor claiming that if you absolutely have to hard-code credentials into a PowerShell script, that you'd at least be safer by using their product to wrap the script into a binary. If all reverse engineers were monkeys this might be true... and there are a lot of monkeys out there. To their credit, they advise their readers to never hard-code credentials into scripts. However, this monkey, when armed with a debugger will dispute (i.e. throw feces at) the vendor's claim that their product offers an additional layer of security.

Today, I'll be analyzing WMIQueryPS1.exe which can be obtained via the link above. WMIQueryPS1.exe is simply a .NET-compiled binary wrapper for a PowerShell script. The script used in this example passes domain credentials to a remote machine in order to execute a WMI query. The goal of this exercise is to pull out the credentials without decompiling the binary. Here's my step-by-step walk-though of how this was achieved.

1) Fire up the executable in WinDbg.

2) Load the CLR debugging extension for WinDbg - SOS.dll.

SOS.dll is a WinDbg extension used to aid in debugging managed code. More details on SOS.dll can be found here.

3) Let the program run its course and see what happens.

Lol. We have a null-pointer dereference and conveniently, a good place to stop and inspect the CLR environment.

4) First, let's see what method in managed code triggered the exception:

The !IP2MD command will tell you what method a particular JITed address belongs to. In this example, an exception was thrown in the PoshExeHostCmd.VBSPoSH.GetValue method.

5) Now let's see the CLR call stack and get some context as to how we got to where we did:

Considering this binary just wraps an obfuscated PowerShell script, it has to pass the deobfuscated script block as a parameter at some point. PoshExeHostCmd.VBSPoSH.Execute(System.String, System.String[]) looks like a good candidate method worth inspecting. Let's launch the assembly again and set a managed breakpoint on that method

6) In WinDbg, you can only set breakpoints on native code. To break on managed code, you rely upon the !bpmd command. Note: You cannot execute CLR debugger extension commands until mscorwks.dll has been loaded. Therefore, I'll set a conditional breakpoint upon the loading of a module and set a breakpoint for the managed method in a single instruction.

The sx command confirms that my 'conditional' breakpoint was set. Now, let the program run and it will break on the method in question.

7) Here we are. Let's check out the string that was passed to the method as an argument.

8) After poking around a bit, it turns out that the address of the 'command' object (0x0309f09c) is what we want to dump

9) Boom! All your creds are belong to me! I've just dumped the secret credentials that this vendor is claiming to protect. Not a difficult exercise.

I could have used these techniques in conjunction with a tool like .NET Reflector to decompile the method (SimpleDecodeData) that pulls the obfuscated scriptblock from the PE file's resource section and then deobfuscate the Powershell scriptblock but that would just be redundant. That, and the vendor might not appreciate it that much.

So what's the lesson in all this? Do not ever, EVER hard-code credentials into a file! If someone wants them bad enough (me), they will get them.