I am trying to solve this CTF challenge:
#!/usr/bin/env python3

from hashlib import md5, sha1, sha256
from datetime import datetime

print("Try to login on my super safe computer! Be fast, you have at most 30 minutes.")

now = str(datetime.now())
print(now)

try:
	m = bytes.fromhex(input())
except:
	print("Access denied!")
	exit(1)

t = sha256(now.encode()).hexdigest()
if t.encode() not in m:
	print("Access denied!")
	exit(1)

if not md5(m).hexdigest().endswith("fc5c25"):
	print("Access denied!")
	exit(1)

if not sha1(m).hexdigest().endswith("fc5c25"):
	print("Access denied!")
	exit(1)

print("Welcome! Here is your flag:")
print(open("flag.txt").read())


My latest attempt (with a shorter suffix for testing purposes):

import hashlib
import time
import binascii  # For bytes.fromhex

def solve_challenge(target_suffix_hex, timestamp_str):
    """
    Finds an input for the CTF challenge.

    Args:
        target_suffix_hex (str): The desired suffix for SHA1 and MD5 hashes (e.g., "fc5c25").
        timestamp_str (str): The timestamp string (e.g., "2025-04-24 20:38:02.110961").
    """
    print(f"Target suffix: '{target_suffix_hex}'")
    print(f"Using timestamp string: '{timestamp_str}'")

    # 1. Calculate SHA256(timestamp)
    ts_bytes = timestamp_str.encode('utf-8')
    sha256_of_ts_hex = hashlib.sha256(ts_bytes).hexdigest()
    print(f"SHA256(timestamp) to embed: {sha256_of_ts_hex}")

    nonce_int = 0
    # Choose nonce length (in hex chars). 8 hex chars = 4 bytes.
    # This allows 2^32 possibilities, good for up to 4-char suffix.
    nonce_hex_len = 8

    max_attempts_for_suffix_len = {
        1: 16 ** 2 * 2,  # ~500
        2: 16 ** 4 * 2,  # ~130k
        3: 16 ** 6 * 2,  # ~33M
        4: 16 ** 8 * 2,  # ~8.6B
        5: 16 ** 10 * 2,  # ~1.1T
        6: 16 ** 12 * 2  # ~281T
    }
    # Safety break: max attempts overall or based on suffix length
    max_nonce_val = max_attempts_for_suffix_len.get(len(target_suffix_hex), 2 ** 32)  # Default to 4-byte nonce space
    # Max attempts for a typical CTF runnable time (e.g. 50 million for L=3)
    # Adjust practical_max_attempts as needed based on typical CTF time limits
    practical_max_attempts = 100 * 1000 * 1000 * 1000
    if len(target_suffix_hex) > 3:
        print(
            f"Warning: Suffix length {len(target_suffix_hex)} may require many attempts (expected ~16^{2 * len(target_suffix_hex)}).")

    start_time = time.time()

    while nonce_int < max_nonce_val:
        # 2. Construct input_hex_string
        nonce_hex = format(nonce_int, f'0{nonce_hex_len}x')  # e.g., "00000000", "00000001", ...

        # Option A: Nonce before timestamp hash
        submitted_hex_string = nonce_hex + sha256_of_ts_hex
        # Option B: Nonce after timestamp hash
        # submitted_hex_string = sha256_of_ts_hex + nonce_hex

        try:
            input_bytes = binascii.unhexlify(submitted_hex_string)
        except binascii.Error as e:
            print(f"Error unhexlifying input '{submitted_hex_string}': {e}")
            # This shouldn't happen if nonce_hex and sha256_of_ts_hex are valid hex
            # and their combined length is even. sha256_of_ts_hex is 64 chars (even).
            # nonce_hex_len=8 is also even. So total length is even.
            nonce_int += 1
            continue

        # 3. Calculate Hashes
        sha1_hash = hashlib.sha1(input_bytes).hexdigest()
        md5_hash = hashlib.md5(input_bytes).hexdigest()

        # Progress indicator
        if nonce_int > 0 and nonce_int % 500000 == 0:
            elapsed_time = time.time() - start_time
            rate = nonce_int / elapsed_time if elapsed_time > 0 else float('inf')
            print(f"Attempt {nonce_int:10d} ({rate:,.0f} hashpairs/sec)... "
                  f"SHA1 ends: ...{sha1_hash[-len(target_suffix_hex):]}, "
                  f"MD5 ends: ...{md5_hash[-len(target_suffix_hex):]}")

        # 4. Check Suffixes
        if sha1_hash.endswith(target_suffix_hex) and \
                md5_hash.endswith(target_suffix_hex):
            end_time = time.time()
            print(f"\n--- Solution Found! ---")
            print(f"Time taken: {end_time - start_time:.2f} seconds")
            print(f"Attempts: {nonce_int + 1}")
            print(f"Submitted Hex Input: {submitted_hex_string}")
            # print(f"Bytes Hashed (hex): {input_bytes.hex()}")
            print(f"SHA1: {sha1_hash}")
            print(f"MD5: {md5_hash}")
            return submitted_hex_string

        nonce_int += 1
        if nonce_int > practical_max_attempts and practical_max_attempts < max_nonce_val:
            print(f"Stopped after {practical_max_attempts} attempts due to practical limit.")
            break

    print(f"\nNo solution found within {nonce_int} attempts.")
    return None


if __name__ == '__main__':
    # --- Configuration for the challenge ---
    # Replace with the actual suffix provided by the CTF
    TARGET_SUFFIX = "5c25" #"fc5c25"  # Corrected suffix

    # Replace with how you get the timestamp for the challenge
    # If the server gives it to you, use that.
    # If it's server's current time, you need to be fast or predict it.
    # For testing, we can use a fixed string or current local time.
    current_timestamp_str = "2025-04-24 20:38:02.110961"  # Example fixed timestamp

    # --- Run the solver ---
    solution_hex = solve_challenge(TARGET_SUFFIX, current_timestamp_str)

    if solution_hex:
        print(f"\nThe input to submit (hex string) is: {solution_hex}")
    else:
        print("\nFailed to find a solution within the attempt limit.")




Any better ideas than that brute-force approach?