Scope

The text that came as description with the CTF was the following:

Naming things is hard. This challenge is not. Just some simple math.

The only interesting file for this challenge was chal.py which looks like this:

from os import environ
from secrets import randbelow

from Crypto.Util.number import bytes_to_long

FLAG = bytes_to_long(environ.get("FLAG", "stairctf{redacted}").encode())

def main():
    randval = randbelow(FLAG)
    print(
        "You provide an integer 'm', and we return the result of (m ^ randval) % FLAG."
    )
    print(f"The FLAG is {len(str(FLAG))}-digits long. Good luck!")
    print("Type 'exit' to quit anytime.\n")

    while True:
        try:
            user_input = input("Enter an integer m: ")
            if user_input.lower() == "exit":
                print("Goodbye!")
                break

            m = int(user_input)

            result = pow(m, randval, FLAG)
            print(f"Result: (m ^ randval) % FLAG = {result}\n")
        except ValueError:
            print(
                "Invalid input. Please enter a valid integer or type 'exit' to quit.\n"
            )


if __name__ == "__main__":
    main()

Walkthrough

Even when executed there is the hint, that the calculation is (m ^ randval) % FLAG whereas randval is the same once the script is started. This means that if we enter -1 we either get 1 or FLAG - 1, depending on the randval. If you get 1 restart the application and try again until you get a really high number. With this number you can now do:

num = <number> + 1

length = (num.bit_length() + 7) // 8  # Calculate minimal number of bytes
byte_string = num.to_bytes(length, 'big')
print(byte_string.decode())

Which will print the decoded flag.