


Executive Summary
In August 2026 Check Point Research published the latest wave of Operation Dream Job: North Korea’s Lazarus cluster spent a Windows kernel zero-day on a fake recruiter email. The bug is CVE-2026-68820, a use-after-free in afd.sys (CWE-416), the Ancillary Function Driver under WinSock. Microsoft scored it Important, CVSS 7.0: local, needs code execution first, no remote reach. That number is a lie of omission. The exploit is a driver-free path from a low-privilege PDF reader to SYSTEM and a kernel read/write primitive. From there FudModule 3.1 tears down the callbacks, minifilters and ETW providers your EDR uses to see anything.
Cyllex’s 3 September 2026 post is the defender’s walkthrough of that chain: two delivery variants, an in-memory Graph-API downloader, the race, the rootkit, the Troy backdoor, and compromised Roundcube/WordPress/PrestaShop relays. This draft keeps every table, listing and diagram from that post, then adds the kitchen-table picture (the signed viewer that loads a stranger’s DLL from its own folder), the BYOVD-without-the-D contrast, Check Point’s extra hashes and RelayShell YARA, and a purple-team order of operations that stops at the red line: do not weaponise the race. Detect the DLL load. Confirm the reboot after KB5121003.
A zero-day in the Windows kernel is worth six figures on the open market. Lazarus spent one on a PDF sent to an aerospace engineer who thought he was applying for a job.
Cyllex, 3 September 2026
The Cookie Jar Is the Kernel, the Letter Is the Job Offer

Check Point tracked the wave from early 2026 against defence, aerospace and aviation, with a preference for shops that build sensors, drones and robotics. Confirmed geography: France, Germany, India, Brazil. At least one compromised French organisation was then used as the sending mailbox for the next wave, so the second round arrived from a real industry-peer address. That defeats SPF/DKIM theatre if you only trust known partners.
A Note on Names: Google’s Cryptonyms
On 24 July 2026 Google Threat Intelligence Group retired Mandiant APTnn / FINnn numbering for a two-word scheme: a memorable first word plus a category word for origin. MITRE still uses APTnn. Google keeps old names searchable. UNC numbers remain for unattributed clusters. Lazarus was not in the first published batch, so Cyllex (and this draft) keep the community name. Practical rule: actor names are aliases. Technique IDs are primary keys.
| Category word | Meaning | Published examples |
|---|---|---|
| CASTLE | People’s Republic of China | APT40 → ISLAND CASTLE, APT41 → SPIRE CASTLE |
| RELIC | Russia | APT44 → SANDWORM RELIC, APT29 → ICE RELIC, APT28 → LAKE RELIC |
| NEPTUNE | North Korea | APT37 → PLAIN NEPTUNE |
| ION | Iran | APT33 → BLEAK ION |
| COMET | Financially motivated cybercrime | FIN7 → WILD COMET, FIN6 → SQUID COMET |
Two Ways Into the Same Kind of Trouble

Chain 1 — encrypted archive and a side-loaded DLL
- The archive. Password-protected ZIP: a legitimately signed MuPDF-based viewer, an encrypted PDF, and a malicious
libmupdf.dllwhere the viewer expects its real dependency. - The side-load. The user runs the viewer. Windows searches the application directory first. The signed parent loads the attacker’s library. Authenticode on the EXE is genuine because the EXE is genuine. ATT&CK: T1574.001 (Hijack Execution Flow: DLL). The old T1574.002 DLL Side-Loading ID is gone; do not import it.
- The decoy. A Lockheed Martin job description renders. Meanwhile the DLL stages MISTPEN in memory. Check Point’s later stages on this chain: recon plugins, a persistence module, the LPE loader, then ForestTiger as the long-term backdoor.
Chain 2 — SecurityPDF and the SEO-poisoned vendor
From July 2026 a second route dropped the suspicious archive. Mail impersonated Enveil, a real privacy-enhancing-technology firm founded by US IC alumni. Lookalike sites envell[.]xyz, enveil[.]online, uxtramine[.]org were ranked so that a victim who searched instead of clicking still landed on attacker infrastructure (T1608.006). Enveil itself was not compromised; only impersonated.
Those sites served SecurityPDF, a MuPDF fork. Check Point: the actor patched File → Open and drag-and-drop. Any PDF is parsed for this marker:
This document is encrypted with sumatrapdf reader!!!!!!!!!!!!
If present, the viewer extracts the appended blob, XOR-decrypts with key 0x39, writes %TEMP%\new.exe, and runs it. That binary reflectively loads Troy. Any other PDF opens normally. Submit the viewer alone to a sandbox and you have a PDF reader. Split the tool and the trigger across hosts so neither half convicts.
743172aa…8d45d1, db3d69b7…0376d (full values in the IOC table below).MISTPEN: A Downloader That Lives in Your Tenant

