One of the key tenets in penetration testing is stealth. The sooner we are seen on the network, the faster the responders can stop us from progressing. As a result, using tools that seem natural on the network and using utilities that do not generate any noticeable impact for users is one of the ways we can stay under the radar. In this chapter we are going to look at some ways to gain access and move laterally through an environment while using tools that are native on the target systems.
In this chapter, we discuss the following topics:
• Capturing password hashes
• Using Winexe
• Using WMI
• Taking advantage of WinRM
When we look at ways to gain access to systems that don’t involve exploits, one of the first challenges we have to overcome is how to gain credentials to one of these target systems. We’re going to focus on our target Windows 10 system for this chapter, so first you need to know what hashes we can capture, and second you need to know how we can use those hashes to our advantage.
When we look up a DNS name, Windows systems go through a number of different steps to resolve that name to an IP address for us. The first step involves searching local files. Windows will search the hosts or LMHosts file on the system to see if there’s an entry in that file. If there isn’t, then the next step is to query DNS. Windows will send a DNS query to the default nameserver to see if it can find an entry. In most cases, this will return an answer, and we’ll see the web page or target host we’re trying to connect to.
In situations where DNS fails, modern Windows systems use two protocols to try to resolve the hostname on the local network. The first is Link Local Multicast Name Resolution (LLMNR). As the name suggests, this protocol uses multicast in order to try to find the host on the network. Other Windows systems will subscribe to this multicast address, and when a request is sent out by a host, if anyone listening owns that name and can turn it into an IP address, a response is generated. Once the response is received, the system will take us to the host.
However, if the host can’t be found using LLMNR, Windows has one additional way to try to find the host. NetBIOS Name Service (NBNS) uses the NetBIOS protocol to try to discover the IP. It does this by sending out a broadcast request for the host to the local subnet, and then it waits for someone to respond to that request. If a host exists with that name, it can respond directly, and then our system knows that to get to that resource, it needs to go to that location.
Both LLMNR and NBNS rely on trust. In a normal environment, a host will only respond to these protocols if it is the host being searched for. As a malicious actor, though, we can respond to any request sent out to LLMNR or NBNS and say that the host being searched for is owned by us. Then when the system goes to that address, it will try to negotiate a connection to our host, and we can gain information about the account that is trying to connect to us.
When Windows hosts communicate among themselves, there are a number of ways in which systems can authenticate, such as via Kerberos, certificates, and NetNTLM. The first protocol we are going to focus on is NetNTLM. As the name suggests, NetNTLM provides a safer way of sending Windows NT LAN Manager (NTLM) hashes across the network. Before Windows NT, LAN Manager (LM) hashes were used for network-based authentication. The LM hash was generated using Data Encryption Standard (DES) encryption. One of the weaknesses of the LM hash was that it was actually two separate hashes combined together. A password would be converted to uppercase and padded with null characters until it reached 14 characters, and then the first and second halves of the password would be used to create the two portions of the hash. As technologies progressed, this became a bigger deal because each half of the password could be cracked individually, meaning that a password cracker would at most have to crack two 7-character passwords.
With the advent of rainbow tables, cracking became even easier, so Windows NT switched to using the NT LAN Manager (NTLM) hashes. Passwords of any length could be hashed, and the RC4 algorithm was used for generating the hash. This is vastly more secure for host-based authentication, but there’s an issue with network-based authentication. If someone is listening and we’re just passing raw NTLM hashes around, what stops that person from grabbing a hash and replaying it? As a result, the NetNTLMv1 and NetNTLMv2 challenge/response hashes were created to give additional randomness to the hashes and make them slower to crack.
NTLMv1 uses a server-based nonce to add to the randomness. When we connect to a host using NTLMv1, we first ask for a nonce. Next, we take our NTLM hash and re-hash it with that nonce. Then we send that to the server for authentication. If the server knows the NT hash, it can re-create the challenge hash using the challenge that was sent. If the two match, then the password is correct. The problem with this protocol is that a malicious attacker could trick someone into connecting to their server and provide a static nonce. This means that the NTLMv1 hash is just slightly more complex than the raw NTLM credential and can be cracked almost as quickly as the raw NTLM hash. Therefore, NTLMv2 was created.
NTLMv2 provides two different nonces in the challenge hash creation. The first is specified by the server, and the second by the client. Regardless of whether the server is compromised and has a static nonce, the client will still add complexity through its nonce, thus ensuring that these credentials crack more slowly. This also means that the use of rainbow tables is no longer an efficient way to crack these types of hashes.
NOTE It is worth noting that challenge hashes cannot be used for pass-the-hash attacks. If you don’t know what type of hash you are dealing with, refer to the entry for hashcat Hash Type Reference in the “For Further Reading” section at the end of this chapter. Use the URL provided to identify the type of hash you’re dealing with.
In order to capture hashes, we need to use a program to encourage the victim host to give up the NetNTLM hashes. To get these hashes, we’ll use Responder to answer the LLMNR and NBNS queries issued. We’re going to use a fixed challenge on the server side, so we’ll only have to deal with one set of randomness instead of two.
Responder already exists on our Kali Linux distribution. However, Kali doesn’t always update as frequently as the creator of Responder, Laurent Gaffie, commits updates. Because of this, we’re going to use git to download the latest version of Responder. To ensure we have all the software we need, let’s make sure our build tools are installed in Kali:
Now that git is installed, we need to clone the repository. Cloning the repository will download the source code as well as create a location where it is easy to keep our software up to date. To clone the repository, do the following:
In order to update our repository, simply do the following:
If there are any updates, our code would now be up to date. By verifying that our code is up to date before each execution, we can make sure we’re using the latest techniques to get the most out of Responder.
Now that we have Responder installed, let’s look at some of the options we can use. First of all, let’s look at all the help options:
There are a lot of options here, so let’s concentrate on the ones that are most useful and less likely to break anything. Some of these options, such as wredir, will break networks under certain conditions. Also, some actions will give us away, such as forcing basic authentication. When we force basic authentication, the victim will see a pop-up box asking for a username and password. The upside is that we will get the password in plain text, but the downside is that the user might realize that something is up.
Now that we’ve covered what not to do, let’s take a look at how to call Responder. The most important option is specifying the interface . For our test, we’re going to be using our primary network interface, eth0. If you are in a system that has multiple interfaces, you could specify an alternate interface or use ALL to listen to all interfaces. The next option we’ll specify is fingerprint
. This option gives us some basic information about hosts using NetBIOS on the network, such as the names being looked up and the host OS versions. This will give us an indication of what types of boxes are on the network.
Finally, we’ll specify to set up the WPAD server . WPAD is the Web Proxy Auto-Discovery protocol. It is used by Windows devices to find a proxy server on the network. This is safe to use if your Kali box has direct access to the Internet. However, if you’re on a network where your Kali box has to go through a proxy, then this will break the clients you poison, so don’t use it. The benefit of setting this up is that if hosts look for a WPAD server for web traffic, any web traffic will trigger Responder’s poisoning to get a hash—whereas without it, you have to wait for someone to go to a share that doesn’t exist.
NOTE This lab has a README file that discusses the setup of the network for this and other labs in this chapter. Therefore, you should read this file before continuing to make sure these labs work for you.
Now that you have the basics down, let’s put your knowledge to work. In our network we have a Windows 10 server with the settings applied from the README file. We need to make sure that both our systems are on the same network. Then we run Responder and start the poisoning process:
Now that Responder is listening, we should be able to make a simple request with our Windows 10 host for a share that doesn’t exist, and Responder should take care of the rest.
As you can see in Figure 10-1, our Windows system just returns an “Access is denied” message when we try to access the share. We don’t see any other strange behavior on the Windows system. On the Kali box, though, we see a lot of activity.
Figure 10-1 Requesting a file from a share that doesn’t exist
Notice that two different types of poisoning are being done here. The first is NBNS poisoning and the second is LLMNR
. Because of the fingerprinting, both requests give us information about the underlying host OS, and we can see the IP address of the requesting host as well as what system it was trying to connect to. The final piece of data we are given is the NetNTLMv2 hash along with the username
. We can try to crack this credential and see if it works on the system.
Now that we have a valid hash, press CTRL-C on the Responder window to stop it from running. The next step is to dump the hashes out of Responder in a format that John the Ripper can process:
We can see our NetNTLMv2 hash here, but we also see two new files created in the directory: DumpNTLMv2.txt and DumpNTLMv1.txt. We know that the hash passed to Responder was Version 2 (v2), so we can just run John against the v2 file and see if it can crack the password:
John has successfully cracked our password, and it found the password “Password1” for the “User” user. With these credentials, we can access the system remotely. In the rest of this chapter, we’re going to use these credentials to further interact with our victim machine.
Winexe is a remote administration tool for Windows systems that runs on Linux. With Winexe, we can run applications on the target system or open up an interactive command prompt. One additional benefit is that we can ask Winexe to launch our shell as “system” if we are targeting a system where our user has elevated credentials, giving us additional privileges to the system.
We have a password to our victim system from using Responder, but how do we now interact with our victim system? Using Winexe is a common way for attackers to access remote systems. It uses named pipes through the hidden IPC share on the target system to create a management service. Once that service is created, we can connect to it and call commands as the service.
To verify that the target system is sharing the IPC share, we use smbclient to list the shares on the target system:
For many of the tools we use in the rest of this chapter, we’re going to see this common way of specifying the logon credentials for the target system. The format is <DOMAIN>\<USERNAME>%<PASSWORD>. Here, we specified our user credentials as User%Password1, our username and password. The -L option asks smbclient to list the shares on the system. We can see that there are a number of shares, including our IPC$ share.
With knowledge that our IPC share is available, let’s see if we have the ability to launch a command prompt. We’ll use the same syntax for specifying the username, only this time, we’ll use the syntax //<IP ADDRESS> to specify the target system. We also add the --uninstall flag, which will uninstall our service on exit. Finally, we specify cmd.exe for the cmd.exe application, which gives us an interactive shell on the target system.
We now see the Windows banner and command prompt, which means we succeeded. Next, we want to check our privilege level so that we can determine the rights we are operating with. By typing in whoami, we can print out the user ID of our shell. In this case, our user is the “user” user, which means that we will have privileges as that user.
WARNING If you exit the shell by using CTRL-C or if you don’t use the --uninstall flag, the service that’s created will remain on the target system. As an attacker, this is bad because you’re leaving a trace of the techniques you’re using for remote access. As a penetration tester, leaving artifacts makes it difficult to determine if another breach has occurred, and it may set off red flags after you’ve left a system. This doesn’t always come up right away. In six months, someone might ask if you left the service around. So, if you aren’t cleaning up, you’ll be left relying on notes to answer some very uncomfortable questions.
Finally, to leave our shell, we can just type exit at the command prompt. We should then see the Bash prompt, which lets us know that we have left the shell. On the server side, our service is being uninstalled and our connection closed.
In many cases, the things we want to do on a target system will require elevated privileges. In the previous lab, we were able to get access as a normal user, but we really want access as the SYSTEM user. Because this user has full privileges over the system, we can access credentials, memory, and other valuable targets.
To execute our attack, we’re going to use all the same options as our previous lab, but we’ll add in the --system flag. This will take care of escalation for us, and the end result is a highly privileged shell, as shown here:
As you can see here, we’re now accessing the victim machine as the SYSTEM user. Although not part of the scope of this exercise, this allows us to dump credentials, create new users, reconfigure the device, and perform many other tasks that a normal user might not be able to do.
Windows Management Instrumentation (WMI) is a set of specifications for accessing system configuration information across an enterprise. WMI allows administrators to view processes, patches, hardware, and many other pieces of information about the target system. It has the ability to list information, create new data, delete data, and change data on the target system based on the permissions of the calling user. As an attacker, this means that we can use WMI to find out quite a bit about a target system as well as manipulate the system state.
Knowing that we can query system information with WMI, we might want to know a number of things about our target system. For example, we might want to know who is logged on interactively to see if there is a risk of us getting caught. In this lab, we’re going to use two different WMI queries to see what user or users are logged into the target system.
To query WMI, we have to build a WMI Query Language (WQL) query that will get the information we are looking for. WQL looks similar to Structured Query Language (SQL), which is used for database queries. To build our query, though, we have to know a little bit more about how WMI works. The most important of the things we need to know is the class we will be querying. The “For Further Reading” section at the end of this chapter contains an entry that points to Microsoft’s list of classes that are accessible through WMI. However, we’re going to look at just two in this exercise.
The first class we’re going to be querying is the win32_logonsession class.1 This class contains information about the sessions that are logged in, the type of logon that has been performed, the start time, and other data. Let’s put together a query to use first, and then we’ll look at how to execute this query using WMI:
Using this query, we select two different pieces of data from the win32_logonsession class. The first is LogonType, which contains information about the type of login being performed. The second, LogonId, is the internal ID number for the logon session. To execute this query, we have to use a WMI client. Kali has two different clients for WMI queries: the first is pth-wmic, and the second is part of Impacket’s scripts. The pth-wmic client is easier for scripting, so we’re going to be focusing on that.
The syntax for pth-wmic is similar to that of the Winexe tool we used in the last lab. We’ll specify the user and the host the same way, and then add our WQL query to the end of the command, like so:
Looking at the output from our query, we see the session and the logon type. A number of logon types are shown here, so how do we know which sessions we are interested in? To determine this, refer to Table 10-1, which shows the different types of logons and what they mean.
Table 10-1 Logon Types for Logon Sessions
Now that we know what the types mean, let’s limit our query to just type 2 logons. This should tell us what logon IDs we need to look for in order to find the interactive user logons.
We still see a number of different logons. Let’s take a look at three of them: one in the 30K series, one in the 50K series, and one in the “over 1 million” series. The logon sessions are mapped to users in the win32_loggedonuser table. Unfortunately, this is hard to query through WQL for specific logon IDs because the values are strings and not integers, so we’re going to script this with pth-wmic and egrep to target the values we want:
We see three users: User, DWM-1, and UMFD-0. DWM and UMFD are driver-based accounts, so we can safely ignore them. We see a pattern here, so let’s look at only the processes above 1 million:
Finally, we can see the sessions logged into the box. Both are for the User user. Using WMI, we have determined that User is logged in interactively to the system. Therefore, if we do anything that pops up a window or causes disruptions, we might be detected.
Now that we know a bit more about WMI, let’s look at how to execute commands. We have two options for executing commands using WMI: we could create a new process with WMI and then monitor the output, or we could use one of the tools built into Kali. For this example, we’ll use the pth-wmis binary to launch commands. However, this requires us to create a place to capture the output of our commands.
In the setup for this exercise, we are going to load up the latest Impacket source code and use a stand-alone SMB server provided with it. Impacket is a series of Python scripts that allow us to interact with things outside of Samba. It’s frequently used in exploit tool development for things that require SMB interaction. Here are the instructions for getting and installing the latest tools:
Next, we want to start our SMB server. Let’s do this in another window so that we can have our current window for doing work. We’re going to use the smbserver.py script that we just installed to launch our share. We want to map the /tmp directory to a share called “share.” Let’s try it:
Now that our SMB server is started, let’s verify that it works. We’re going to do this by using the smbclient tool along with the -N flag to tell it not to use authentication, and we’re going to list the shares on our local system.
We see that our share is present. This share is mapped to the Kali system tmp directory and it allows for writes, so we can redirect output to the share. One of the nice things about Windows is that you don’t have to map a share to read and write to it, so the logged-in user won’t notice a strange share being loaded.
To do a basic test, let’s run a pth-wmis command that will just echo something simple to a file. In this example, we’re going to use a similar command to pth-wmic, but we’ll include our command at the end. We run this command against our Windows target:
Next, let’s do something a bit more interesting. Let’s create a backdoor user so that we can get back in later. We want to add this user to the Administrators group locally so that we have full access when we connect back. This ensures that if the user changes their password, we still have access to the target system. To start with, we’re going to use the net user command to create a new user called evilhacker:
We can see that our command succeeded, but with WMI, that just means it successfully launched the binary; this doesn’t mean the activity worked. We logged the output from our command to a file so we can see what the application printed out. In this case, the file says that the command completed successfully. So now that we have a new user on the system, let’s add this new user to the local Administrators group using net localuser:
Now that we’ve added our user evilhacker to the Administrators group, let’s make sure our activity worked. We’ll go back in and use net localgroup for the Administrators group to make sure our user appears. We check our output file, and it is in the group, so we have succeeded. Last but not least, let’s check to make sure we have access:
We’ve successfully created a backdoor into the system that will allow us to come back later and access it. We have added it to the Administrators group so that we can escalate privileges to the SYSTEM user. When we tried our winexe command, we successfully got back a shell, verifying that we have access when we need it in the future, regardless of what the user changes their password to.
WinRM is a relatively new tool that is supported on Windows systems. Starting with Windows 8 and Windows Server 2012, this tool creates an additional way of remotely interacting with Windows systems. WinRM uses SOAP over web-based connections to interact with a target system. It supports both HTTP and HTTPS, as well as authentication based on Basic Auth, hashes, and Kerberos. Along with the ability to do scripting with WMI-based interfaces, launch applications, and interact with PowerShell, this is a very powerful tool we can use when we find it available.
One of the ways that WinRM can help us is by allowing us to execute commands on remote systems. Unfortunately, at the time of this writing, there weren’t a lot of command-line tools from Kali to do this. However, a Python library called pywinrm is available that will interact with WinRM. We are going to use that library to execute commands. We’ve included a script in the Ch10 directory of the Gray Hat Hacking github repo for Chapter 5 that will help us execute our commands. But first, we need to install the pywinrm Python module.
To do this, open a Kali shell and type in pip install pywinrm. This will download and install the Python module as well as any other required submodules. Once the install is finished, make sure you have the ghwinrm.py script from the book material. The ghwinrm.py script uses pywinrm to allow us to call either PowerShell commands or shell scripts over WinRM.
The syntax for ghwinrm.py is similar to the other tools we’ve used. Let’s use it to run a simple whoami command. We just need to specify the user, target, and command we’re going to run:
You can see that we specified -U for the user credentials, as normal, but there are some additional syntax pieces here. The -c flag means “run a command.” The -t flag specifies the target, and the command is added to the end. Although we can see that we successfully ran a command, one of the differences with running commands with WinRM versus WMI is that the commands don’t maintain any kind of state and you can’t do an interactive session. Let’s look at an example:
You can see here that when we print the current directory with cd, we are in the User directory. When we cd to the root of C:, it doesn’t maintain state. This means that we’ll have to stack commands if we need to move around, as shown here:
By stacking commands using the && operator, we can move around and run commands on the same line. The && operator says that if the first command was successful, run the second command. We can use multiple && operators in a row, but in this case, we just cd into the root of C: and then perform a dir command. We can see the contents of the root of C:, showing we successfully moved around and ran a command.
This is just a quick example of the things you can do; using WinRM will allow you to execute any command you don’t need an interactive session to run. This includes creating and manipulating services, processes, and other system states.
One of the popular techniques attackers are employing right now is to use PowerShell to interact with systems. Because many systems don’t log PowerShell very well, attackers can hide their activities. This is part of the reason why Chapter 15 is devoted to exploitation using PowerShell. Although we’re not going to look at exploitation in this chapter, let’s take a look at using our ghwinrm.py script to launch some basic PowerShell commands:
You can see we changed our -c option to -p so that we run PowerShell instead of a command shell. The user and target options are the same, and we pass a PowerShell method to the script to get it to run. In this case, we get a process list, and it prints the same things it would in a regular PowerShell shell. This is all well and good, but being able to put together more complex scripts will allow us to get a lot further in working with a target system.
Let’s create a basic script that prints who logged onto the system. We’re going to save this file as psscript.
This script prints information about the user who logged in or out of the system, the type of action, and when it happened. We’ve saved this information to a file because the ghwinrm.py script can also take a file as an argument to be run on the remote system with PowerShell. It doesn’t actually drop any files on the target system; instead, it runs them encoded with PowerShell, so we don’t have to worry about script signing and other security constraints.
Here, you can see that we’ve specified our file to run using the -f option, and when it runs on the remote system, it returns the logon information for us. This is just one example of a script we might want to run, but the possibilities are almost limitless. However, keep in mind that there is a size constraint. Large files won’t work, but we can combine multiple techniques to get these larger files across. We’ll look more at that topic in Chapter 15.
In this chapter, we looked at a number of ways to get onto a target system without using an exploit. We looked at stealing and cracking credentials using Responder to spoof LLMNR and NetBIOS Name Services responses. This allowed us to gather credentials that were passed using NetNTLM, and then we cracked those credentials with John the Ripper.
We looked at different ways to run commands as well with the credentials we captured. This includes using Winexe, which gives us a remote interactive shell. We also used WMI to query system information and run commands. With WinRM, we went beyond simply launching shells to being able to pass PowerShell scripts to the target.
While doing this, we were able to “live off the land” and use built-in tools and processes on these target systems. This reduces the risk of being caught and reduces the possibility we’ll leave something bad on a victim system.
hashcat Hash Type Reference https://hashcat.net/wiki/doku.php?id=example_hashes
Pass the Hash Toolkit https://github.com/byt3bl33d3r/pth-toolkit and https://media.blackhat.com/us-13/US-13-Duckwall-Pass-the-Hash-Slides.pdf
Responder Blog http://g-laurent.blogspot.com/
Responder GitHub Repository https://github.com/lgandx/Responder
Winexe Tools Page https://tools.kali.org/maintaining-access/winexe
WMI Class Lists https://msdn.microsoft.com/en-us/library/aa394554(v=vs.85).aspx
WMI Reference https://msdn.microsoft.com/en-us/library/aa394572(v=vs.85).aspx
1. Microsoft, “Win32_LogonSession class,” August 1, 2017, https://msdn.microsoft.com/en-us/library/aa394189(v=vs.85).aspx.