# the payload

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FwtcJ4mOTrc6eoALSdFpT%2Fimage.png?alt=media&#x26;token=7b494166-f47a-439d-b5c8-2170598789e7" alt=""><figcaption></figcaption></figure>

* *Difficulty: Hard*
* Narrative:

> With the malware extracted, Holmes inspects its logic. The strain spreads silently across the entire network. Its goal? Not destruction-but something more persistent…friends.&#x20;
>
> <mark style="color:$danger;">NOTE: The downloaded file is active malware. Take the necessary precautions when attempting this challenge.</mark>

Now we get into more serious challenge!!!

### tldr;

<table><thead><tr><th width="40">#</th><th width="308.75">question</th><th>flag</th><th>tldr;</th></tr></thead><tbody><tr><td>1</td><td>During execution, the malware initializes the COM library on its main thread. Based on the imported functions, which DLL is responsible for providing this functionality? (filename.ext)</td><td>ole32.dll</td><td>Listed in import table; exports CoInitialize / CoCreateInstance used by any.run</td></tr><tr><td>2</td><td>Which GUID is used by the binary to instantiate the object containing the data and code for execution?</td><td>DABCD999-1234-4567-89AB-1234567890FF</td><td>Extracted from <code>.rdata</code> structure passed to CoCreateInstance; decompilers (IDA/Binja) show rclsid.</td></tr><tr><td>3</td><td>Which .NET framework feature is the attacker using to bridge calls between a managed .NET class and an unmanaged native binary? (string)</td><td>COM interop</td><td>Observed native binary using COM + managed-style dispatched methods via vtable offsets.</td></tr><tr><td>4</td><td>Which Opcode in the disassembly is responsible for calling the first function from the managed code? (** ** **)</td><td>FF 50 68</td><td>Indirect call through COM vtable: <code>call qword ptr [rax+68h]</code> in disassembly.</td></tr><tr><td>5</td><td>Identify the multiplication and addition constants used by the binary’s key generation algorithm for decryption. (*, **h)</td><td>7, 42h</td><td>Loop sets key bytes: <code>byte[i] = i * 7 + 0x42</code>; seen in decompiled function.</td></tr><tr><td>6</td><td>Which Opcode in the disassembly is responsible for calling the decryption logic from the managed code? (** ** **)</td><td>FF 50 58</td><td>Vtable call at <code>call qword ptr [rax+58h]</code> corresponding to method invoking decryption routine.</td></tr><tr><td>7</td><td>Which Win32 API is being utilized by the binary to resolve the killswitch domain name? (string)</td><td>getaddrinfo</td><td>Present in WS2_32 import list; used for DNS resolution of target domain.</td></tr><tr><td>8</td><td>Which network-related API does the binary use to gather details about each shared resource on a server? (string)</td><td>NetShareEnum</td><td>Imported from NETAPI32; classic enumeration of remote shares for lateral movement.</td></tr><tr><td>9</td><td>Which Opcode is responsible for running the encrypted payload? (** ** **)</td><td>FF 50 60</td><td>Indirect call <code>call qword ptr [rax+60h]</code> after payload prep in ScanAndSpread logic.</td></tr><tr><td>10</td><td>Find → Block → Flag: Identify the killswitch domain, spawn the Docker to block it, and claim the flag. (HTB{_})</td><td><mark style="color:blue;"><strong><code>HTB{Eternal_Companions_Reunited_Again}</code></strong></mark></td><td>Derived key (i*7+0x42), XOR with Base64-decoded blob “KXgmYHMADxsV8uHiuPPB3w==” → <code>k1v7-echosim.net</code>; blocking domain in challenge environment reveals flag.</td></tr></tbody></table>

## what we have?

* AetherDesk-v74-77.exe
* AetherDesk-v74-77.pdb

well, since it is a .exe file my first instinct is to ~~run it~~ oh hold on.

{% code overflow="wrap" %}