MISTPEN (Mandiant 2024, catalogued under UNC2970) is an in-memory modular downloader. C2 is Microsoft Graph API: AES-encrypted files in OneDrive, separate keys for up and down. No attacker domain, no unusual TLS peer, no newly registered infrastructure. Traffic is to Microsoft, 443, from a Windows host in a Microsoft shop. Blocklists and newly-observed-domain rules are structurally blind.
| Module | File | Function |
|---|---|---|
| GetInfoPlugin | Release_GetInfoPlugin_x64.dll | Host profile: domain or workgroup, hostname, username, OS version and build |
| PvPlugin | Release_PvPlugin_x64.dll | Process enumeration: PID, PPID, creation timestamp, owning user and domain |
| OneScreenCapture | OneScreenCapture64.dll | Multi-monitor desktop capture, JPEG then Base64 |
| LPE loader | staged in memory | Fingerprint, session key, retrieve and detonate FudModule |
GetInfoPlugin formats a single wide string Check Point recovered as:
Domain: <domain_or_workgroup>
ComputerName: <hostname>
UserName: <username>
OsInfo: <Windows product name> <build_number>.<UBR>
The LPE loader is selective. Check Point documents a four-stage handshake before the exploit is delivered:
- Fingerprint: exact OS build and installed security products.
- Request a public key from C2, keyed to that fingerprint (Check Point: a set of four public keys).
- Derive a session key with Kyber / ML-KEM; transport under GOST-CBC with a random 16-byte session key prepended, then Base64.
- Deploy FudModule via export
DestroyEnv. Status messages go back through MISTPEN’s Graph channel via a shared RPC buffer.
Compiler timestamp on the investigated LPE DLL Afd4Eop12_x64.dll: 7 July 2026, 22:07:44 UTC. Strings include enable_god_mode passed. Minimum-version check: Windows 11 26100 (24H2) and 26200 (25H2). The vulnerability itself reaches back through Windows 10 ESU; the observed exploit does not. A sandbox on the wrong build never sees the payload. That discipline is why five weeks of live use stayed quiet.
CVE-2026-68820: A Race Inside afd.sys


afd.sys services every user-mode socket. Any process that can open a socket can talk to it, including sandboxed ones. Lazarus already burned CVE-2024-38193 in the same driver (FudModule 2024). CVE-2025-60719 was another AFD UAF, patched November 2025, not attributed here. Check Point tested a fully patched Windows 11 box and confirmed this sample hits a distinct bug.
High level only — neither Cyllex nor Check Point published a PoC, and this draft will not invent one. Two of the driver’s own paths can operate on the same socket state without synchronisation. Win the race, reclaim the freed allocation with attacker data, dereference at t4, and you have arbitrary kernel read/write. That converts to SYSTEM by rewriting the process token. CWE-416. ATT&CK T1068, not a T1548 sub-technique (those are UAC/sudo/macOS).
BYOVD without the D
The last decade of kernel defence assumed a third-party .sys would arrive: Microsoft’s vulnerable-driver blocklist, HVCI, driver-load telemetry, hunts for unexpected files in C:\Windows\Temp. Exploiting afd.sys skips the arrival. The driver is already resident, already Microsoft-signed, already required for TCP/IP. Every control that watches for a bad driver observes nothing.
CVSS 7.0 undersells the campaign value: it is local and needs prior code exec, yes. In this operation the prior code exec is a recruiter PDF. The LPE is the last honest step before FudModule unplugs the cameras.
| Date | Event |
|---|---|
| Early July 2026 | In-the-wild exploitation begins as a zero-day |
| 28 July 2026 | Reported to MSRC by Check Point Research |
| 31 July 2026 | Microsoft confirms the vulnerability |
| 5 August 2026 | CVE-2026-68820 assigned |
| 11 August 2026 | Patched on Patch Tuesday; added to CISA KEV the same day |
Fixes: KB5121003 (Windows 11 → builds 26100.9168 and 26200.9168), KB5120249 (Windows 10 ESU). Because the fix replaces a kernel driver, install is not remediated until reboot. Dashboards that count “patched” on MSI install will lie.
FudModule 3.1: Unplugging the Cameras

