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.

Monday, April 23, 2012

Architecture Independent Windows Shellcode

What's this? A non PowerShell-related blog post??? Unheard of! Today's post is more of a novelty but perhaps someone might benefit from it.

There may be times when you’d like to execute shellcode but don’t know the architecture of the processor that you’ll be running on. I’ve seen at least two techniques to solve this problem [1] [2]. Well, here’s yet another technique that is specific to Windows. The following shellcode will detect whether it’s running in pure 32-bit, pure 64-bit, or Wow64 mode:
On 64-bit processors in Windows, the GS segment register stores the pointer to the PEB (Process Environment Block) in GS:[0x60]. In Wow64 mode this is a DWORD value. In 32-bit mode, the GS segment register is not used and uses FS:[0x30] to point to the PEB.

1. Berend-Jan "SkyLined" Wever, w32-exec-calc-shellcode, http://code.google.com/p/w32-exec-calc-shellcode/

2. “isX64 Gem”, July 31, 2011, http://www.ragestorm.net/blogs/?p=376

Sunday, April 22, 2012

64-bit Process Replacement in Powershell

Download here: Replace-x64-Process.ps1

For those of you who follow me on Twitter, you may have noticed that I posted a few teasers related to replacing processes in Powershell. Without further ado, I am releasing Replace-x64-Process. This tool is intended solely as a proof-of-concept tool. I say that because I make absolutely no guarantees that it will work in all cases. In fact, it won't work in many cases.

The intent of this tool is to circumvent application whitelisting products. Assuming Powershell is whitelisted, you can use this tool to load a blacklisted executable within a whitelisted process. I have not tested this tool on any whitelisting products, however so I cannot attest to its level of effectiveness.

Replace-x64-Process makes use of some common techniques seen in malware to replace a suspended process' executable image. Fortunately, Powershell gives us access to many of the mechanisms required to achieve this goal.

Basic steps required to replace a process in memory:

1) Load the host process in a suspended state.
2) Open a handle to the main thread of the executable
3) Get the context of the suspended thread. In 64-bit the entry point to the process is located in RCX. A pointer to the PEB (Process Environment Block) is located in RDX.
4) Call ZwUnmapViewOfSection to unmap the image of the host process
5) Parse the section headers of the target process
6) Find the image base of the target process
7) Allocate space to contain the image of the target process
8) Map the PE header and each section of the executable to the newly allocated memory.
9) Update the PEB to reflect the new image base address
10) Call SetThreadContext to redirect execution to the target process
11) Resume the process

Here is an example of the script in action:

Replacing Internet Explorer with cmd.exe
Replacing notepad.exe with a 64-bit bind shell
In the last example, it is worth noting that the Microsoft code signature is not invalidated after loading the malicious process. This is due to the fact that code signatures are validated  prior to the main thread loading. This is an unintended but awesome side effect of this process.

Lastly, I have a 32-bit version of this script. It is however even more flaky than the 64-bit version. I suspect it's due to the fact that I don't account for relocations. Because instructions in 64-bit are RIP-relative, relocations are no longer necessary. I may release a more polished script for both 32 and 64-bit in the future once I become more familiar with the loading process.

Replace-x64-Process Help File


Enjoy and try not to get too frustrated when the tool doesn't work for you. Also, if you use the -verbose option, you'll find that much of the code in this script demonstrates the beginnings of a full-fledged PE parser. Perhaps more on that in a future posting... If you have any suggestions on how to increase the reliability of this tool, please leave a comment.

Sunday, March 11, 2012

Powershell Live-Memory Analysis Tools: Dump-Memory, Dump-Strings, Check-MemoryProtection

 I’m releasing three new tools for Powershell that may be of use for those performing live-memory forensics or for penetration testers trying to pull sensitive information from memory. Dump-Memory will simply dump the contents of memory to stdout or to a raw binary file on disk. Dump-Strings is like Sysinternals Strings but it operates on memory. It will dump the strings of any readable portion of memory in both Ascii and Unicode format. Lastly, Check-MemoryProtection is more of a helper function that will return the memory page protections of any address. All of these scripts operate entirely within memory unless you explicitly choose to write to disk.

Note: For Dump-Memory and Dump-Strings to work, the Check-MemoryProtection function must be defined. It is used to ensure that an access violation doesn’t occur if you try to access an inaccessible portion of memory.

Download here: Memory-Tools.ps1

I’m always open to feature requests. Just leave a comment if there is a feature you want implemented and I will try to make that happen. For example, one feature I might consider adding is a ‘-Force’ switch that would forcibly change the protections on the requested range of memory. Currently, these tools use only the minimum level of privilege needed to query the memory of a remote process.