```
# DANGER.txt
Dear Player,

This text file is to warn you that the downloaded artifacts for this challenge should be considered to be real malware. This software has been intentionally included for educational purposes and is NOT intended to be executed or used otherwise. Always handle such files in isolated, controlled, and secure environments.

It is strongly recommend that you proceed by:

1 - Running the sample in a controlled environment, for example EP Pwnbox or an isolated virtual machine.
2 - Only analyse the software in this controlled environment,and enjoy analysing!

PLEASE EXERCISE EXTREME CAUTION!

By reading this file and using the provided password to unzip the file, you acknowledge and fully understand the risks as detailed in this warning.
```

{% endcode %}

Well, there goes my plans. I guess I have to run it in an isolated environment.&#x20;

This process is dynamic analysis, of course, when talking about dynamic analysis, there are plenty of tools you can use to cheese out the necessary information for investigation. This is my togo tool (for now) <https://any.run/>.&#x20;

You can achieve super quick analysis if you are familiar with window overall.

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FnNrxj3f0cz7vA9eKJn24%2Fimage.png?alt=media&#x26;token=cf20f0bd-e011-40a5-b9df-1721e8a9774e" alt=""><figcaption><p>any.run dynamic analysis</p></figcaption></figure>

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FLqK9UZorr9F8JY1DqB7U%2Fimage.png?alt=media&#x26;token=f7cbaa3d-e35a-4b0b-a572-cf51affa56ae" alt=""><figcaption><p>any.run analysis result</p></figcaption></figure>

