Sep 07, 2026

Unpacking malware: Hancitor

Analysis of a packed sample attributed to the Hancitor loader (also known as Chanitor and Tordal), with unpacking, encrypted configuration extraction, and C2 infrastructure identification.

malware-analysisunpackingloaderhancitorreverse-engineeringwindows
sample.metadatahigh
family
Hancitor

Summary

This article documents the analysis of a packed sample attributed to the Hancitor loader (also known as Chanitor and Tordal). The goal was to unpack the sample, extract its encrypted configuration, and identify the command-and-control (C2) infrastructure for correlation with active threats.

The observed chain has two stages: a custom packer that decrypts and executes a payload in memory, and the Hancitor loader itself, whose configuration — encrypted with RC4 in the .data section — contained the build ID and three malicious server gates. The decryption routine matches the publicly known Hancitor scheme (RC4 with a key derived from SHA-1 via CryptoAPI), which supported the attribution.

Unpacking process, configuration extraction, and infrastructure attribution

I received a malicious file for analysis with the goal of understanding more about the attacker’s infrastructure and whether it could be linked to any currently active threat.

First things first, I used the good old architecture overview for the file, which returned the following information: it’s a 32-bit PE binary, written in C, with some identifiable layer of protection.

Detect It Easy: PE32, GUI, Visual Studio 2022, Generic[No IAT], overlay at 0x00023a00

Looks suspicious? We’ll see.

Stage 1 (packer)

The binary has 4 sections and, apparently, not all strings are readable, reinforcing a high probability that they’re still heavily encoded.

Binary sections: .text, .rdata, .data, .rsrc

The .text (6.5) and .rsrc (7.3) sections are present with high entropy, which calls for extremely careful analysis.

Section entropy: .text and .rsrc flagged as packed

A subset of strings was visible in readable text and were tied to credentials and abuse of the legitimate “ScreenConnect” tool, suggesting the use of remote access software. Could this file be related to an infostealer? As tempting as it is to lean on some biases during the investigation, I can’t attribute it to an infostealer until the hypothesis is proven based on reliable evidence.

Credential-related strings found in the binary

ScreenConnect-related strings found in the binary

Checking the import table, only kernel32.dll and msimg32.dll are present. The export table is empty.

Import table: only KERNEL32.dll and MSIMG32.dll

There’s also an API function called IsDebuggerPresent, giving an insight into checks for malware-debugging tools.

Adding up these signals, there’s a strong indication that something malicious is being hidden in this binary.

Since the resources (.rsrc) are packed, I used Resource Hacker to check what was inside, and the result was two string tables.

String Table 7:

STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
  101, "sadof asdoufyg a9s7d8gf aosd8yf ga9sd6f aosdf"
  102, "asdjf[ 9as7df 9a7ds8f haosdf"
  103, "[ asdif 87asdtf7asgydhf"
  104, "aps\xF8df pasdtfasd{F ua[sd8f asfd uap9sdyf a"
  105, "SDUfp a7tsdfa"
  106, "sduf asdtf9a78sdyfi7asdf aspdf gas7dfy aosdf["
  107, " aisd0fy aos7d gfasid;fh asfdj a9psdf8 ya97df6gwpt4iu;g p"
  108, "ODFg [98asdfyg 9asd078yf hbwotegn "
  109, "[wdjfvp8YSADf8as9d87ef hw]4"
  110, "[gp ad[fogy97dsftay[08gidofh"
  111, "asdif pas7dtf8asd97f9gwegu"
}

String Table 8:

STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
  112, "asdojf p8sdf8asdfgap87g hsdfog"
  113, "[ jsfgohij w0r7tg ha8sdgf a7sdhf "
  114, "a[sdg jfdoh g97a6dsgfya[08sdyfia7sdyf "
  115, "[asdkf psdf7yg a8sd7fy 8hwouifg na"
  116, "s[odjf a078sdf t8a90f78p9g hwhti \x07"
  117, "sdgk aps9d7fta9sd87f hao8sdfugj "
  118, "a[spdkg p9as8dyf as8dh f"
  119, "[asdojf [ausd f7isd8fh"
  120, "[asdjf p8ysdg f08a7sd gf9a8sduf ap9sduhf as8d9"
}

