# Hancitor

## Initial Triage

***

SHA256 Hash - `8ff43b6ddf6243bd5ee073f9987920fa223809f589d151d7e438fd8cc08ce292`

File Type - `Dll`

#### Initial Triage Using Cutter -

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FoYuRHAcJOzf5QBYlu4IX%2Fimage.png?alt=media&#x26;token=9f651803-cb89-44a2-a69a-20fdb65f1d7d" alt=""><figcaption></figcaption></figure>

* The Dll is written in C and has four library imports -
  * kernel32.dll
  * user32.dll
  * gdi32.dll
  * mpr.dll
* The low number of library imports suggests that this file is most definitely packed. But before performing any unpacking, we need to confirm if this file is malicious or not. We can do this using Virus Total.
* The virus total result comes out as positive. So this Dll is definitely malicious and by the looks of it, seems to come from Hancitor family.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FHXRzs358gg8WCBKjcbdq%2Fimage.png?alt=media&#x26;token=e81d3338-9acd-4ccf-be8e-41484dc60b4c" alt=""><figcaption></figcaption></figure>

* Now that we know that this DLL is malicious, we can start static analysis on it. This can be done using `FLOSS.exe`.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F1TNOg6kjG01cpruQmraB%2Fimage.png?alt=media&#x26;token=0f8b2f9f-df72-4e71-9b04-d3356260e06d" alt=""><figcaption></figcaption></figure>

* Some interesting strings from the string dump are -

{% code overflow="wrap" %}

```
extern "C"
short
unsigned
volatile
std::nullptr_t
std::nullptr_t

// The above basically confirms that the DLL was written in C and contains volatile constants

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
January
February
August
September
October
November
December
MM/dd/yy
dddd, MMMM dd, yyyy
HH:mm:ss

// These suggest that the malware performs some check on the day, Month and time of execution.

AreFileApisANSI
CompareStringEx
EnumSystemLocalesEx
FlsAlloc
FlsFree
FlsGetValue
FlsSetValue
GetActiveWindow
GetCurrentPackageId
GetDateFormatEx
GetEnabledXStateFeatures
GetFileInformationByHandleEx
GetLastActivePopup
GetLocaleInfoEx
GetProcessWindowStation
GetSystemTimePreciseAsFileTime
GetTimeFormatEx
GetUserDefaultLocaleName
GetUserObjectInformationW
GetXStateFeaturesMask
InitializeCriticalSectionEx
IsValidLocaleName
LCMapStringEx
LCIDToLocaleName
LocaleNameToLCID
LocateXStateFeature
MessageBoxA
MessageBoxW
RoInitialize
RoUninitialize
SetThreadStackGuarantee

//These are the WinAPIs used in the malware.
```

{% endcode %}

## Unpacking&#x20;

***

* Let's look at the malware in PE-Bear now to get some more information.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FT0HxOeZZygyAaEGooJg4%2Fimage.png?alt=media&#x26;token=079f81be-f62a-4368-8f55-4bcfce478892" alt=""><figcaption></figcaption></figure>

* We can see that the malware only has 4 imports in the Import Address Table (IAT) and the imports aren't related to networking or cryptography. So, the DLL is most likely packed. Below are the exported functions of the DLL.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FZJtI7LY1r4CZnVLX5ceL%2Fimage.png?alt=media&#x26;token=c906603b-4615-4205-8d4d-f07bbe9b6af6" alt=""><figcaption></figcaption></figure>

* Using **pestudio** tool, we can see that there is a difference between the raw-size and the virtual size of the `.data` section of the DLL. So this confirms our suspicion that the DLL malware is packed.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F1EetcdxgI9iw8ZKfgVsx%2Fimage.png?alt=media&#x26;token=99952c5a-2296-482e-ad21-aa479fa038da" alt=""><figcaption></figcaption></figure>

