Follow Up on SYSTEM to Domain Admin Post

I learned a few new things and made a few updates to my script after the last post that I thought I would share. First things first, someone commented on the article on another site and mentioned that the Metasploit module auxiliary/scanner/smb/smb_enumusers_domain provides the same functionality over SMB by calling the Windows NetWkstaUserEnum function.

Example for how to use the module:

  use auxiliary/scanner/smb/smb_enumusers_domain
  set RHOSTS
  set SMBUser <user>
  set SMBPass <password OR hash>

If you have obtained access via Metasploit this is better than the WMI module I wrote for several reasons:

  1. You can pass-the-hash
  2. SMB is much faster than WMI
  3. You can eliminate the use of smb_login

So, I apparently didn’t spend enough time checking out the info for each module when I was looking for this functionality. Oh well, it gave me an opportunity to learn and to use Python a little bit more.

With that being said, if the systems you are scanning have for whatever reason been hardened and part of that hardening includes disabling file sharing on the NIC (not something that is common in a production environment), then my module still has value as it relies on WMI instead of SMB.

The script I wrote in Python and compiled to an executable with py2exe still has value in a few situations:

  1. You don’t use Metasploit
  2. You obtain access to the initial system(s) manually

I have run into several instances lately where the target is running a web application that has a remote code execution vulnerability. However, in each of these cases the Metasploit module failed, usually due to AV picking up the executable or whatever else Metasploit attempts to upload to the system, or DEP prevents the process from running. I have ended up having to manually exploit these vulnerabilities and end up with access to the host without Metasploit. Sometimes I use Veil to create a custom payload that I then later upload to the system, but sometimes I just create my own local account and RDP in or setup a reverse VNC listener back to my attacking host. In these situations, or in the case where you aren’t using Metasploit at all, the script I wrote might be useful.

After writing the script, I was frustrated that I couldn’t pass-the-hash, so I did a bit of research and found that you could use the NetWkstaUserEnum function linked above to get the same data over SMB. SMB means we can probably pass-the-hash as well. I came across this article for a function that provides the ability to authenticate over SMB and then a more detailed explanation of how to use it here.

Now I just needed to figure out how to call the function. There was some good information on this here. I whipped up some code, reorganized my script so that I had two functions, one for WMI and one for SMB and was ready to go. However, I found that these libraries don’t support passing the hash, which is a bummer. I was happy that I could use WMI or SMB, and that SMB was much, much faster, but I really wanted to be able to pass-the-hash as well. I did some searching around and couldn’t find any scenarios involving the standard win32net/win32security modules.

Much searching led me to the Core Impacket library, which I wasn’t super excited about because I was aware of it enough to look at the code and being a guy that just hacks stuff together, the API isn’t exactly easy to follow. I used sample code from the example in the library, which got me as far as learning how to make a DCE RPC connection, and then to authenticate with credentials, but the library doesn’t include any native methods or examples for accessing NetWkstaUserEnum. Fortunately, I found an example from a SecuriTeam DoS exploit that uses the Impacket library to call NetWkstaUserEnum.

I leveraged the SecuriTeam exploit for an idea of how to do what I wanted to do and then referenced this article for the UUID I needed. Eventually, I got it working and printing out all the users under which processes were running on my test systems. The only issue was that there was a bunch of garbage/un-printable characters in the raw output. I couldn’t find a good example for the packet structure that would enable me to pick out the specific portions I wanted in binary and then encode to ASCII, so instead I played with encoding, stripping data, and then decoding. It is pretty ugly, as in a real developer would probably vomit, but it works. I just hex encode the data, use some regex’s to remove stuff I didn’t want, use some other regex’s to change certain chars to something I could parse (like ; and \), and then used a function to remove the remaining un-printable characters and voila.

The updated script options are:

  usage: [-h] --iplist IPLIST --user USER --pass PASS [--domain DOMAIN]
              --type TYPE

  Find running process that can be used to escalate access.

  optional arguments:
    -h, --help       show this help message and exit
    --iplist IPLIST  file list of IPs that we can login with using provided
                     username and password (default: None)
    --user USER      the username to use for authentication (default: None)
    --pass PASS      the password to use for authentication (default: None)
    --domain DOMAIN  the Domain to use for authentication (default: )
    --type TYPE      which type of connection to we use, WMI or SMB (default:

  Example: --iplist iplist.txt --user test --pass testpass --domain \
             testdomain --type smb

The –domain option is optional but all others are required. If you use SMB in the –type option and used a hash with the –pass option, then it will automatically figure this out and use the Impacket library to pass-the-hash. So to wrap it up, you can still grab the info with WMI and a valid username and password, and now you can also grab the info with SMB and a valid username and password OR with a valid username and password hash.

You can find the updated Python script in the same place, here. An updated version of the Python code compiled to executable can be found here. Or, if you want to compile it yourself, just download the script, install py2exe, drop this file in the same directory as the script, and run `python py2exe.`

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: