Tags: misc

Rating:

# PlaidCTF 2019

## Space Saver

> we couldn't think of anything cute so [here](https://play.plaidctf.com/files/space_saver-90a5a93dfdda2d0333f573eb3fac9789.dd) you go

[ **misc** : 100pts ]

As this appeared to be an genuine .dd file, the first step was to simply mount the disk image:


mount -o loop space_saver-90a5a93dfdda2d0333f573eb3fac9789.dd /mnt/tmp


However, the only file that could initially be found did not contain the flag despite being named flag.png:

![flag.png](space-saver-flag.png)

Running various steganography tools against the image didn't uncover anything useful; however, the tildes (~) used in ~WIN~ suggested re-examining the original .dd and searching for **deleted** files. Using testdisk uncovered the following files which were duly extracted from the disk image:

The P.png, PP.png and PPP.png files were all identical and showed the CTF organiser's logo ([PPP](http://pwning.net/)). Again, steganography tools uncovered nothing. The space.rar file was more interesting, but unfortunately password-encoded.

While running some basic brute-forcing using john, I randomly decided to investigate the raw hex of the .dd file for more clues. Focusing primarily on the P/PP/PPP.png file data (as I was curious as to why they were hidden along with the .rar file), I uncovered the following near the IEND footers of each PNG:


00040260: 0000 4945 4e44 ae42 6082 0053 7061 6300 ..IEND.B..Spac.
00044260: 0000 4945 4e44 ae42 6082 0033 6569 3200 ..IEND.B..3ei2.
00048260: 0000 4945 4e44 ae42 6082 0068 6572 4500 ..IEND.B..herE.


Re-constructing the suspicious looking text into Spac3ei2herE provided the correct password to space.rar and allowed final.png to be extracted:

Flag:


PCTF{2pac3_3v34ry_wh3r3}


## A Whaley Good Joke

> You'll have a whale of a time with [this one](https://play.plaidctf.com/files/pctf-whales_169aeb74f82dcdceb76e36a6c4c22a89)! I couldn't decide what I wanted the flag to be so I alternated adding and removing stuff in waves until I got something that looked good. Can you dive right in and tell me what was so punny?

[ **misc** : 150pts ]

Used file to determine that the given download contained gzip compressed data before extracting the contents using tar. This extracted a bunch of directories (each containing layer.tar and some other unimportant files), 44922ae2...c67ff784.json and manifest.json.

I initially just decompressed all the layer.tar files after discovering references to /root/flag.sh within 44922ae2...c67ff784.json:

js
{
"container": "23e9240f8ca97d3bfba72f23a57703138fb3a16d7e3e19f7d5b80d177ab50b5d",
"created": "2019-04-13T20:58:53.322050465Z",
"os": "linux",
"container_config": {
"Tty": false,
"Cmd": [
"\/bin\/sh",
"-c",
"chmod +x .\/flag.sh && .\/flag.sh"
],
"Volumes": null,
"Domainname": "",
"WorkingDir": "\/root\/",
...
}


Unfortunately, after extracting everything in no particular order, running flag.sh resulted in output that was clearly not correct.


$./flag.sh pctf{1_b3tk4_auultn__s0lk3m7tr_ui2l7u_h_er}  A quick look at flag.sh showed that it was concatenating 32 files (also within /root) named using the numbers 1 through 32 (with later examination revealing that each file contained a single character). The fact that the resulting flag was incorrect suggested files had been overwritten, and that the **order** of extraction was important. bash #!/bin/bash for i in {1..32} do test -f$i
if [[ $? -ne 0 ]] then echo "Missing file$i - no flag for you!"
exit
fi
done

echo pctf{1_b3t\$(cat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32)}


The manifest.json file (and also 44922ae2...c67ff784.json) from the original archive confirmed a particular extraction sequence for the layer.tar files, however, the names of **21** of the 27 directories extracted from the archive had been masked.

js
{
"Layers": [
"7204dd4cdfd9b6d29a095cf1fd3b2e7efe366f191c31a75df4ea8e9f47a70801\/layer.tar",
"????????????????????????????????????????????????????????????????\/layer.tar",
"????????????????????????????????????????????????????????????????\/layer.tar",
"????????????????????????????????????????????????????????????????\/layer.tar",
...
"????????????????????????????????????????????????????????????????\/layer.tar",
"????????????????????????????????????????????????????????????????\/layer.tar",
"????????????????????????????????????????????????????????????????\/layer.tar",
"b94e5d83dbbff95e883f0f53bcf47c017471b13d81325697be6e22cdc8c369aa\/layer.tar",
"24d12bbeb0a9fd321a8decc0c544f84bf1f6fc2fd69fa043602e012e3ee6558b\/layer.tar"
],
...
}


The layer.tar files from those particular directories also happened to specify only revisions that added or deleted different numbers and combinations of the 32 files comprising the flag within /root. This step did require some searching to discover that .wh. files are special **whiteout** files used by Docker to represent file and folder deletion.

Using the above knowledge and the clue within the challenge description about alternated adding and removing stuff, I eventually realised that it might be possible to determine the correct extraction order based on the following two principles:

* No file can be deleted that doesn't exist (ie, it must be added first)
* No file can be added that currently exists (ie, it must have *not* been added yet or needs to be deleted first)

The code in [ [a-whaley-good-joke.py](a-whaley-good-joke.py) ] creates a tree structure of alternating ADD/DEL revision nodes that explores sequence orders of extractions which satisfy the above rules. A valid sequence order will have a tree depth of 21 (ie, using all the possible revisions). The script then extracts the files based on each valid sequence ordering and displays the potential flags.

There were actually 24 valid revision sequences combining for an assortment of possible flags:


Processing valid sequences ...
Extracting sequence #00 : pctf{1_b3tttzalkzgn_7s0lknq6___ui2l_u_h_er}
Extracting sequence #01 : pctf{1_b3tttzalkzgn_7s0lknq6___ui2l_u_h_er}
Extracting sequence #02 : pctf{1_b3tttzalkzgn_7s0lknq6___ui2l_u_h_er}
Extracting sequence #03 : pctf{1_b3tttzalkzgn_7s0lknq6___ui2l_u_h_er}
Extracting sequence #04 : pctf{1_b3t_u_couldnt_c0nt4in3r_ur_l4ught3r}
Extracting sequence #05 : pctf{1_b3t_u_couldnt0s0nt4in3e_urel4ught3r}
Extracting sequence #06 : pctf{1_b3t_u_couldnt0s0nt4in3e_urel4ught3r}
...


The correct result was determined by simply seeing which of the flags made sense:


pctf{1_b3t_u_couldnt_c0nt4in3r_ur_l4ught3r}
`

Original writeup (https://github.com/zhengzufu/ctf/tree/master/2019/2019-04-13-plaidctf#space-saver).