next, you can also put the file into a decompiler to see anything obvious (i just yeet them into [dogbolt](https://dogbolt.org/), 5s no brainer, and I regret shortly after)

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FAREX6sj4fbHa3JgJVo9n%2Fimage.png?alt=media&#x26;token=4e3eaaf3-1f8c-47c1-ab4d-9130c782da4d" alt=""><figcaption></figcaption></figure>

## solulu

### flag 1

> During execution, the malware initializes the COM library on its main thread. Based on the imported functions, which DLL is responsible for providing this functionality? (filename.ext)

Google is your best friend, I did a search and some reading to identify the possible dll for COM library. The answer only further confirmed when I have the exact name appear after any.run dynamic analysis. As you can see in the screenshot below. Of course, you can also do this via an IDA or Ghidra. Which just make me feels dumb because I was being lazy and not using it right away.&#x20;

The answer is <mark style="color:blue;">**`ole32.dll`**</mark>&#x20;

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FUVrKc9FvVFudxw3DDQg4%2Fimage.png?alt=media&#x26;token=2ec89fc4-2d5d-47e5-a97e-7509d4a3b44d" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2Fd2zPLi39OWKXj6M6Qvmq%2Fimage.png?alt=media&#x26;token=278c90e2-677d-4d8d-b3b6-6d4d434befc9" alt=""><figcaption></figcaption></figure>

flag: <mark style="color:blue;">**`ole32.dll`**</mark>&#x20;

### flag 2

> Which GUID is used by the binary to instantiate the object containing the data and code for execution? (\*\*\*\*\*\*\*\*-**-**-\*\***-**\*\*\*\*\*\*\*\*\*\*)

This is reference from flag 1, which is the COM (Component Object Model) still. In COM every creatable class has a unique Class ID (CLSID), which is just a GUID. When code calls <mark style="color:$info;">**`CoCreateInstance`**</mark>, it passes:

1. CLSID (which class to create)
2. Optional outer object (usually null)
3. Context flags (in-proc / local / remote)
4. Interface ID (IID) of the interface it wants back (often `IID_IUnknown` or something specific)
5. Output pointer to receive the new object

So if we find the `CoCreateInstance` call, we can see which CLSID (GUID) the malware is trying to instantiate.

From dogbolt decompiler I quickly grab these:

```c
# the call
LODWORD(v3) = CoCreateInstance(&rclsid, 0, 0x17u, &riid, &ppv);

# and the data
const IID rclsid = { 3669809561u, 4660u, 17767u,
                     { 137u, 171u, 18u, 52u, 86u, 120u, 144u, 255u } };
                     
# This is a C struct of type _GUID / IID:
typedef struct _GUID {
    unsigned long  Data1;      // 32 bits
    unsigned short Data2;      // 16 bits
    unsigned short Data3;      // 16 bits
    unsigned char  Data4[8];   // 8 bytes (big-end formatting when printed)
} GUID;
```

So we have to do some mapping here (manually by hand <img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FhKWzzkmFtiwgMwZlwMs9%2Fimage.png?alt=media&#x26;token=ef42cf90-9576-4992-b616-50a5d349846b" alt="" data-size="line"> my bad, I regretted guys), we know he textual [GUID format](https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-guid) is:

{% code overflow="wrap" %}

```
Data1-Data2-Data3-Data4[0]Data4[1]-Data4[2]Data4[3]Data4[4]Data4[5]Data4[6]Data4[7]
```

{% endcode %}

Lets convert:

* Data1: 3669809561 decimal → 0xDABCD999
* Data2: 4660 decimal → 0x1234
* Data3: 17767 decimal → 0x4567
* Data4 array (already byte values): 137, 171, 18, 52, 86, 120, 144, 255 → hex: 89 AB 12 34 56 78 90 FF

And our flag finally is <mark style="color:blue;">**`dabcd999-1234-4567-89ab-1234567890ff`**</mark>

And later when I spin up my binary ninja, the decompiler just do it for you.&#x20;

<div><figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FvFL1YvOV1WoZ0XfXCcOf%2Fimage.png?alt=media&#x26;token=d4933ef0-9443-4a05-b909-ea211714753c" alt=""><figcaption><p>binary ninja (in main)</p></figcaption></figure> <figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FwSRWiYoybOQtExqcOrsz%2Fimage.png?alt=media&#x26;token=ff97c524-72bd-4545-83cb-4c68a77da377" alt="" width="188"><figcaption><p>my reaction to binary ninja</p></figcaption></figure></div>

flag: <mark style="color:blue;">**`dabcd999-1234-4567-89ab-1234567890ff`**</mark>

### flag 3

> **Which .NET framework feature is the attacker using to bridge calls between a managed .NET class and an unmanaged native binary?**

So to rephrase the question in googoo gaga term (aka, my language) it wants the name of the .NET feature that lets unmanaged native code $$\rightarrow$$ and $$\leftarrow$$ managed .NET code call each other. (Answer: [COM interop](https://learn.microsoft.com/en-us/dotnet/standard/native-interop/cominterop) — the COM interface mechanism, via **`CoCreateInstance`**, letting native code spin up and use a managed class.) I did read the official writeup for this one and it seems like my guess could have been a lucky guess, because that is a lot of conditions needed to prove that it is COM interop. &#x20;

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FXruw7JMkUYFeF24yW6tp%2Fimage.png?alt=media&#x26;token=ae6b24c1-7ae1-464f-87e4-e67cb0d2b04f" alt=""><figcaption></figcaption></figure>

flag: <mark style="color:blue;">**`COM interop`**</mark>

### flag 4

> Which Opcode in the disassembly is responsible for calling the first function from the managed code? `(** ** **)`

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FRDqPJTIIu1xvNQsrGAlZ%2Fimage.png?alt=media&#x26;token=d112f7e6-5b7a-4c51-ad7b-759a175cb9e3" alt=""><figcaption></figcaption></figure>

Okay, this is when my assembly class kicked in, right in main, and after COM object instantiation our code ultimately landed here.

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FochhDh75zx8KxclxKvzW%2Fimage.png?alt=media&#x26;token=f503c49d-6055-4034-b6c7-9abd498f890e" alt=""><figcaption></figcaption></figure>

* `mov rax, qword [rcx]` → load the interface’s **vtable** pointer from `this` (in Win-x64, `this` is in `RCX`).
* `mov rdx, [rsp+0x68]` → set up the 2nd argument (`&var_210`).
* The call itself: `call qword [rax+0x68]`&#x20;

This translate to:  `rax` points at the COM vtable (array of function pointers). Offset `0x68` (i.e., slot `0x68 / 8 = 13`) is the interface method that the native stub calls. Because this COM class is implemented in .NET, that function pointer is a CLR/interop thunk that transitions into **managed code**. That’s why this is the “first function from the managed code.”

* **What you see in the decompiler** matches the above:
  * `(*(rcx_2 + 0x68))(rcx_2, &var_210);`
  * Bytes shown as `call qword ptr [rax+68h]`, hence hex is `ff 50 68`&#x20;

That is the yapping explanation that I can come up with, but during the competition I just simply...oh look at this...the op code

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FBLA7h9PnfhLLadqxkHqB%2Fimage.png?alt=media&#x26;token=d550927b-712c-47d3-9612-8328fe809f8a" alt=""><figcaption></figcaption></figure>

flag: <mark style="color:blue;">**`ff 50 68`**</mark>

### flag 5

> Identify the multiplication and addition constants used by the binary's key generation algorithm for decryption.

Have to find the key generation algorithm in the the binary first. What could be the constants that generate the key which later gets Base64-encoded and passed into the decryption routine. hmmmm. Oh you look at that...

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FwPFbjLWgoZbKTP9tv3vM%2Fimage.png?alt=media&#x26;token=a62d998d-ce15-4bd2-ae0a-51caf3991b44" alt=""><figcaption></figcaption></figure>

* **multiplier = 7**
* **adder = 0x42** (ASCII `'B'`)

flag: <mark style="color:blue;">**`7, 42h`**</mark>

The formula (explicitly)

```python
key[i] = ( i * 7 + 0x42 ) & 0xFF
```

This will be useful for the latter flags.

### flag 6

> Which Opcode in the disassembly is responsible for calling the decryption logic from the managed code?

Okay, now we need to find the calling of "decryption" logic,&#x20;

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FMkhu33jT75AW1hCRdPmy%2Fimage.png?alt=media&#x26;token=b475dcd8-a55f-4a29-b32b-2d99cd0b177f" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FiilIk5VKwmH6eUd8ebie%2Fimage.png?alt=media&#x26;token=432c30d6-35df-4a3b-80d6-66928ddec52a" alt=""><figcaption></figcaption></figure>

You know the drill

flag: <mark style="color:blue;">**`FF 50 58`**</mark>&#x20;

Also at this point, i have a full picture of this .exe file and how the attack went down

* **Stage 1 (bootstrap):** Native stub initializes COM and jumps into a managed COM server via vtable call (`call qword ptr [rax+0x68]`).
* **Stage 2 (keygen):** Generates a XOR key with `key[i]=i×7+0x42`, Base64-encodes it.
* **Stage 3 (decrypt):** Calls COM method at vtable+0x58 with the encoded key and a fixed ciphertext to recover a **hostname**.
* **Stage 4 (kill switch):** If that hostname **resolves**, the program **exits**; otherwise it continues.
* **Stage 5 (worming):** Attempts **SMB propagation** across `192.168.1.0`, calling `ScanAndSpread()` for each host.
* **Stage 6 (cleanup):** Releases resources and exits.

### flag 7

> Which Win32 API is being utilized by the binary to resolve the killswitch domain name?

In `main` (after the COM decrypt returns the plaintext hostname in `pNodeName_1`) the code does:

1. `WSAStartup(0x202, &wsa)` → initialize Winsock.
2. `memset(&hints, 0, 0x30); hints.ai_flags = 1;` (basic hints struct).
3. `rax_36 = getaddrinfo(pNodeName, NULL, &hints, &pAddrInfo);`
4. If `pAddrInfo != 0` → `freeaddrinfo(pAddrInfo)`, then `WSACleanup()`.

**Logic (kill-switch)**

* If **either** `WSAStartup` fails **or** `getaddrinfo` fails (non-zero), it prints **“\[No Kill Switch Detected] Continuing Execution…”** and keeps going.
* If **both succeed**, it prints **“\[Kill Switch Triggered] Exiting…”** and stops.
* That proves the API used to resolve the decrypted hostname is **`getaddrinfo`**

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2F3OANT63rYLCgdBA4uy6K%2Fimage.png?alt=media&#x26;token=fd8ac575-21d4-4b34-b677-dd11d4ba34a6" alt=""><figcaption></figcaption></figure>

flag: <mark style="color:blue;">**`getaddrinfo`**</mark>

### flag 8

> Which network-related API does the binary use to gather details about each shared resource on a server?

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FRqekukEgzCx7RcMNvWGo%2Fimage.png?alt=media&#x26;token=90fe92be-6031-4af6-a72c-634053fca12a" alt=""><figcaption></figcaption></figure>

This is **NetAPI32** share enumeration used for SMB propagation/recon.&#x20;

flag: <mark style="color:blue;">**`NetShareEnum`**</mark>&#x20;

### flag 9

> Which Opcode is responsible for running the encrypted payload?

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FHPw2sLShAuJIOjOG0l2Q%2Fimage.png?alt=media&#x26;token=ea993364-abe9-4559-86d9-8ac3edc2d819" alt=""><figcaption></figcaption></figure>

```wasm
mov   rax, [rbx]         ; load vtable pointer from the COM object in rbx
call  qword [rax+0x58]   ; indirect call through vtable slot at +0x58
```

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FTKzyHqIjVgFp4ccUMGTx%2Fimage.png?alt=media&#x26;token=30d86233-11d6-4d05-a2de-26acc4423e06" alt=""><figcaption></figcaption></figure>

```c
struct DNS::ProgramVTable {
    char _pad[0x38];                   // IUnknown/IDispatch slots etc.
    HRESULT (*get_ToString)(...);      // at vtable+0x38
    HRESULT (*Equals)(...);            // +0x40
    HRESULT (*GetHashCode)(...);       // +0x48
    HRESULT (*GetType)(...);           // +0x50
    HRESULT (*SendEncryptedFlag)(...); // 
    HRESULT (*Execute)(...);           // +0x60  ← flag 9
    HRESULT (*Dummy)(...);             // +0x68
};
```

You know the drill...

flag: <mark style="color:blue;">**`FF 50 60`**</mark>

### flag 10

> Find → Block → Flag: Identify the killswitch domain, spawn the Docker to block it, and claim the flag. (HTB {***\_\_\_***})

Thank you for reading this far you probably know how the entire incident unfolded, this is simply the reverse implementation of the encryption to retrieve the network we have to block.

```python
import base64

data = base64.b64decode("KXgmYHMADxsV8uHiuPPB3w==")

key = bytearray()
for i in range(32):
    key.append((i * 7 + 0x42) & 0xFF)

print(bytes([x ^ y for x, y in zip(key, data)]))
# b'k1v7-echosim.net'
```

<mark style="color:blue;">**`k1v7-echosim.net`**</mark>

And with that...we got into some cutscene...I'm not gonna comment about them (skip cutscenes button pressed)

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2Fgje213ff9HVdoRukm7Zd%2Fimage.png?alt=media&#x26;token=b014da1c-cd47-4e87-97f2-c5dd9fd91c88" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2268275695-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUrHD5lu5pQjrB9B8IR6W%2Fuploads%2FYbzj0TIjHh5ts9ZLYP3q%2Fimage.png?alt=media&#x26;token=3cedefd1-9933-45fb-ae8f-f30ebd8586df" alt=""><figcaption></figcaption></figure>

flag: <mark style="color:blue;">**`HTB{Eternal_Companions_Reunited_Again}`**</mark>
