Note: This post was published back in 2017
This post was originally published on https://www.mdsec.co.uk/blog/ when I was under employment of MDSec Consulting Limited in the United Kingdom. This is mirrored on my own blog for archiving reasons.
ANGRYPUPPY is a tool for the Cobalt Strike framework, designed to automatically parse and execute BloodHound attack paths. ANGRYPUPPY was partly inspired by the GoFetch and DeathStar projects, which also automate BloodHound attack path execution. ANGRYPUPPY uses Cobalt Strike’s built-in lateral movement and credential-stealing capabilities of its agent, Beacon.
This allows for automated retrieval of sessions for management within Cobalt Strike and allows for the use of its SMB C2 communications channel for internal pivoting. Additionally, ANGRYPUPPY allows the operator to choose the technique they wish to use to perform lateral movement actions. Currently, an operator can choose psexec_psh, WMI, WinRM, or psexec techniques.
The following displays a video of the tool in action within the RASTALABS environment, created by @_rastamouse
BloodHound is an AD relationship mapping and visualisation tool developed by Andy Robbins, Rohan Vazarkar, and Will Schroeder. BloodHound ultimately analyzes trust relationships in a Windows Active Directory Domain with the goal to support operators and provide the ability to analyze the most efficient ways to target specific systems/users/groups.
BloodHound has some shortcomings whereby a full view of the environment is required and therefore a large amount of AD data collection is necessary for it to operate.
Upon its initial release, BloodHound could take a long time to collect its data in large environments; well over 24 hours in certain cases. However, with recent upgrades, BloodHound can now finish collection in a fraction of the time. Primarily as a result of BloodHound, AD data collection is now coming into the spotlight of defenders, and a large amount of AD traffic can be a detection criteria for defenders. Therefore, when using BloodHound in offensive operations it is vital to execute an attack as swiftly and as accurately as possible.
ANGRYPUPPY increases the speed and accuracy of executing the attack paths generated by BloodHound. In our test trials it was possible to execute a 5 hop attack within 3 minutes — one which may take an operator slightly longer to do manually, and reducing the possibility of operator error (which could alert defenders).
As mentioned, AD data collection is moving into the spotlight of the defender space. Traditional lateral movement techniques are also widely detected and analysed. Therefore such techniques would most likely be only viable against less mature organisations where the defense capability is lacking or an educated SOC is not present. As ANGRYPUPPY automates the attack, this leaves more time for project management, tactical planning and focus on achieving objectives with less time worrying about execution. Alternatively, in a mature environment this may be used as a means to simulate an actor with a financial gain agenda and more likely to follow a “smash and grab” approach.
ANGRYPUPPY ingests a BloodHound attack path in JSON format and is then able to determine the actions necessary to execute the attack path, stealing credentials or moving laterally as necessary.
The operator simply types “angrypuppy” into any Cobalt Strike beacon console and is then able to import the attack path, select a lateral movement technique and execute the attack. This action is recorded in the Cobalt Strike event log, along with the operator name and the ANGRYPUPPY identifier. We do not recommend performing other lateral movement activity while ANGRYPUPPY is running.
ANGRYPUPPY running using psexec_psh as the lateral movement method.
ANGRYPUPPY assigns a random identifier each time it is run, to allow for differentiation between attack paths executed. This identifier is used when the attack is started and completed, and will also be set as a beacon note when each new beacon checks in.
In order to help with determining valid attack paths from current accessible sessions, the “cypher” command is also implemented to allow the operator to generate several queries based on the beacons currently in Cobalt Strike. The operator can then copy and paste these queries from the event log into the “raw query” section of BloodHound in order to determine paths to Domain Admins without having to manually check each user or computer. This attack path can then be exported as JSON after a valid single path is found, which can then be automatically executed by ANGRYPUPPY.
Output from the “cypher” command, showing Cypher queries generated from current beacons.
Cobalt Strike’s Aggressor Script has the “binfo” function to obtain information on a specific beacon. Using this information we can obtain a list of all current user sessions, along with machines. A computer is only used as a valid item for a BloodHound query if there is an administrator-level beacon on the device. This had to be enforced as BloodHound has no knowledge of current context and would often assume full machine compromise when only a low privileged beacon was present.
A number of basic queries were developed with assistance from Andy Robbins. Currently, two types of queries are available:
- Query from all current beacon contexts to Domain Admin via Group membership and Admin to target machines.
- Query from all current beacon contexts to Domain Admin using all possible relationships including ACL vectors. (Not yet implemented in ANGRYPUPPY)
With each query, an additional statement that selects only one unique attack path is also included, which basically just appends “LIMIT 1” to the end of the query for easy export into JSON, which we can then be ingested with ANGRYPUPPY. This is to remove situations where the attack path may fork, which poses issues when sorting nodes.
To implement ANGRYPUPPY, there are two types of data that we needed to ingest from BloodHound: nodes and edges. A node is an item such as a user, a computer, or a group; an edge is the relationship between two nodes. There are several types of possible relationships between nodes, depending on node type.
We quickly realized an issue upon beginning to write the JSON parsing logic for ANGRYPUPPY. BloodHound’s graph export feature, while giving us JSON that we can quickly ingest, returns nodes and edges in unordered arrays. This meant that we not only had to parse the data, but we had to find a way to sort the nodes. Luckily, the graph contains the information needed, in the form of edges.
The parsing logic works out the possible nodes and determines a start node by finding a node that is not the “target” of any edge. With the first node, we are then able to step through and sort the nodes by using the “source” and “target” fields from each edge to arrange them in order.
What we realized while making ANGRYPUPPY is that the type of edge doesn’t really matter for our purposes, as the action that we take for each node is solely determined by the *node *type, rather than the edge type. Additionally, we determined that while group nodes are necessary to sort the attack path into the correct order, we can effectively ignore the group nodes after we sort the attack path, as below:
User1 –MemberOf → Group1 –AdminTo→ Computer1
In this case, the group node effectively only exists to show that User1 has admin rights to Computer1, and there is no action that we can take on the Group1 node. Thus, our parsing logic will drop all group nodes before the final attack path is generated.
The attack execution is roughly described in the following flow chart:
Cobalt Strike posed certain issues due to the asynchronous nature of beacon communications. A limited number of callbacks were available and therefore many had to be implemented manually on a periodic polling basis of 1 second whereby a flag would be set and trigger another part of the code to execute.
At the time of developing ANGRYPUPPY, the best way we found to handle detection and callbacks was by creating a loop that would be executed every second. This loop looked for changes in the state and flip switches that we have written in as global variables. Other sections of code would then detect these states and act accordingly.
Let’s take lateral movement for example. It was necessary to implement a variable that prevents a second attempt at moving to the target machine if an attempt has already been made to move to the next target. Once the session comes back, this flag is reset, and only then do we attempt to perform the next action in the attack path.
- 2.Run install.ps1 or install.sh (depending on your OS). This rewrites the CNA script to contain the correct path to a necessary Java library we use for JSON parsing.
- 3.In Cobalt Strike, load the CNA script in.
- 1.Once data is loaded into BloodHound and is queryable, type “cypher” into any current beacon session. Ensure that only active sessions are left on the screen.
- 2.Go to the event log and copy the “non-ACL” path to domain admins that is ready for ANGRYPUPPY (with LIMIT 1) at end.
- 3.Paste this query into the raw query section of BloodHound.
- 4.If a path is available, export the path as a JSON file. If not, go ahead and manipulate the target group to one that is accessible but may not be “Domain Admins”.
- 5.In Cobalt Strike within any beacon session, type in “angrypuppy”. This will launch a prompt.
- 6.Select the exported JSON attack path. Choose a preferred lateral movement technique and listener callback (for ex, SMB bind pipe). Press Run.
- 7.This will begin executing the attack path.
Note: if any errors occur or the code hangs, you can terminate by typing “angrypuppykill”.
For more information on usage, refer to the previously highlighted video.
- Utilize BloodHound REST API to automate end to end, no more copy/pasting Cypher query
- Type “Bloodhound”
- Script executes
- Downloads ingestable files
- Uses REST API to upload files to Neo4j DB
- Retrieves a path from the query if found
- Executes the path
- Support for Access Control Lists. Current limitation is the built-in Mimikatz does not allow for NTLM hash injection. Once Mimikatz is updated in the next build it would be possible to automate an ACL attack path and completely recover the state within minutes to minimise the window for disruption.
This blog post was co-authored by: