may your code be under par. execute the getflag binary somewhere in the filesystem to win  
`nc mc.ax 31774`  
[jail.zsh](https://gthub.com/Nightxade/ctf-writeups/blob/master/assets/CTFs/Dice-CTF-Quals-2024/jail.zshs)  
---
We're given a "zsh" jail file:  
```bash#!/bin/zshprint -n -P "%F{green}Specify your charset: %f"read -r charset# get uniq characters in charsetcharset=("${(us..)charset}")banned=('*' '?' '`')
if [[ ${#charset} -gt 6 || ${#charset:|banned} -ne ${#charset} ]]; then    print -P "\n%F{red}That's too easy. Sorry.%f\n"    exit 1fiprint -P "\n%F{green}OK! Got $charset.%f"charset+=($'\n')
# start jail via coproccoproc zsh -sexec 3>&p 4<&p
# read chars from fd 4 (jail stdout), print to stdoutwhile IFS= read -u4 -r -k1 char; do    print -u1 -n -- "$char"done &# read chars from stdin, send to jail stdin if validwhile IFS= read -u0 -r -k1 char; do    if [[ ! ${#char:|charset} -eq 0 ]]; then        print -P "\n%F{red}Nope.%f\n"        exit 1    fi    # send to fd 3 (jail stdin)    print -u3 -n -- "$char"done
```
Looking up zsh, I found out it was essentially just a Unix shell that's typically used in Macs. It didn't seem to actually impact the problem -- i.e. most Linux commands work just the same.  
Taking a look through the source code, the only constraints seemed to be 1. only 6 characters were allowed for use during each session and 2. the characters of "*", "?", and "\`" were blacklisted. THe blacklisted characters are two wildcards (\* and ?) and a backtick character, which allows for certain command executions.  
Immediately, I figured wildcards might be important for this challenge. I looked up wildcards for Linux, and found [this site](https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm) documenting all of them. Importantly, doing something like `[!x]` seemed to be potentially very useful, as it act basically like a `?`.  
After doing this, I ran `ls -al` on the service. This showed the following:  
```total 16drwxr-xr-x 1 nobody nogroup 4096 Feb  2 21:56 .drwxr-xr-x 1 nobody nogroup 4096 Feb  2 13:31 ..-rwxr-xr-x 1 nobody nogroup  795 Feb  2 21:55 rundrwxr-xr-x 1 nobody nogroup 4096 Feb  2 13:31 y0u```
Testing run with `./run` shows that it's just the binary version of the jail source file. We also have a directory named `y0u`. Let's list that out with `ls y0u`.  
```w1ll```
At this point, I figured it was going to be several nested directories spelling out some message starting with `y0u/w1ll`. Unfortunately, I wasn't sure how to list the next directories. In fact, I spent the next hour trying to figure out how to call `ls` on the next file using only 6 characters (I could only get it to work with 7) or test all possible directory name lengths with `[!.]` acting as a wildcard.  
Eventually, I realized that `ls` probably had a recursive function... wasted an hour of my life because of this T^T  
Sending `ls -R` to the service, I got:  
```.:runy0u
./y0u:w1ll
./y0u/w1ll:n3v3r_g3t
./y0u/w1ll/n3v3r_g3t:th1s
./y0u/w1ll/n3v3r_g3t/th1s:getflag```
So that's our path! `./y0u/w1ll/n3v3r_g3t/th1s/getflag`, Because of our useful wild card `[!.]`, we can specify our charset as `./[!]` and send `./[!.][!.][!.]/[!.][!.][!.][!.]/[!.][!.][!.][!.][!.][!.][!.][!.][!.]/[!.][!.][!.][!.]/[!.][!.][!.][!.][!.][!.][!.]` to execute the getflag binary.  
    dice{d0nt_u_jU5T_l00oo0ve_c0d3_g0lf?}
TL;DR: Not knowing ls had a recursive option cost me an hour of my life.  