# Appnote.txtmisc | 50pts | 210 solves
## DescriptionEvery single archive manager unpacks this to a different file...
## First ImpressionsThe challenge comes with an zip file called `dump.zip`. Unzipping it results in a file called `hello.txt` containing the following text:
```txt
There's more to it than meets the eye...
```
From the challenge description and the text from `hello.txt`, we can guess that there are some hidden files. I checked the zip file with `binwalk`, and we can find A LOT of hidden files.
```bashDECIMAL       HEXADECIMAL     DESCRIPTION--------------------------------------------------------------------------------0             0x0             Zip archive data, v0.0 compressed size: 41, uncompressed size: 41, name: hello.txt135           0x87            Zip archive data, v0.0 compressed size: 33, uncompressed size: 33, name: hi.txt256           0x100           Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag00345           0x159           Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag00434           0x1B2           Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag00523           0x20B           Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag00612           0x264           Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag00...60598         0xECB6          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1860687         0xED0F          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1860776         0xED68          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1860865         0xEDC1          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1860954         0xEE1A          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1861043         0xEE73          Zip archive data, v0.0 compressed size: 1, uncompressed size: 1, name: flag1861572         0xF084          End of Zip archive, footer length: 22```The names range from flag00.zip to flag18.zip, and each file name appears 36 times. Interesting, maybe we can find something if we check the strings in this zip file?
```txtV~uK)hello.txtThere's more to it than meets the eye...V~uK)hello.txtPKhi.txtFind a needle in the haystack...hi.txtPKflag00aPKflag00PKflag00bPKflag00PKflag00cPKflag00PK...flag18{PKflag18PKflag18CPKflag18PKflag18TPKflag18PKflag18FPKflag18PKflag180PKflag18PKflag181PKflag18PKflag183PKflag18PKflag187PKflag18PKflag18}PKflag18PKflag18_PKflag18PK```
Each file name is followed by a character, which is one of the following: all lowercase letters (`a-z`), `{`, `C`, `T`, `F`, `0`, `1`, `3`, `7`, `}`, `_`. From the range of characters, it looks like extracting the right files would make the flag. We need to find out which files to extract.
## Searching for the SolutionI came across [this Stack Overflow post](https://stackoverflow.com/questions/4802097/how-does-one-find-the-start-of-the-central-directory-in-zip-files) in my searches. What caught my eye was the name APPNOTE.TXT in the question, which is the name of this challenge.
[APPNOTE.TXT](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT) happens to be the document containing the file format specification for the ZIP file. With that I figured that I would have to look into the hex bytes for something.
The second thing that caught my eye was the term "central directory". I knew a bit about the ZIP file structure, but needed to look it up more in detail.
### Central directory: a short introduction
The central directory consists of[^1] :- central directory file headers, which point to files in the archive and contain additional metadata.- end of central directory record or EOCDR, which is used by zip tools to correctly read and extract files from the archive. This structure contains information about the archive and points to the start of the central directory, which further points to the data in the archive.
File structure from APPNOTE.TXT```4.3.16  End of central directory record:
      end of central dir signature    4 bytes  (0x06054b50)      number of this disk             2 bytes      number of the disk with the      start of the central directory  2 bytes      total number of entries in the      central directory on this disk  2 bytes      total number of entries in      the central directory           2 bytes      size of the central directory   4 bytes      offset of start of central      directory with respect to      the starting disk number        4 bytes      .ZIP file comment length        2 bytes      .ZIP file comment       (variable size)```
