← Back to Writeups
CUSTOMEasyMisc

Условный реверс (Conditional Reverse)

XESXOR9/2/20263 min read
#misc#custom#easy#ascii_code_arithmetic#cell_dependency_resolution#xlsx_conditional_formatting_ex#linux

Условный реверс (Conditional Reverse)

Platform: bug-makers | Category: Misc | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-05-25 | Status: Solved Techniques: ascii_code_arithmetic, cell_dependency_resolution, xlsx_conditional_formatting_extraction

Summary

Task: Google Spreadsheet with conditional formatting rules on empty cells; reconstruct the flag by satisfying all rules. Solution: export as xlsx, parse conditional formatting with openpyxl, solve ASCII code arithmetic and cell dependency chains.

Условный реверс (Conditional Reverse) — Bug Makers CTF

Description

Нужно восстановить все символы флага так, чтобы они соответсвовали правилам условного форматирования в гугловой таблице. Ссылка на таблицу: https://docs.google.com/spreadsheets/d/14_eCC-Qyse0uUgxdm8yl5HDIJz9Jrqy7ZcdB7K_Na6Y/edit?gid=0#gid=0

English summary: A Google Spreadsheet titled "Реверс в экселе" (Reverse in Excel) contains conditional formatting rules on row 15. Some cells are pre-filled (BugCTF{...}), while cells F15–O15 are empty. The goal is to determine what value each empty cell must contain to satisfy its conditional formatting rule, thereby reconstructing the flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Analysis

Row 15 of the spreadsheet contains the flag spread across cells C15 through P15:

  • Pre-filled cells: C15="Bug", D15="CTF", E15="{", P15="}"
  • Empty cells to solve: F15 through O15

Each cell has a conditional formatting rule that turns the cell green (or applies some visual indicator) when the correct value is entered. The rules use various Google Sheets formula constructs:

  • Direct equality checks (cellIs equal)
  • String prefix matching (beginsWith)
  • Numeric range constraints (AND(x>2, x<4))
  • ASCII code arithmetic (CODE(), CHAR())
  • Cross-cell references creating dependency chains ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The key insight is that some cells depend on other cells' values, creating a dependency graph that must be resolved in the correct order.

Solution

Step 1: Export the spreadsheet as .xlsx

Google Sheets conditional formatting rules are not visible in CSV exports but are preserved in xlsx format:

bash
curl -L "https://docs.google.com/spreadsheets/d/14_eCC-Qyse0uUgxdm8yl5HDIJz9Jrqy7ZcdB7K_Na6Y/export?format=xlsx" -o spreadsheet.xlsx

Step 2: Extract conditional formatting rules

python
#!/usr/bin/env python3
import openpyxl
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

wb = openpyxl.load_workbook('spreadsheet.xlsx')
ws = wb.active

# Extract all conditional formatting rules
for cf in ws.conditional_formatting:
    for rule in cf.rules:
        cells = str(cf)
        print(f"Cells: {cells}")
        print(f"  Type: {rule.type}")
        print(f"  Operator: {rule.operator}")
        print(f"  Formula: {rule.formula}")
        print(f"  Text: {rule.text}")
        print()

Step 3: Solve each cell's rule

Solving order matters — start with cells that have direct constraints, then resolve dependent cells. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Phase 1: Direct constraints (no dependencies)

CellRule TypeConditionValue
C15cellIs equal"Bug"Bug (pre-filled)
D15cellIs equal"CTF"CTF (pre-filled)
E15cellIs equal"{"{ (pre-filled)
F15beginsWithLEFT(F15,LEN("s"))="s"s
G15cellIs equal"h"h
H15expressionAND(H15>2, H15<4)3 (only integer satisfying 2 < x < 4)
L15cellIs equal"_"_
M15expressionCODE(M15)=114r (chr(114) = 'r')
N15expressionCODE(N15)=101e (chr(101) = 'e')
O15expressionCODE(O15)=(120-2)v (120-2=118, chr(118) = 'v')
P15cellIs equal"}"} (pre-filled)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Phase 2: Dependent cells (resolved using Phase 1 values)

CellRule TypeConditionResolutionValue
I15expressionAND(I15=H15, I15<>"")Must equal H15=3, non-empty3
K15expressionCHAR(CODE(K15)-1)=M15M15='r', CODE('r')=114, so CODE(K15)-1=114 → K15=chr(115)s
J15expressionCHAR(CODE(J15)-1)=K15K15='s', CODE('s')=115, so CODE(J15)-1=115 → J15=chr(116)t

Step 4: Assemble the flag

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

C15  D15  E15  F15  G15  H15  I15  J15  K15  L15  M15  N15  O15  P15
Bug  CTF  {    s    h    3    3    t    s    _    r    e    v    }

Flag: BugCTF{REDACTED}

The flag content "sh33ts_rev" is leetspeak for "sheets_rev" (sheets reverse), a wordplay on the challenge theme of reverse-engineering Google Sheets conditional formatting. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