aggrokatz
is an Aggressor plugin extension for CobaltStrike
which enables pypykatz
to interface with the beacons remotely.
The current version of aggrokatz
allows pypykatz
to parse LSASS dump files and Registry hive files to extract credentials and other secrets stored without downloading the file and without uploading any suspicious code to the beacon (Cobalt Strike is already there anyhow). In the future this project aims to provide additional features for covert operations such as searching and decrypting all DPAPI secrets/kerberoasting/etc.
We have published a short blog post
for this tool release which also includes some screenshots.
IMPORTANT NOTES – PLEASE READ THIS
LSASS/Registry dumping is not the goal of this project, only parsing. Reasons:
CredBandit
that dumps the raw bytes to disk instead of base64. Cool tool, check it out.In CS client, do not use “reload” nor try to manually unload then reload the script if you modified it. You MUST unload it, close the client and start it anew, then load the modified script. Otherwise you will have multiple versions running simultaneously and a ton of errors and weird behaviours will happen!
While parsing LSASS/registry files on the remote end please don’t interact with the specific beacon you started the script on. Normally it wouldn’t cause any problems, but I can’t give any guarantees.
Install
pycobalt
installed and set up. There is a readme on their github page.pypykatz
version must be >=0.4.8
Setup
aggressor.cna
file is set up and is aware of your python interpreter’s locationaggrokatz.cna
to point to pycobalt.cna
View > Script Console
and Cobalt Strike > Script Manager
windows. Using Script Manager
load the aggkatz.cna
script.Usage
aggkatz.cna
script loaded successfully you will have a new menu item pypykatz
when right-clicking on a beacon.Script Console
window.Script Console
window and the Beacon’s own window.LSASS dump parse menu parameters
LSASS file
: The location of the lsass.dmp
file on the remote computer. You can also use UNC paths to access shared lsass.dmp
files over SMBchunksize
: The maximum amount that will be read in one goBOF file
: The BOF file (Beacon Object File) which allows chunked reads. This file will be uploaded and executed (in-memory) each time a new chunk is being read.(module)
: Specifies which modules will be parsed. Default: all
Output
: Specifies the output format(s)Populate Credential tab
: After a sucsessful parsing all obtained credentials will be available on the Cobalt Srike’s Credential tab. This feature is in betaDelete remote file after parsing
: After a sucsessful parsing the LSASS dump file will be removed from the targetRegistry dump parse menu parameters
SYSTEM file
: The location of the SYSTEM.reg
file on the remote computer. You can also use UNC paths to access shared files over SMBSAM file (optional)
: The location of the SAM.reg
file on the remote computer. You can also use UNC paths to access shared files over SMBSECURITY file (optional)
: The location of the SECURITY.reg
file on the remote computer. You can also use UNC paths to access shared files over SMBSOFTWARE file (optional)
: The location of the SOFTWARE.reg
file on the remote computer. You can also use UNC paths to access shared files over SMBchunksize
: The maximum amount that will be read in one goBOF file
: The BOF file (Beacon Object File) which allows chunked reads. This file will be uploaded and executed (in-memory) each time a new chunk is being read.Output
: Specifies the output format(s)Limitations
The file read BOF currently supports file reads up to 4Gb. This can be extended with some modifications but so far such large files haven’t been observed.
How It Works
TL;DR
Normally pypykatz
‘s parser performs a series of file read operations on disk, but with the help of aggrokatz these read operations are tunneled to the beacon using a specially crafted BOF (Beacon Object File) which allows reading the remote file contents in chunks. This allows pypykatz
to extract all secrets from the remote files without reading the whole file, only grabbing the necessary chunks where the secrets are located.
In-depth
To get the full picture of the entire process, there are two parts we’d need to highlight:
pypykatz
integrates with CobaltStrike
pypykatz
performs the credential extraction without reading the whole file.pypykatz integration to CobaltStrike
CobaltStrike (agent) is written in Java, pypykatz is written in python. This is a problem. Lucky for us an unknown entity has created pycobalt
which provides a neat interface between the two worlds complete with usefule APIs which can be invoked directly from python. Despite pycobalt
being a marvellous piece of engineering, there are some problems/drawbacks with it that we need to point out:
pycobalt
project:pycobalt
project will be maintained in the future.pycobalt
‘s development.pycobalt
and CobaltSrike
. This results in some API calls which would return bytes that can’t be used because some bytes get mangled by the encoder. By checking the code we conclude that most encoding/decoding issues are because pycobalt
uses STDOUT/STDIN to communicate with the Java processbof_pack
API call which is crucial for this project had to be implemented as a pure-aggressor script and only invoked from python using basic data structures (string and int) and not using bytes.pycobalt
package without threading support. Well, at least we observed that threading breaks randomly, but we kinda expected this.Credential parsing on a stack of cards
pypykatz
and it’s companion module minidump
had to be modified to allow a more efficient chunked parsing than what was implemented before, but this is a topic for another day.
After pypykatz
was capable to interface with CobaltStrike
via pycobalt
the next step was to allow chunked file reading. Sadly this feature is not available by-default on any of the C2 solutions we have seen, so we had to implement it. The way we approached this problem is by implementing chunked reading via the use of CobaltStrike
‘s Beacon Object Files interface, BOF for short. BOFs are C programs that run on the beacon not as a separate executable but as a part of the already running beacon. This interface is super-useful because it makes BOFs much stealthier since all of the code executes in memory without anything being written to disk.
Our BOF solution is a simple function and takes 4 arguments:
fileName
: Full file path of the LSASS dump file or registry hive (on the remote end)buffsize
: Amount (in bytes) to be read from the fileseekSize
: The position where the file read operation should start from (from the beginning of the file)rplyid
: An identification number to be incorporated in the reply to avoid possible collisionsWith these parameters, pypykatz
(running on the agent) can issue file read operations on the beacon (target computer) that specifically target certain parts of the file.
On the other end (in CobaltStrike) aggrokatz
registers a callback to monitor every message returned by the target beacon. If the message’s header matches the header of a file read operation it will be processed as a chunk of a minidump
file and will be dispatched to the minidump
parser which will dispatch the result to pypykatz
. In case more read is needed pypykatz
will issue a read using the minidump
reader that will dispatch a new read command on the beacon via the BOF interface. This process repeats until the file is parsed.
Results
After parsing around a 100 LSASS dumps using this method, we can state the following (chunk size used was 20k):
Drawbacks
shadow-rs is a Windows kernel rootkit written in Rust, demonstrating advanced techniques for kernel manipulation…
Extract and execute a PE embedded within a PNG file using an LNK file. The…
Embark on the journey of becoming a certified Red Team professional with our definitive guide.…
This repository contains proof of concept exploits for CVE-2024-5836 and CVE-2024-6778, which are vulnerabilities within…
This took me like 4 days (+2 days for an update), but I got it…
MaLDAPtive is a framework for LDAP SearchFilter parsing, obfuscation, deobfuscation and detection. Its foundation is…