FudModule is not persistence and not a backdoor. It is a data-only kernel rootkit whose job is unobservability. v3.1 is injected into SYSTEM msiexec.exe (two-hop: services.exe → msiexec). Gen Digital documented v3 in 2024; 3.1 keeps most of that teardown and adds Smart App Control tampering.
- Callback teardown. Process, thread, image-load notify callbacks; object and registry callbacks. EDR still runs. It is not told.
- Minifilter removal by altitude band. File-activity visibility for whole product classes, gone.
- ETW blinding. Check Point: 94 provider GUIDs, matching the first 94 of Gen’s published 95, same order. NT Kernel Logger session killed.
- Crash-dump suppression first. No dump, no bugcheck announcement.
- Driver selection engine with preserve/kill rules so the host stays up.
- WFP stage when Kaspersky is present and Symantec is absent — per-vendor branching.
- Privileged handle forgery rather than requesting handles.
Shared log strings with v3, almost word-for-word: GetGodMode failed, GetSystemHandle passed., CreateRemoteProcess passed., RemoteDllExecute passed., the ClearVaccine* family. Removed: dedicated Defender stage against MsMpEng.exe (orphaned string SuspendDefender passed.; Gen’s YARA still has SuspendDefender skipped.) and PPL stripping of AhnLab asdsvc.exe. Defender is still blinded, via the generic suppressor.
The version bump: Smart App Control
Inside the SYSTEM msiexec child, the remote stub sets VerifiedAndReputablePolicyState to zero, then NtSetSystemInformation with information class 0xA4 and option 0x10000000. Windows re-reads code-integrity policy in place. No reboot, no policy file change on disk, the machine stops enforcing a control it still believes is on. ATT&CK T1553. Do not treat SAC as a load-bearing control against a kernel primitive.
VerifiedAndReputablePolicyState = 0;
NtSetSystemInformation(/* class */ 0xA4, /* option */ 0x10000000, ...);
Troy: 17 Commands and a PDB Left On
Troy is a newly documented 64-bit DLL RAT. Name from an unstripped PDB, which is both a hunting artefact and a look at the build box. ESET previously saw E:\Work\Troy\... in another Lazarus UAV-sector sample; this one is more specific:
E:\HK\Tool_Module\Troy_Handle\1Troy_Create_Dll_Tool\x64\Release\Test_Dll.pdb
Startup: iterate three hardcoded C2 URL/port pairs until the response is CONNECTED, challenge-response auth, then register with client id plus profile (user directory, account, Windows version, IPv4, cwd). Tasks are Base64. Results go back as:
{"to":"<channel>","msg":"<base64>"}
Large results are chunked. Check Point notes SET_CONFIG writes eight fields but only the idle interval takes effect at runtime; stored servers are not re-read and the port stays hardcoded to 80.
| Command | Capability |
|---|---|
WAIT | Keepalive no-op |
DRIVES | Enumerate mounted volumes |
LIST|<path> | Directory listing with timestamps |
OPEN|<exe> [args] | Launch executable, hidden window |
DELETE|<path> | Recursive file or folder delete |
ZIPDOWNLOAD|<src>|<dst> | PowerShell Compress-Archive, then upload |
DOWNLOAD|<src>|<dst> | Chunked file exfil |
UPLOAD|<src>|<dst> | Write a file to disk |
CMD|<commandline> | Interactive shell, 10-second watchdog |
mem <dllpath> <pid> | Reflective DLL injection, arch-matched |
pk <pid> | Terminate process by PID |
sleep <N> | One-shot delay, N minutes |
DEFAULTSLEEP | Revert to configured beacon interval |
GET_CONFIG / SET_CONFIG | Read or update eight stored config fields |
pv / pvd | Process listing; pvd adds WMI command lines |
Injection is textbook: RWX in the remote process, write loader and payload, RtlCreateUserThread. Absent on purpose: no credential dump, no built-in lateral movement, no domain enum. Espionage against one engineer’s workstation, not ransomware prep. Check Point still saw ForestTiger as the long-term implant on the MISTPEN chain; Troy is the SecurityPDF chain’s hands-on tool.
RelayShell: Someone Else’s CMS Is the C2