Here are the help files for each tool:

Dump-Memory


Dump-Strings


Check-MemoryProtection

Monday, November 21, 2011

PowerSyringe - PowerShell-based Code/DLL Injection Utility

Download Link: PowerSyringe.ps1

So I decided to expand upon my previous post and create a slightly more full-featured Powershell-based code/DLL injection utility. Behold, PowerSyringe. As the name implies, I based some of the code on the original Syringe toolkit. I added several features though - specifically, 64-bit support and encryption. Here is a rundown of its features:

  • Shellcode injection from within Powershell
  • Shellcode injection into any 32 or 64-bit process
  • DLL injection into any 32 or 64-bit process
  • Encryption - The script can encrypt itself and outputs the encrypted version to .\evil.ps1. This will make analysis of the script impossible/improbable without the correct password and salt (or if they happen to perform live memory forensics). >D
  • Decryption - evil.ps1 will decrypt itself back into its original form if you provide the right password and salt
  • Doesn't flag DEP b/c it doesn't execute in the stack
  • Fairly detailed documentation

I’ve tested the tool on several 32 and 64-bit platforms but I would love to get some feedback/feature requests. To execute the script, ensure that your execution policy allows you to execute scripts. If not, no worries. You can simply copy and paste the all of the code into a PowerShell prompt. Then you can run ‘help PowerSyringe -full’ for detailed documentation. There are several other methods for bypassing the execution policy. One of those methods is detailed here.


Here is an excerpt of the documentation with usage examples:

DLL Injection
C:\PS>PowerSyringe 1 4274 .\evil.dll

Description
Inject 'evil.dll' into process ID 4274.


Inject shellcode into process
C:\PS>PowerSyringe 2 4274

Description
Inject the shellcode as defined in the script into process ID 4274


Execute shellcode within the context of PowerShell
C:\PS>PowerSyringe 3

Description
Execute the shellcode as defined in the script within the context of Powershell.


Encrypt the script with the password:'password' and salt:'salty'
C:\PS>PowerSyringe 4 .\PowerSyringe.ps1 password salty

Description
Encrypt the contents of this file with a password and salt. This will make analysis of the script impossible without the correct password and salt combination. This command will generate evil.ps1 that can dropped onto the victim machine. It only consists of a decryption function 'de' and the base64-encoded ciphertext.

Note: This command can be used to encrypt any text-based file/script


Decrypt encrypted script and execute it in memory
C:\PS>[String] $cmd = Get-Content .\evil.ps1
C:\PS>Invoke-Expression $cmd
C:\PS>$decrypted = de password salt
C:\PS>Invoke-Expression $decrypted

Description
After you run the encryption option and generate evil.ps1 these commands will decrypt and execute
(i.e. define the function) PowerSyringe entirely in memory assuming you provided the proper password and salt combination.

Upon successful completion of these commands, you can execute PowerSyringe as normal.

Note: "Invoke-Expression $decrypted" may generate an error. Just ignore it. PowerSyringe will
still work.


This is what evil.ps1 will look like after the encryption function is called:
As you can see, the decryption script is slightly 'obfuscated' if you even want to call it that. It's pretty obvious that it decrypts the $a variable. Unfortunately, anyone performing analysis on this evil script will have no idea what the contents of $a are without the correct password and salt.

The primary reason I wrote this was because I had been using Syringe on assessments to bypass host-based IPS systems but I didn't like some of the limitations of Syringe (specifically, no 64-bit support) and I like the idea of performing everything in memory without needing to drop any executables. That being said, I welcome your constructive feedback.

Enjoy!

Monday, November 14, 2011

Man vs. ROP - Overcoming Adversity One Gadget at a Time

Introduction

I recently discovered a rather simple stack-based buffer overflow in a legacy application that shall remain unnamed. With DEP disabled, exploiting the vulnerability was trivial. It’s no longer 1999, however. If you want to write any exploit these days you have to at least be proficient in return-oriented programming techniques to bypass data execution prevention. This article will detail some of the nonorthodox techniques that were required to get code execution for this particular vulnerability.

Prerequisites

Before reading this, you should be rather comfortable with return-oriented programming techniques. I highly recommend checking out the following presentations/articles before diving in to the techniques I’ll describe:

Stephen Sims - "SANS Security 660 Series: Return-Oriented Programming and Exploitation"

Dino Dai Zovi (@dinodaizovi) - "Practical Return-Oriented Programming"

