Challenge Overview

Challenge Name Category Difficulty Link
Sugar Free Candies Crypto Very Easy Link to Challenge

Description

An image to describe post

For years, strange signals pulsed through the air on the eve of October 31st. Some said it was the voice of an ancient witch, while others believed it was a message from something far darker. A cryptic message, scattered in three parts, was intercepted by a daring group of villagers. Legend spoke of a deal made between the witch and a shadowy figure, but the true intent of their secret could only be revealed by those brave enough to decipher it before midnight, when the veil between worlds would thin.

Process

Upon downloading the assistive ZIP file, I found two files: output.txt and source.py.

Contents of output.txt

v1 = 4196604293528562019178729176959696479940189487937638820300425092623669070870963842968690664766177268414970591786532318240478088400508536
v2 = 11553755018372917030893247277947844502733193007054515695939193023629350385471097895533448484666684220755712537476486600303519342608532236
v3 = 14943875659428467087081841480998474044007665197104764079769879270204055794811591927815227928936527971132575961879124968229204795457570030
v4 = 6336816260107995932250378492551290960420748628

Contents of source.py

FLAG = open("flag.txt", "rb").read() 

step = len(FLAG) // 3 
candies = [bytes_to_long(FLAG[i:i+step]) for i in range(0, len(FLAG), step)] 

cnd1, cnd2, cnd3 = candies 

with open('output.txt', 'w') as f:     
	f.write(f'v1 = {cnd1**3 + cnd3**2 + cnd2}\n')     
	f.write(f'v2 = {cnd2**3 + cnd1**2 + cnd3}\n')
	f.write(f'v3 = {cnd3**3 + cnd2**2 + cnd1}\n')
	f.write(f'v4 = {cnd1 + cnd2 + cnd3}\n')

The source.py script reads a file named flag.txt, splits its content into three parts, converts them into long integers, and writes four calculated values (v1, v2, v3, v4) to output.txt.

Breakdown of the Calculation:

  1. The FLAG (content from flag.txt) is divided into three equal parts.
  2. These parts are converted to long integers (cnd1, cnd2, cnd3).
  3. The script performs mathematical operations on these integers and writes the results to output.txt.

Specifically:

  • v1 is calculated as $cnd1^3+cnd3^2+cnd2.$
  • v2 is calculated as $cnd2^3+cnd1^2+cnd3.$
  • v3 is calculated as $cnd3^3+cnd2^2+cnd1.$
  • v4 is the sum of $cnd1+cnd2+cnd3.$

Decoding the Flag

To decrypt output.txt and retrieve the flag, I needed to reverse these mathematical operations defined in source.py. Using v4, I know the sum of cnd1, cnd2, and cnd3, so I can treat this as a system of equations and solve for cnd1, cnd2, and cnd3 (kind of high school math, lol).

System of Equations:

  1. $cnd1^3+cnd3^2+cnd2=v1$
  2. $cnd2^3+cnd1^2+cnd3=v2$
  3. $cnd3^3+cnd2^2+cnd1=v3$
  4. $cnd1+cnd2+cnd3=v4$

From Equation 4: $cnd3=v4−cnd1−cnd2$

Substituting into the First Equation:

Substituting the expression for cnd3 into the first equation gives: $cnd1^3+(v4−cnd1−cnd2)^2+cnd2=v1$

Expanding this results in a more complex equation. The same substitution process is applied to the other equations as well.

Implementing the Decryption

I then wrote a script to decrypt the text based on the derived equations.

from sympy import symbols, Eq, solve from Crypto.Util.number import long_to_bytes  

v1 = 4196604293528562019178729176959696479940189487937638820300425092623669070870963842968690664766177268414970591786532318240478088400508536 
v2 = 11553755018372917030893247277947844502733193007054515695939193023629350385471097895533448484666684220755712537476486600303519342608532236 
v3 = 14943875659428467087081841480998474044007665197104764079769879270204055794811591927815227928936527971132575961879124968229204795457570030 
v4 = 6336816260107995932250378492551290960420748628  

eq1 = Eq(cnd1**3 + cnd3**2 + cnd2, v1) 
eq2 = Eq(cnd2**3 + cnd1**2 + cnd3, v2) 
eq3 = Eq(cnd3**3 + cnd2**2 + cnd1, v3) 
eq4 = Eq(cnd1 + cnd2 + cnd3, v4)  

solutions = solve((eq1, eq2, eq3, eq4), (cnd1, cnd2, cnd3))  

cnd1_value = sol[0]     
cnd2_value = sol[1]     
cnd3_value = sol[2]          

flag_part1 = long_to_bytes(cnd1_value)     
flag_part2 = long_to_bytes(cnd2_value)     
flag_part3 = long_to_bytes(cnd3_value)          

flag = flag_part1 + flag_part2 + flag_part3     

print(f"Decrypted flag: {flag.decode('utf-8', errors='ignore')}")`

Explanation of the Script

  • Libraries Used:

    • sympy is used for symbolic mathematics to solve the equations.
    • Crypto.Util.number provides utilities for converting long integers to byte strings.
  • Equations Setup: The equations derived from the initial problem are set up using Eq().

  • Solving the Equations: The solve() function finds the values of cnd1, cnd2, and cnd3.

  • Reconstructing the Flag: The flag parts are converted back to bytes and concatenated to reveal the full flag.

After executing the script, I successfully recovered the flag.

An image to describe post