71c94a6452ada81c4387f5e31811488679f9df13 — Stick 7 months ago ee0b670
challenge writeup: squirrel
A content/stick/2022-02-09-challenge-writeup-squirrel/EVIL.jpg => content/stick/2022-02-09-challenge-writeup-squirrel/EVIL.jpg +0 -0
A content/stick/2022-02-09-challenge-writeup-squirrel/iamnotreal.zip => content/stick/2022-02-09-challenge-writeup-squirrel/iamnotreal.zip +0 -0
A content/stick/2022-02-09-challenge-writeup-squirrel/index.md => content/stick/2022-02-09-challenge-writeup-squirrel/index.md +180 -0
@@ 0,0 1,180 @@
title: "Challenge Writeup: Squirrel"
author: "Stick"
date: 2022-02-09


This little bugger caused me no end of grief the last two days.

It's part of a [ctf](https://ctftime.org/ctf-wtf/) challenge.
The text of the challenge reads as below.

> a picture tells a story. search for more details. [download](squirrel.zip)

The download link is a zipped file containing the squirrel image above.
Once unzipped, I checked the file out.

[bash 5.1.16] $ file squirrel.jpg
squirrel.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 180x180, segment length 16

Looks normal.
Running `strings` produces a ton of output; I find it's easier to start with longer bits and you don't even need `strings` if you have `grep`.

[bash 5.1.16] $ grep -aEo '[[:graph:]]{15,}' squirrel.jpg