Peter Van Eeckhoutte (@corelanc0d3r) - "Exploit writing tutorial part 10 : Chaining DEP with ROP – the Rubik’s[TM] Cube"

Also, if you enjoy Peter’s article, please be sure to donate to his fight against plagiarism in the infosec community.

Vulnerability Synopsis

The application was vulnerable to a simple stack buffer overflow when it read in a particular value from a config file. An excessively long value overwrote the stack cookie, saved frame pointer, return address, SE handler, and a virtual function pointer on the stack. Because the app was compiled with the /GS flag, overwriting the saved EIP wasn't going to cut it since the stack cookie would have been validated and the process terminate upon detecting the clobbered cookie value. No problem. Fortunately, the SE handler was overwritten and the app crashed upon calling the virtual function pointer - both valid avenues to exploitation. It seemed all too simple until I started trying to find valid ROP gadgets. This is where the fun/frustration began.

Here are some additional details worth noting:
  • All but three modules (the executable and two DLLs) were compiled with ASLR. However, only one of the DLLs could be used for building a ROP chain since the other DLL contained a bad character, thus truly limiting the amount of potential ROP gadgets.
  • The following were bad characters: '\x00\x0a\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x28\x29\x2a'
  • The stack was always mapped to the same base address – 0x0017xxxx
  • Let’s just say that the virtual function pointer was overwritten at offset 1400 and the SE handler pointer was overwritten at offset 1700
Exploitation

As stated before, I had two angles of attack at my disposal – SEH overwrite and a call to a virtual function pointer. I chose to explore the SEH route first.

When writing a ROP exploit for an SEH overwrite, you need specific gadgets to perform the stack pivot (i.e. get ESP to point to your shellcode). The traditional gadgets that would perform this task are as follows:
  • XCHG reg, ESP; RETN 
  • MOV  reg, ESP; RETN 
  • CALL reg
  • POP  reg; JMP reg
  • ADD  ESP, offset; RETN
Unfortunately, upon passing control to the SE handler, there were no registers under my control nor were there any registers that pointed to my buffer. The only option left for me was MOV reg, ESP; RETN. The ROP compiler I used found no such gadget, however aside from a lone ADD ESP, 0x0C; RETN which just wasn’t going to cut it since my buffer was approximately 0x800 bytes away from ESP. Originally, I thought that the ADD ESP, 0x0C; RETN gadget might work because it would essentially “walk” down the stack returning to invalid memory addresses along the way until it hit the beginning of my buffer. Then, upon attempting to return to an invalid memory address the SE handler that I overwrote would then kick in and return to itself, continuing to walk the stack. I was naive however and it didn’t work that way. The unhandled exception handler kicked in and I got nowhere.

I tried to get creative with gadgets. For example, I thought that I might be able to find a ROP variation to the classic pop-pop-ret instruction sequence:

POP reg
POP reg
POP ESP  <-- this would point to the beginning of my ROP chain
RETN

Alas, I found no such gadget. So I decided to shift my attention to the call to the virtual function pointer – CALL DWORD PTR [EAX+A0].

At the time of the crash, I had full control over EAX. Also, ESI and EDI contained pointers to my buffer in the stack. [EAX+A0] is a pointer to a function pointer, however so you would need to find an interesting pointer to a pointer within the DLL that I was targeting. I found no address in the DLL. I needed a pointer to a pointer that I could control. Solution: the buffer that I controlled on the stack. The problem was that the stack was mapped to 0x0017xxxx which contains a null – one of the bad characters. I mentioned that the function pointer was overwritten at offset 1400. So the solution to getting EAX to point to the stack was a partial EAX overwrite.

After running the process in WinDbg and tracing calls to CALL [EAX+A0], I observed that all calls were being made from the stack – 0x0017xxxx. Due to the little-endian nature of the Intel architecture, that means that overwriting EAX with just three bytes would allow EAX to point to any address with a null high-order byte – i.e. 0x00414141.

Upon crashing, I noticed that my buffer reliably resided within a range of approximately 0x40 bytes. So at this point, I was dealing with the following:
  • Ability to point EAX to the stack using a partial EAX overwrite
  • A buffer that shifted slightly at each crash but only within a range of about 0x40 bytes.
So now I potentially had a range of addresses that I could “spray” with pointers to a stack pivot gadget. Since the sprayed addresses reside in the stack, I guess you could call this method stack-spraying ;D. I found a few XCHG EAX, ESP; RETN gadgets and got them to execute reliably but there was a problem, however. Executing a stack pivot twice “unpivots” the stack and you’re back to where you were when you started. After many hours of banging my head on the desk I realized that I could use a series of alternating gadgets to only execute the stack pivot once then jump to a series of ROP-NOPs that jumped over the remaining stack pivot gadgets. I tried my best to illustrate this concept in the following diagram:

