2024-10-22 Rustline (Cryptography)

image.png

VirusTotal
VirusTotal
https://www.virustotal.com/gui/file/c1cafeca938971cdb2b0d71690e896ffbe75d3c4bc0c6554123ae983913917f7/behavior

image.png

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

image.png

XOR a big enough file so we can walk back into the key

XorFiles v1.0
https://www.nirsoft.net/utils/xorfiles.html

image.png

What it looks like, can see the reoccuring pattern

image.png

hex dump of it, with the key

b8f7 2ff6 9558 7745 b08f dc8e e71a df7e

image.png

image.png

flag{bfe12aadd139def4d47f5f51a539249d}

image.png

##########################################################################

Some more of troubleshooting the scripts

image.png

image.png

beginning and end or private key from decoding

image.png