That [mediafire link](https://www.mediafire.com/file/yuy6pf4pj3004em/iamnotreal.zip/file) looks interesting.
It gives you [iamnotreal.zip](iamnotreal.zip), which is an encrypted zip file.
No clue about the password, so I needed to crack it.
I started by trying [fcrackzip](https://pentaroot.com/cracking-encrypted-zip-fcrackzip/) (because it was in the [Arch Linux repositories](https://archlinux.org/packages/?q=fcrackzip)), but... it didn't work with the [rockyou wordlist](https://www.kaggle.com/wjburns/common-password-list-rockyoutxt).
Even running it with just a simple password input throws tons of errors.

[bash 5.1.16] $ fcrackzip -v -u -D -p /usr/share/wordlists/seclists/Passwords/Leaked-Databases/rockyou.txt iamnotreal.zip
*** buffer overflow detected ***: terminated
Aborted (core dumped)

[bash 5.1.16] $ fcrackzip -uvp squirrel iamnotreal.zip
found file 'evil/EVIL', (size cp/uc 415382/422982, flags 9, chk 982f)
sh: -c: line 1: unexpected EOF while looking for matching `"'
sh: -c: line 2: syntax error: unexpected end of file
sh: -c: line 1: unexpected EOF while looking for matching `"'
sh: -c: line 2: syntax error: unexpected end of file

Next try: [zip2john](https://linuxconfig.org/how-to-crack-zip-password-on-kali-linux).
I originally skipped over this option because I couldn't find it to install on Arch, but eventually I realized that's because it's [part](https://github.com/openwall/john/blob/bleeding-jumbo/src/zip2john.c) of [john](https://github.com/openwall/john), which _is_ [on Arch](https://archlinux.org/packages/?q=john).

[bash 5.1.16] $ zip2john iamnotreal.zip > iamnotreal.john
ver 2.0 efh 5455 efh 7875 iamnotreal.zip/evil/EVIL PKZIP Encr: 2b chk, TS_chk, cmplen=415382, decmplen=422982, crc=B9A27A8

[bash 5.1.16] $ john iamnotreal.john --wordlist=/usr/share/wordlists/seclists/Passwords/Leaked-Databases/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
squirrel07       (iamnotreal.zip/evil/EVIL)
1g 0:00:00:00 DONE (2022-02-10 09:22) 2.325g/s 2971Kp/s 2971Kc/s 2971KC/s swell!..slavemaster69
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Using the cracked password (`squirrel07`), `iamnotreal.zip` unzips to a folder called `evil` with one file in it, called `EVIL`.
What's scarier is the `evil/EVIL` file doesn't match a known filetype.

[bash 5.1.16] $ unzip iamnotreal.zip
Archive:  iamnotreal.zip
[iamnotreal.zip] evil/EVIL password:
  inflating: evil/EVIL

[bash 5.1.16] $ file evil/EVIL
evil/EVIL: data

`grep`ing for strings in `evil/EVIL` yielded another [mediafire link](https://www.mediafire.com/file/mp58jgugpsah96g/iamnotreal.zip/file), but it led to a missing file.
The contest organizers confirmed this was by design.

I tried a few file carvers: [binwalk](https://github.com/ReFirmLabs/binwalk), [foremost](http://foremost.sourceforge.net/), and [scalpel](https://github.com/sleuthkit/scalpel).
They all gave basically the same few results: two copies of a smaller (lower resolution) version of the original squirrel picture.
Out of curiosity, I ran the carver on the original `squirrel.jpg`.
Same result: two copies of the smaller version.

[bash 5.1.16] $ md5sum evilEVIL_output/jpg/* squirreljpg_output/jpg/*
489243ba7f9ba7998e4a777253ecde35  evilEVIL_output/jpg/00000002.jpg
489243ba7f9ba7998e4a777253ecde35  evilEVIL_output/jpg/00000015.jpg
489243ba7f9ba7998e4a777253ecde35  squirreljpg_output/jpg/00000002.jpg
489243ba7f9ba7998e4a777253ecde35  squirreljpg_output/jpg/00000016.jpg

So, it looks like our `EVIL` might be a ~~squirrel~~ [JPEG](https://docs.fileformat.com/image/jpeg/).
Attempting to open it in any number of image viewers failed, so I needed to look closely at the format.
I compared the first few bytes against `squirrel.jpg`.

[bash 5.1.16] $ xxd squirrel.jpg | head -n1
00000000: ffd8 ffe0 0010 4a46 4946 0001 0101 00b4  ......JFIF......

[bash 5.1.16] $ xxd evil/EVIL | head -n1
00000000: a119 74bc 0010 4a46 4946 0001 0101 0048  ..t...JFIF.....H

This seemed to confirm my suspicions: it looks like a JPEG, but is missing the file signature (in the first four bytes).
At this point things went off the rails and I got stuck.
The _right way_ to do this would be to open `evil/EVIL` in a hex editor, change the first four bytes, and save the file.
But no, I try it in [Vim, with `xxd`](https://vim.fandom.com/wiki/Improved_hex_editing).
I open it using the binary switch (`vim -b evil/EVIL`), run it through `xxd` (`:%!xxd`), and get a nice hex representation.
I change the first four bytes from `a119 74bc` to `ffd8 ffe0`, then use `xxd` to go back to binary (`:%!xxd -r`).
Hooray, right?
I try to open the file again in an image viewer and I get `Error interpreting JPEG image file (Invalid JPEG file structure: two SOI markers)`.
So I try a lot of other things: removing the first bit of the file (up to the next SOI marker `ffd8 ffe0`), which gets me "Error interpreting JPEG image file (Bogus DHT index 4)", looking more closely at the found strings, OSINT on the broken mediafire link, wasting hours and hours....

Eventually I asked, and the contest organizer confirmed that fixing the first four bytes should have resulted in a valid JPEG.
What had I done wrong?
I piped the original `evil/EVIL` and my "fixed" version each to `xxd` and then ran `diff` on the output, expecting to see that they only differed in the first four bytes.
Somehow my attempt to change only the first four bytes resulted in a radically different file.
PEBKAC, surely, so I tried it again, and again... and confirmed that whatever I was doing in Vim was not working.
I tried walking through the binary -> `xxd` -> binary steps in Vim, without changing anything: the file still changed.

[bash 5.1.16] $ md5sum EVIL.fix evil/EVIL
8902c2752e0a8e4a21eef405d4841c52  EVIL.fix
5cd6869c76d3ae42eb1a2b5cf27c299e  evil/EVIL

Based on [a StackOverflow post](https://vi.stackexchange.com/a/345), I think it has to do with file encodings, or something.
I tried everything I could think of to make Vim treat the file correctly, and time ran out on the contest.
Finally, I decided to [try `dd`](https://superuser.com/a/121039).
And it worked.

sh 5.1.16] $ echo -ne \\xff\\xd8\\xff\\xe0 | dd conv=notrunc bs=4 count=1 of=EVIL.jpg
1+0 records in
1+0 records out
4 bytes copied, 7.6742e-05 s, 52.1 kB/s

The file (the picture below) opened just fine, and the flag was had... too late.
I have [Bless](https://github.com/bwrsandman/Bless) and [hexcurse](https://github.com/LonnyGomes/hexcurse) installed now (makes a nice symmetry of names); I'll use one of those next time.


[bash 5.1.16] $ echo MZWGCZ33IV3DC3C7KM4XK2LSOIZWY6T5 | base32 -d

Then I saw [Braden Best's](http://gitlab.com/u/bradenbest) comment on the StackOverflow answer:

> The only thing that works is `:r !xxd file` (or `$ xxd file | vim -`) to read, and `:w !xxd -r > file` to write, but this is not ideal.
> [Braden Best](https://vi.stackexchange.com/users/16977/braden-best), Apr 1 2018 at 19:46

I tried it.
It worked.
I am very upset.

A content/stick/2022-02-09-challenge-writeup-squirrel/squirrel.jpg => content/stick/2022-02-09-challenge-writeup-squirrel/squirrel.jpg +0 -0
A content/stick/2022-02-09-challenge-writeup-squirrel/squirrel.zip => content/stick/2022-02-09-challenge-writeup-squirrel/squirrel.zip +0 -0