1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-03-24 18:16:24 +01:00

Test AES-256-CBC and ChaCha20 crypto

This commit is contained in:
sjanusz-r7 2023-10-24 14:26:35 +01:00
parent 1bc7e3e3ae
commit cf1b82f07e
3 changed files with 41 additions and 15 deletions
gem
lib
spec/metasploit_payloads

@ -154,9 +154,6 @@ module MetasploitPayloads
raise e
end
encrypted_file = file_contents.start_with?(Crypto::ENCRYPTED_PAYLOAD_HEADER)
return file_contents unless encrypted_file
Crypto.decrypt(ciphertext: file_contents)
end

@ -65,8 +65,10 @@ module MetasploitPayloads
def self.decrypt(ciphertext: '')
raise ::ArgumentError, 'Unable to decrypt ciphertext: ' << ciphertext, caller unless ciphertext.to_s
return ciphertext unless ciphertext.start_with?('msf'.b)
# Use the correct algorithm based on the version in the header
_msf_header, cipher_version, iv_version, key_version = ciphertext.unpack('A3CCC')
msf_header, cipher_version, iv_version, key_version = ciphertext.unpack('A3CCC')
current_cipher = CIPHERS[cipher_version]
cipher = ::OpenSSL::Cipher.new(current_cipher[:name])
@ -77,8 +79,9 @@ module MetasploitPayloads
cipher.iv = iv
cipher.key = key
# Remove encrypted header if present
ciphertext = ciphertext.sub(ENCRYPTED_PAYLOAD_HEADER, '')
header = [msf_header, cipher_version, iv_version, key_version].pack('A*CCC').b
# Remove encrypted header
ciphertext = ciphertext.sub(header, '')
output = cipher.update(ciphertext)
output << cipher.final

@ -1,22 +1,48 @@
require 'spec_helper'
require 'metasploit-payloads'
RSpec.describe ::MetasploitPayloads::Crypto do
let(:plaintext) { "Hello World!".b }
describe '#encrypt' do
let(:encrypted_header) { ::MetasploitPayloads::Crypto::ENCRYPTED_PAYLOAD_HEADER }
let(:plaintext) { "Hello World!".b }
let(:encrypted_header) { "msf\x02\x01\x01".b }
let(:ciphertext) { encrypted_header + "F=\xF9\xCB\xF6\xA1\xE4h\x89\x96DD\xC0+\x04\xF1".b }
it 'can encrypt plaintext' do
it 'encrypts using aes-256-cbc' do
expect(described_class.encrypt(plaintext: plaintext)).to eq ciphertext
end
end
it 'can decrypt ciphertext' do
expect(described_class.decrypt(ciphertext: ciphertext)).to eq plaintext
end
describe '#decrypt' do
context 'when the ciphertext is' do
context 'encrypted with chacha20' do
let(:encrypted_header) { "msf\x01\x01\x01".b }
let(:ciphertext) { encrypted_header + "\x89:^r\xC1\xC9\xD9\xA1\xDC\xEB\xBFm".b }
it 'is idempotent' do
expect(described_class.decrypt(ciphertext: described_class.encrypt(plaintext: plaintext))).to eq plaintext
it 'returns plaintext' do
expect(described_class.decrypt(ciphertext: ciphertext)).to eq plaintext
end
end
context 'encrypted with aes-256-cbc' do
let(:encrypted_header) { "msf\x02\x01\x01".b }
let(:ciphertext) { encrypted_header + "F=\xF9\xCB\xF6\xA1\xE4h\x89\x96DD\xC0+\x04\xF1".b }
it 'returns plaintext' do
expect(described_class.decrypt(ciphertext: ciphertext)).to eq plaintext
end
end
context 'not encrypted' do
let(:ciphertext) { plaintext }
it 'returns plaintext' do
expect(described_class.decrypt(ciphertext: ciphertext)).to eq plaintext
end
end
end
end
it 'is idempotent' do
expect(described_class.decrypt(ciphertext: described_class.encrypt(plaintext: plaintext))).to eq plaintext
end
end