Flare-On 11 CTF Challenge Solutions – array

Challenge 3: array

If you know Yara rules, this challenge becomes a little easier to solve. But don’t worry, this challenge is not just about Yara rules. When we look inside “aray.7z” file, we see the contents of Yara rules file named “aray.yara”.

YARA rule file is highly complex, with a large number of conditions that include file size checks, bit wise operations, modular arithmetic, and hash validations.

Understanding the YARA Rule

The YARA rule under analysis is defined as follows:

import "hash"

rule aray
{
    meta:
        description = "Matches on b7dc94ca98aa58dabb5404541c812db2"
    condition:
        filesize == 85 and
        hash.md5(0, filesize) == "b7dc94ca98aa58dabb5404541c812db2" and
        uint8(7) & 128 == 0 and
        uint8(58) + 25 == 122 and
        uint8(36) + 4 == 72
        // ... many more conditions
}

This rule checks the file size (filesize), validates the MD5 hash of the entire file, and evaluates several logical and mathematical conditions on specific byte values. The goal is to identify files with a precise structure.

Reverse Engineering Process

1. Breaking Down the Rule

Each condition in the YARA rule specifies a characteristic of the target file. For example:

  • filesize == 85: The file must be exactly 85 bytes long.
  • hash.md5(0, filesize) == "b7dc94ca98aa58dabb5404541c812db2": The MD5 hash of the file must match the given value.
  • uint8(7) & 128 == 0: The 8th byte must have its highest bit unset.
  • uint8(58) + 25 == 122: The 59th byte must equal 97 (122 – 25).
  • uint8(36) + 4 == 72: The 37th byte must equal 68 (72 – 4).

This is a pretty long list of conditions, but in this section we see that we can extract the flag as decimal.

2. Applying the Conditions

Using these conditions, we can construct a target byte array that satisfies the rule:

byte_array = [0] * 85  # Create an array with 85 bytes, initialized to zero

# Apply conditions derived from the YARA rule
# Condition: uint8(7) & 128 == 0 -> Ensure the 8th byte's highest bit is not set
byte_array[7] &= 0x7F  # Clear the most significant bit (MSB)

# Condition: uint8(58) + 25 == 122 -> The 59th byte must be 97
byte_array[58] = 97  # Derived directly from the equation (122 - 25)

# Condition: uint8(36) + 4 == 72 -> The 37th byte must be 68
byte_array[36] = 68  # Derived directly from the equation (72 - 4)

# Additional conditions can be added similarly as per the rule's requirements

3. Validating the Hashes

To ensure the constructed byte array meets the hash requirements, we calculate the MD5, CRC32, and SHA256 values using Python’s hashlib and zlib libraries:

import hashlib
import zlib

# Calculate MD5 hash
md5_hash = hashlib.md5(bytes(byte_array)).hexdigest()
print(f"MD5: {md5_hash}")

# Calculate CRC32 hash for specific bytes
crc32_value = zlib.crc32(bytes(byte_array[8:10]))
print(f"CRC32: {hex(crc32_value)}")

If you want to check out the full code, here is my github link below:

https://github.com/sevkaz/flare-on11/blob/main/Challenge-3/yara_reverse.py

4. Verifying the Results

After applying the conditions and computing the hashes, the byte array should satisfy all the rule’s requirements. If we run the code in its completed form, we should see:

[114, 117, 108, 101, 32, 102, 108, 97, 114, 101, 111, 110, 32, 123, 32, 115, 116, 114, 105, 110, 103, 115, 58, 32, 36, 102, 32, 61, 32, 34, 49, 82, 117, 108, 101, 65, 68, 97, 121, 75, 51, 51, 112, 36, 77, 97, 198, 65, 13, 65, 51, 65, 119, 52, 121, 64, 102, 108, 97, 114, 101, 45, 111, 110, 46, 99, 111, 109, 34, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 126, 32, 36, 102, 32, 125]

This is the flag but it is in decimal format and we need to convert it to UTF8. Finally, the flag seems a bit complicated.

rule flareon { strings: $f = "1RuleADayK33p$MaÆ[email protected]" condition~ $f }

If we tidy up a bit

[email protected]

Leave a Reply

Your email address will not be published. Required fields are marked *