No attacker-owned C2 in the classic sense. Relays are compromised Roundcube, WordPress and PrestaShop hosts running a PHP webshell Check Point named RelayShell. At least 17 distinct relay identifiers. Operators egress via commercial VPN (ExpressVPN observed). Roundcube path: dark-web credential leaks, then CVE-2025-49113 (CVSS 9.9 authenticated PHP object deserialisation RCE in upload.php, patched in 1.5.10 / 1.6.11, on CISA KEV since February 2026). The relay pool cost a dump and a public exploit.
Two passwords, two modes. Victim mode: new PHP session, decrypt hidden config with a custom substitution cipher (backbone URL + unique PID), POST to the backbone to announce the session. Operator mode: pick latest .ses, connectivity check, upload/delete with Base64 paths, pull logs. After both sides are up, send/receive is file-based: <session_id><object>.log with 1 = victim, 2 = operator. No long-lived socket. If you run internet-facing Roundcube/WordPress/PrestaShop, those files under the webroot are your hunt, not theirs.
ATT&CK Mapping (the IDs Other Write-ups Get Wrong)
Cyllex checked the live matrix. T1574.001 is now “Hijack Execution Flow: DLL”; T1574.002 is gone. Kernel LPE is T1068, not T1548.
| Stage | Technique | ATT&CK ID |
|---|---|---|
| Recruiter approach over LinkedIn or messaging | Phishing: Spearphishing via Service | T1566.003 |
| Mail with malicious attachment or link | Spearphishing Attachment, Link | T1566.001, T1566.002 |
| Fake Enveil sites ranked in search | Stage Capabilities: SEO Poisoning | T1608.006 |
| Lookalike vendor domains | Acquire Infrastructure: Domains | T1583.001 |
| Victim opens archive or installs SecurityPDF | User Execution: Malicious File | T1204.002 |
| SecurityPDF posing as a real viewer | Masquerading: Match Legitimate Name or Location | T1036.005 |
| libmupdf.dll beside a signed binary | Hijack Execution Flow: DLL | T1574.001 |
| XOR and AES payload unpacking | Deobfuscate/Decode Files or Information | T1140 |
| MISTPEN and Troy staged in memory | Reflective Code Loading | T1620 |
| Host, process and AV profiling | System Info, Process, Security Software Discovery | T1082, T1057, T1518.001 |
| Multi-monitor screenshots | Screen Capture | T1113 |
| AFD.sys zero-day to SYSTEM | Exploitation for Privilege Escalation | T1068 |
| FudModule into SYSTEM msiexec, Troy mem | Process Injection | T1055 |
| Callbacks, minifilters, ETW torn down | Impair Defenses: Disable/Modify Tools, Indicator Blocking | T1562.001, T1562.006 |
| Smart App Control policy state reset | Subvert Trust Controls | T1553 |
| Kernel-resident concealment | Rootkit | T1014 |
| Graph API and OneDrive command channel | Web Service: Bidirectional Communication | T1102.002 |
| RelayShell on hijacked CMS and webmail | Web Shell, Compromise Infrastructure | T1505.003, T1584 |
| Troy CMD and ZIPDOWNLOAD | Windows Command Shell, PowerShell | T1059.003, T1059.001 |
| Archive and exfil over C2 | Archive via Utility, Exfiltration Over C2 Channel | T1560.001, T1041 |
| On-disk persistence after reboot | Registry Run Keys, Scheduled Task | T1547.001, T1053.005 |
| Operator egress through commercial VPN | Proxy: Multi-hop Proxy | T1090.003 |
Where the Detection Window Actually Is