The APPNOTE also mentioned that a ZIP file must have only one EOCDR. So, maybe checking the EOCDR segment of the ZIP file will help find out which files to extract?
## Solution
The EOCDR begins with the hex bytes `50 4B 05 06` (big-endian). After opening the file in a hex editor (UltraEdit in my case) I searched for the hex bytes. And...there's multiple results, specifically 21 of them?
```txt50 4B 05 06 00 00 00 00 01 00 01 00 00 EE 00 00 CC 00 00 0050 4B 05 06 00 00 00 00 01 00 01 00 5A E4 00 00 88 0A 00 0050 4B 05 06 00 00 00 00 01 00 01 00 93 D7 00 00 65 17 00 0050 4B 05 06 00 00 00 00 01 00 01 00 CC CA 00 00 42 24 00 0050 4B 05 06 00 00 00 00 01 00 01 00 69 BF 00 00 BB 2F 00 0050 4B 05 06 00 00 00 00 01 00 01 00 CE B6 00 00 6C 38 00 0050 4B 05 06 00 00 00 00 01 00 01 00 29 A5 00 00 27 4A 00 0050 4B 05 06 00 00 00 00 01 00 01 00 E7 9C 00 00 7F 52 00 0050 4B 05 06 00 00 00 00 01 00 01 00 42 8B 00 00 3A 64 00 0050 4B 05 06 00 00 00 00 01 00 01 00 21 86 00 00 71 69 00 0050 4B 05 06 00 00 00 00 01 00 01 00 71 73 00 00 37 7C 00 0050 4B 05 06 00 00 00 00 01 00 01 00 66 70 00 00 58 7F 00 0050 4B 05 06 00 00 00 00 01 00 01 00 E3 59 00 00 F1 95 00 0050 4B 05 06 00 00 00 00 01 00 01 00 AC 52 00 00 3E 9D 00 0050 4B 05 06 00 00 00 00 01 00 01 00 A2 47 00 00 5E A8 00 0050 4B 05 06 00 00 00 00 01 00 01 00 8E 33 00 00 88 BC 00 0050 4B 05 06 00 00 00 00 01 00 01 00 9A 2A 00 00 92 C5 00 0050 4B 05 06 00 00 00 00 01 00 01 00 16 1C 00 00 2C D4 00 0050 4B 05 06 00 00 00 00 01 00 01 00 38 15 00 00 20 DB 00 0050 4B 05 06 00 00 00 00 01 00 01 00 2F 02 00 00 3F EE 00 0050 4B 05 06 00 00 00 00 01 00 01 00 34 F0 00 00 50 00 00 00```When checking for hidden files in `dump.zip`, we found a total of 21 unique file names:- hello.txt- hi.txt- flag00 to flag18
OH! Each EOCDR corresponds to each of the files in the archive. And since we have multiple files with the same name for flag00 to flag18, the EOCDR will help to point out which file to extract, LETSGO!
To understand the data in the records better, here is a representation with one of the records as an example
```txt50 4B 05 06 00 00 00 00 01 00 01 00 5A E4 00 00 88 0A 00 00
50 4B 05 06     end of central dir signature 00 00           number of this disk00 00           number of the disk with the start of the central directory01 00           total number of entries in the central directory on this disk01 00           total number of entries in the central directory5A 34           size of the central directory00 00 88 0A     offset of start of central directory with respect to the starting disk number00 00           .ZIP file comment length```
The data significant for the solution is the "offset of start of central directory with respect to the starting disk number". In short, this points to the start of the central directory. In the above example, the address is 0x0000880a in big-endian, or 0x00000a88 in little-endian. I entered the address (in little-endian format) in the hex editor and it points to the central directory header (40 5B 01 02). We can see the character 'C' 1 byte before the file header (highlighted). As the flag begins with `CTF`, I know that this is the correct character.
![](images/appnote-char.png)
A similar process can be followed remaining records, and we get our flag! Of course, I wanted to make a script to make this process easier, so I did.
**[appnote-sol.py](src/appnote-sol.py)**```pythonimport binascii
with open('dump.zip', "rb") as file:    content = file.read()hexadecimal = binascii.hexlify(content)
flag = []for i in range(0, len(hexadecimal), 32):    line = hexadecimal.decode('utf-8')[i:i+32]    if "0506" in line:        f = line.find("0506")
        # offset of start of central directory        address = hexadecimal.decode('utf-8')[i+f+28:i+f+36]
        # converting address to little-endian format        ba = bytearray.fromhex(address)        ba.reverse()        s = ''.join(format(x, '02x') for x in ba)
        # retriving the byte before the file header, i.e., the character        index = int(s, 16) - 0x1        flag.append(chr(content[index]))
print(''.join(flag).strip('\n'))```
```bash$ python3 appnote-sol.pyCTF{p0s7m0d3rn_z1p}```
Flag: `CTF{p0s7m0d3rn_z1p}`
[^1]: Sources    - https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html#centraldirectory    - https://www.hanshq.net/zip.html#eocdr    - https://en.wikipedia.org/wiki/ZIP_(file_format)#End_of_central_directory_record_(EOCD)