# LACTF – My-Chemical-Romance
* **Category:** Web
* **Author:** bliutech
## Challenge
> When I was... a young boy... I made a "My Chemical Romance" fanpage!
>
> https://my-chemical-romance.lac.tf/
## Solution
The challenge contains a link to a MCR fanpage. After doing some enumeration, I find that the `.hg` directory is exposed. This appears to be the hidden directory of the `Mercurial` version control system.
Sjoerd Langkemper has an excellent [blogpost](https://www.sjoerdlangkemper.nl/2017/04/12/download-mercurial-hg-directory/) which explains how to use his [tool](https://github.com/Sjord/sprengel) to download the entire folder and rebuild the repository.
First, I download the tool and install mercurial.
```
$ sudo git clone https://github.com/Sjord/sprengel.git
$ pip install mercurial
$ sudo apt-get install mercurial
```
When using the tool for the first time, it downloads multiple files. Then, it errors when listing the files in the repository.
```
$ sudo python3 /opt/sprengel/sprengel.py https://my-chemical-romance.lac.tf/
.hg/store/00manifest.i -
.hg/store/00manifest.d -
.hg/store/00changelog.i -
.hg/store/00changelog.d -
.hg/store/fncache -
.hg/dirstate -
.hg/requires -
.hg/hgrc -
.hg/last-message.txt -
config error at /media/sf_CTF/temp/chemical/.hg/hgrc:1: <!DOCTYPE html>
Traceback (most recent call last):
File "/opt/sprengel/sprengel.py", line 99, in <module>
download_hg_directory(host)
File "/opt/sprengel/sprengel.py", line 92, in download_hg_directory
files = get_manifest_file_list()
File "/opt/sprengel/sprengel.py", line 74, in get_manifest_file_list
manifest = subprocess.check_output(['hg', '--debug', 'manifest'])
File "/usr/lib/python3.10/subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/lib/python3.10/subprocess.py", line 524, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['hg', '--debug', 'manifest']' returned non-zero exit status 255.
```
Let's check what's going wrong and fix it:
First of all, each file that is not found returns a custom 404 error page. The tool does not realise this and thinks that these are the desired files. `.hg/hgrc`, `.hg/store/00manifest.d` and `.hg/store/00changelog.d` thus need to be deleted.
`hgrc` is an optional config file. The `.i` and `.d` files are revlogs. Eric Sink [explains](https://ericsink.com/vcbe/html/repository_structure.html) what these are:
```
An important part of Mercurial’s design is the notion of a revlog, a file format which is designed to store all versions of a given file in an efficient manner. Mercurial uses the revlog format for basically everything it stores in the repository.
A revlog is actually two files. The .d file contains the actual file data. The .i file is an index designed to make it easier to find things. When the revlog is small, these two files are combined into one, with the data stored in the .i file and no .d file.
```
Since the `.i` files are indeed small, it is safe to assume I don't need any `.d` files. Let's again try to list the repository.
```
$ sudo hg --debug manifest
abort: No such file or directory: '/media/sf_CTF/temp/chemical/.hg/store/requires'
```
There seems to be a missing file. It can be downloaded manually at `https://my-chemical-romance.lac.tf/.hg/store/requires`.
```
$ sudo hg --debug manifest
starting pager for command 'manifest'
cb5af2bdac9c1b21f23d5287eec589d80b29618e 644 gerard_way2001.py
c428d632b200caecb71172f2abe2a7a4e26582a9 644 static/404.html
7b05bd5a60b9fe5405a5f58cd3b8cad9cd47a11a 644 static/index.css
b26221d3c933cbc0a1f25572a60490e2417e131b 644 static/index.html
9247a34928e6681765666f6333fb8c1afbbf5865 644 static/mcr-meme.jpeg
a89c540a13ca5bc45cb2ec98904ad8d879ca5ff9 644 static/my-chemical-romance.jpeg
```
Aha! The command now shows which files were present in the repository. I can even check the logs.
```
$ hg log -v
changeset: 1:3ecb3a79e255
tag: tip
user: bliutech <bensonhliu@gmail.com>
date: Fri Feb 10 06:50:48 2023 -0800
files: gerard_way2001.py static/index.html
description:
Decided to keep my favorite song a secret :D
changeset: 0:2445227b04cd
user: bliutech <bensonhliu@gmail.com>
date: Fri Feb 10 06:49:48 2023 -0800
files: gerard_way2001.py static/404.html static/index.css static/index.html static/mcr-meme.jpeg static/my-chemical-romance.jpeg
description:
I love 'My Chemical Romance'
```
However, restoring the repository still fails:
```
$ hg update -C
abort: data/gerard_way2001.py@cb5af2bdac9c1b21f23d5287eec589d80b29618e: no match found
```
At this point, I was stuck so I looked through the remaining files that I previously downloaded. One of them stood out:
```
$ cat fncache
data/static/404.html.i
data/static/mcr-meme.jpeg.i
data/static/index.css.i
data/gerard_way2001.py.i
data/static/my-chemical-romance.jpeg.i
data/static/index.html.i
data/static/my-chemical-romance.jpeg.d
```
These seem to be revlogs for individual files. I download all of these manually except for `data/gerard_way2001.py.i`, which seems to be missing. However, the same error persists. We can get in depth information with `hg verify`.
```
$ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
warning: revlog 'data/gerard_way2001.py.i' not in fncache!
0: empty or missing gerard_way2001.py
gerard_way2001.py@0: manifest refers to unknown revision c87e2916933c
gerard_way2001.py@1: manifest refers to unknown revision cb5af2bdac9c
checked 2 changesets with 6 changes to 6 files
1 warnings encountered!
hint: run "hg debugrebuildfncache" to recover from corrupt fncache
3 integrity errors encountered!
(first damaged changeset appears to be 0)
```
While my teammate kept looking for the `data/gerard_way2001.py.i` file, I tried to get the remainder of the repository. It is possible to reconstruct specific versions of individual files with `hg revert -r <VERSION> <FILE>`. Since the changelogs show the admin hid his favourite song, we rebuild the versions of `index.html` and compare them with `diff`
We can reconstruct the other files. We rebuild the two versions of `index.html` with `hg revert -r 0 static/index.html` and compare them using `diff`. Another way of checking the difference between both versions is to simply check the logs with `hg log -r0 -r1 -p static/index.html`.
```
$ diff static/index.html static/index.html.orig
10a11,12
>
> <iframe width="560" height="315" src="https://www.youtube.com/embed/RRKJiM9Njr8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
```
Although this is a nice song, it does not contain a flag. I also started looking for the missing file and decided to check the [Mercurial docs](https://www.mercurial-scm.org/wiki/Repository). It explains the repository structure. One entry caught my attention:
```
A revlog per tracked file — Files .hg/store/data/<encoded path>.i and .hg/store/data/<encoded path>.d
<encoded path> is the path of the tracked file in the working directory, encoded according to CaseFoldingPlan.
```
The file revlogs are encoded according to [CaseFoldingPlan](https://www.mercurial-scm.org/wiki/CaseFoldingPlan). This means that `data/gerard_way2001.py.i` is actually located at `https://my-chemical-romance.lac.tf/.hg/store/data/gerard__way2001.py.i`. Super logical right! Anyway, once this file is downloaded, rebuilding the repository it trivial.
```
$ hg update -C
6 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ tree
.
├── gerard_way2001.py
└── static
├── 404.html
├── index.css
├── index.html
├── index.html.orig
├── mcr-meme.jpeg
└── my-chemical-romance.jpeg
1 directory, 7 files
```
The flag is present in the previous version of the `.py` file.
```
$ hg log -r0 -r1 -p gerard_way2001.py | grep lactf
+# FLAG: lactf{d0nT_6r1nk_m3rCur1al_fr0m_8_f1aSk}
-# FLAG: lactf{d0nT_6r1nk_m3rCur1al_fr0m_8_f1aSk}
```