← Back to Writeups
CUSTOMEasyMisc

Product List

XESXOR9/2/20262 min read
#misc#custom#easy#fake_spreadsheet_decoding#online_decoder_usage#spammimic_format_recognition#text_steganography_decoding

Product List

Platform: hackerlab | Category: Misc | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-04-08 | Status: Solved Techniques: fake_spreadsheet_decoding, online_decoder_usage, spammimic_format_recognition, text_steganography_decoding

Summary

Task: a ZIP archive contains a plain-text expense sheet whose rows and dollar amounts look ordinary but actually encode hidden text in SpamMimic fake spreadsheet format. Solution: recognize the characteristic pattern, submit the full text to the SpamMimic decoder, and recover the embedded flag.

Product List — HackerLab

Description

Мама отправила меня в магазин купить подуктов, но тут явно что-то лишнее. Она точно ничего не перепутала?

English summary: the archive contains a single text file, products.txt, with spreadsheet-like rows of expenses and dollar amounts. The obvious numeric, ordering, and acrostic ideas do not immediately produce a result; the real goal is to identify the text as an encoded fake spreadsheet and decode it.

Analysis

Initial reconnaissance

The ZIP archive extracts to one file: products.txt. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Its content looks like a simple spreadsheet export:

text
Expenses
Entertainment,$52.14
Coffee Service,$8546.11
Gas,$701.84
Lodging,$415.88
Internet,$5.40
Insurance,$3.49
Phone,$29.84
Motor Vehicle,$267.84
Office Supplies,$65.79
Property Tax,$7.91
Software Licenses,$2.38
Security Alarm,$3.40
Transportation,$6.61
Loan Interest,$1.25
Maintenance,$7.95
Advertising,$360.63
Meals,$5

At first glance this suggests common text-puzzle ideas such as:

  • extracting letters from category names,
  • using integer or decimal parts of the numbers as indexes,
  • sorting rows by amount,
  • interpreting initials as an acrostic. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

None of these simple approaches produces anything useful.

Key recognition: SpamMimic fake spreadsheet

The breakthrough is recognizing that the file is not a real spreadsheet at all. Its structure matches the SpamMimic fake spreadsheet format: a title line followed by rows that look like business expenses with plausible labels and amounts.

Once that pattern is recognized, the task becomes straightforward: decode the full text with the SpamMimic spreadsheet decoder instead of trying to derive the flag manually from the visible values. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Identify the format

The important clue is that the entire file is already the ciphertext. Nothing needs to be reordered or partially extracted; the whole block should be treated as one encoded SpamMimic spreadsheet.

Step 2: Decode with SpamMimic

Open the SpamMimic spreadsheet decoder:

  • https://www.spammimic.com/spreadsheet.php?action=decode

Paste the complete contents of products.txt into the decoder and submit it.

The decoder returns:

text
CODEBY{REDACTED}

Optional automation script

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

The following script posts the fake spreadsheet to SpamMimic and extracts the decoded plaintext automatically:

python
#!/usr/bin/env python3
import html
import re
import requests

DATA = """Expenses
Entertainment,$52.14
Coffee Service,$8546.11
Gas,$701.84
Lodging,$415.88
Internet,$5.40
Insurance,$3.49
Phone,$29.84
Motor Vehicle,$267.84
Office Supplies,$65.79
Property Tax,$7.91
Software Licenses,$2.38
Security Alarm,$3.40
Transportation,$6.61
Loan Interest,$1.25
Maintenance,$7.95
Advertising,$360.63
Meals,$5"""
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

resp = requests.post(
    "https://www.spammimic.com/spreadsheet.php",
    data={
        "spreadsheet": DATA,
        "lang": "en",
        "action": "decode",
    },
    timeout=30,
)
resp.raise_for_status()

match = re.search(r"name='plaintext' value='([^']+)'", resp.text)
if not match:
    raise SystemExit("Could not extract decoded plaintext from response")

print(html.unescape(match.group(1)))

Running it prints:

text
CODEBY{REDACTED}

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