Once T1068 succeeds and FudModule is resident, endpoint telemetry stops being evidence. Hunts return clean because the data was never born. Any strategy that depends on catching the rootkit after landing has already lost. The question collapses to: can you see the chain before ring 0?
- Anomalous image loads. A MuPDF-family binary loading a DLL from its own directory whose signer does not match the vendor. Highest-value signal, fires first.
- Process lineage. A document viewer spawning
new.exeor any unsigned child. Legitimate readers do not create executables. - Graph API from the wrong process.
graph.microsoft.com/login.microsoftonline.comfrom something that is not Office, OneDrive, or a known LoB app. You cannot block the destination. Identify the caller. - SYSTEM msiexec.exe with no MSI. Implausible parent, no installer on the command line: FudModule’s injection target.
- Telemetry going quiet. Absence of expected ETW/EDR events on a host that used to emit them. The one signal that survives the rootkit. Almost nobody instruments it.
- Smart App Control state changes with no policy deployment.
- Server-side artefacts:
.sesand<id>1.log/<id>2.logunder Roundcube/WordPress/PrestaShop webroots; Roundcube auths from unexpected ASNs just before.
The best detection opportunity in this whole intrusion is a DLL load inside a PDF reader, about five minutes in, long before any of it looks like an attack.
Cyllex
How to Emulate This Kill Chain (Without the Zero-Day)
Reading an advisory is not a test of your environment. Run behaviours in order so you learn the first visible hop, not a flat checklist. Do not weaponise CVE-2026-68820. Be sceptical of any tool that offers to.
- Delivery and execution. Emulate T1574.001, T1204.002, T1036.005 with a benign side-loaded library next to a signed binary. If image-load does not fire here, later does not matter.
- Discovery and collection. T1082, T1057, T1518.001, T1113. Cheap, noisy, often unalerted. Many teams learn here that screen capture is silent.
- Cloud-service C2. T1102.002 against a legitimate cloud endpoint from an unusual process. Correlate in Sentinel/MDE and in whatever holds the web-server tail.
- Escalation and evasion, simulated only. Safe proxies for T1068, T1055, T1562.001, T1553: an unprivileged handle that should not open, a benign injection into a lab SYSTEM process, a reversible tamper with a test ETW provider, a SAC state read. Not the race.
- Score per technique, not per campaign. A pass/fail for “Lazarus” is useless. Verdicts per ID, with the events that prove them.
Emulation does not tell you whether hosts were vulnerable to the AFD race. That is inventory plus reboot after KB5121003. It does tell you whether the surrounding behaviours are visible. Most organisations were patched within days of 11 August. Far fewer can prove they would have seen an unsigned DLL load into a signed PDF viewer on 3 July.

