// CyberDefenders  ·  writeup

MarkShell - TA577

CyberDefenders CyberChefDetect It EasySplunkIDAPEStudioscdbgCobaltStrikeParser

Scenario

A regional healthcare provider escalated an urgent security incident after an employee reported unexpected background activity during routine external communications. Triage uncovered evidence of credential harvesting and unauthorised lateral movement toward critical internal infrastructure. KAPE triage images and SIEM logs from four hosts — IT-WS-7, DC01, FILE-SERVER-01, and HR-WS-29 — were provided for investigation.


Methodology

Initial Triage — Archive Download and Delivery (Q1)

The first pivot was Sysmon EventCode=15 (Zone.Identifier) on IT-WS-7. Zone.Identifier events are written whenever a file is marked as downloaded from the internet, and their Contents field encodes the source URL. Filtering for .7z files immediately surfaced the malicious archive.

index=main host=IT-WS-7 EventCode=15 "7z"
| rex field=_raw "TargetFilename\">(?P<fullpath>[^<]+\.7z)"
| table _time, fullpath
| dedup fullpath

Zone.Identifier event showing archive download from phishing infrastructure

The archive downloaded to C:\Users\manalalberta\Downloads\40811eyack.com.MAIL_xsbsxxypt8dh6!App\ was named google.com!organcorp.com!1690000000!1690086400.7z. The !-separated naming convention is not arbitrary — it exactly mirrors the DMARC aggregate report filename specification (RFC 7489), where filenames take the form submitter!policy-domain!begin!end.zip. An organcorp.com sysadmin receiving what appears to be a legitimate DMARC report from Google would have little reason to be suspicious. The delivery server was hxxp[://]3[.]74[.]149[.]241:8888.


Phishing Email Origin — The Q2 Hunt

This question took longer than the rest of the lab combined and produced the most interesting forensic path of the entire investigation. The question asks for the unique message ID from the mail history. Mail data was not present as a Splunk sourcetype — the index contained only Windows Event Log data. The investigation shifted entirely to the KAPE artifacts.

The first stop was the Windows Mail UWP app store at AppData\Local\Packages\microsoft.windowscommunicationsapps_8wekyb3d8bbwe\LocalState\. The HxStore.hxd database is the Mail ESE store, but bstrings returned zero hits on Message-ID or the phishing domain. esentutl /mh confirmed the database header was corrupted (JET_errDatabaseCorrupted). The Exported folder was empty. The Comms\UnistoreDB\store.vol database (the actual Unistore message store) also returned nothing. The WebCacheV01.dat (MSHTML/WebView cache) showed fragments of googleusercontent.com mail domains — indicating Gmail was rendered somewhere — but no message URLs.

The breakthrough came from ActivitiesCache.db. Windows Timeline logs app activity for every UWP application separately, keyed by package identity. Querying the Activity table in DB Browser revealed rows for 40811eyack.com.MAIL_xsbsxxypt8dh6!App — a separate third-party mail client UWP package, distinct from the built-in Windows Mail app.

ActivitiesCache.db showing 40811eyack mail client UWP app activity rows

Navigating to that package’s local storage at AppData\Local\Packages\40811eyack.com.MAIL_xsbsxxypt8dh6\LocalState\EBWebView\Default\ revealed a History SQLite database — the embedded Chromium WebView2 engine used by the mail client to render email bodies stores its own browsing history exactly like a standalone Chrome profile. Opening it in DB Browser and browsing the urls table exposed the victim’s Gmail session.

EBWebView History database showing Gmail URLs

Row 23 contained https://mail.google.com/mail/u/0/#inbox/KtbxLvhRWjDKFCvLNwcrhFlvzXJLkPNWqq with the title “Report Domain: organcorp.com” — the phishing email subject reinforcing the DMARC lure. The hex string after #inbox/ is Gmail’s internal message thread identifier, which is what the lab treats as the unique message ID.

Gmail message URL confirming phishing email thread ID

The technique worth internalising here: modern mail clients that render HTML email via an embedded Chromium/WebView2 engine leave behind a full browser history database in their UWP package folder. That history logs every URL the rendering engine visited — including the webmail session URLs the user navigated during the email open. Standard browser history collection tooling misses this entirely because it only targets the canonical Chrome/Edge profile paths.


Execution Chain — HTA to PowerShell Stager (Q3, Q4)

With the archive name confirmed, the next pivot was process creation events on IT-WS-7 around the download timestamp.

index=main host=IT-WS-7 EventCode=1 "mshta"
| rex field=_raw "CommandLine\">(?P<cmdline>[^<]+)"
| table _time, cmdline
| sort _time

Sysmon EventCode=1 showing mshta.exe executing deploy.hta

Two events returned. At 22:07:52, mshta.exe executed deploy.hta from the extracted archive path at C:\Users\manalalberta\Desktop\dmarc\google.com!organcorp.com!1690000000!1690086400\. At 22:07:56, a heavily base64-encoded PowerShell command fired as a child process — the stager. mshta.exe is a Living Off the Land Binary that executes HTML Application files, making it a common TA577 initial execution vehicle. The deploy.hta filename was deliberately chosen to look like a configuration deployment tool, consistent with the fake project onboarding lure documented in the archive’s README.md.

The archive also contained config.xml — an MSBuild inline task loader. Its <UsingTask> element instructs msbuild.exe to compile and execute a C# DeflateStream payload entirely in memory, loading the decompressed .NET assembly via Assembly.Load() with no file written to disk. The README.md lure surfaced this directly, embedding mshta.exe config.xml as a “troubleshooting” step and deploy.hta as a fake config viewer link.

README.md lure content

config.xml MSBuild inline task loader in browser history


Stager Analysis — Multi-Stage Deobfuscation (Q7, Q8, Q9, Q10, Q11)

The base64-encoded PowerShell command from the EventCode=1 log was decoded in CyberChef using From Base64 → Decode Text (UTF-16LE), which is the standard powershell -EncodedCommand encoding. The decoded script opened a GzipStream decompressor over a base64-encoded blob and immediately piped the output to IEX, confirming GZIP as the compression algorithm. The H4sI magic bytes visible at the start of the base64 string are the base64 encoding of the GZIP magic bytes \x1f\x8b, which is a reliable detection shortcut.

CyberChef stage 1 decode — base64 to UTF-16LE revealing GzipStream

The GZIP-decompressed output was a second PowerShell script containing a byte array and an XOR loop:

for ($x = 0; $x -lt $var_code.Count; $x++) {
    $var_code[$x] = $var_code[$x] -bxor 35
}

The XOR key is 35 decimal, which is 0x23 in hex. The script then calls VirtualAlloc, copies the XOR-decrypted bytes into the allocated buffer, and executes them as shellcode via a delegate — a standard reflective shellcode injection pattern.

CyberChef stage 2 — XOR key 0x23 visible in decoded stager

The XOR decryption was applied in CyberChef (From Base64 → XOR, key: 35, decimal) to produce the raw shellcode bytes. The output, while not human-readable, contained recoverable string fragments. hwini and hnet are visible in the decoded bytes — the shellcode building wininet.dll on the stack as a null-free string, which is a hallmark of PEB-walking shellcode that needs to resolve wininet functions without triggering static string detection.

CyberChef XOR decode output showing wininet string fragments and C2 IP

At the bottom of the decoded output, the C2 IP address 3.72.9.217 appears in plaintext — the shellcode’s hardcoded download server. The ror13 API hashing algorithm identification (rotating right 13 bits before comparing against a precomputed hash table) was confirmed via static analysis; it is the most common API hashing scheme in public shellcode loaders and Cobalt Strike stagers. The first library the shellcode resolves after PEB-walking kernel32 is wininet.dll, which provides the InternetOpenUrl and related functions needed to download the second-stage loader.


Second-Stage Loader — Covenant Grunt (Q5, Q6, Q12, Q13)

Network connection events in Splunk confirmed andy.exe dropping to C:\Users\manalalberta\AppData\Local\ and beaconing outbound.

index=main host=IT-WS-7 EventCode=3
| rex field=_raw "Name='DestinationIp'>(?P<dst>[^<]+)"
| rex field=_raw "Name='DestinationPort'>(?P<dport>[^<]+)"
| rex field=_raw "Name='Image'>(?P<proc>[^<]+)"
| rex field=_raw "Name='UtcTime'>(?P<utc>[^<]+)"
| where utc > "2026-03-24 22:07"
| where NOT dst LIKE "10.%"
| where NOT dst LIKE "52.%"
| table utc, proc, dst, dport
| sort utc

Splunk EventCode=3 showing andy.exe beaconing to external IP

Sysmon EventCode=1 for andy.exe provided the SHA256 hash from the Hashes field.

andy.exe SHA256 from Sysmon process creation

The Splunk-observed beacon destination was 18.151.105.76:80. However, this turned out to be a redirector. CobaltStrikeParser against andy.exe failed with Failed to find .data section. Detect It Easy identified the binary as .NET MSIL (CLR v4.0.30319), explaining why a native PE parser couldn’t find the beacon config.

DIE showing andy.exe as .NET MSIL assembly

dnSpy decompilation of andy.exe immediately revealed the GruntStager namespace — the class name of the Covenant C2 framework’s agent. The hardcoded C2 address was http://18.153.105.76:80 (note 153, not 151 as Splunk logged — 18.151.105.76 was the redirector). The Covenant fingerprints throughout the decompiled code are distinctive: the Grunt session ID prefix (cccce89e29), the URL patterns (/en-us/index.html?page={GUID}&v=1), the cookie-based data transport format, and the terminal Assembly.Load() call that reflectively loads the in-memory stage 3 Grunt agent.

dnSpy decompilation showing GruntStager class and hardcoded C2 IP


Privilege Escalation — AlwaysInstallElevated (Q14, Q15, Q16)

PowerUp was loaded in-memory via Covenant’s PowerShellImport task — no file was written to disk, which is why Sysmon EventCode=1 and EventCode=11 returned no hits for any privesc tooling. PowerUp checks both HKCU and HKLM registry keys for AlwaysInstallElevated=1. When both are set, any user can install MSI packages with SYSTEM privileges, making it trivial to drop a malicious installer and obtain full privilege escalation with no UAC prompt. PowerUp also enumerates HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon for AutoAdminLogon entries, which surfaced the plaintext credential stored in that same registry path.

index=main host=IT-WS-7 EventCode=1 "msiexec"
| rex field=_raw "Name='CommandLine'>(?P<cmdline>[^<]+)"
| table _time, cmdline
| sort _time

Splunk showing organInstaller.msi executed silently via msiexec

At 22:51:19, msiexec /quiet /qn /i C:\Users\Public\organInstaller.msi ran and spawned MsiExec.exe -Embedding child processes immediately after — the silent elevated installation completing. The /quiet /qn flags suppress all UI and confirmation dialogs, producing zero user-visible indicators.


Credential Harvesting — Registry AutoAdminLogon (Q17, Q18)

AutoAdminLogon is a Windows feature that stores plaintext credentials in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon to enable automatic login. Administrators sometimes enable it for kiosk machines or shared workstations without realising the credentials are readable by any process with HKLM read access. PowerUp’s Get-RegistryAutoLogon check exposed domain.admin:aduserad@26 directly.

index=main host=IT-WS-7 EventCode=1
| rex field=_raw "Name='CommandLine'>(?P<cmdline>[^<]+)"
| where match(cmdline, "(?i)file-server-01")
| table _time, cmdline
| sort _time

Splunk showing net.exe mounting \FILE-SERVER-01\shares$ with harvested credentials

The harvested credentials were immediately used to authenticate to FILE-SERVER-01. The net use \\FILE-SERVER-01\shares$ /fo domain.admin:organcorp.local\domain.admin aduserad@26 command at 23:21:15 confirms the credential reuse.


Lateral Movement — Cobalt Strike on FILE-SERVER-01 (Q19, Q20, Q21)

fsrv.exe was found in the KAPE artifact for FILE-SERVER-01 at C:\shares$\fsrv.exe, timestamped 3/24/2026 11:16 PM. Unlike andy.exe, fsrv.exe is a native PE and CobaltStrikeParser parsed it cleanly.

CobaltStrikeParser output for fsrv.exe showing full beacon configuration

The beacon configuration confirmed Cobalt Strike HTTP beacon, with the C2 server as 3.72.9.217,/ga.js — the same IP as the shellcode C2, indicating infrastructure reuse between the initial stager and the lateral movement beacon. The PublicKey_MD5 was extracted directly from the parser output: 07e8d31ff072cabf51c1aa50141d3f61. The Watermark value 100000 is a licensed Cobalt Strike instance identifier rather than a cracked copy. The spawn-to processes (syswow64\rundll32.exe and sysnative\rundll32.exe) are the default CS injection targets.

Before pivoting to FILE-SERVER-01, the attacker used esentutl.exe to copy a locked browser database on the beachhead. esentutl.exe is a native Windows ESE database utility that can copy files with open handles, commonly abused to extract Chrome’s Login Data or Cookies SQLite databases while the browser is running and has them locked.


Domain Controller Compromise (Q23-Q26)

RDP access to DC01 using the domain.admin credentials was followed immediately by network reconnaissance. SoftPerfect Network Scanner (netscan.exe) was extracted via 7-Zip and executed to map the internal network.

Splunk showing 7-Zip extracting netscan and netscan.exe execution on DC01

Enter-PSSession established an interactive PowerShell remoting session to a downstream server. Within that session, Invoke-ShareFinder from PowerView enumerated accessible network shares across the domain — a standard pre-ransomware network share discovery pattern to identify file storage targets. Atera RMM was then deployed on DC01 as a persistence mechanism, providing the attacker with a legitimate-looking remote management channel that would survive a reboot and blend into normal IT tooling traffic.


Attack Summary

PhaseAction
Initial AccessDMARC-lure archive google.com!organcorp.com!1690000000!1690086400.7z delivered via phishing email (Gmail thread KtbxLvhRWjDKFCvLNwcrhFlvzXJLkPNWqq)
Executiondeploy.hta executed via mshta.exe; MSBuild config.xml loads .NET assembly in-memory
StagerMulti-stage PS stager: GZIP → base64 → XOR 0x23 → shellcode injected via VirtualAlloc
C2 Stage 1Shellcode downloads andy.exe from hxxp[://]3[.]72[.]9[.]217; Covenant Grunt beacons to hxxp[://]18[.]153[.]105[.]76:80
Privilege EscalationPowerUp loaded in-memory identifies AlwaysInstallElevated; organInstaller.msi executed SYSTEM
Credential AccessAutoAdminLogon registry exposes domain.admin:aduserad@26 in plaintext
Collectionesentutl.exe copies locked browser credential database
Lateral Movementnet use \\FILE-SERVER-01\shares$ with harvested creds; fsrv.exe Cobalt Strike beacon deployed
DC CompromiseRDP to DC01; netscan.exe network recon; Enter-PSSession to downstream server; Invoke-ShareFinder share enumeration
PersistenceAtera RMM installed on DC01

IOCs

TypeValue
IP (Phishing Delivery)hxxp[://]3[.]74[.]149[.]241:8888
IP (Shellcode C2 / CS Beacon)3[.]72[.]9[.]217
IP (Covenant C2)hxxp[://]18[.]153[.]105[.]76:80
Filegoogle.com!organcorp.com!1690000000!1690086400.7z
Filedeploy.hta
Fileconfig.xml (MSBuild inline task loader)
Fileandy.exe (Covenant Grunt)
FileorganInstaller.msi
Filefsrv.exe (Cobalt Strike beacon)
Hash (andy.exe SHA256)0F6600C312D880D8A6271009CEEEF5C19647ABE3B452BCFAA206130D9A76F33E
Hash (fsrv.exe PublicKey MD5)07e8d31ff072cabf51c1aa50141d3f61
Credentialdomain.admin:aduserad@26 (ORGCORP\domain.admin)
Gmail Thread IDKtbxLvhRWjDKFCvLNwcrhFlvzXJLkPNWqq
CS Watermark100000

MITRE ATT&CK

TechniqueIDDescription
Phishing: Spearphishing LinkT1566.002DMARC-lure archive delivered via Gmail phishing email
System Binary Proxy Execution: MshtaT1218.005deploy.hta executed via mshta.exe
PowerShellT1059.001Multi-stage PS stager; PowerUp loaded via Covenant PowerShellImport
Obfuscated Files or Information: Command ObfuscationT1027.010GZIP + base64 + XOR 0x23 layered encoding of shellcode payload
Process InjectionT1055Shellcode injected into allocated memory via VirtualAlloc delegate
Application Layer Protocol: Web ProtocolsT1071.001Covenant and Cobalt Strike C2 over HTTP
Abuse Elevation Control Mechanism: Bypass UACT1548.002AlwaysInstallElevated registry keys enable SYSTEM MSI installation
Unsecured Credentials: Credentials in RegistryT1552.002AutoAdminLogon stores domain.admin plaintext in Winlogon registry key
Valid AccountsT1078domain.admin credentials used for lateral movement to FILE-SERVER-01 and DC01
Remote Services: Remote Desktop ProtocolT1021.001RDP used to access DC01 with harvested domain admin credentials
Remote Services: Windows Remote ManagementT1021.006Enter-PSSession for interactive PS remoting to downstream server
Network Service DiscoveryT1046SoftPerfect Network Scanner (netscan.exe) deployed on DC01
Network Share DiscoveryT1135Invoke-ShareFinder enumerates accessible shares across the domain
Credentials from Web BrowsersT1555.003esentutl.exe copies locked browser credential database
Remote Access SoftwareT1219Atera RMM deployed on DC01 for persistent remote access
MasqueradingT1036.005fsrv.exe and andy.exe named to blend with legitimate service binaries

Defender Takeaways

UWP mail client browser history is a blind spot in standard collection. Mail clients that render email via an embedded Chromium/WebView2 engine store browsing history in AppData\Local\Packages\<package-id>\LocalState\EBWebView\Default\History — a separate SQLite database invisible to tools that only target canonical Chrome/Edge profile paths. KAPE targets and forensic collection workflows should explicitly include UWP package LocalState directories to capture this data. The Gmail thread ID that anchored the phishing email origin would have been unrecoverable without it.

AlwaysInstallElevated is a trivially exploitable misconfiguration. Both HKCU\Software\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated and HKLM\... must be set to 1 for exploitation. Group Policy should enforce these keys to 0 across the domain, and a Purple Team or Vulnerability Management scan should flag any deviations. PowerUp’s Get-RegistryAlwaysInstallElevated check takes seconds and should be a standard item in any internal penetration test.

AutoAdminLogon credentials are plaintext and readable by any process. The DefaultPassword value under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon is not encrypted or protected in any way. Any workstation or server configured for automatic login is storing domain credentials in a location accessible to any malware running in user context. Disable AutoAdminLogon on all machines that do not have a documented operational requirement, and rotate any credentials that were ever stored there.

Covenant and Cobalt Strike beacons reused the same infrastructure. The shellcode C2 IP 3.72.9.217 appeared in both the initial download stage and the Cobalt Strike beacon configuration for fsrv.exe. IP-based network detections pivoting from the first observed IOC would have flagged the lateral movement beacon automatically. Threat hunting queries on outbound connections to known C2 IPs should extend across all hosts, not just the initial beachhead.

DMARC report naming conventions make highly convincing lures for mail administrators. The domain!domain!timestamp!timestamp.zip filename format is specified in RFC 7489 and is what legitimate DMARC aggregate report senders produce. Security awareness training for mail administrators should specifically cover the risk of unsolicited DMARC reports from external senders, and mail flow rules should flag or quarantine archives originating from infrastructure with no prior correspondence history.


The user downloaded a malicious archive file that initiated the infection. What is the full name of this archive file?
Click flag to reveal google.com!organcorp.com!1690000000!1690086400.7z
The malicious archive link was delivered via a phishing email. What is the unique message ID of this email, as captured from the mail history?
Click to reveal answer KtbxLvhRWjDKFCvLNwcrhFlvzXJLkPNWqq
After the user extracted the archive, a malicious file was executed. What is the name of the first malicious file the user ran?
Click flag to reveal deploy.hta
What legitimate Windows process was used to run the initial malicious payload?
Click to reveal answer mshta.exe
The first malicious file launched a multi-stage obfuscated PowerShell script that decoded and dropped a shellcode payload into memory. This initial shellcode downloaded a second-stage loader. What is the filename of this loader?
Click flag to reveal andy.exe
What is the SHA256 hash of the second-stage loader?
Click to reveal answer 0F6600C312D880D8A6271009CEEEF5C19647ABE3B452BCFAA206130D9A76F33E
The initial PowerShell stager contained a compressed payload. Based on the magic bytes of the encoded string, what compression algorithm was used?
Click flag to reveal GZIP
After decompressing and decoding the PowerShell stager, an additional layer of XOR encryption is still protecting the final payload. What is the XOR key used to decrypt it?
Click to reveal answer 0x23
During analysis of the shellcode, you noticed it implements API Hashing to obfuscate its Windows API calls at runtime. What is the hashing algorithm used?
Click flag to reveal ror13
In order to resolve APIs, this shellcode implements two techniques — PEB Walking and PE Parsing. What is the first library it resolves and loads?
Click to reveal answer wininet.dll
After the shellcode was executed previously, it initiated a network connection to download the second-stage loader. What is the C2 server IP address the shellcode connected to?
Click flag to reveal 3.72.9.217
After the second-stage loader was executed, it established its own C2 communication channel. What is the C2 server IP address it connected to?
Click to reveal answer 18.153.105.76
Analyzing the second-stage loader, network indicators, and communication patterns, what C2 framework is it associated with?
Click flag to reveal Covenant
The attacker ran a comprehensive host enumeration tool in memory before Privilege Escalation to gather information about the compromised system. What is the name of this tool?
Click to reveal answer PowerUp
The enumeration tool revealed a Windows policy misconfiguration that allows MSI packages to be installed with elevated privileges. What is the name of this setting?
Click flag to reveal AlwaysInstallElevated
What is the name of the MSI package the attacker executed to exploit the misconfiguration and escalate privileges?
Click to reveal answer organInstaller.msi
The discovery script also found plaintext credentials stored in the registry. What is the username and password of the compromised account?
Click flag to reveal domain.admin:aduserad@26
What is the Windows policy misconfiguration that revealed the account credentials in the registry?
Click to reveal answer AutoAdminLogon
Using the compromised credentials, the attacker executed a payload from a remote share. What is the full UNC path of this payload?
Click flag to reveal \\FILE-SERVER-01\shares$\fsrv.exe
The payload executed during lateral movement was a beacon from what well-known C2 framework?
Click to reveal answer Cobalt Strike
What is the MD5 hash of the public key found in the C2 beacon's configuration?
Click flag to reveal 07e8d31ff072cabf51c1aa50141d3f61
Before leaving beachhead host, The attacker used a native Windows utility to copy a locked browser database file. What is the name of this utility?
Click to reveal answer esentutl.exe
Using the compromised credentials, Attacker moved laterally to the domain controller via RDP, the attacker installed a tool to scan the network. What is the name of this network scanning tool?
Click flag to reveal netscan.exe
From the domain controller, the attacker used a PowerShell cmdlet to establish a remote session with another server. What is the name of this cmdlet?
Click to reveal answer Enter-PSSession
While in the remote session, the attacker executed a command to find network shares. What is the name of this command?
Click flag to reveal Invoke-ShareFinder
The attacker deployed a legitimate Remote Management and Monitoring (RMM) tool on the domain controller to maintain access. What is the name of this tool?
Click to reveal answer Atera