Building Custom Modules for Core Impact, Part 1 of n-1

In this installment, we’ll start diving into the anatomy of an Impact module where you'll get the opportunity to absorb some of the features and implications before we dive into building something real and useful.

In the course of conducting penetration tests, we often come across password hashes of various types. We can sometimes use these without cracking them, but, it is often useful and necessary to crack those hashes. Why? You may ask.

  1. We might want to use those passwords on services like SSH, telnet and FTP
  2. People are really bad about reusing passwords, so we may luck out and find some juicy infrastructure with an admin's passwords

I usually suggest that Impact run from a decently configured laptop—as those laptops normally have reasonably powerful GPUs. GPUs are great for cracking passwords with the right tools. 

Enter Hashat. Hashcat’s 3.x releases (now under the MIT open source license) have combined the previously separate codebases for CPU, AMD GPU and nVidia GPU cracking into a single executable. This vastly simplifies things for us. Over the next few weeks, we’ll walk through building an integration module between Impact and Hashcat that will hopefully prove useful. 

Like any good software project, we need to figure out exactly what we're going to do. At its basic point, we want to be able to select a number of uncracked password hashes from Impact's Identity Store, shove them into Hashcat, and pull them back into Impact as they're cracked. Pretty simple, right? Not really. We're going to gloss over a lot of functionality that we might want to build in later. So, for the sake of simplicity, we're going to make some assumptions:

  1. We're only going to be cracking NTLM hashes. This is to simplify out the need for detection logic and logic to reject any hashes that aren't what we expect if they're accidentally selected.
  2. We only care about brute-forcing passwords. This means that we're not going to care about things like dictionaries or masks yet.
  3. We're going to use the full character set supported by Hashcat, so we'll be using lower case letters, upper case letters, digits and symbols.

These assumptions are not assumptions I'd be making in a production application, but we're just building a minimal proof of concept this week (and next). 

With those assumptions in mind, what does the module need to do?

  • The module needs to know where the Hashcat executable lives
  • The module needs to know what hashes we want cracked
  • The module needs to know the minimum password length to brute force
  • The module needs to know the maximum password length to brute force
  • The module needs to know how often to poll Hashcat for the output file
  • The module needs to extract the hashes specified and write them out to a file
  • The module needs to execute Hashcat, passing in the list of hashes
  • The module needs to read the output from Hashcat, and then update the Identity Store to add the cracked passwords back in

In product management speak, these are our requirements for what we're building. 

One of the things that makes Impact so awesome to work with is that all of our modules are written in Python. We ship out the Python code for pretty much everything except for the User Interface and our agent that exploits install. This means that with a little bit of judicious exploring, we can usually find a module that already does a good bit of what we want to do and can copy, paste and modify to our specific needs. 

I'm going to send you off with a little bit of homework to look at some modules that are already in the system, for some of this functionality. Take a look under Tools > Cracking > Password cracking using Core CloudCypher. Inside this module we'll find functionality for accessing the Identity Store, updating the Identity Store and polling an external service (or file). Also take a look at Tools > Cracking > Password cracking using John The Ripper. In this module, we'll find code for calling an external application —which we'll definitely need to do.

If you take a look at our module from last week, you’ll see that more than half of the module isn’t Python code at all, but is XML. At the top, there’s a hunk of XML data, creatively called "__xmldata__" that encodes some information that tells Impact how it should handle this module.

Inside the block, we describe a series of <property/> entries that tell Impact a bunch of useful things, like what the name of the main class of the module is, what parameters Impact should collect prior to running the module, and what type of targets the module can be executed against. 

The information contained within the "__xmldata__" is quite descriptive and not all of it is going to be useful to us building an integration module. Here's what we'll be using for the Hashcat integration, and then I'll walk you through the important bits:

