random & Kindergarten
Cryptography · Харуул Занги U18: 2022 · unknown
random
Problem
Description:
XOR use custom random function
🧠 Understanding the Script
Initialization:
nis initialized as the current Unix time divided by 10000. This meansnstarts with a value based on when the script is run.xoris an empty list that will store the XORed values of the flag and the generated key.
random()Function:This function generates a pseudo-random number by performing a series of arithmetic operations on
n.The operations include additions, multiplications, XORs, and modulo operations.
Finally, it returns
n % 100, ensuring the result is between 0 and 99.
XOR()Function:Generates a key list where each element is a random number from the
random()function. The length of the key matches the length of the flag.Performs an XOR operation between each byte of the flag and the corresponding key byte, storing the result in the
xorlist.
Reading the Flag:
Reads the flag from
flag.txtand strips any extra whitespace.
Execution:
Calls
XOR()and prints the resulting XOR list.
🎯 Goal
We need to recover the original flag from this XOR list. To do this, we need to reverse the XOR operation, which requires knowing the key used. Since the key is generated based on the random() function, which depends on the initial n (derived from the time the script was run), we need to find the correct n that was used.
👽 Approach
Understand the
random()Function:The
random()function is deterministic given the same initialn. It performs a series of operations to generate the nextnand returnsn % 100.The sequence of
nvalues (and thus the key) depends solely on the initialn.
Brute-Force Initial
n:Since
nis derived from the Unix time divided by 10000, it's a large but not infinite range.However, the exact time isn't provided, so we need to find
nsuch that when we generate the key and XOR it with the givenxorlist, we get a meaningful flag (likely starting withflag{).
Generate Possible
nValues:Unix time is the number of seconds since January 1, 1970. As of now (2023), it's around 1.6 billion.
n = int(time.time() / 10000)would be around 160,000 to 170,000 for recent times.We can brute-force
nin this range, generate the key, and see if the decrypted flag makes sense.
Decryption Process:
For a candidate
n, generate the key sequence of the same length as thexorlist (36 bytes).XOR each element of the
xorlist with the corresponding key byte to get the original flag bytes.Check if the result is a printable string, especially starting with
HZ.
Exploitation Code
Kindergarten
Cryptography · Харуул Занги: 2024 · zjzoloo
🧠 Understanding the Code
Characters Used (
CHILDREN):CHILDRENis a string containing printable characters (letters and digits) plus'\\='. So, it's[a-zA-Z0-9\\=], totaling 64 characters (sincestring.printable[:62]is 62, plus 2 more).
Finite Field (
GF(64)):Z = list(GF(64))creates a list of elements in the finite field of order 64. This means each element inZcorresponds to a unique element inGF(64).
Mapping Characters to Field Elements (
maptokindergarten):maptokindergarten(c)takes a charactercfromCHILDRENand returns the corresponding element fromZbased on its index inCHILDREN.
Key Generation (
keygen):keygen(l)generates a key by selectinglrandom non-zero elements fromZ(sincerandint(1, 63)excludes 0) and multiplies them together (math.prod(key)). Here,l=14, so the key is the product of 14 random non-zero elements fromGF(64).
Encryption (
encrypt):First, the message (
msg) is base64 encoded (m64).Then,
pkeyis computed askey**5 + key**3 + key**2 + 1.For each byte
min the base64 encoded message:Convert
mto a character, map it toGF(64)usingmaptokindergarten.Multiply this by
pkeyinGF(64).Find the index of the resulting element in
Zand get the corresponding character fromCHILDREN.
Concatenate all these characters to form the encrypted string
enc.
Given Output:
Output: HudnBsx03TGdBIK4NS50=vlo=8NoMouoMSCdBLm9yoK41vl03M0Q
🎯 Goal
We need to recover the original flag from the given enc output, knowing how encrypt works.
👽 Approach
To decrypt, we need to reverse the encryption process:
Understand
pkey:pkey = key**5 + key**3 + key**2 + 1.Since operations are in
GF(64),pkeyis a polynomial inGF(64).
Decryption Steps:
For each character in
enc, find its index inCHILDRENto get the correspondingGF(64)element.To reverse the multiplication by
pkey, we need to multiply by the inverse ofpkeyinGF(64).Then, map the resulting
GF(64)element back to a character inCHILDREN.Finally, decode the resulting base64 string to get the original
flag.
Finding
pkey:The challenge is that we don't know
key, but we knowkeyis the product of 14 random non-zero elements inGF(64).However,
GF(64)is a field, so every non-zero element has a multiplicative inverse.The size of
GF(64)is small (64 elements), so we can brute-force possiblekeyvalues.
Brute-Forcing
key:Since
keyis the product of 14 non-zero elements, and multiplication inGF(64)is closed,keyis also a non-zero element.There are 63 possible non-zero elements for
key.For each possible
key, computepkey, then its inverse, and try to decryptenc.
Checking Valid Decryption:
After decrypting, we'll get a base64 string. Decoding this should give us printable characters (the flag).
We can check if the decoded result makes sense (e.g., starts with
HZ).
Exploitation Code
To run the exploit
sage exp.sageLast updated