Fortunately, upon executing CALL [EAX+A0], the program reliably landed on one of the stack pivot gadgets – Gadget1. Gadget 1 then returned to Gadget 2. The purpose of Gadget 2 is to walk the stack while jumping over Gadget 1. I then added a few ROP-NOPs - &RETN followed by the primary ROP chain, which eventually called VirtualProtect(). Utilizing these techniques ultimately resulted in an extremely reliable exploit.

Conclusion

Just because the solution isn’t staring you in the face doesn’t mean it’s not there. Finding specific ROP gadgets can be like trying to find a needle in the haystack. With enough patience, persistence, and a good ROP compiler at your disposal, you’ll be well on your way to popping shells in the modern world.

Future Work

I would really like to get the ADD ESP, 0x0C; RETN gadget to work. I thought it might work if I overwrote the pointer to the next SEH handler with 0xFFFFFFFF, marking my crafted handler as the last in the chain and thus the handler of last resort. This wasn’t the case though. If anyone has successfully used this method to walk the stack down the attacker-controlled buffer I would love to hear how you accomplished it.

Tuesday, October 18, 2011

Exploiting Powershell's Features (Not Flaws)

tl;dr version

Using the features built in to Microsoft Powershell one can execute arbitrary shellcode. The method described in this post is both 32 and 64 bit compatible. Because we are exploiting the features of the .NET framework, ASLR and DEP doesn't even come into play here. Just copy and paste your shellcode and you're good to go.

lengthy, pedantic version

Those us that use Powershell know just how powerful it can be in automating administrative tasks. However, with great power comes great responsibility and the Powershell developers certainly assumed that it would be used responsibly. Unfortunately, (get ready for another clichéd expression/pun) absolute power corrupts absolutely. ;D I'll show you how you can use Powershell's integrated features to execute arbitrary shellcode.

Powershell's true power comes in the form of access to the .NET framework. One of the greatest features of Powershell, IMHO is the ability to add custom classes to the .NET framework. This can be accomplished using the Add-Type cmdlet. The great thing about Add-Type is that it will compile CSharp code on the fly for you. Why is this so great? It allows you to import functions from any DLL. The Add-Type documentation provides some pretty good examples on how to create your own classes using CSharp source code.

It's pretty easy to import a function from a DLL. You just have to alter the C-style function prototype a bit to a CSharp-style prototype. Since we'll be importing the VirtualAlloc function later, I'll use it as an example.

Here's what the VirtualAlloc C-style prototype would look like:

LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);

Here's what it would look like in CSharp:

IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

Finally, here's how you would be able to reference VirtualAlloc in Powershell:
The .NET framework doesn't deal too well with directly referencing memory. For security reasons, this is a good thing. However, since you can import functions that deal with unmanaged memory, we should in theory have all the tools necessary to allocate executable memory, copy shellcode to it, and then execute it as a thread. So without further ado, let's do just that in Powershell. The following code will execute any arbitrary 32 or 64 bit payload within Powershell. All you have to do is copy and paste the relevant 32 and 64 bit payloads and the code will determine on the fly if it is running in a 32 vs. 64 bit context. And because it's copy and paste, it should be popular with the skiddies. ;D
As you can see in the Powershell script, I'm doing a few things:

1) Importing the VirtualAlloc, CreateThread, and memset methods and adding them to my 'winFunc' class
2) Inserting both the 32 and 64 bit payloads as byte arrays
3) Determining whether PS is running as 32 vs. 64 bit by using the [IntPtr]::Size property
4) Allocating enough memory to accommodate the shellcode
5) Copying the shellcode to the executable region of memory
6) Executing the shellcode in its own thread

Here are some pretty pictures:

Popping a calc on 32-bit Powershell


Popping a calc on 64-bit Powershell

Now if you wanted to be even more stealthy in executing this attack, you could base64 encode the entire payload and execute it using the '-encodedCommand' option in PS. You could take this one step further and execute the encoded payload within a batch file thus bypassing the Powershell execution policy. I'll spare you details on how to accomplish this since this method is already well documented.

Lastly, I am by no means a CSharp developer or even a developer for that matter so you can certainly spare me any criticisms of my poor coding practices. The bottom line is, it works and it works extremely reliably and that's all I care about. Also, there's absolutely more than one way to accomplish this. I would love to hear suggestions on alternate ways to execute shellcode from within Powershell. And please feel free to leave comments and questions below. Enjoy!