__xmldata__ = """<?xml version="1.0" ?>
<entity class="module" name="Crack NTML using Hashcat" type="python">
    <property key="classname" type="string">NTLM_Crack_Hashcat</property>
    <property key="parameters" priority="2" type="parameters"/>
    <property key="parameter_description" type="parameters"/>
    <property key="category" type="string">Tools/Cracking</property>
    <property key="author" readonly="1" type="string">Bobby Kuzma</property>
    <property key="autorunnable" readonly="1" type="bool">false</property>
    <property key="features" readonly="1" type="container">
        <property key="network" readonly="1" type="string"/></property>
        <property key="products" type="container">
            <property key="impact" type="bool">true</property>
            <property key="insight" type="bool">false</property>
        <property key="version" readonly="2" type="string">$Revision: 1 $</property>
        <property key="brief" readonly="1" type="string">Initial Test Module</property>
        <property key="Description" readonly="1" type="xmldata">
            <para>Edit me!</para>
        <property key="parameters" type="parameters">
            <property type="entity_name:identity,multiple" key="TARGET"></property>
                <property key="HashCatPath" type="file:local">c:\hashcat-3.20\hashcat64.exe</property>
            <property key="Minimum Length" type="int">1</property>
            <property key="Maximum Length" type="int">8</property>
                <property key="Polling Interval" type="int">60</property>
        <property key="parameter_description" type="parameters">
            <property key="HashCatPath" type="string">Path to the Hashcat executable.</property>
            <property key="Minimum Length" type="string">Minimum password length that will be tested.</property>
            <property key="Maximum Length" type="string">Maximum password length that will be tested.</property>
            <property key="Polling Interval" type="string">How often this module will check the cracking job</property>
        <property type="container" key="highlight_preconditions" readonly="1">
        <property type="container" key="TargetClasses" readonly="1">
               <property type="string" key="identity" readonly="1"/>
        <property type="container" key="Not" readonly="1">
            <property type="container" key="non_empty_ntlm_hashes" readonly="1">
                <property type="user:EvaluateValue,EvaluateKey" key="conditiontype" readonly="1">EvaluateValue</property>
                <property type="string" key="target" readonly="1">properties/NTLM hash</property>
                <property type="container" key="alternatives" readonly="1">
                    <property type="string" key="" readonly="1" />
        <property type="container" key="windows_ntlm_protocols" readonly="1">
            <property type="user:EvaluateValue,EvaluateKey" key="conditiontype" readonly="1">EvaluateValue</property>
                <property type="string" key="target" readonly="1">properties/Protocol</property>
                <property type="container" key="alternatives" readonly="1">
                    <property type="string" key="Windows NTLM" readonly="1" />
        <property type="string" key="RunOnlyInLocalAgent" readonly="1"/>

On Line 3, we see the "classname" property. This is important as this tells the Impact framework what class inside the module is the actual module class (you can have multiple classes in a module file).

Lines 20-32 are the parameters that Impact will request when you run the module. If you look at the subkeys inside the parameters block, you'll see where we have some interesting entries. The first one, on line 21, we have a TARGET as the key. The type is a little complex, so let's parse it out.

type="entity_name:identity,multiple": Inside of Impact, things like hosts, web pages and identities are referred to as an Entity. There's a standardized way of hanging parameters off of an entity. In this case, we're looking for an Identity Entity. However, we want to accept multiple instances so we can pass several of them to the module for processing.

On line 22, we have a type="file:local", which will give us the option of pulling a file dialog to hunt for a file path locally.

Lines 23-25 are pretty simple, expecting an integer value.

All of these parameters will be passed into the module by the Impact framework as a dictionary object for ease of access.

Lines 33-53 tell Impact how to handle what we call "Preconditions." Preconditions are how Impact is able to tell what modules you can run against a selected item in the user interface. It's pretty complicated and definitely deserves a post of its own later on.

Line 54 is probably the most important safety feature of this module: It forces the module to only run on the machine that Impact is installed on. We don't want to take over systems that we've popped during a pen-test to crack the passwords for us. It would be rude.

There's a lot of functionality that can be embedded in the "__xmldata__" block that affects how Impact handles a module, but for now, we've covered the basics that we need to know about how to build this Hashcat integration.

Next time, we'll start filling out some actual Python code to make the module actually start doing work. Until next time...


<< Return to part 0                                                                                                                                             Continue to part 2 >>