Supply Chain Attacks and Trusted Binary Abuse: When Your Own Software is the Threat

21 April 2026 | 5 min read | justruss.tech

Supply chain attacks are identified by Group-IB as the top global cyber threat in 2026. Over 30 threat actors in current tracking use supply chain techniques. The reason is straightforward: compromising a piece of software used by thousands of organisations achieves a scale of access that no direct attack can match, and the initial malicious code arrives signed by a legitimate vendor’s certificate and passes all standard integrity checks.

How supply chain attacks work

Supply chain attacks compromise software or its distribution at a point before it reaches the target. The most common points of compromise are the build environment (SolarWinds, XZ Utils), the update mechanism (CCleaner 2017, ASUS Live Update), software repositories (PyPI and npm malicious packages), and third-party libraries included in legitimate software (log4shell’s reach across software that included log4j).

// What makes supply chain attacks so hard to detect:
// 1. The software is legitimately signed by the real vendor
// 2. The installation process is normal and expected
// 3. The initial payload may be dormant for weeks or months
// 4. Delivery happens through trusted channels (auto-update, package manager)
// 5. File hashes match what the vendor published (if the compromise was upstream)

// The SolarWinds pattern (DLL side-loading via update mechanism):
// - SUNBURST was embedded in a legitimate SolarWinds Orion DLL
// - The DLL was signed by SolarWinds's legitimate code signing certificate
// - It was delivered via the normal Orion update mechanism
// - It was dormant for 12-14 days after installation before calling out
// - C2 traffic mimicked legitimate Orion API traffic patterns

Detection approach 1: behavioural baselining of trusted software

// Even if you cannot detect the malicious code inside a trusted binary,
// you CAN detect when that binary starts doing things it has never done before

// Build a behaviour baseline for commonly targeted software:
// - What processes does each software spawn?
// - What network connections does each software make?
// - What registry keys does each software modify?
// - What files does each software read and write?

// Splunk: detect new network destinations from trusted software
// Step 1: Build baseline
index=sysmon EventCode=3 earliest=-30d latest=-1d
 Image IN ("*\\SolarWinds.BusinessLayerHost.exe",
 "*\\MsMpEng.exe",
 "*\\OUTLOOK.exe",
 "*\\chrome.exe")
| stats dc(DestinationIp) AS unique_ips, values(DestinationIp) AS known_ips
 by Image
| outputlookup trusted_software_network_baseline.csv

// Step 2: Hunt for deviations
index=sysmon EventCode=3 earliest=-24h
 Image IN ("*\\SolarWinds.BusinessLayerHost.exe", ...)
| lookup trusted_software_network_baseline.csv Image OUTPUT known_ips
| where NOT match(DestinationIp, known_ips)
| table _time, Image, DestinationIp, DestinationPort

Detection approach 2: network traffic analysis for dormant C2 activation

// Supply chain malware often lies dormant then activates
// Activation usually involves:
// 1. First outbound connection to C2 (check-in)
// 2. DNS queries for previously unseen domains
// 3. HTTPS connections to new IPs from trusted processes

// Zeek: detect first-time DNS queries from specific processes
// (Requires process tracking, available in Zeek with process_info plugin)
cat dns.log | zeek-cut ts query id.orig_h |
 sort -k2 | uniq -f1 | // First occurrence of each query per source
 grep -f monitored_processes.txt | // Filter for processes you want to track
 head -20

// Alternative: use Sysmon Event ID 22 (DNS Query) correlated with network events
index=sysmon EventCode=22 earliest=-24h
| join SourceIp, DestinationIp [
 search index=sysmon EventCode=3 earliest=-30d latest=-7d
 | stats count by SourceIp, DestinationIp
 | where count > 5 // Established connections
]
| where isnull(count) // New connection with no prior history
| where match(Image, "trusted_software_patterns")
| table _time, Image, QueryName, DestinationIp

Detection approach 3: software bill of materials (SBOM) and hash monitoring

// Maintain a hash database of every version of software you have deployed
// Alert when a file you thought you knew changes unexpectedly

python3 << EOF
import os, hashlib, json, datetime
from pathlib import Path

# Software directories to monitor
monitored_dirs = [
 "C:\\Program Files\\SolarWinds",
 "C:\\Program Files\\Microsoft Office",
 "C:\\Program Files\\Common Files\\Adobe",
]

def hash_file(path):
 sha256 = hashlib.sha256()
 try:
 with open(path, "rb") as f:
 for chunk in iter(lambda: f.read(65536), b""):
 sha256.update(chunk)
 return sha256.hexdigest()
 except:
 return None

# Build current inventory
inventory = {}
for directory in monitored_dirs:
 for root, dirs, files in os.walk(directory):
 for file in files:
 if file.endswith((".exe", ".dll", ".sys")):
 filepath = os.path.join(root, file)
 h = hash_file(filepath)
 if h:
 inventory[filepath] = {
 "hash": h,
 "size": os.path.getsize(filepath),
 "modified": os.path.getmtime(filepath)
 }

# Compare against known-good baseline
with open("software_baseline.json") as f:
 baseline = json.load(f)

for filepath, data in inventory.items():
 if filepath in baseline:
 if data["hash"] != baseline[filepath]["hash"]:
 print(f"HASH CHANGED: {filepath}")
 print(f" Old: {baseline[filepath]['hash']}")
 print(f" New: {data['hash']}")
 else:
 print(f"NEW FILE: {filepath} ({data['hash']})")

print(f"\nInventory: {len(inventory)} files checked")
EOF

Detection approach 4: package repository monitoring

// For organisations that use PyPI, npm, RubyGems etc:
// Monitor for typosquatting and dependency confusion attacks

python3 << EOF
import pkg_resources, requests

# Get all installed Python packages
installed = {pkg.project_name.lower(): pkg.version
 for pkg in pkg_resources.working_set}

# Check PyPI for each package
suspicious = []
for package_name, version in installed.items():
 try:
 resp = requests.get(f"https://pypi.org/pypi/{package_name}/json", timeout=5)
 if resp.status_code == 200:
 pypi_data = resp.json()
 # Check author and package age
 info = pypi_data.get("info", {})
 upload_time = pypi_data.get("releases", {}).get(version, [{}])[0].get("upload_time", "")

 # Flag recently uploaded packages with generic names
 if upload_time > "2024-01-01":
 suspicious.append({
 "package": package_name,
 "version": version,
 "upload_time": upload_time,
 "author": info.get("author", "unknown")
 })
 except:
 pass

print("Recently published packages in your environment:")
for pkg in suspicious[:20]:
 print(f" {pkg['package']} {pkg['version']} (uploaded: {pkg['upload_time']}, author: {pkg['author']})")
EOF