Cyllex positions this post as the spec for a pre-release emulation profile. That is product context, not a finding. The detection argument stands without the product.
What Actually Reduces Exposure
- Patch, then confirm the reboot. KB5121003 / KB5120249. Report reboot compliance, not install compliance.
- Alert on missing telemetry. ETW providers and EDR agents that go silent on a previously chatty host. Against a suppression rootkit, absence is the signal.
- Do not rely on Smart App Control alone. Pair with WDAC and ASR rules that constrain what a document viewer may spawn.
- Attribute cloud egress to processes. Blocking graph.microsoft.com is not an option. Ask which binaries legitimately hold Graph tokens.
- Harden internet-facing CMS and webmail. Roundcube ≥ 1.5.10 or 1.6.11, MFA on webmail, hunt your own webroots for stray .ses/.log. Your marketing WordPress is somebody’s relay.
- Brief the people being targeted. Defence/aerospace/drone/robotics engineers, a recruiter conversation that runs two weeks, sometimes from a compromised peer mailbox. Generic phishing training does not cover that.
A five-week zero-day window means patching was never available as a control. What was available, the entire time, was noticing that a signed PDF reader had loaded a DLL nobody signed. Go and find out whether yours would have.
Cyllex
Indicators (Cyllex table, then Check Point’s fuller set)
| Type | Indicator |
|---|---|
| Domains | envell[.]xyz, enveil[.]online, uxtramine[.]org |
| IP addresses | 135.181.67[.]203, 135.181.185[.]158 |
| Side-loaded DLL | libmupdf.dll (malicious build, beside a signed MuPDF viewer) |
| MISTPEN modules | Release_GetInfoPlugin_x64.dll, Release_PvPlugin_x64.dll, OneScreenCapture64.dll |
| Dropped executable | new.exe (written by SecurityPDF) |
| PDF trigger marker | This document is encrypted with sumatrapdf reader!!!!!!!!!!!! |
| Troy PDB path | E:\HK\Tool_Module\Troy_Handle\1Troy_Create_Dll_Tool\x64\Release\Test_Dll.pdb |
| FudModule 3.1 SHA-256 | 3b6378df8442e63a6ed7317075913e4720847a510d95022d4a8347b2637c245d |
| Troy sample SHA-256 | 590fb6ae19480d694e08ee85859cad8066f2f87e7e5abba2960c6d115e1615d6 |
| Webshell artefacts | *.ses, <session_id>1.log, <session_id>2.log under a webroot |
Malpedia: FudModule (Lazarus, prior write-ups and YARA), MISTPEN (UNC2970; the family predates this campaign, only this delivery is new). Troy had no Malpedia entry at Cyllex’s publish time. NVD: CVE-2026-68820. Additional SHA-256 from Check Point’s IOC section, not in the Cyllex table, reproduced here as an addition:
| Family | SHA-256 (Check Point) |
|---|---|
| SecurityPDF.exe | 743172aab606974b054a64561534ae66baa3a840657f79d7c6fa18350e8d45d1 |
| SecurityPDF.exe | db3d69b7eeda2e35e23006bf4b7e206281fce809584207214fc213f9bc30376d |
| Troy | 68d4fba7b1300a59cd6212c08910a260cd71b40cd9f51cac933030a68faac0bb |
| Troy | a738059ce07c951c31ab2da3d93d8f69bff32f9b7d933dbf5943441b9cc99075 |
| RelayShell | 21c3ad4838c4324bc5f081021da5fb2e9073d0c9304087811c21eb47c9e22762 |
| RelayShell | cc4e06aa378a190f71384c03023bb3d18a6d66e297d46701220e132963d2e222 |
| ForestTiger | 72dccae85e062f541fecad9ec7a18a3123e7ae5ac5d53c91709b53a46dbbd289 |
RelayShell YARA from Check Point Research (verbatim):
rule lazarus_relayshell
{
meta:
author = "@_CPResearch_"
description = "Lazarus RelayShell Webshell"
target_entity = "file"
hash = "21c3ad4838c4324bc5f081021da5fb2e9073d0c9304087811c21eb47c9e22762"
strings:
$str1 = "'PqCWom'"
$str2 = "'a84038'"
$str3 = "'biwbih'"
$str4 = "'ddf7acea'"
$str5 = "'enRU904U'"
$str6 = "'fou2rm'"
$str7 = "'kurhiW'"
$str8 = "'qcrgl'"
$str9 = "'rlzbiw'"
$str10 = "'tmmvr1'"
$str11 = "'win386'"
$str12 = "\"biwbih\""
$str13 = "\"PqCWom\""
$str14 = "\"a84038\""
$str15 = "\"ddf7acea\""
$str16 = "\"enRU904U\""
$str17 = "\"fou2rm\""
$str18 = "\"kurhiW\""
$str19 = "\"qcrgl\""
$str20 = "\"rlzbiw\""
$str21 = "\"tmmvr1\""
$str22 = "\"win386\""
$str23 = "D9hWnVEqdgzJ67/B8euS0yKCIMrw5jc:fGUX3AakLH2oYQRp"
condition:
3 of ($str*)
}
Operator Notes the Original Left Implicit
- Do not write or run an AFD race PoC against production. The patch is the control. The detection gap is the DLL load.
- Image-load: Sysmon Event 7 (if you still collect it; many shops dropped it for volume) or equivalent EDR module-load. Filter: signed parent, unsigned or differently signed DLL, path = parent directory, parent name matches PDF/MuPDF/Sumatra/SecurityPDF.
- new.exe from a viewer: Sysmon 1 / 4688 parent-child. ASR rules that block Office/PDF children from creating executables are the cheap prevent.
- Graph from the wrong process: Defender for Endpoint deviceNetworkEvents or equivalent, join to process. Not a DNS block.
- Silent host: baseline daily ETW provider volume per device, alert on a drop. That is the post-rootkit signal.
- Webroots: find /var/www -name ‘*.ses’ -o -name ‘*1.log’ -o -name ‘*2.log’ is a start, not a complete hunt. Also Roundcube version and leaked-credential resets.
What Check Point Saw That Cyllex Compressed
Cyllex is the defender’s cut. Check Point is the RE cut. A few facts that matter once you are hunting, and that the shorter post only implied.
ForestTiger is still on the MISTPEN chain
After recon, persistence, and FudModule, MISTPEN’s long-term backdoor on chain 1 is ForestTiger, a previously documented Lazarus family, not Troy. Troy is chain 2. If your hunt is only for the Troy PDB, you will miss the ZIP-and-side-load victims. ForestTiger historically used compromised WordPress and SharePoint; this wave shifted C2 toward Roundcube. Same actor, two implants, two channels. Correlate by victimology and timing, not by a single hash family.
SecurityPDF patches two open paths
The trojan is not a new viewer from scratch. It is MuPDF with File → Open and drag-and-drop hooked. That means a user who never uses the Open dialog and only double-clicks a PDF from Explorer still hits the marker check if the shell association launches this binary. Hunt both: the viewer as a downloaded EXE named like a security product, and the association change if they installed it.
MISTPEN persistence is a later module
Cyllex emphasises the in-memory footprint. Check Point is explicit that after the host looks like a real target, MISTPEN receives a persistence module that drops on disk so the downloader survives reboot. That is T1547.001 / T1053.005 in the ATT&CK table. Hunt Run keys and scheduled tasks created by a PDF-viewer lineage, not only in-memory loaders. The “no disk footprint” claim is true for the first hours, not for a host that passed fingerprinting.
The LPE sample looks like FudModule 2024 on purpose
Afd4Eop12_x64.dll’s main is similar to the 2024 variant; strings still say god mode. The exploit is new; the post-exploit is a maintained product. Targeting narrowed to 26100/26200. If you still have 23H2 or Windows 10 ESU unpatched, you are in the vulnerability set even if this build of the exploit would have refused you. Patch the class, not the sample.
RelayShell is not a command shell
Operators do not get a PHP system() box. They get a drop-box. Victim implant and operator browser both write files. Backbone URL is another RelayShell. Taking down one node costs them one of seventeen. Your win is finding the files, the version of Roundcube, and the reused password, not sinking a C2 domain that does not exist.
Hunting Queries You Can Actually Run
These are ours, not Cyllex’s. They encode the pre-ring-0 window. Tune table names to your SIEM. Do not paste them into production without a volume check.
# Sysmon 7 / EDR module load: signed PDF parent, DLL from same directory
DeviceImageLoadEvents
| where FileName has_any ("libmupdf.dll","mupdf.dll")
or InitiatingProcessFileName has_any ("SecurityPDF","SumatraPDF","mupdf")
| where FolderPath startswith InitiatingProcessFolderPath
| where InitiatingProcessSigner != Signer or isempty(Signer)
# Viewer spawning new.exe
DeviceProcessEvents
| where InitiatingProcessFileName has_any ("SecurityPDF.exe","SumatraPDF.exe")
| where FileName =~ "new.exe" or FolderPath has @"\Temp\"
# Graph API from a process that should not hold a token
DeviceNetworkEvents
| where RemoteUrl has_any ("graph.microsoft.com","login.microsoftonline.com")
| where InitiatingProcessFileName !in ("OUTLOOK.EXE","WINWORD.EXE","EXCEL.EXE","OneDrive.exe","Teams.exe","Msedge.exe")
| where InitiatingProcessFileName has_any ("SecurityPDF","mupdf","msiexec","new.exe")
# SYSTEM msiexec with no MSI on the command line
DeviceProcessEvents
| where FileName =~ "msiexec.exe" and ProcessIntegrityLevel == "System"
| where ProcessCommandLine !has ".msi" and ProcessCommandLine !has "/i"
Webroot hunt on a Linux CMS host, as a starting point, not a complete audit:
find /var/www /usr/share/nginx /home/*/public_html -type f \(
-name '*.ses' -o -name '*1.log' -o -name '*2.log'
\) 2>/dev/null
Why Five Weeks Is the Number That Should Anger You
MSRC got the bug on 28 July. Patch Tuesday was 11 August. Exploitation started early July. For those five weeks the only available controls were the ones that do not need a Microsoft update: image-load, child-process, Graph-by-process, Roundcube hygiene. If your programme treats “we patch in 14 days” as the kernel-LPE story, this campaign is the counterexample. KEV listing on the same day as the patch is Microsoft and CISA telling civilian agencies to move. It does not resurrect telemetry FudModule already deleted on a host that was hit in July.
Sources disagree on June versus July for first exploitation. Cyllex follows the majority (Check Point timeline, BleepingComputer, five-weeks-before-patch). If your IR timeline needs a conservative start, use early June and hunt side-loads from then. False positives on PDF readers are cheaper than missing a Dream Job box that has been quiet since June.
What This Is Not
- It is not a remote worm. CVE-2026-68820 is local. The remote part is a human opening a job PDF.
- It is not ransomware. Troy does not dump LSASS or walk the domain. The goal is files off a specific engineer.
- It is not BYOVD in the 2021 sense. No third-party .sys. Your blocklist did not get a vote.
- It is not “undetectable.” It is undetectable after DestroyEnv. Before that it is a DLL next to a signed EXE.
- It is not an Enveil breach. The brand was stolen for SEO. Do not page their CISO; page your aerospace hiring managers.
- Emulation is not a substitute for patch inventory. Cyllex is explicit. So is this draft.
A Short Ring-0 Glossary for People Who Do Not Live in WinDbg
- Ring 0 is kernel mode. User apps are ring 3. A kernel R/W primitive lets ring 3 edit ring 0 memory, including the token that says who you are.
- afd.sys is the kernel half of Winsock. Sockets are not “just user mode.”
- Use-after-free (CWE-416): one path frees an object, another path still has a pointer, a third allocation (yours) lands in the hole.
- Data-only rootkit: no new kernel code, just unlinked lists and zeroed function pointers. PatchGuard is less angry; your EDR is more blind.
- ETW is the firehose Defender, Sysmon-adjacent tools and hunting queries drink from. Kill 94 GUIDs and the hose is dry.
- Smart App Control is a reputation gate on Windows 11. Setting its policy state to zero from the kernel is not a Group Policy change you will see in GPResult.
Key Takeaways
- Lazarus spent a kernel zero-day on a fake job PDF. The expensive part was not the lure. It was the five weeks before Patch Tuesday.
- CVE-2026-68820 is a local AFD.sys UAF. CVSS 7.0 hides that it skips every BYOVD control you bought after 2021.
- The exploit is fingerprint-gated. Sandboxes on the wrong build never receive it. Absence of a sample is not absence of exploitation.
- FudModule 3.1 does not persist you. It unplugs callbacks, minifilters, 94 ETW GUIDs, crash dumps, and Smart App Control without a reboot.
- After ring 0, hunts return clean because events were never generated. The window is the unsigned DLL in the signed viewer, minutes in.
- C2 is Graph/OneDrive or someone else’s Roundcube. There is no attacker domain to block. There are .ses files in your webroot.
- Patch is necessary and insufficient until reboot. Emulation should not include the race. It should include the side-load.
Defensive Recommendations
- Ship KB5121003 / KB5120249 and measure reboot, not MSI install. Unrebooted hosts are still in the KEV set.
- Alert on MuPDF/PDF viewers loading a same-directory DLL with a signer mismatch. That is T1574.001 and the best pre-ring-0 catch.
- Block document processors from spawning new.exe / unsigned children (ASR / WDAC). Chain 2 dies there even if the viewer is allowed.
- Tag Graph and login.microsoftonline.com traffic by process. Investigate PDF readers and msiexec holding tokens.
- Treat ETW/EDR silence as an incident, not as health. Baseline, then alert on drop.
- Assume Smart App Control can be switched off from the kernel. Complement with WDAC.
- Patch Roundcube, MFA webmail, hunt .ses and <id>N.log on every internet CMS you own. You are potential Lazarus infrastructure.
- Train defence and aerospace engineers on two-week recruiter lures and mail from compromised peer domains, not just generic phishing.
Conclusion
Dream Job is an old play. What is new is spending a kernel race in a Microsoft inbox driver so the rest of the play becomes invisible. Cyllex’s point, and Check Point’s, is that the SOC question is not “would we have caught FudModule?” — after DestroyEnv, there is nothing to catch. The question is whether a signed PDF reader loading libmupdf.dll from its own folder would have lit anything up on 3 July, when patching was not a control that existed. Go find out. Then reboot the boxes that think they already did.
Original text: “From Job Offer to Ring 0: Lazarus, CVE-2026-68820 and FudModule 3.1” by author not clearly listed (site: Cyllex) at Cyllex. Primary analysis: Check Point Research.


