rapid7/meterpreter — pull request #71 by OJ (2014-01-24 11:16:08+00:00)
Title: Fix hashdumping from non-privileged process in Vista and Later

[SeeRM #8750]

Hashdumping in Meterpreter is a feature that reads SAM hashes directly from `lsass.exe` that is running as the `SYSTEM` user. In order to do this, Meterpreter must also be running as `SYSTEM` otherwise it will fail. Assuming that it is, Meterpreter then does the following:

* Gets hold of the `lsass` process using `OpenProcess`.
* Sets up a few function pointers and various other state in a single structure, and copies/injects into `lsass` using the usual techniques (`VirtualAllocEx`, `WriteProcessMemory`).
* Figures out where the `dump_sam` function is in memory (and its size) and copies/injects it into `lsass` using the same method.
* Creates a new thread in `lsass` which kicks off `dump_sam`.
* Waits on a couple of event handles to deal with synchronisation and reads the results if and when the come in.

This has worked nicely in the following scenarios:

* On any version of Windows up to and including Windows XP in any process with `SYSTEM` privleges.
* On any version of Windows from Vista onwards, but only processes that were started as the system user.

The latter of those two scenarios is the reason for this PR. Windows Vista onwards had changes made to the implementation of the `CreateRemoteThread` function which locked it down a bit security-wise. Processes are not able to create threads in other processes that are not in the same session using this function.

Given that this was the function that was being used by Meterpreter, we were unable to create the remote threads, and hence hashdumping didn't work.

It's worth noting that the migration functionality also attempts to use `CreateRemoteThread`, but falls back to APC injection, which is why that works on newer versions of Windows. The fix made in this PR could well be applied to `migrate` (something I'll look into soon).

To fix this problem, the use of the undocumented function `RtlCreateUserThread` was employed, which does the job nicely on the newer versions of Windows. However, since this function does not exist on the early versions of Windows, we have to cater for both scenarios.

The approach taken here is:

1. Attempt to use `CreateRemoteThread` first. This means that all the existing scenarios that work will function exactly the same as they did before.
1. If the call fails because of the cross-session problem, the result that comes out of `GetLastError` is `ERROR_NOT_ENOUGH_MEMORY`. If this is the case, we attempt to locate the `RtlCreateUserThread` function, and if found, we call that instead.

This fallback is a good option as it means that we don't break existing stuff.

There was one other issue that came about when doing cross-session interaction, and that was the use of Event objects in Windows. For named Event objects to be available across session boundaries, the Events themselves need to have names that are prefixed with `Global\`. Two events called `SAM` and `FREE` are used by this code, and so both of those had to be updated to `Global\SAM` and `Global\FREE` for them to work. Without this, the process would hang, waiting for signals that weren't ever going to arrive. This also meant that the function arguments object had to be updated to make room for the extra characters in both those cases.

## Sample Run

### Details of the session
```
meterpreter > sysinfo
Computer : WIN-KM66F94HDLL
OS : Windows 7 (Build 7600).
Architecture : x86
System Language : en_US
Meterpreter : x86/win32
```
### Before
```
meterpreter > getuid
Server username: WIN-KM66F94HDLL\OJ
meterpreter > getsystem
...got system (via technique 1).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > hashdump
[-] priv_passwd_get_sam_hashes: Operation failed: The parameter is incorrect.
```
### After
```
meterpreter > getuid
Server username: WIN-KM66F94HDLL\OJ
meterpreter > getsystem
...got system (via technique 1).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > hashdump
Administrator:500:aad3b435b51404eeaad3b435b51404ee:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:::
OJ:1000:aad3b435b51404eeaad3b435b51404ee:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:::
```

## My testing

I tested my fix on:

* Windows 2000 x86
* Windows XP x86
* Windows Vista x86
* Windows 7 x86, x64
* Windows 8 x64
* Windows 2012 x64

## Verification

Don't trust my testing. Please check out:

- [ ] Windows 2000
- [ ] Windows XP
- [ ] Windows Vista
- [ ] Windows 2003
- [ ] Windows 7
- [ ] Windows 2008
- [ ] Windows 8
- [ ] Windows 8.1
- [ ] Windows 2012

With varying 64/32 bit flavours

## Obligatory Gif

Meterpreter is now much more like this:

![Thief!](http://i.imgur.com/8OZCNtX.gif)