* Now that we know that the DLL is a packed malware, we can use **x32DBG** to unpack it and analyze the contents underneath.&#x20;
* The malware has five exported functions and without further static analysis, it's difficult to know what they do. Thus we can go one by one to figure out what they do. Let's start with the first one - "Callrun".
* When the execution is stopped at the start of execution (INT3 OPCODE), set up breakpoints (ctrl + G to search the function up and after it comes up, click on the small dot on the left of the assembly instruction) on&#x20;
  * VirtualAlloc
  * VirtualProtect
  * ResumeThread
  * WriteProcessMemory

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2Fv4fUfKDqTWTU8wu3jHBm%2Fimage.png?alt=media&#x26;token=b03627d7-0643-4cee-acb5-9fbe07584cee" alt=""><figcaption></figcaption></figure>

* These are some classical WinAPIs that are used in unpacking process. Now run the program (F9) until it hits the first breakpoint (VirtualAlloc). Now `Right click on the EAX register and follow it in Dump 1`. You can see the memory contents of the adress being pointed to by EAX.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FYaAjRKM2OBiEplOTTDur%2Fimage.png?alt=media&#x26;token=51ebd7a7-d4aa-470c-851c-108c364e5cb9" alt=""><figcaption></figcaption></figure>

* As you can see, the memory dump starts with a magic byte "MZ" which denotes that it is a Windows PE program. But this isn't what we need right now. Now Click on Execute till Return (CTRL+F9) to see what the VirtualAlloc function allocates. To see what the function returns, repeat the same process of `right-clicking on the EAX register -> Follow in Dump`. This memory dump will soon get filled when the next VirtualAlloc function runs (run the program until it hits the breakpoint at the VirtualAlloc function again).&#x20;

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F6VYJvjKE9vMH68Avgx3w%2Fimage.png?alt=media&#x26;token=616423c6-20a2-4143-824e-06ef9d8b6db4" alt=""><figcaption><p>At the Return Point of First VirtualAlloc</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FzL4hojkVrFOQqpYL7nqI%2Fimage.png?alt=media&#x26;token=5fa8bfa9-0879-4e1d-b89e-e4c6342674b0" alt=""><figcaption><p>When the second VirtualAlloc runs</p></figcaption></figure>

* This memory data is still gibberish to us. So we need to repeat the same process again and again while visualizing the return data in different dumps to make sense of this gibberish data.

> If the malware is unpacking very slowly, you can Singleshot the memory dumps. In order to do that, go to the dump that is going to be written on by the next VirtualAlloc function call, select the first four hex bytes, `right click → Breakpoint → Memory, Write → Singleshot`**.** This helps in cases where malware takes a long time to write on that region

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FPZr67bec7Yz3QCiOLh6j%2Fimage.png?alt=media&#x26;token=8ae08bfd-e857-4581-b157-1f8b0bc104cc" alt=""><figcaption><p>Second VirtualAlloc return address</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F3HQh54lEM7Aclc42a1lg%2Fimage.png?alt=media&#x26;token=c9bb42fb-785e-49ec-9331-6921e88f5c28" alt=""><figcaption><p>That address gets written on by the third calling of the VirtualAlloc function</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FOYgQmGpbxYvfmHTYweCv%2Fimage.png?alt=media&#x26;token=ba1cae77-016e-427c-9438-9e2cd499cca5" alt=""><figcaption><p>Third VirtualAlloc return Address</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FNJdTjMMWLsqcqSdznJPv%2Fimage.png?alt=media&#x26;token=ccaa838b-291a-458d-a616-90cfb9aa70ee" alt=""><figcaption><p>Which gets overwritten by the time VirtualProtect is called</p></figcaption></figure>

* In this specific strain of Hancitor, it took three VirtualAlloc calls to fully place the unpacked malware in memory. It can vary depending on the strain of Hancitor. In the above picture, at the start of Dump 3, we can see the ASCII characters "**M8Z**". Just like the magic bytes of Windows PEs, "**M8Z**" is the magic byte of **PLib Compression.** We can dump this whole region by `right-clicking on the bytes and choosing "Follow in Memory Map"`.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FsAJccnNEHg5FGiHTPsP5%2Fimage.png?alt=media&#x26;token=da90a078-44f7-45f9-b1b1-6348dc011677" alt=""><figcaption></figcaption></figure>

