CovenantDecryptor is designed to decrypt the communication data of Covenant traffic.
The extraction of the private key from memory is applicable to other C2, such as Empire, given its use of the
RSACryptoServiceProvider
to create the key.
The Covenant communication initialization consists of 3 stages :
- Stage0 :
- The infected agent initiates an RSA session by transmitting a public key encrypted using the
SetupAESKey
, which is embedded in a malicious executable. Before sending, it formats the text as described in GruntHTTPStager with the type set to 0. - The C2 transfers a
SessionKey
, encrypted with the RSA public key, for subsequent communication.
- The infected agent initiates an RSA session by transmitting a public key encrypted using the
- Stage1 :
- The infected agent employs the
SetupAESKey
to decrypt the message, and then leverages the RSA private key to decrypt theSessionKey
. Afterwards, it encrypts 4 randomly generated bytes with theSessionKey
and transmits them. Before sending, it formats the text as described in GruntHTTPStager with the type set to 1. - The C2 decrypts the 4 bytes using the
SessionKey
, appends 4 additional randomly generated bytes and transfers the resulting 8 bytes data to the infected agent.
- The infected agent employs the
- Stage2 :
- The infected agent decrypts the 8 bytes with the
SessionKey
. Subsequently, it checks if the first 4 bytes match the data it had previously transmitted, and proceeds transfer the last 4 bytes back to the C2. Before sending, it formats the text as described in GruntHTTPStager with the type set to 2. - The C2 decrypts the 4 bytes and verifies if they correspond to those it had transmitted earlier.
- The infected agent decrypts the 8 bytes with the
Once verification is complete, data can be exchanged.
CovenantDecryptor is composed of two utilities. The extract_privatekey
script retrieves the p and q primes from a minidump file to construct an RSA private key by employing the public modulus. The decrypt_covenant_traffic
script consists of 3 commands modulus
, key
and decrypt
. The first command extracts the modulus from Covenant communication, while the second recovers the AES key used for encrypting data traffic. Lastly, the third command decrypts the traffic.
- The data traffic of Covenant is extracted from a network capture and stored in a separate file.
- The AES key, which is embedded in the stage 0 binary, employed at the beginning of the communication.
- A minidump file of an infected process.
Extract the modulus from the stage 0 request of an infected host :
$ python3 decrypt_covenant_traffic.py modulus -i traffic.txt -k "EQCZiHdmVUQzIhEAmYh3ZlVEMyIRAJmId2ZVRDMiEQA=" -t base64
[+] Modulus:
19574201286059123715221634877085223155972629451020572575626246458715199192950082143183900970133840359007922584516900405154928253156404028820410452946729670930374022025730036806358075325420793866358986719444785030579682635785758091517397518826225327945861556948820837789390500920096562699893770094581497500786817915616026940285194220703907757879335069896978124429681515117633335502362832425521219599726902327020044791308869970455616185847823063474157292399830070541968662959133724209945293515201291844650765335146840662879479678554559446535460674863857818111377905454946004143554616401168150446865964806314366426743287
[+] Exponent: 65537
Retrieve the RSA private key from a minidump file of an infected Covenant process :
$ python3 extract_privatekey.py -i memory.dmp -m 19574201286059123715221634877085223155972629451020572575626246458715199192950082143183900970133840359007922584516900405154928253156404028820410452946729670930374022025730036806358075325420793866358986719444785030579682635785758091517397518826225327945861556948820837789390500920096562699893770094581497500786817915616026940285194220703907757879335069896978124429681515117633335502362832425521219599726902327020044791308869970455616185847823063474157292399830070541968662959133724209945293515201291844650765335146840662879479678554559446535460674863857818111377905454946004143554616401168150446865964806314366426743287 -o ./keys/
[+] Saved private key /home/user/privkey1.pem
The script will try to get p and q as little and big endian.
Recover the SessionKey
from the stage 0 response of Covenant C2, which is employed to encrypt network traffic :
$ python3 decrypt_covenant_traffic.py key -i traffic.txt --key "EQCZiHdmVUQzIhEAmYh3ZlVEMyIRAJmId2ZVRDMiEQA=" -t base64 -r mykey.pem -s 1
[+] New AES key : 0011223344556677889900112233445566778899001122334455667788990011
Decrypt the Covenant communication :
$ python3 decrypt_covenant_traffic.py decrypt -i traffic.txt -k "0011223344556677889900112233445566778899001122334455667788990011" -t hex -s 2
[...]
[*] Response message 10 : {"status":"2","output":"Hello.\r\n"}
[...]
-
extract_privatekey
- Parse raw file. -
extract_privatekey
- Search private keys based on the header (without the modulus).
As mentioned on StackOverflow, decryption of data is also achievable by utilizing the raw Microsoft RSA private key.