# SeeTwo

{% embed url="<https://tryhackme.com/r/room/seetworoom>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

In this scenario, we take on the role of a member of the digital forensic team and are tasked with looking at some suspicious network activity. The zip file that is created in the room contains a PCAP file. In this, we can see traffic on port 22, possibly SSH, which we have no access to, and a single large HTTP request containing a lot of base64-encoded data.

<figure><img src="/files/XDetZZpQYS12RvUMe2pE" alt=""><figcaption></figcaption></figure>

When we exclude the ports mentioned first, we also find traffic on port 1337.

<figure><img src="/files/cXnVixcYGrNcEvtZfBHb" alt=""><figcaption></figcaption></figure>

If we follow the TCP stream by clicking on one of those packets, we can see that the data that is transferred here is base64-encoded. Nothing is conspicuous at first glance. Scrolling through the following TCP stream, you will find some requests with two base64-encoded strings, recognizable by the padding string `==`.

<figure><img src="/files/BFeRbtM9Vzde36Duihqo" alt=""><figcaption></figcaption></figure>

If we decode this using CyberChef, it suggests that we generate a raw image from the decoded binary data. We can detect at least three images. A milk bottle...

<figure><img src="/files/MTdHZgzuYhpCuVGWs2WQ" alt=""><figcaption></figcaption></figure>

A green bear,&#x20;

<figure><img src="/files/ulMIken8Y1uxQKeUArOO" alt=""><figcaption></figcaption></figure>

... and a poke ball. But here we can see something else. At the end, we see the padding encoding two times. Interesting. But we move on, since that data seems to be just gibberish after decoding.

<figure><img src="/files/byYJYUcMSmayD6ezsHwF" alt=""><figcaption></figcaption></figure>

We head back to the HTTP request. We can see that a `base64_client` endpoint was requested. Furthermore, we can assume that this might be binary data, bas64-encoded. As indicated in the room, this may be a C2: `Can you see who is in command and control?` `SeeTwo`

A C2, or command and control, refers to a system used by attackers to maintain communications with compromised machines, allowing them to remotely control, exfiltrate data, or manage malware operations.

<figure><img src="/files/lszxSPBqtDcegpPwXmnw" alt=""><figcaption></figcaption></figure>

We can export the Object via the following path:&#x20;

`File -> Export Objects -> HTTP`

<figure><img src="/files/aHR0P8YEFgHL08ColZF6" alt=""><figcaption></figcaption></figure>

After we have saved the file on our system, we decode it and then check it. It actually is an executable binary.

<figure><img src="/files/bwItGSozHDbOcI2NMNBq" alt=""><figcaption></figcaption></figure>

This appears to reference Python C API functions and error handling messages.&#x20;

<figure><img src="/files/SrxLbLs0LkTE9Pp4wmdb" alt=""><figcaption></figcaption></figure>

Using strings would have revealed this too...

<figure><img src="/files/yrrvRtuEztxM8Got1zf8" alt=""><figcaption></figcaption></figure>

It is not recommended, but the execution also points to a Python executable.

<figure><img src="/files/a4s2vrXJIbDPiyUvIfBl" alt=""><figcaption></figcaption></figure>

The binary might be packaged with PyInstaller. Then `pyinstxtractor` can extract the `.pyc` files, which we can then decompile.

{% embed url="<https://github.com/extremecoders-re/pyinstxtractor>" %}

We use `pyinstxtractor` to extract the archive.

<figure><img src="/files/7iGKrIfCbMx5Cw5Ry9cw" alt=""><figcaption></figcaption></figure>

With that we are able to decompile the `.pyc` files.

<figure><img src="/files/rCWPseSAdPwYVShh1Rnk" alt=""><figcaption></figcaption></figure>

ChatGPT suggests to use uncompyle6, so we give it a try. First, we need to install it.

```
pip3 install uncompyle6
```

<figure><img src="/files/FUFWFRdhdTpcu0TT4idS" alt=""><figcaption></figcaption></figure>

After that we can run `uncompyle6` on `client.pyc`. In `client_extracted` should now be `client.py.`

```
uncompyle6 -o client_extracted client_extracted/client.pyc
```

<figure><img src="/files/GJnrovdNJzuEzZti8mzt" alt=""><figcaption></figcaption></figure>

After decompilation we are able to investigate what the client actually does. It sets up a socket connection to a remote server, to a host at IP address `10.0.2.64` on port `1337`. It functions as a remote command-and-control client that securely receives commands from a server, executes them locally, and transmits the encrypted results back. The data transmitted is somewhat obfuscated, an encoded image is concatenated with an encoded command, separated by `"AAAAAAAAAA"`.&#x20;

The command itself is XOR encrypted and base64 encoded.&#x20;

<figure><img src="/files/QxGPxFVC3vtWRh1t1MAb" alt=""><figcaption></figcaption></figure>

We investigate the traffic on port 1337 again.

<figure><img src="/files/Ow4DakTCigyTvrTpN3t9" alt=""><figcaption></figcaption></figure>

And follow the TCP stream on packet 1594 again. And we can see after `AAAAAAAAAA` there is the command.

<figure><img src="/files/pd10shPdrd4nEd7PVhPq" alt=""><figcaption></figcaption></figure>

The following shows an example script that accepts base64, decodes it and decrypts the xor encoding. Here we can see its command id.&#x20;

<figure><img src="/files/oo15y2FFtSPtY5uydzmo" alt=""><figcaption></figcaption></figure>

We have a total of two TCP streams, starting at `1594` and `1706`.

<figure><img src="/files/8nlq3TNbdGkRtGqauDrn" alt=""><figcaption></figcaption></figure>

We follow both.

```
right click -> Follow -> TCP Stream
```

<figure><img src="/files/kmxQxF0mPp5ylluFMiBS" alt=""><figcaption></figcaption></figure>

And save the content to a text file.&#x20;

<figure><img src="/files/LXRbbRA7U6xd5KudN6jb" alt=""><figcaption></figcaption></figure>

Checking the first base64 string of the data, we can see the magic bytes for a PNG file.

<figure><img src="/files/Ffofr7xU4ehkoI0WMEP1" alt=""><figcaption></figcaption></figure>

We know from the source of client.py that every `AAAAAAAAAAAA` is followed by the command, which is then followed by the magic bytes of the image. From this, we can build a regex that filters out only the commands from the data stream. We then decode and decrypt the command using the key in `client.py.`

{% code title="" overflow="wrap" lineNumbers="true" %}

```python
import re
import base64

# Define the path to your file
file_path = 'b64traffic.txt'

# Define the XOR key
xor_key = "REDACTED"

def xor_decrypt(data, key):
    return ''.join(chr(data[i] ^ ord(key[i % len(key)])) for i in range(len(data)))

# Read the file
with open(file_path, 'r') as file:
    content = file.read()

# Regular expression to match the base64 encoded command
pattern = r"AAAAAAAAAA(.*?)iVBORw"
matches = re.findall(pattern, content)

# Decode and XOR each command
for match in matches:
    try:
        # Base64 decode the command
        decoded_command = base64.b64decode(match)
        
        # XOR with the key
        decrypted_command = xor_decrypt(decoded_command, xor_key)
        
        print("Decrypted Command:", decrypted_command)
    except Exception as e:
        print("Error decoding command:", e)

```

{% endcode %}

After running the script we are able to answer all questions from the task.

<figure><img src="/files/kSUH4ZsAKM1nPdtl2VgM" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/tryhackme/2024/seetwo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
