Description
The Multiverse is within your grasp! Unfortunately, the server that contains the secrets of the multiverse is in a universe where keyboards only have numbers and (most) symbols.
Setup
SSH to mimas.picoctf.net on port <PORT_FROM_INSTANCE> with password <PASSWORD_FROM_INSTANCE>.
Pressing Enter on an invalid command prints helpful error messages containing letters you can reuse.
Solution
Walk me through it- Step 1Capture an error message into a variablePick an invalid token like $ or ? and trap its error output in a variable. _1=
$ 2>&1runs the bare $ as a command, redirects stderr into stdout, and stores "bash: $: command not found" in $_1. Verify with echo "$_1" - if you see "bash: bash: $: command not found: command not found" you have your character source.bash_1=`$ 2>&1`bashecho "$_1"Learn more
The keyboard restriction blocks letters, but parameter expansion (
${_1:N:1}) does not require typing letters - it indexes into a string by position. By trappingbash's own error output we get a long string full of letters we can index into.$as a standalone command is the cleanest trigger because it parses, fails immediately, and produces exactly one line:bash: $: command not found.?works similarly. Wrapping in backticks runs the command in a subshell and captures its output; the2>&1redirection sends stderr (where the error actually lives) onto stdout so it can be captured. Without that redirection$_1would silently end up empty, and the next step would fail with no useful diagnostic. - Step 2Extract characters with parameter expansionBash ${var:offset:length} slices a substring out of a variable. Test locally first: echo "${_1:9:1}" should print c, and echo "${_1:10:1}" should print o. From the captured string "bash: bash: $: command not found: command not found", you can pluck b/a/s/h/c/o/m/n/d/t/f/u as needed.
Learn more
This is the heart of the trick. The captured error string contains the lower-case alphabet's commonly-used letters in fixed positions, so you can spell short command names like
echo,cat,sh, orbashby chaining slices.String: bash: bash: $: command not found: command not found Position: 0123456789012345678901234567890123456789012345678901 1111111111222222222233333333334444444444555 Useful indices (verify with: echo "${_1:N:1}"): ${_1:0:1} = b ${_1:1:1} = a ${_1:2:1} = s ${_1:3:1} = h ${_1:9:1} = c <- needed for /bin/echo ${_1:10:1} = o <- needed for /bin/echo ${_1:13:1} = m ${_1:15:1} = n ${_1:17:1} = d ${_1:19:1} = t ${_1:23:1} = f ${_1:24:1} = u - Step 3Locate the flag file with a globRun ./*/* and bash expands the glob to whatever paths exist; the listing here shows the flag at ./blargh/flag.txt, matching pattern ./*/????.???.bash
./*/*Learn more
./*/*expands to the list of files exactly one directory deep below the current directory. Bash tries to execute the first match as a command, which (helpfully) fails and prints the file path in the error message - giving you the path even when you can't type letters tols. The pattern./*/????.???later picks out the same path by structure (4-letter name, 3-letter extension). - Step 4Build /bin/echo from globs and slicesGlob /???/?${_1:9:1}?${_1:10:1} into the path /bin/echo. The /??? matches /bin (any 3-char directory under /), and the inner ?c?o pattern matches "echo" via positions 9 and 10 of $_1. The earlier attempt at /usr/bin/cat (/?${_1:2:1}?/???/??${_1:19:1}) failed because the ?s? prefix didn't expand to /usr on the box (the glob found no matches and bash printed "bash: /?s?/???/??t: No such file or directory").bash
/???/?${_1:9:1}?${_1:10:1}Learn more
Verify the glob expands the way you expect before using it as the command:
echo /???/?${_1:9:1}?${_1:10:1}should print/bin/echoand nothing else. If it prints multiple matches or the literal pattern, the glob is wrong and the command will not execute echo.When a glob has no match, bash on this image leaves the literal pattern in place, so the failure surface is "
/?s?/???/??t: No such file or directory" - the unmatched pattern itself appears in the error, which doubles as a diagnostic. That's the failure mode you should expect, and how you knew the/usr/bin/catpath's middle?s?wedge wasn't hitting/usr. - Step 5Read the flagCombine the constructed echo with bash process substitution: /???/?${_1:9:1}?${_1:10:1} "$(<./*/????.???)" prints the contents of ./blargh/flag.txt without ever typing the literal letters cat, less, or grep.bash
/???/?${_1:9:1}?${_1:10:1} "$(<./*/????.???)"Learn more
$(<file)is a bash builtin that reads the contents offilewithout spawningcat; it's the bash idiom for "file slurp." Combined with the globbed-upecho, the final command never types any disallowed character but still prints the flag contents.
Flag
picoCTF{7h15_mu171v3r53_15_m4dn355_145...}
There are multiple paths through this challenge - the key insight from the hint 'Where can you get some letters?' is to harvest characters from error messages and use bash parameter expansion to build valid commands.