Files
ctf/2026/cscg/rev/connivance/find_flag.py
2026-03-24 00:35:37 +01:00

67 lines
2.3 KiB
Python

import hashlib
def bitwise_not(data: bytes) -> bytes:
"""Inverts all bits in the byte array."""
return bytes(~b & 0xFF for b in data)
def shift_right_1(data: bytes) -> bytes:
"""
Shifts the entire byte array to the right by 1 bit.
Note: This implementation assumes a forward-flowing carry (byte 0 to byte N).
If the VM's BigInt implementation is little-endian, you might need to reverse
the carry logic so it flows from index i+1 to i.
"""
result = bytearray(len(data))
carry = 0
for i in range(len(data)):
# Shift current byte right by 1, and OR it with the carry from the previous byte
result[i] = (data[i] >> 1) | carry
# The lowest bit of the current byte becomes the MSB carry for the next byte
carry = (data[i] & 1) << 7
return bytes(result)
def check_flag(test_flag: bytes, target_hash_blob: bytes) -> bool:
"""Simulates the VM's flag verification logic."""
# 1. Length Check
if len(test_flag) != 29:
print(f"[-] Incorrect length: {len(test_flag)}. Must be 29 bytes.")
return False
# 2. Initial Mutation (BITWISE_NOT)
current_state = bitwise_not(test_flag)
# 3. The Shift-and-Hash Loop
generated_blob = bytearray()
for iteration in range(8):
# Compute SHA256 of the current state
current_hash = hashlib.sha256(current_state).digest()
generated_blob.extend(current_hash)
# Shift the state right by 1 bit for the next iteration
current_state = shift_right_1(current_state)
# 4. Final Verification
if generated_blob == target_hash_blob:
print("[+] Correct! Flag matches.")
return True
else:
print("[-] Incorrect! Hash mismatch.")
return False
# ==========================================
# Example Usage
# ==========================================
if __name__ == "__main__":
# TODO: Load the actual 256-byte target blob from 'romfs:/dragonfly.bin'
# Here is a dummy 256-byte array for testing the script structure
with open("./romfs/damocles.bin", "rb") as flag_hash:
dragonfly_bin_data = flag_hash.read()
# The flag you want to test
my_test_flag = b"dach2026{dummy_test_flag_pay}" # Exactly 29 bytes
check_flag(my_test_flag, dragonfly_bin_data)