basic-mod1 picoCTF 2022 Solution

Published: July 20, 2023

Description

A list of integers is provided along with instructions to take each number mod 37 and map it onto a custom alphabet (A-Z, digits, underscore). Implement the mapping to decode the hidden flag.

Grab the message file and convert the space-separated numbers into a Python list.

Apply modulo 37 to each entry, then treat 0-25 as A-Z, 26-35 as digits, and 36 as an underscore.

Concatenate the recovered characters and wrap them with picoCTF{...}.

bash
wget https://artifacts.picoctf.net/c/128/message.txt
bash
cat message.txt
bash
sed -e "s/^/[/" -e 's/ *$//' -e "s/$/]/" -e "s/ /, /g" message.txt
python
python3 mod1.py
  1. Step 1Normalize the input
    Wrap the space-separated numbers as a Python list with one sed invocation, then iterate.
    Learn more

    One sed invocation, four -e expressions applied in order to the same stream: -e "s/^/[/" prepends [, -e 's/ *$//' trims trailing spaces, -e "s/$/]/" appends ], and -e "s/ /, /g" rewrites every space as , . The result is a valid Python list literal in one pass.

    You could just open the file in Python and call .split() - the sed trick is a habit, not a requirement. Useful when you want a single shell-pipeline solution.

  2. Step 2Map each value
    For every number n, compute n % 37 to keep it inside the alphabet range, then index into the character set ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.
    Learn more

    Modular arithmetic reduces a number to the remainder after dividing by a modulus. Here the modulus is 37 because the custom alphabet has exactly 37 characters (26 letters + 10 digits + 1 underscore). Any integer, no matter how large, maps to a value in 0..36 after % 37.

    The encoding rule is a simple positional table:

    index 0..25  -> 'A'..'Z'
    index 26..35 -> '0'..'9'
    index 36     -> '_'
    
    Worked example for n = 306:
      306 / 37 = 8.27...     (integer quotient = 8)
      8 * 37   = 296
      306 - 296 = 10         (remainder)
      alphabet[10] = 'K'
    
    More:
      617 % 37 = 25 -> 'Z'    (16 * 37 = 592, 617 - 592 = 25)
       28 % 37 = 28 -> '2'    (digit slot: 26 + 2)

    37 is prime, which means every non-zero value has a multiplicative inverse modulo 37 - a property the follow-up challenge basic-mod2 leans on.

    Python's % follows the divisor's sign: with a positive modulus the result is always in [0, m), even for negative dividends. C does not guarantee this; in C the sign can carry from the dividend, so -1 % 37 may give -1 instead of 36. A single comprehension - [alphabet[n % 37] for n in numbers] - is enough here.

  3. Step 3Assemble the flag
    Build a string starting with picoCTF{...} to produce the final answer.
    Learn more

    Once every integer is decoded into its character, joining the list with ''.join(chars) and wrapping it in the standard picoCTF{} format gives the submission-ready flag. This final assembly step is trivial but teaches an important habit: always verify the structure of your output matches what the challenge expects before submitting.

    The picoCTF{} wrapper is a flag format convention. Most CTF platforms use a consistent prefix (like flag{}, CTF{}, or competition-specific variants) so automated checkers can validate submissions. Recognizing these patterns helps you quickly confirm you decoded something correctly even before you know what the inner text means.

Flag

picoCTF{R0UND_N_R0UND_B6B...}

Simple modular arithmetic plus a custom alphabet turns the numeric sequence back into the plaintext flag.

Want more picoCTF 2022 writeups?

Tools used in this challenge

What to try next