67 lines
2.3 KiB
Python
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)
|