String tables 7 and 8 in Resource Hacker

I still don’t have enough correlation to confirm this content is tied to the actual unpack routine in this analysis — it could be padding or an additional layer of encoded data.

Looking at the Windows API calls, some of them can point toward the malicious file’s objective:

  • LoadLibraryW
  • CreateHardLinkA
  • WriteFile
  • CreateFileW
  • VirtualProtect

In IDA, you can see a considerable .data area marked as “unexplored” and a mention of “dfighjbsdiofj.dll” in both .data and .rdata, plus an instruction that could point to in-memory decompression.

IDA: sub_401F00 calling sub_401390/sub_402B20

IDA: sub_807C10 with CreateHardLinkA and calls to GetProcAddress

The binary calls a .txt file (push 01:adfspgkjsdflkgjsdkfgmpskdfjgopsdfgpsdfmgpsdflgm.txt). Right after, an oddly named DLL was also identified: dfighjbsdiofj.dll.

With the pseudocode in evidence, you can read the entire unpack routine and know exactly where to focus while running the debugger.

The CreateHardLinkA function stands out for not being a commonly abused API by malware — it could indicate anti-forensic evasion (creating a link to the same file at another path) or a remnant of reused legitimate code.

In routine sub_807C10, several of these calls (CreateHardLinkA, GetPrivateProfileSectionW, CreateFileA with a random filename, TransparentBlt with all null parameters) are anti-analysis decoys with no functional effect. The two do;while loops with unlikely comparisons are timing delays. The real core of the unpack is just four steps, described below.

v5 = LocalAlloc(0, 0x7550u);                       // allocate buffer
VirtualProtect(v5, 0x7550u, 0x40u, &floldProtect);  // RWX (PAGE_EXECUTE_READWRITE)
TransparentBlt(nullptr, 0, 0, 0, 0, ...);
[..]
for (i=0; i<0x7550; i++)                            // copy the blob (loop at 0x807D80)
    v5[i] = src[i + (0x811D65 - v5)];               // src is fixed inside the binary itself
sub_807B70();                                       // decrypt (TEA)
((void(*)())v5)();                                  // call [ebp-824] -> executes the payload

Pseudocode of sub_807C10: decoy calls and buffer allocation

Pseudocode continuing: VirtualProtect and TransparentBlt

What actually copies the payload is the byte-by-byte copy loop at 0x807D80, and the routine sub_807B70 implements TEA (Tiny Encryption Algorithm) in decryption mode, identified by the constants 0xC6EF3720 (initial sum = delta × 32) and 0x61C88647 (−delta). The key used is four DWORDs stored in .rdata. After this step runs, the buffer contains a valid PE (MZ), and the loader is executed via call [ebp-824].

The call to TransparentBlt (exported by msimg32.dll) shows up with null parameters — meaning it doesn’t perform any useful copy in this flow, which points to a possible attempt at disguise, meant to add noise and misattribute the real copy to the identified loop.

With this information in hand, breakpoints were used on important functions that cover the in-memory unpacker cycle:

  • LocalAlloc: allocation of the destination buffer
  • VirtualProtect: setting up executable permissions (RWX)
  • CreateFileA: persisting artifacts to disk

Practical capture tip: stopping at VirtualProtect, the buffer (lpAddress, at [esp+4]) is still encrypted. The ideal dump point is right after the TEA decryption and before the call [ebp+824], because at that instant the MZ header is already fully formed.

Breakpoint at VirtualProtect, dfighjbsdiofj.dll check (STATUS_OBJECT_NAME_NOT_FOUND)

TransparentBlt IAT resolution (msimg32.dll)

Copying the blob to the buffer and TEA decryption happening — payload unpacked

Stage 2 (payload)

