| name | analyzing-supply-chain-malware-artifacts |
| description | Investigate supply chain attack artifacts including trojanized software updates, compromised build pipelines, and sideloaded dependencies to identify intrusion vectors and scope of compromise. |
| domain | cybersecurity |
| subdomain | malware-analysis |
| tags | ["supply-chain","malware-analysis","trojanized-software","solarwinds","3cx","dependency-confusion","software-integrity"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
Analyzing Supply Chain Malware Artifacts
Overview
Supply chain attacks compromise legitimate software distribution channels to deliver malware through trusted update mechanisms. Notable examples include SolarWinds SUNBURST (2020, affecting 18,000+ customers), 3CX SmoothOperator (2023, a cascading supply chain attack originating from Trading Technologies), and numerous npm/PyPI package poisoning campaigns. Analysis involves comparing trojanized binaries against legitimate versions, identifying injected code in build artifacts, examining code signing anomalies, and tracing the infection chain from initial compromise through payload delivery. As of 2025, supply chain attacks account for 30% of all breaches, a 100% increase from prior years.
Prerequisites
- Python 3.9+ with
pefile, ssdeep, hashlib
- Binary diff tools (BinDiff, Diaphora)
- Code signing verification tools (sigcheck, codesign)
- Software composition analysis (SCA) tools
- Access to legitimate software versions for comparison
- Package repository monitoring (npm, PyPI, NuGet)
Practical Steps
Step 1: Binary Comparison Analysis
"""Compare trojanized binary against legitimate version."""
import hashlib
import pefile
import sys
import json
def compare_pe_files(legitimate_path, suspect_path):
"""Compare PE file structures between legitimate and suspect versions."""
legit_pe = pefile.PE(legitimate_path)
suspect_pe = pefile.PE(suspect_path)
report = {"differences": [], "suspicious_sections": [], "import_changes": []}
legit_sections = {s.Name.rstrip(b'\x00').decode(): {
"size": s.SizeOfRawData,
"entropy": s.get_entropy(),
"characteristics": s.Characteristics,
} for s in legit_pe.sections}
suspect_sections = {s.Name.rstrip(b'\x00').decode(): {
"size": s.SizeOfRawData,
"entropy": s.get_entropy(),
"characteristics": s.Characteristics,
} for s in suspect_pe.sections}
for name, props in suspect_sections.items():
if name not in legit_sections:
report["suspicious_sections"].append({
"name": name, "reason": "New section not in legitimate version",
"size": props["size"], "entropy": round(props["entropy"], ),
})
(props[] - legit_sections[name][]) > :
report[].append({
: name, : ,
: legit_sections[name][],
: props[],
})
legit_imports = ()
(legit_pe, ):
entry legit_pe.DIRECTORY_ENTRY_IMPORT:
imp entry.imports:
imp.name:
legit_imports.add()
suspect_imports = ()
(suspect_pe, ):
entry suspect_pe.DIRECTORY_ENTRY_IMPORT:
imp entry.imports:
imp.name:
suspect_imports.add()
new_imports = suspect_imports - legit_imports
new_imports:
report[] = (new_imports)
report[] = (legit_pe.OPTIONAL_HEADER.DATA_DIRECTORY[].Size)
report[] = (suspect_pe.OPTIONAL_HEADER.DATA_DIRECTORY[].Size)
report
():
hashes = {}
(filepath, ) f:
data = f.read()
algo [, , ]:
h = hashlib.new(algo)
h.update(data)
hashes[algo] = h.hexdigest()
hashes
__name__ == :
(sys.argv) < :
()
sys.exit()
report = compare_pe_files(sys.argv[], sys.argv[])
(json.dumps(report, indent=))
Validation Criteria
- Trojanized components identified through binary diffing
- Injected code isolated and analyzed separately
- Code signing anomalies documented
- Infection timeline reconstructed from build artifacts
- Downstream impact scope assessed across affected systems
- IOCs extracted for detection and blocking
References