d65f14e5652a4330354826925dc56937334163656f24dd10f112c15bc7559de1meshcentral-agent-dropper: d65f14e5 — Go 1.26.2 MeshCentral installer with anti-debug hardening
Executive Summary
A Go 1.26.2 PE64+ distributed via the gcleaner pipeline (OpenCTI label uniq.file). Near-identical to sibling 90989061 but adds a harden_windows.go anti-debug module: debugger detection via IsDebuggerPresent, CheckRemoteDebuggerPresent, PEB.BeingDebugged, debug-port enumeration, and parent-process name checks against RE tools. Same azurenetfiles.net C2 and MeshCentral agent payload. Static-only — no CAPE detonation available.
What It Is
- File: PE32+ executable (GUI) x86-64, 8 sections, 6,115,328 bytes ^[file.txt]
- Compiler / Linker: Go 1.26.2,
CGO_ENABLED=0,-trimpath=true^[strings.txt:6404] - Go build ID:
0uj9SmzzVpuARzN9Ycd_/3T_FrFCvyrm61RfiJlX7/KCKCZl87HlwAX-MDEjKg/xuPWLgZek611TvGhl4NY^[strings.txt:9] - Module path:
meshdrop(devel) ^[strings.txt:6401] - Source files recovered:
meshdrop/main.go,meshdrop/exec_windows.go,meshdrop/install_windows.go,meshdrop/harden_windows.go^[strings.txt:15666] - TimeDateStamp: 0x0 (stripped / reproducible build) ^[pefile.txt:34]
- Signed: No — IMAGE_DIRECTORY_ENTRY_SECURITY empty ^[rabin2-info.txt:27]
- No VS_VERSIONINFO / resource directory ^[pefile.txt:246]
- IAT: Minimal — only
kernel32.dllimports (48 entries), nowininet/winhttpIAT entries; all networking via Go stdlib ^[pefile.txt:288] - OpenCTI labels:
uniq.file,dropped-by-gcleaner,exe,u,malware-bazaar^[triage.json]
How It Works
1. Build / RE
Toolchain: Go 1.26.2 with -trimpath=true and CGO_ENABLED=0. Standard Go cross-compile for Windows AMD64 — no packing, no obfuscation, no UPX. The binary is ~2.7 MB .text (Go runtime) plus standard library HTTP/TLS/crypto code.
Anti-analysis — the delta from sibling 90989061:
This sample adds a full anti-debug / anti-RE hardening module (meshdrop/harden_windows.go) absent from the first sibling:
| Function | Technique | Evidence |
|---|---|---|
main.detectDebugger |
Composite debugger detection | main.detectDebugger symbol ^[strings.txt:14272] |
main.isDebuggerPresent |
IsDebuggerPresent API |
IsDebuggerPresent in runtime strings + function symbol ^[strings.txt:6141] |
main.isRemoteDebuggerPresent |
CheckRemoteDebuggerPresent API |
main.isRemoteDebuggerPresent symbol ^[strings.txt:14274] |
main.pebDebugged |
PEB.BeingDebugged byte read |
main.pebDebugged, main.readPEBByte symbols ^[strings.txt:14277] |
main.hasDebugPort |
Debug port enumeration | main.hasDebugPort symbol ^[strings.txt:14275] |
main.debugFlagsUnset |
NtGlobalFlag / heap flag checks |
main.debugFlagsUnset symbol ^[strings.txt:14276] |
main.readPEBUint32 |
PEB dword reads for field parsing | main.readPEBUint32 symbol ^[strings.txt:14279] |
main.suspiciousParent |
Parent process name check | main.suspiciousParent, main.parentProcessName symbols ^[strings.txt:14280] |
main.hardenPostInstall |
Post-install hardening | main.hardenPostInstall symbol ^[strings.txt:14283] |
main.installWatchdog |
Watchdog / respawn | main.installWatchdog symbol ^[strings.txt:14288] |
RE tool blacklist (checked by main.suspiciousParent or main.detectDebugger):
x64dbg.exe, x32dbg.exe, windbg.exe, idaq.exe, idaq64.exe, dnspy-x86.exe, dnspy.exe, ghidrarun.exe, wireshark.exe, procmon.exe, procmon64.exe, procexp.exe, procexp64.exe, devenv.exe ^[strings.txt:6136]
Code quality: Idiomatic Go — defer wrappers, error returns, context propagation. Function names are not randomized (unlike acrstealer / lummastealer clusters), making static analysis trivial once recognized as Go. The hardening module appears to be a clean Go syscall/unsafe implementation rather than copied from a public snippet.
2. Deploy / ATT&CK
Entry-point flow (inferred from recovered Go symbol names):
main.main→ checks admin rights (main.requireAdmin), hides console window (main.hideWindow), runs anti-debug checks (main.detectDebugger) ^[strings.txt:14239]main.download→ HTTPS GET tohttps://azurenetfiles.net/meshagents?id=4&meshid=9Y7M9CsyteFGxSZPNyUB%4027EFbzf0wS%40r8bsW77uObPaWIigg2EiEGfpoYF%24W8Bb^[strings.txt:6398]main.validatePE→ checks the downloaded blob is a valid PE before writing to disk ^[strings.txt:14306]main.runInstall→ stages the agent to a temp path (main.tempAgentPath), installs it as a Windows service (main.waitForService,main.serviceRunning,main.scRunning), and starts it ^[strings.txt:14297]main.runAgent→ executes the installed agent binary ^[strings.txt:14296]main.hardenPostInstall→ post-installation hardening (registry or file permission tweaks) ^[strings.txt:14283]main.installWatchdog→ installs a watchdog withrestart/60000interval ^[strings.txt:14288]
ATT&CK mapping:
| Behavior | Technique | Evidence |
|---|---|---|
| Service installation | T1543.003 — Create or Modify System Process: Windows Service | main.waitForService, main.serviceRunning, main.scRunning, OpenSCManagerW ^[strings.txt:6136] |
| Admin privilege check | T1088 — Bypass User Account Control (inferred) | main.requireAdmin ^[strings.txt:14292] |
| Window hiding | T1564.010 — Hide Artifacts: VBScript (analogous) | main.hideWindow ^[strings.txt:14291] |
| HTTPS payload download | T1105 — Ingress Tool Transfer | Hardcoded azurenetfiles.net URL ^[strings.txt:6398] |
| PE validation before execution | T1027.002 — Obfuscated Files or Information: Software Packing (analogous) | main.validatePE ^[strings.txt:14306] |
| Masquerade as legitimate software | T1036.005 — Masquerading: Match Legitimate Name or Location | Installs to C:\Program Files\Mesh Agent\MeshAgent.exe ^[strings.txt:6186] |
| Debugger detection | T1622 — Debugger Evasion | main.detectDebugger, IsDebuggerPresent, CheckRemoteDebuggerPresent, PEB.BeingDebugged ^[strings.txt:14272] |
| Anti-RE parent check | T1497.001 — Virtualization/Sandbox Evasion: System Checks | main.suspiciousParent checking against x64dbg.exe, idaq.exe, etc. ^[strings.txt:14280] |
| Watchdog persistence | T1543.003 / T1547.001 — respawn monitor | main.installWatchdog with restart/60000 ^[strings.txt:14288] |
C2 Infrastructure:
- URL:
https://azurenetfiles.net/meshagents?id=4&meshid=9Y7M9CsyteFGxSZPNyUB%4027EFbzf0wS%40r8bsW77uObPaWIigg2EiEGfpoYF%24W8Bb^[strings.txt:6398] - Domain:
azurenetfiles.net - Mesh ID: Embedded in URL query parameter (URL-encoded
@as%40) - Protocol: HTTPS over TLS 1.2/1.3 via Go
crypto/tlsandnet/http^[strings.txt:460]
Attribution:
- Distributed via
gcleanerdropper pipeline per OpenCTI labeldropped-by-gcleaner^[triage.json] - The
uniq.filelabel is a distribution classification, not a technical family. Actual payload is a MeshCentral agent installer. azurenetfiles.netdomain masquerades as Azure cloud infrastructure — brand-typosquatting pattern.- Builder iteration: sibling
90989061had no anti-debug; this sample addsharden_windows.go. Indicates active development / A/B testing of hardening features.
Decompiled Behavior
Go symbol table is intact — no Ghidra decompilation required. Key functions:
main.detectDebugger— composite check: callsmain.isDebuggerPresent(API),main.isRemoteDebuggerPresent(API),main.pebDebugged(PEB byte read at offset 0x02),main.hasDebugPort(debug object port enumeration), andmain.debugFlagsUnset(NtGlobalFlag / heap flags). Returns boolean; if true, likely exits or sleeps.main.suspiciousParent— walks the process tree viaCreateToolhelp32Snapshot/Process32FirstW/Process32NextW(implied byprocessEntry32Wtype) and compares parent executable name against a blacklist of 13 RE/debugger tools. ^[strings.txt:4827]main.download— wrapsnet/http.Client.Dowith HTTPS transport. No custom TLS pinning; uses system CA store.main.validatePE— parses DOS/NT headers, checkse_magic/Signaturefields. Error stringvalidate pe: not a PE fileconfirms behavior. ^[strings.txt:6170]main.runInstall— uses Windows SCM APIs (OpenSCManagerW,CreateServiceW,StartServiceW) viasyscallpackage.main.installWatchdog— creates a watchdog process or scheduled task withrestart/60000interval (60-second respawn). ^[strings.txt:14288]main.hardenPostInstall— likely adjusts file permissions or registry values to protect the installed agent from removal.
C2 Infrastructure
| Indicator | Value | Type |
|---|---|---|
| C2 URL | https://azurenetfiles.net/meshagents?id=4&meshid=9Y7M9CsyteFGxSZPNyUB%4027EFbzf0wS%40r8bsW77uObPaWIigg2EiEGfpoYF%24W8Bb |
hardcoded HTTPS download |
| Domain | azurenetfiles.net |
brand-typosquatting |
| Install path | C:\Program Files\Mesh Agent\MeshAgent.exe |
hardcoded service binary path |
| Service name | Mesh Agent (inferred from path and sc query string) |
Windows service |
| Watchdog interval | restart/60000 |
60-second respawn |
Interesting Tidbits
- Builder evolution: Sibling
90989061had zero anti-debug. This sample addsharden_windows.gowith 10 new anti-analysis functions. The builder is actively iterating — first deploy bare installer, then add hardening. ^[/intel/analyses/9098906159e0e4c845eb918886fadc2723f2a321281b8003e471f09140321f91.html] - FIPS 140 mode: Build flags include FIPS 140-3 references (
crypto/internal/fips140/*) — unusual for crimeware, likely inherited from Go 1.26 toolchain defaults. ^[strings.txt:822] - No
.rsrcsection: No icons, no version info, no manifest. DespiteSubsystem: Windows GUI, this is a bare command-line Go binary — anti-triage by appearing unfinished. - cmd /c sc query: The binary contains the literal batch command
cmd /c sc query "Mesh Agent" | find "RUNNING" >nul || (confirming service-status polling before installation. ^[strings.txt:6189] - MeshCentral abuse: Repurposes the legitimate open-source remote-management platform for unauthorized access — textbook legitimate-remote-access-tool-abuse.
How To Mess With It (Homelab Replication)
Toolchain: Go 1.26.2 for Windows AMD64
Build flags: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-s -w"
Anti-debug module sketch:
package main
import (
"syscall"
"unsafe"
)
func isDebuggerPresent() bool {
var b bool
syscall.NewLazyDLL("kernel32.dll").NewProc("IsDebuggerPresent").Call(uintptr(unsafe.Pointer(&b)))
return b
}
func pebDebugged() bool {
// read PEB at offset 0x02 via NtQueryInformationProcess or direct TEB access
}
Verification: Build a minimal HTTPS downloader + service installer in Go using net/http + golang.org/x/sys/windows/svc. Add the above anti-debug checks. Compare string density and section entropy to this sample.
What you'll learn: How Go's buildinfo leaks module paths even with -trimpath, and how trivial it is to add anti-debug checks that are instantly visible in the symbol table.
Deployable Signatures
YARA rule
rule MESHDROP_Go126_MeshCentral_Hardened {
meta:
description = "Go 1.26.2 MeshCentral agent dropper with anti-debug hardening (meshdrop)"
author = "PacketPursuit"
date = "2026-08-18"
hash1 = "d65f14e5652a4330354826925dc56937334163656f24dd10f112c15bc7559de1"
hash2 = "9098906159e0e4c845eb918886fadc2723f2a321281b8003e471f09140321f91"
strings:
$go_build = "go1.26.2" ascii
$mod_path = "path\tmeshdrop" ascii
$c2_url = "https://azurenetfiles.net/meshagents" ascii
$func1 = "main.detectDebugger" ascii
$func2 = "main.isDebuggerPresent" ascii
$func3 = "main.isRemoteDebuggerPresent" ascii
$func4 = "main.pebDebugged" ascii
$func5 = "main.hasDebugPort" ascii
$func6 = "main.suspiciousParent" ascii
$func7 = "main.hardenPostInstall" ascii
$func8 = "main.installWatchdog" ascii
$install_path = "C:\\Program Files\\Mesh Agent\\MeshAgent.exe" ascii
$tool1 = "x64dbg.exe" ascii
$tool2 = "idaq.exe" ascii
$tool3 = "dnspy.exe" ascii
$svc1 = "OpenSCManagerW" ascii
$svc2 = "QueryServiceStatus" ascii
condition:
uint16(0) == 0x5A4D and
$go_build and
$mod_path and
($c2_url or $install_path) and
3 of ($func*) and
1 of ($tool*) and
1 of ($svc*)
}
Sigma rule
title: MeshCentral Agent Dropper with Anti-Debug Hardening
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection:
- Image|endswith: '\\MeshAgent.exe'
- CommandLine|contains:
- 'Mesh Agent'
- 'azurenetfiles'
anti_debug:
- CommandLine|contains:
- 'x64dbg'
- 'idaq'
- 'dnspy'
- 'procmon'
- 'procexp'
- ParentImage|endswith:
- '\\MeshAgent.exe'
network:
Initiated: 'true'
DestinationHostname|contains: 'azurenetfiles.net'
condition: selection or anti_debug or network
falsepositives:
- Legitimate MeshCentral agent installation by authorized IT staff
level: high
IOC list
| Indicator | Type | Context |
|---|---|---|
d65f14e5652a4330354826925dc56937334163656f24dd10f112c15bc7559de1 |
SHA-256 | This sample (hardened sibling) |
9098906159e0e4c845eb918886fadc2723f2a321281b8003e471f09140321f91 |
SHA-256 | Bare installer sibling |
azurenetfiles.net |
Domain | C2 / payload hosting |
https://azurenetfiles.net/meshagents?id=4&meshid=... |
URL | Hardcoded download URL |
C:\Program Files\Mesh Agent\MeshAgent.exe |
File path | Install target |
Mesh Agent |
Service name | Windows service (inferred) |
restart/60000 |
String | Watchdog respawn interval |
Behavioral fingerprint statement
This binary is a Go 1.26.2 PE64+ with a minimal IAT (kernel32 only) and no .rsrc section. On launch, it performs composite anti-debug checks (IsDebuggerPresent, CheckRemoteDebuggerPresent, PEB.BeingDebugged, debug-port enumeration, and parent-process name blacklist against 13 RE tools). If checks pass, it performs an HTTPS GET to azurenetfiles.net, downloads a PE payload, validates DOS/NT headers, stages to a temp path, and installs it as a Windows service named "Mesh Agent" under C:\Program Files\Mesh Agent\. Post-install hardening and a 60-second watchdog respawn follow. The process tree will show the parent Go binary spawning MeshAgent.exe or service execution via svchost.
Detection Signatures
| Capability | ATT&CK | Source |
|---|---|---|
| Ingress Tool Transfer | T1105 | Hardcoded HTTPS download URL ^[strings.txt:6398] |
| Create or Modify System Process: Windows Service | T1543.003 | SCM API strings + main.*Service* functions ^[strings.txt:6136] |
| Masquerading | T1036.005 | Installs to Program Files\Mesh Agent\ ^[strings.txt:6186] |
| Debugger Evasion | T1622 | main.detectDebugger, IsDebuggerPresent, PEB.BeingDebugged ^[strings.txt:14272] |
| Virtualization/Sandbox Evasion: System Checks | T1497.001 | Parent process name check against RE tools ^[strings.txt:14280] |
| Abuse Legitimate Remote Access Software | T1219 | MeshCentral agent abuse ^[strings.txt:6401] |
References
- Sample:
d65f14e5652a4330354826925dc56937334163656f24dd10f112c15bc7559de1 - Sibling:
9098906159e0e4c845eb918886fadc2723f2a321281b8003e471f09140321f91 - OpenCTI labels:
uniq.file,dropped-by-gcleaner,bb5.file - MeshCentral project: https://github.com/Ylianst/MeshCentral (legitimate open-source tool)
- Related wiki pages: meshcentral-agent-dropper, gcleaner, legitimate-remote-access-tool-abuse
Provenance
Analysis derived from static artefacts in raw/analyses/d65f14e5652a4330354826925dc56937334163656f24dd10f112c15bc7559de1/:
file.txt— file type identificationpefile.txt— PE header and import table inspectionstrings.txt— string extraction (Go symbols, URLs, API names, anti-debug functions)rabin2-info.txt— radare2 binary summarytriage.json— OpenCTI labels and family classificationbinwalk.txt— embedded artefact scanmetadata.json— artifact metadata Tools: strings, pefile, rabin2 (radare2 5.9.8). No Ghidra decompilation required — Go symbol table was intact.