After unpacking and dumping, the newly generated file has an Imports table with the functions: wininet, iphlpapi, psapi, ntdll, kernel32, user32, advapi. Also, the number of sections increased to 6, with .data showing packed status and high entropy (7.8).

Sections and import table after the dump (6 sections, ADVAPI32.dll etc.)

This time, looking at the strings pane, it was possible to notice a new range of information such as:

  • Connection (wininet.dll, InternetConnect)
  • Process enumeration and system information gathering
  • Crypt/decrypt routines
  • Memory manipulation
  • Decompression of packed data (ntdll > RtlDecompressBuffer)
  • Loader self-deletion after execution (\System32\svchost.exe /c del >> NUL)
  • Connectivity check services: http://api.ipify.org and http://google.com
  • IP placeholder: 0.0.0.0
  • Beacon: GUID=%I64u&BUILD=%s&INFO=%s&IP=%s&TYPE=1&WIN=%d.%d(x32 ;x64)
  • User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko

Host profiling: possibly generating a unique victim ID from the Windows directory’s volume serial combined with the adapters’ MAC addresses, collecting OS version, IP, machine/user name, and domain trusts. Malware commonly uses this information to decide the next payload (based on the victim’s environment). This explains the GUID/INFO/IP fields in the beacon.

Ok, but what’s in .data? (Stage 3 - final)

Analyzing the unexplored part of the binary in .data, which starts with: 00406000 10 20 30 40 50 60 70 80 31 33 2E 36 37 00 00 00. 0@P’p.13.67, it’s likely that the sequence 10 20 30 40 50 60 70 80 could be the 8-byte key for decryption (0@P’p), followed by the version string “13.67”.

The routine sub_401F00 is what drives the decryption action, calling "call sub_401390", "call sub_401450", and finally "call sub_402B20", which in turn does the decrypt using the key.

Basically, it goes in this order:

sub_401390 > sub_401450 > sub_402B20

allocate 0x2000 > copy the blob > decrypt via CryptoAPI

Disassembling sub_402B20 reveals the following scheme:

  • CryptCreateHash with ALG_ID 0x8004 = SHA-1
  • CryptHashData on the 8-byte key (pbData at 0x406010)
  • CryptDeriveKey with ALG_ID 0x6801 = RC4 and flags 0x280011 → 40-bit (5-byte) key
  • CryptDecrypt (RC4) on the blob at 0x406018, in-place

In other words, the RC4 key is, in fact, the first 5 bytes of the SHA-1 (of the 8-byte key). This type of config-extraction mechanism has been observed and attributed to the Hancitor malware, described in articles from Unit 42, OALabs, Binary Defense, and others. This is a strong indicator of the malware family.

CryptDecrypt function signature:

CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen)
              [esp+4] [esp+8] [esp+C] [esp+10] [esp+14]  [esp+18]

The following text was pulled from the Microsoft wiki for the CryptDecrypt function:


CryptDecrypt function (wincrypt.h)

The CryptDecrypt function decrypts data previously encrypted using the CryptEncrypt function. Important changes to support Secure/Multipurpose Internet Mail Extensions (S/MIME) interoperability have been made to CryptoAPI, affecting how enveloped messages are handled. For more information, see the Remarks section of CryptMsgOpenToEncode.

Syntax

BOOL CryptDecrypt(
  [in]      HCRYPTKEY hKey,
  [in]      HCRYPTHASH hHash,
  [in]      BOOL      Final,
  [in]      DWORD     dwFlags,
  [in, out] BYTE      *pbData,
  [in, out] DWORD     *pdwDataLen
);

Parameters

[in, out] pbData : A pointer to a buffer that contains the data to be decrypted. After decryption has taken place, the plaintext is placed back in this same buffer. The number of encrypted bytes in this buffer is specified by pdwDataLen.

[in, out] pdwDataLen : A pointer to a DWORD value that indicates the length of the pbData buffer. Before calling this function, the calling application sets this DWORD value to the number of bytes to be decrypted. On return, the DWORD value contains the number of bytes of decrypted plaintext. When a block cipher is used, this data length must be a multiple of the block size, unless this is the final section of data to decrypt and the Final parameter is TRUE.

