2024-10-22 Rustline (Cryptography)
VirusTotal
VirusTotal
https://www.virustotal.com/gui/file/c1cafeca938971cdb2b0d71690e896ffbe75d3c4bc0c6554123ae983913917f7/behavior
I was onto it but just struggling with the walking to the scripting, I was able to get the chunks of Latin data but just not the flag section.
#!/usr/bin/env python3
def xor_bytes(b1, b2):
return bytes([x ^ y for x, y in zip(b1, b2)])
def recover_key_segments(file_pairs, additional_plaintexts):
key_stream = {}
key_pos = 0
# Recover key segments from known plaintext files
for item in file_pairs:
plaintext_file, ciphertext_file = item
with open(plaintext_file, 'rb') as f_plain:
plaintext = f_plain.read()
with open(ciphertext_file, 'rb') as f_cipher:
ciphertext = f_cipher.read()
min_length = min(len(plaintext), len(ciphertext))
plaintext = plaintext[:min_length]
ciphertext = ciphertext[:min_length]
key_segment = xor_bytes(plaintext, ciphertext)
for i in range(len(key_segment)):
key_stream[key_pos + i] = key_segment[i]
key_pos += len(key_segment)
# Recover key segments from additional known plaintexts
for known_plaintext, ciphertext_file, offset in additional_plaintexts:
with open(ciphertext_file, 'rb') as f_cipher:
ciphertext = f_cipher.read()
ciphertext_segment = ciphertext[offset:offset + len(known_plaintext)]
key_segment = xor_bytes(known_plaintext, ciphertext_segment)
for i in range(len(key_segment)):
key_stream[offset + i] = key_segment[i]
return key_stream
def decrypt_with_key_stream(ciphertext_file, key_stream):
with open(ciphertext_file, 'rb') as f_cipher:
ciphertext = f_cipher.read()
decrypted = bytearray(len(ciphertext))
for i in range(len(ciphertext)):
if i in key_stream:
decrypted[i] = ciphertext[i] ^ key_stream[i]
else:
decrypted[i] = ord('_') # Placeholder for unknown key positions
return decrypted
def main():
file_pairs = [
# Known plaintext-ciphertext pairs
('challenge-files/id_rsa_aws_ec2.pub', 'encrypted-files/id_rsa_aws_ec2.pub'),
('challenge-files/id_rsa_dba_srv.pub', 'encrypted-files/id_rsa_dba_srv.pub'),
('challenge-files/id_rsa_webserver.pub', 'encrypted-files/id_rsa_webserver.pub'),
('challenge-files/password.txt', 'encrypted-files/password.txt'),
('challenge-files/ovpn_config.ovpn', 'encrypted-files/ovpn_config.ovpn'),
]
# Add RSA private key header (for example, "-----BEGIN RSA PRIVATE KEY-----")
rsa_header = b"-----BEGIN OPENSSH PRIVATE KEY-----\n"
# Additional known plaintexts with offsets
additional_plaintexts = [
(rsa_header, 'encrypted-files/id_rsa_aws_ec2', 0), # Adjust for other RSA files similarly
]
# Add Lorem Ipsum and adjust for offsets
with open('encrypted-files/flag.txt', 'rb') as f_cipher:
flag_ciphertext = f_cipher.read()
# Standard Lorem Ipsum text
standard_lorem_ipsum = (
b'"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, '
b'totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. '
b'Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos '
b'qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, '
b'adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. '
b'Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea '
b'commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae '
b'consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"'
)
# Adjust the standard Lorem Ipsum to match the length of the ciphertext
min_length = min(len(standard_lorem_ipsum), len(flag_ciphertext))
standard_lorem_ipsum = standard_lorem_ipsum[:min_length]
# Insert the known parts of the Lorem Ipsum into the list of additional plaintexts
target_sentence = b'Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, '
sentence_index = standard_lorem_ipsum.find(target_sentence)
known_plaintext_before = standard_lorem_ipsum[:sentence_index]
known_plaintext_after = standard_lorem_ipsum[sentence_index + len(target_sentence):]
additional_plaintexts.extend([
(known_plaintext_before, 'encrypted-files/flag.txt', 0),
(known_plaintext_after, 'encrypted-files/flag.txt', sentence_index + len(target_sentence) + len('flag{REPLACE_WITH_FLAG}')),
])
key_stream = recover_key_segments(file_pairs, additional_plaintexts)
# Decrypt the flag file using the key stream
decrypted_flag = decrypt_with_key_stream('encrypted-files/flag.txt', key_stream)
print("Decrypted flag:")
decrypted_text = decrypted_flag.decode('utf-8', errors='ignore')
print(decrypted_text)
# Search for the flag in the decrypted text
if 'flag{' in decrypted_text:
start_idx = decrypted_text.find('flag{')
end_idx = decrypted_text.find('}', start_idx) + 1
if end_idx > start_idx:
flag = decrypted_text[start_idx:end_idx]
print(f"\nFlag found: {flag}")
else:
print("\n'flag{' found but no closing '}'.")
else:
print("\nFlag not found in the decrypted text.")
if __name__ == '__main__':
main()
Was really close with my own script, just missing something, also went down a rabbit whole of trying xortool
XOR a big enough file so we can walk back into the key
XorFiles v1.0
What it looks like, can see the reoccuring pattern
hex dump of it, with the key
b8f7 2ff6 9558 7745 b08f dc8e e71a df7e
flag{bfe12aadd139def4d47f5f51a539249d}
##########################################################################
Some more of troubleshooting the scripts
beginning and end or private key from decoding










