← Back to Writeups
CUSTOMEasyReversing

Cosy

XESXOR9/10/20262 min read
#reversing#custom#easy#per_character_bruteforce#static_binary_analysis#symbol_table_analysis#trigonometric_reverse

Cosy

Platform: rev-kids20.forkbomb.ru | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-03-25 | Status: Solved Techniques: per_character_bruteforce, static_binary_analysis, symbol_table_analysis, trigonometric_reverse

Summary

Task: 64-bit ELF binary validates key using sin/cos trigonometric transformations. Solution: reverse character mapping and trig functions, brute-force each position independently against hardcoded expected values.

Cosy — Reverse Kids 2.0

Description

A 64-bit ELF x86-64 binary (not stripped, dynamically linked, PIE) that asks for a key and validates it using trigonometric functions.

The challenge name "cosy" is a hint about cosine. Binary asks for a key and validates it character by character using sin/cos transformations.

Analysis

Binary Info

  • File: ELF 64-bit LSB pie executable, x86-64, not stripped
  • Strings: "Give me the key: ", "Incorrect length", "Internal error", "Wrong input", "Correct!"
  • Functions: main, modify, toRad
  • Imports: cos, sin (libm), strlen, fgets, puts, exit ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Function Analysis

toRad function — Maps each character to an index (0-38):

  • a-z → 0-25
  • 0-9 → 26-35
  • { → 36
  • } → 37
  • _ → 38

modify function — Applies trigonometric transformation:

  • Converts index to radians: rad = index * π / 180
  • Even positions: sin(rad) * 10000
  • Odd positions: cos(rad) * 10000

main function:

  • Reads input via fgets
  • Checks input length is exactly 22
  • For each character, computes modify(toRad(char), position % 2)
  • Compares result against 22 hardcoded expected values
  • Prints "Correct!" if all match ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Brute-force each position independently: for each of the 22 positions, try all 39 possible characters (a-z, 0-9, {, }, _), compute the trig transformation, and find which character produces the expected hardcoded value.

python
#!/usr/bin/env python3
import math

# Character to index mapping (toRad function)
def to_rad(c):
    if 'a' <= c <= 'z':
        return ord(c) - ord('a')
    elif '0' <= c <= '9':
        return 26 + ord(c) - ord('0')
    elif c == '{':
        return 36
    elif c == '}':
        return 37
    elif c == '_':
        return 38
    return -1
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Trigonometric transformation (modify function)
def modify(index, pos):
    rad = index * math.pi / 180
    if pos % 2 == 0:
        return int(math.sin(rad) * 10000)
    else:
        return int(math.cos(rad) * 10000)

# Hardcoded expected values (extracted from binary)
expected = [...]  # 22 values from the binary

# Charset
charset = "abcdefghijklmnopqrstuvwxyz0123456789{}_"

# Brute-force each position
flag = ""
for pos in range(22):
    for c in charset:
        idx = to_rad(c)
        if idx >= 0 and modify(idx, pos) == expected[pos]:
            flag += c
            break
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

print(flag)  # spbctf{REDACTED}

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