Return value

If the function succeeds, it returns a nonzero value (TRUE). If the function fails, it returns zero (false).


In short, CryptDecrypt decrypts, in memory, a buffer previously encrypted with CryptEncrypt; the relevant parameter here is pbData (5th parameter → [esp+14]), which receives and returns the same buffer — ciphertext goes in, plaintext comes out, in-place.

Keeping this in mind, pbData (the buffer that’s decrypted in-place) is the 5th parameter = [esp+14], located at address 00A3B850. Running the debug up to the return, which lands in the final call to cryptsp, and looking at address 00A3B850, there are now domains in readable text.

In the analyzed case, [esp+14] = 00A3B850; running up to the function’s return and inspecting that address, it’s possible to identify, in readable text, the domains that lead to the infrastructure used by the attacker during the campaign.

  • C2: http://howrowthettof.com/ls5/forum.php
  • C2: http://ratsparropret.ru/ls5/forum.php
  • C2: http://ryropthetsed.ru/ls5/forum.php

CryptDeriveKey in cryptsp.dll and readable domains in the memory dump

With that, the malware was unpacked and the analysis’s initial objective was reached: identifying the campaign’s infrastructure and correlating the attack to a real threat.

Searching historical indicators related to these addresses, it’s possible to see they are indeed malicious, with attribution to the Hancitor family.

Note: there may be more than one call to CryptDecrypt. If the first stop doesn’t expose any URLs, just continue running the debug until the call that decrypts the 0x2000-byte config block.

The convergence between network behavior and the decryption scheme raises the attribution’s confidence from “probable” to “high”.

Hancitor is a downloader/loader active since mid-2014, distributed via malspam with maldocs, historically delivering Pony, Vawtrak, FickerStealer, Sendsafe, and Cobalt Strike Beacon. It has been associated with the Cuba ransomware operation as its loader of choice.

MITRE ATT&CK

TacticTechniqueID
Defense EvasionObfuscated Files or InformationT1027
Defense EvasionObfuscated Files or Information: Software PackingT1027.002
Defense EvasionObfuscated Files or Information: Embedded PayloadsT1027.009
Defense EvasionDeobfuscate/Decode Files or InformationT1140
Defense EvasionDebugger EvasionT1622
Defense EvasionReflective Code LoadingT1620
PersistenceCreate or Modify System Process: Windows ServiceT1543.003
Command and ControlRemote Access Software (ScreenConnect)T1219
Command and ControlApplication Layer Protocol: Web ProtocolsT1071.001
DiscoveryInternet Connection DiscoveryT1016.001
Defense EvasionIndicator Removal: File DeletionT1070.004

IoCs

Files

ArtifactHash
Packer (binary.exe)7dcbb4e490ee52c01e7838288c799981eaab47131b9f3dc21d349b8eac7545d4
Packer (Imphash)4b61c02635e27b3b91e08cf39f0b6207
SHA-13546f8a5f516a12b87ca7fefd83fe806bf9624dd
Dump (payload)bf65a4c82f262241e91a0c5e162ae8520d26dcba257a3c7ed137bf14edd4400b
Unpacker17511446d1943880bf579e703c5fca96d307e10583fa2b98d926a415d8576061

Network

TypeIndicator
URL C2hxxp://howrowthettof[.]com/ls5/forum[.]php
URL C2hxxp://ratsparropret[.]ru/ls5/forum[.]php
URL C2hxxp://ryropthetsed[.]ru/ls5/forum[.]php
Domainhowrowthettof[.]com
Domainratsparropret[.]ru
Domainryropthetsed[.]ru
IP199[.]59[.]242[.]150
IP212[.]116[.]113[.]108
IP163[.]172[.]235[.]143

Other names

  • hancitor[.]exe
  • 7dcbb4e490ee52c01e7838288c799981eaab47131b9f3dc21d349b8eac7545d4[.]exe
  • 7e8c4d0d8ee8310eba3360e7c4f27cd9
  • putty[.]exe

References