* On the gray highlighted base address, `right-click -> Dump Memory to File` to save the memory region of the unpacked malware. Keep the debugger open for now. Open the saved file in **XVI Editor**. This is essential to fix the IAT of the dumped malware. Now in XVI editor, search for the text string - "DOS".&#x20;

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FenIJl5GDuoIfTJTbJb1w%2Fimage.png?alt=media&#x26;token=8c99331a-906d-414d-8095-9db6296fef94" alt=""><figcaption></figcaption></figure>

* Once you found it, look for the PE magic bytes "MZ" 2-3 lines above. Click on the byte just before it and go to `Edit → Delete to cursor`. This will align the packed malware's PE headers.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FJALJ1Rc82iDuciD6wDYj%2Fimage.png?alt=media&#x26;token=80fb713d-ca2b-4b5a-9204-3cfd71c0215d" alt=""><figcaption><p>Before editing</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F9sWoSj26uDkMYr7UKSaf%2Fimage.png?alt=media&#x26;token=fc5bfa7d-5d67-4d47-b331-00a49b1df00a" alt=""><figcaption><p>After editing</p></figcaption></figure>

* Save the hex data to disk and open it in Pe-Bear to see the imports. We can now see all the imports of the malware.&#x20;

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FsyXDI6dGmsLKEi3o3SFV%2Fimage.png?alt=media&#x26;token=b1bf9470-f926-45de-9a24-ab93a8d7d37d" alt=""><figcaption></figcaption></figure>

* By the looks of it, the malware potentially uses "WININET.dll" for some kind of network communication. To know which kind of network communication, we need to further analyze the malware in a disassembler. I will be using Binary Ninja and Ghidra for the task. You can close the debugger for now.&#x20;

## Static Analysis

***

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FcmiUgLnZnvjYgagULVvK%2Fimage.png?alt=media&#x26;token=be708841-5c4f-43af-bfe2-3415f98a1377" alt=""><figcaption></figcaption></figure>

* We can start analyzing the malware by looking at the exported functions. You can see the exported functions of the dll below as seen in Ghidra.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FQStWEPS3HX7wZeve8AwR%2Fimage.png?alt=media&#x26;token=99d865ab-390a-4d87-98a7-552d3680f835" alt=""><figcaption></figcaption></figure>

* There are 2 exported functions -
  * entry
  * MVELLJHNDSVBJLD (I renamed it to **MAL\_MAIN** later)
* The **entry** (or the **DllEntryPoint**) function supposedly only returns the value 1 and exits. So it's not useful for us.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FHPRKqfeGnENzMZRL9zsx%2Fimage.png?alt=media&#x26;token=a1fbd0d8-4a00-4a62-89a6-4075251a54ed" alt=""><figcaption><p>Callgraph in Binja</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FrAH0Sk4wAqhoqbiSSjqy%2Fimage.png?alt=media&#x26;token=a8bfa4e6-8970-4d2c-bcd9-d05de78841af" alt=""><figcaption><p>Decompiled code as seen in Ghidra</p></figcaption></figure>

The other function - MAL\_MAIN seems interesting though. It supposedly compares a data variable "MainCompareWithValue0" with the value "0x0". If they are not equal, then the function returns. Else, it calls "FirstFunctionCalledFromMain" and sets the variable to "1".

