Enhance! picoCTF 2022 Solution

Published: July 20, 2023

Description

Despite the hint to "enhance," there's no need to zoom the image; just read the text stored in the SVG file.

Run strings or open the SVG in a text editor.

Grep for lines containing > / < and strip the XML tags to reveal the embedded characters.

bash
strings drawing.flag.svg | grep ">" | cut -d '>' -f2 | cut -d '<' -f1 | tr -d '\n '
  1. Step 1Treat the SVG as text
    SVG files are XML, so you can view them as text. The flag's letters appear as separate <text> nodes.
    Learn more

    SVG (Scalable Vector Graphics) is an XML-based image format that describes graphics through markup rather than pixels. Unlike raster formats (PNG, JPEG), SVG files are plain text that a browser or renderer interprets - you can open one in any text editor and read the underlying structure directly.

    Because SVG is XML, it embeds arbitrary text inside <text> elements. That XML stays in the file even when the renderer hides it. Authors can shrink the font (font-size="0.1pt"), position the text outside the canvas (x="-9999"), set visibility="hidden", or use color matching the background. None of those affect the underlying XML; strings reads them verbatim.

    The challenge title references the TV trope of endlessly enhancing low-resolution images to reveal hidden detail. The joke is that the real "enhancement" is recognizing that SVG is text, not a bitmap - no image processing needed.

  2. Step 2Remove the markup
    Strip the tags, drop whitespace, and concatenate. Build it up step by step so you can sanity-check each stage.
    bash
    strings drawing.flag.svg | grep '>'
    bash
    strings drawing.flag.svg | grep '>' | cut -d '>' -f2
    bash
    strings drawing.flag.svg | grep '>' | cut -d '>' -f2 | cut -d '<' -f1
    bash
    strings drawing.flag.svg | grep '>' | cut -d '>' -f2 | cut -d '<' -f1 | tr -d '\n '
    bash
    xmlstarlet sel -t -v "//text()" drawing.flag.svg | tr -d '\n '
    Learn more

    Walk the pipeline left to right. strings ... | grep ">" filters to lines that contain at least one tag terminator - i.e. lines with text content sitting next to markup. cut -d '>' -f2 keeps everything to the right of the first >, dropping the opening tag. cut -d '<' -f1 keeps everything to the left of the next <, dropping the closing tag. What survives is the inner text. tr -d '\n ' collapses the per-character lines into one continuous string - that's your flag.

    The pipeline is fragile (multiple tags per line, attributes containing >, mixed content all break it) but fast enough for well-formed simple SVG. For anything bigger, use a real XML parser: xmlstarlet sel -t -v "//text()" drawing.flag.svg uses XPath to extract all text nodes regardless of layout. Python's xml.etree.ElementTree works too:

    import xml.etree.ElementTree as ET
    tree = ET.parse('drawing.flag.svg')
    print(''.join(t.strip() for t in tree.getroot().itertext()))

Flag

picoCTF{...}

Sometimes "enhancing" means simply inspecting the source.

Want more picoCTF 2022 writeups?

Useful tools for Forensics

Related reading

What to try next