> All function and variable names are renamed for brevity. The full reverse source code is available [here](https://github.com/Swayampadhy/Hancitor).

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FN6O67p2tPthD8MdKYM67%2Fimage.png?alt=media&#x26;token=c06f9dff-0cba-4fad-a8bf-6806e6e265f3" alt=""><figcaption><p>Decompiled MAL_MAIN function</p></figcaption></figure>

* The "FirstFunctionCalledFromMain" function does the following -
  * Create a GUID for the victim
  * Initialize C2 communication and send victim information to C2
  * Download and inject shellcode as -
    * Remote injection
    * Self Injection
    * Launching Shellcode
    * Download file to temp directory

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FlRkBMphb1WiCXonLn43i%2Fimage.png?alt=media&#x26;token=cad441d2-8004-4c13-9936-e05556bad722" alt=""><figcaption></figcaption></figure>

#### Creating A GUID For The Victim

* In order to distinguish the victim computer from others, Hancitor creates a unique GUID (Global Unique Identifier) for the machine. This is done by concatenating various unique values from the victim system.
* First Hancitor uses `GetAdapterAddresses` winapi to get the MAC (Media Access Control) addresses of all the network adapters on the pc. Then it XORs all the addresses together to get a final 48-bit value.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F0Ne4AcNd3uUOx5o7ZQtM%2Fimage.png?alt=media&#x26;token=b32f268f-cbfe-4adc-9c36-15a3fb5f2a82" alt=""><figcaption><p>XOR-ing all the MAC addresses</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F2OjpxsPRpmNIA4uqWCzA%2Fimage.png?alt=media&#x26;token=89a1ed60-59db-48e7-8dae-ce91c5f8db4a" alt=""><figcaption><p>XOR implementation</p></figcaption></figure>

* After this, Hancitor extracts the machine volume serial number using `GetVolumeInformationA` and XORs it with the above final MAC value.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F3IgtHvntAywtIcWmAUVb%2Fimage.png?alt=media&#x26;token=2cfcf9ec-df9d-49b9-8ba0-c71677b20602" alt=""><figcaption></figcaption></figure>

* Next, this malware also gets the machine information by calling `GetComputerNameA` . Hancitor also finds the username of the logged-in user by searching for the PID of "explorer.exe", extracting the user SID (Security Identifier) from the process token using `OpenProcessToken` and `GetTokenInformation`, and looking that SID up through `LookupAccountSidA` winapi.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F3ujhi7mVvZd1wT9m6Dci%2Fimage.png?alt=media&#x26;token=0c77b57f-4b1f-41b3-8cf3-21f914169a21" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FwWraQuoTEYfJxJFuw5Z2%2Fimage.png?alt=media&#x26;token=4a42f157-2e4b-4593-8fe1-55d916e6a2b9" alt=""><figcaption></figcaption></figure>

* Finally the machine info is formatted as -

```
Machine_name @ Domain_Name \ User_name
```

* In order to get the public-facing IPV4 address of the victim machine, Hancitor requests a GET request to `hxxp://api[.]ipify[.]org`**.** In case it's unable to get a response, Hancitor uses `0.0.0.0` as the IPV4 address.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F9PHN842LNUd4NGNwFTLh%2Fimage.png?alt=media&#x26;token=843a3e9e-0b9f-4dae-9d31-a62654f52540" alt=""><figcaption><p>Get Public IPV4 address Of Victim</p></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FXJyAopqsQppJhNL7qFM4%2Fimage.png?alt=media&#x26;token=f8666242-264c-425a-a1f4-ba96cb68b3c1" alt=""><figcaption><p>How The GET Request is sent</p></figcaption></figure>

* This GET request function is also later used to download shellcode from the C2.
* The domain shares and NETBIOS names are extracted using `DsEnumerateDomainTrustsA` Winapi.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FdW8oJsXVBf5vhTHwuXIH%2Fimage.png?alt=media&#x26;token=db940f71-3310-4297-8550-b20ba4dd112e" alt=""><figcaption></figcaption></figure>

* Finally before sending the values back to the C2, Hancitor encrypts them using RC4 and formats them as below -

{% code overflow="wrap" %}

```
GUID=<Victim’s GUID>&BUILD=<Build ID>&INFO=<Machine Information>&EXT=<Network domain names>&IP=<Victim’s IP address>&TYPE=1&WIN=<Windows major version>.<Windows minor version>(x64)

GUID=<Victim’s GUID>&BUILD=<Build ID>&INFO=<Machine Information>&EXT=<Network domain names>&IP=<Victim’s IP address>&TYPE=1&WIN=<Windows major version>.<Windows minor version>(x32)
```

{% endcode %}

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FwUvUHXsJY2aGDwIENN9n%2Fimage.png?alt=media&#x26;token=48b5636c-2e42-46f6-96a8-2246cda9e5c4" alt=""><figcaption></figcaption></figure>

#### Initialize C2 communication and send victim information to C2

* After the victim data is completed and encrypted, the malware runs an infinite loop to communicate with the C2 server. To send information to the server, Hancitor uses POST HTTP requests. The code is the same as that of downloading the shellcode.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F0Ehy4Oxj74TtUBnCgKxW%2Fimage.png?alt=media&#x26;token=d6e53eee-d8de-48bb-9c1d-1cb2ab0e99dd" alt=""><figcaption></figcaption></figure>

* As the C2 servers are long down, we can't do a PCAP analysis of the communications but looking at the code, the C2 sends a BASE64 string to hancitor. Hancitor checks the first 4 bytes of the response to verify if the response is from the C2 server.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FjGKkLxIeEj7dRukaZNqN%2Fimage.png?alt=media&#x26;token=8fd1957a-6971-4928-8769-b14820408903" alt=""><figcaption></figcaption></figure>

* After the check, the result is decoded using Base64 and accepted. The C2 response contains a CLI argument which is tokenized (using a custom implementation of strtok C++ function) and checked to determine which type of payload execution method is to be used.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FmItOoSCi63sQKBjkPCbe%2Fimage.png?alt=media&#x26;token=340ae959-1527-4aa0-ad56-0f2d52a74575" alt=""><figcaption></figcaption></figure>

* Here are the possible commands given to Hancitor -
  * `b` - Download and remote injection of shellcode
  * `e` - Download and self injection of shellcode
  * `l` - Download shellcode and use Svchost to launch it
  * `r` - Download Shellcode in temp folder and execute it
  * `n` - Do Nothing

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FnX35H5i4P6Ih0XFp26lf%2Fimage.png?alt=media&#x26;token=a31fd133-d197-43e8-969f-e7ce8b97b720" alt=""><figcaption></figcaption></figure>

#### Download And Remote Injection Of Shellcode

* Hancitor downloads the file from the URL in the response and performs remote reflective PE injection to execute it.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FlOGNcjfu9arxgSzvCbCM%2Fimage.png?alt=media&#x26;token=69df1739-f16d-4aa3-8b29-57d2f2bab3c2" alt=""><figcaption></figcaption></figure>

* The malware first parses the response using pipes as delimiters and downloads the file contents. After receiving them, Hancitor validates the UNC path and goes forward with the payload processing. After processing, it checks the magic byte of the processed payload to check if it is a "MZ" (Windows PE) or not.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FidKO69ayZJb99J6xQN5I%2Fimage.png?alt=media&#x26;token=1c3cf662-2f2c-4b48-a19c-b578368ae79b" alt=""><figcaption></figcaption></figure>

* In order to process the payload, the malware decrypts it using a XOR cipher with its first 8 bytes as the key. Next, it calls **RtlDecompressBuffer** to perform LZ decompression to decompress the final executable.&#x20;

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FLM3Wto3qCJ0c7lHGgxGH%2Fimage.png?alt=media&#x26;token=5aaac194-decf-40dc-a503-fcdbf59d9e97" alt=""><figcaption></figcaption></figure>

* Next up, it performs reflective PE injection by injecting the downloaded payload into a `svchost.exe` process.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FdyXwbTFFP62yVQkYzjQs%2Fimage.png?alt=media&#x26;token=26166955-ad83-44c2-9ea9-8a431ce4600c" alt=""><figcaption></figcaption></figure>

* How the reflective injection works is, first a suspended `svchost.exe` process is created for the payload to be injected in. That is done by getting the SystemRoot variable (C drive) using `GetEnvironmentVariableA` winapi, adding "\System32\svchost.exe" to it and creating it is suspended mode using `CreateProcessA`.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F2a4LAOhPJ2iKiwQM5RpR%2Fimage.png?alt=media&#x26;token=885ad3c8-d75d-4e7a-91f0-7e52abdefbf5" alt=""><figcaption></figcaption></figure>

* Next, Hancitor uses `VirtualAllocEx` to create a buffer in target memory for the injection. The Payload is copied to a heap buffer created using HeapAlloc and mapped to it through relocating it's PE base. Finally `WriteProcessMemory` is used to write the payload from the heap to **svchost’s** allocated memory.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2Fo8Vw9UfNRny09LJZ567f%2Fimage.png?alt=media&#x26;token=9937967e-6fa3-4270-8d99-6f82211f8cb9" alt=""><figcaption></figcaption></figure>

* Now that the payload is set to the suspended "svchost.exe" process, Hancitor sets up the injected thread’s context by setting the image base address from PEB (through the context’s **EBX** register) to the injected base address and the thread’s entry point (through the context’s **EAX** register) to the injected entry point. Finally the payload is launched by calling `ResumeThread`.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F1Qy7vqSeJppZjAqWHely%2Fimage.png?alt=media&#x26;token=fb295fd9-a7ba-459a-9d01-c5c3bc872a88" alt=""><figcaption></figcaption></figure>

#### Download and self injection of shellcode

* When given the `e` command, Hancitor downloads a file from the URL in the response and injects it into its own process.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FWXHu6XMyX9jKdLlXQvWY%2Fimage.png?alt=media&#x26;token=c5872056-2a1d-4c89-b114-94fef70cfb17" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FofwOLxuYm5Pyoun9Kmgf%2Fimage.png?alt=media&#x26;token=cd0c0902-b584-45e3-b4f4-dceb0617b107" alt=""><figcaption><p>The whole self injection process</p></figcaption></figure>

* After payload download, the malware checks if the download payload is a Windows PE or not. After that, it calls `VirtualAlloc` to allocate a buffer and loads the payload there.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2Fnfng37Ltb2AkRVUavcL3%2Fimage.png?alt=media&#x26;token=29846d21-ddcb-4c08-84f7-c171d18cdcea" alt=""><figcaption></figcaption></figure>

* Now, the malware set's up the IAT for the reflective self injection. This is done by extracting all imported DLL names and calling `GetModuleHandleA` or `LoadLibraryA` to retrieve the DLL’s base. For each imported DLL, the malware manually iterates through its own Import Address Table (IAT) to retrieve the name of each imported function. It calls `GetProcAddress` to get the address of the imported function and updates it in its IAT.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FVEwo0jtyUGkCXoJkwVHC%2Fimage.png?alt=media&#x26;token=6f212b94-670f-4b65-a0d4-547cf518accb" alt=""><figcaption></figcaption></figure>

* Lastly, the malware creates a new thread using `CreateThread` and launches the payload in it.

#### Download shellcode and use Svchost to launch it

* Hancitor downloads the shellcode from the URL in the C2 response and runs it either locally or in svchost.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2F6CmZQ2LKluyTSmJEBFpF%2Fimage.png?alt=media&#x26;token=dcb3ac93-cdd1-43ee-8e9e-f9cc3e701c56" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2Frvd4UJQYq32oQIejcutX%2Fimage.png?alt=media&#x26;token=81d7f62b-11e1-465c-a6f1-e4f6fe0d365e" alt=""><figcaption></figcaption></figure>

* This function takes in a parameter to determine whether the shellcode is injected locally or in svchost. The process of injecting to svchost is same as earlier and the shellcode is launched using `CreateRemoteThread` winapi.
* Injecting locally works the same as before - memory is allocated using `VirtualAlloc`, shellcode is copied into this buffer and finally executed using `CreateThread`.

#### Download Shellcode in temp folder and execute it

* Lastly, when `r` is given, Hancitor downloads a file from the URL specified in the response, drops it in the Windows Temp folder, and launches it.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FDaJg2D5tT7ZJMLGyzTix%2Fimage.png?alt=media&#x26;token=3e314ef3-1157-4e00-873a-4f932f691469" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2FlL4n8fe7opkpNwTvMDZS%2Fimage.png?alt=media&#x26;token=e694c279-3442-4b2a-969b-b1a620bc5d1b" alt=""><figcaption></figcaption></figure>

* Hancitor gets the temp folder location using the `GetTempPathA` winapi and `GetTempFileNameA` to generate a temporary file’s name in that path with the prefix of “BN”.
* Then it calls `CreateFileA` and `WriteFile` to write the downloaded content to the temporary file.

<figure><img src="https://2429440930-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvmiq90eCUf7ZZMUGm7Qu%2Fuploads%2Fa52PTluZr4yftywBQust%2Fimage.png?alt=media&#x26;token=3f3d3361-5770-4291-8190-1f0b69bb064b" alt=""><figcaption></figcaption></figure>

* After that, the malware checks the `Characteristics` flag in the file header to determine if the payload is a PE or a DLL. If the file is an executable, it's launched by calling `CreateProcessA` with the file’s path as the command line to be executed.&#x20;
* If the file is a DLL, the malware launches it by calling `CreateProcessA` with a formatted `rundll32.exe` command as the command line.
* The analysis of Hancitor is now complete. The yara detection rules for this malware are below.

## YARA Rule

***

{% code overflow="wrap" %}

```json
rule Hancitor_General {
    meta:
        description = "Hancitor detection general rule"
        author = "Swayam Tejas Padhy"
        date = "2025-10-12"
        malware_family = "Hancitor"
        malware_type = "Trojan"
        severity = "high"
        
    strings:
        // User-Agent string
        $ua_string = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko" ascii
        
        // Content-Type header
        $content_type = "Content-Type: application/x-www-form-urlencoded" ascii
        
        // IP service
        $ipify_url = "http://api.ipify.org" ascii nocase
        
        // Beacon parameters
        $beacon_guid = "GUID=%I64u" ascii
        $beacon_build = "&BUILD=" ascii
        $beacon_info = "&INFO=" ascii
        $beacon_ext = "&EXT=" ascii
        $beacon_ip = "&IP=" ascii
        $beacon_type = "&TYPE=1" ascii
        $beacon_win_x64 = "&WIN=%d.%d(x64)" ascii
        $beacon_win_x32 = "&WIN=%d.%d(x32)" ascii
        
        // Command validation
        $cmd_valid = "ncdrleb" ascii
        
        // Rundll32 execution
        $rundll_pattern = "Rundll32.exe %s, start" ascii
        
        // System path construction
        $svchost_path = "\\System32\\svchost.exe" ascii
        
        // Compression marker
        $compression_marker = { 80 A8 15 54 }
             
        // XOR deobfuscation
        $xor_key = { 7A }
        
        // Base64
        $base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ascii
        
        // Windows API imports
        $api_1 = "GetAdaptersAddresses" ascii
        $api_2 = "DsEnumerateDomainTrustsA" ascii
        $api_3 = "K32GetProcessImageFileNameA" ascii
        $api_4 = "RtlDecompressBuffer" ascii
        $api_5 = "CryptDeriveKey" ascii
        
        // Process creation
        $create_suspended = { 00 00 00 04 } // CREATE_SUSPENDED flag
        
        // Pipe delimiter
        $pipe_delim_check = { 7C 00 } // pipe character check
        
        // Stack strings
        $explorer_exe = "explorer.exe" ascii
        $temp_prefix = "tmp" ascii wide
        
        // Registry and mutexs
        $systemroot = "SystemRoot" ascii
        
        // Thread context manipulation
        $context_integer = { 00 00 01 00 } // CONTEXT_INTEGER
        
        // RC4 algorithm
        $rc4_algid = { 01 68 00 00 } // CALG_RC4 = 0x6801
        
        // SHA1 algorithm  
        $sha1_algid = { 03 80 00 00 } // CALG_SHA1 = 0x8003
        
        // LZNT1 compression
        $lznt1_format = { 02 00 } // Compression format 2
        
        // HTTPS
        $sec_flag_ignore_ca = { 00 00 01 00 } // SECURITY_FLAG_IGNORE_UNKNOWN_CA
        
        // VirtualAlloc
        $page_exec_readwrite = { 40 00 00 00 } // PAGE_EXECUTE_READWRITE
        
        // Dynamic resolution
        $getprocaddr = "GetProcAddress" ascii
        $loadlibrary = "LoadLibraryA" ascii
        
        // HTTP methods
        $http_get = "GET" ascii fullword
        $http_post = "POST" ascii fullword
        
        // WinINet flags
        $internet_open_type = { 01 00 00 00 } // INTERNET_OPEN_TYPE_PRECONFIG
        
    condition:
        uint16(0) == 0x5A4D and // MZ header
        filesize < 5MB and
        (
            // Core C2 communication
            (
                $ua_string and
                $content_type and
                ($beacon_guid or $beacon_build) and
                2 of ($beacon_*)
            ) or
            
            // Fingerprinting
            (
                $ipify_url and
                $api_1 and
                ($explorer_exe or $systemroot)
            ) or
            
            // Payload execution
            (
                $rundll_pattern and
                $svchost_path and
                $create_suspended and
                $page_exec_readwrite
            ) or
            
            // Cryptographic operations
            (
                $base64_alphabet and
                $xor_key and
                ($rc4_algid or $sha1_algid) and
                $api_5
            ) or
            
            // Combination
            (
                3 of ($api_*) and
                $compression_marker and
                $cmd_valid and
                2 of ($http_*)
            ) or
            
            // Decompression and obfuscation
            (
                $api_4 and
                $lznt1_format and
                $compression_marker and
                $base64_alphabet
            )
        ) and
        
        // API imports
        (
            3 of ($api_*) or
            (
                $getprocaddr and
                $loadlibrary and
                2 of ($beacon_*)
            )
        )
}

rule Hancitor_Definitive {
    meta:
        description = "Patterns which are definitively Hancitor"
        author = "Swayam Tejas Padhy"
        reference = "Hancitor beacon"
        date = "2025-10-12"
        severity = "critical"
        
    strings:
        $beacon_format_1 = "GUID=%I64u&BUILD=%s&INFO=%s&EXT=%s&IP=%s&TYPE=1&WIN=%d.%d(x64)" ascii
        $beacon_format_2 = "GUID=%I64u&BUILD=%s&INFO=%s&EXT=%s&IP=%s&TYPE=1&WIN=%d.%d(x32)" ascii
        $ipify = "http://api.ipify.org" ascii
        $ua = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko" ascii
        $content_type = "Content-Type: application/x-www-form-urlencoded" ascii
        $commands = "ncdrleb" ascii
        
    condition:
        uint16(0) == 0x5A4D and
        filesize < 3MB and
        (
            ($beacon_format_1 or $beacon_format_2) and
            $ipify and
            $ua and
            $content_type and
            $commands
        )
}

rule Hancitor_Payload_Execution {
    meta:
        description = "Hancitor payload execution"
        author = "Swayam Tejas Padhy"
        reference = "Hancitor reflective injection analysis"
        date = "2025-10-12"
        severity = "high"
        
    strings:
        $svchost = "\\System32\\svchost.exe" ascii
        $rundll = "Rundll32.exe %s, start" ascii
        $compression = { 80 A8 15 54 }
        $proc_api_1 = "CreateProcessA" ascii
        $proc_api_2 = "WriteProcessMemory" ascii
        $proc_api_3 = "VirtualAllocEx" ascii
        $proc_api_4 = "CreateRemoteThread" ascii
        $proc_api_5 = "GetThreadContext" ascii
        $proc_api_6 = "SetThreadContext" ascii
        $temp_prefix = "tmp" ascii
        
    condition:
        uint16(0) == 0x5A4D and
        filesize < 3MB and
        $svchost and
        (
            ($rundll and $temp_prefix and $compression) or
            (4 of ($proc_api_*) and $compression)
        )
}
```

{% endcode %}

***
