Exploiting Windows COM/WinRT Services. XueFeng Li of Sangfor Dr. Zhiniang Peng of Sangfor
C:> whoarewe
- Xuefeng Li Xuefeng Li (@lxf02942370) is an intern at Sangfor and a student at South China University of Technology. He has been engaged in Windows vulnerability hunting and exploitation for almost one year and ranked #10 on the MSRC Most Valuable Security Researcher list in 2020.
- Zhiniang Peng Dr. Zhiniang Peng (@edwardzpeng) is the Principal Security Researcher at Sangfor. His current research areas include applied cryptography, software security and threat hunting. He has more than 10 years of experience in both offensive and defensive security and published many research in both academia and industry.
Agenda
- Basic of COM 2. Race Condition bugs in COM/WinRT 2.1 The inner working of COM Thread Model 2.2 Win Race Condition to get Use-After-Free 2.3 Win Race Condition to get Out-Of-Bound Writing
- From Type Confusion bugs to code execution 4. From Out-Of-Bound Writing to Arbitrary Reading/Writing 4.1 From Arbitrary Writing to code execution 4.2 From Arbitrary Reading to code execution
- Conclusion
01 Basic Of COM
What is COM(Component Object Model)?
Invoker Native Code C/C++ ... .NET Managed Code C# , VB , .NET ...
COM Object Framework
Runtime Callable Wrapper
COM Binary Protocol
Runtime CCOaMllabClaellable WrWaprappepr er
PrPPorrvooivdviieddreerr Native Code C/C++ ... .NET Managed Code C# , VB , .NET ...
Related Research of COM/WinRT · Having Fun with COM James Forshaw · The Inner Workings of the Windows Runtime - James Forshaw
02 Race Condition bugs in COM The Inner working of COM Thread model Win Race Condition to get Use-After-Free Win Race Condition to get Out-Of-Bound Writing
The inner working of COM Thread Model Thread Safety Thread safety is a computer programming concept applicable in the context of multi-threaded programs. Different threads can access the same resources without exposing erroneous behavior or producing unpredictable results Thread Safety of Client/Server For Client · Whether a COM server is thread safety is unknowable. · Any COM client can access any COM server in anytime anywhere. · Client is not responsible for thread safety. For Server · COM Assumption: All COM Server must be thread safety
Apartment Models with Invoker Thread · Invoker Thread is used to complete the Client-Server callable task, created in sever process during the Client-Server call. · Apartment is a Property of a COM thread stored in Thread-Local Storage(TLS). Single-threaded Apartment Model (STA) 0-N apartments in a process, 1 thread in each apartment Multi-threaded Apartment Model (MTA) 0-1 apartments in a process, N threads in each apartment Neutral Apartment Model (NA) 0-1 apartments in a process, 0 thread in each apartment
Apartment Models with Invoker Thread
Process
MTA
Share this Apartment
NA
...
STA0
STA1
STA2
STAN
...
Reference from: "Understanding and Using COM Threading Model"
Thread Windows Message Pumping STA: Single Room MTA: Dormitory NA: Activity Room
Thread Models of COM Object What is COM Thread Model? Thread Model is a Property of COM Object. Thread models are related to the COM object, while apartment models are related to the invoker thread.
Thread Model classification
· Single Thread Model (Single, only support STA0 apartments)
· Apartment Thread Model (Apartment, support all the STA apartments)
No thread safety issues
· Free Thread Model (Free, support the MTA apartment) · Both Thread Model (Both, support the STA,MTA,NA apartments)There may be thread safety issues · Neutral Thread Model (Neutral, support the NA apartment)
https://docs.microsoft.com/en-us/windows/win32/cossdk/threading-model-attribute
Thread Models and Apartment Models
· Method calls to COM objects in the same apartment are made directly. · Method calls made across apartments are achieved via marshalling.
process
COM Runtime
... Worker Threads
STA0 Queue
Listen Thread Create
STA 0~N
Create ... Worker Threads
COM Object
Dispatch message
MTA
... Worker Threads
NA
COM Object
COM Object
Thread Safety
STA0
Single
invoke
For Single, Apartment threading model com object, there could be only one invoker threads accessing the object at the same time.
Thread Safety
MTA invoke
Free, Both
For Free, Both threading model com object, there could be multiple invoker threads accessing the same object at the same time.
Thread Safety
NA Neutral invoke
For Neutral thread modeling com object there could be only multiple invoker threads accessing the object at the same time.
Win Race Condition to get Use-After-Free Escape AppContainer Sandbox
DCOM Activator
UWP Application
RPCSS
Runtime Broker Partial Trust Class
AppContainer Sandbox
Medium User Level
Reference from: "The Inner Workings of the Windows Runtime"
CVE-2020-1404 - Root cause Analysis UWP Application in AppContainer Sandbox
Runtime Broker
SecondaryTile object can be created in Multi-threaded Apartment
CVE-2020-1404 - Root cause Analysis Thread 1 and 2 arrive here together
Thread 1 and 2 arrive here together
Trigger a UAF issue!
CVE-2020-1404 - Proof of concept Crash
CVE-2020-1404 - Exploitation HSTRING 1 HSTRING 1 HSTRING 1 HSTRING 1 HSTRING 1 HSTRING 1
All the HSTRING need to be large enough to avoid LFH
HSTRING 2 Freed Freed
HSTRING 3
HSTRING 4
Free HSTRING 2 HSTRING 3
HSTRING 4
Thread 1 enters: free HSTRING 3
Freed
HSTRING 4
Windows Heap Manager merges freed chunk
Freed
HSTRING 4
Thread 2 enters: allocate a new HSTRING
NEW HSTRING
HSTRING 4
Thread 3 enters: use freed HSTRING 3 (Where UAF happens)
NEW HSTRING HSTRING 3 Filled with user-controllable data
HSTRING 4
HSTRING
Flag
Length
GAP
Buffer Pointer
Ref Count
Real Buffer
rewrite
Evil HSTRING
Flag
Arbitrary Length
GAP
Arbitrary Address
Ref Count
Calling ISecondaryTile->get_PhoneticName with fake HSTRING 3 to get Read-What-Where
Hard to Exploit such Race Condition UAF bugs stably, it's easy to cause the crash, but you can keep trying until you succeed
Win Race Condition to get Out-Of-Bound Writing Public Example : CVE-2020-0625 (Found by shefang Zhong) Vulnerable COM InterfaceISearchRoot (Exposed by Local COM Server WSearch) ISearchRoot->put_Schedule copies user-controlled buffer into ISearchRoot Object. ISearchRoot->get_Schedule reads the data of ISearchRoot object into output buffer.
Win Race Condition to get Out-Of-Bound Writing
Trigger a heap OOB Write issue!
First fetch, taking a small size as allocation size. Call ISearchRoot->put_Schedule in the time window between the upper and lower codes to rewrite buffer Pointer size Second fetch, taking a large size as copy size.
Reference from : https://blog.diffense.co.kr/2020/03/26/SearchIndexer.html
03 From Type Confusion Bugs to Code Execution
From Type Confusion bug to code execution CVE-2020-1011 - Root Cause Analysis Vulnerable WinRT Interface IXmlNode (Get from runtime class: Windows.UI.Notifications.ToastNotificationManager ) Vulnerable function
CVE-2020-1011 - Root Cause Analysis Vulnerable Code Snippetmsxml6.dll!Object::getObjectFromIUnk
Getting from Client, user can forge a fake IUnknown object and pass it to server
Custom implementation
Taking user controllable data as a valid object address
Construct fake COM object for exploitation(x86 system) Primitive: A object pointer we can control What we need: A address we can fully control
Heap Spray in x86 system
0x019ac000 0x019ac040 [...] [...] 0x10000000
Fake Object Fake Object [...] [...] Fake Object
The address we need!
Fake vftable
How to heap spray?
Find a COM interface which allows us to put many usercontrollable HSTRING on the server heap For example: IXmlNode->put_NodeValue
Fake object contents
Require a Info leak for exploitation(x64 system) Heap spray Require huge memory consumption Info leak Require a Info leak bug to leak where our fake objects locates
04 From Out-Of-Bound Writing to Arbitrary Reading/Writing From Arbitrary Writing to code execution From Arbitrary Reading to code execution
From Out-Of-Bound Writing to Arbitrary Reading/Writing CVE-2020-1361 - Root Cause Analysis Vulnerable COM InterfaceIWalletCustomPropery (Exposed by Local COM Server: WalletService)
CVE-2020-1361 - Root Cause Analysis Vulnerable Code Snippet: WalletService.dll!Wallet::WalletCustomProperty::SetGroup Trigger a heap OOB Write issue!
Overwrite Object Pointer Member to get Write-What-Where
Wallet::WalletCustomProperty::SetLabel
Control cstring object to get Write-What-Where
Overwrite Object Pointer Member to get Read-What-Where
Wallet::WalletCustomProperty::GetLabel
Control BSTR object to get Read-What-Where
From Write-What-Where to code execution Overwrite Next Object's Contents
IWalletCustomProperty vftable [...] [...] IWalletCustomProperty vftable [...] [...] IWalletCustomProperty vftable [...] [...]
object1 OOB Write object2 object3
IWalletCustomProperty vftable [...] [...] Fake vftable Fake Contents Fake Contents IWalletCustomProperty vftable [...] [...]
Forge Fake vftable to Get Code Execution
IWalletCustomProperty vftable [...] [...] Fake vftable Fake Contents Fake Contents
Using Write-What-Where to forge a fake vftable
QueryInterface Addref
Release dxgi.dll ATL::CComObject ::`vector deleting destructor' [...]
IWalletCustomProperty vftable [...]
dxgi.dllATL::CComObject::`vector deleting destructor' will call LoadLibraryEx and take a global pointer as the Dll path which could allow us to load arbitrary dll.
[...]
The full exploitation can be found at GitHub.
From Read-What-Where to code execution The way to the heaven IRundown->DoCallback The purpose of DoCallback: cross-apartment call(used by internals) https://googleprojectzero.blogspot.com/2018/11/injecting-code-into-windows-protected.html
Abusing CRemoteUnknown::DoCallback to get RIP control Server Secret
Abusing CRemoteUnknown::DoCallback to get RIP control
Critical Corpus for exploitation: What we have: CProcessSecret::s_guidOle32Secret: Read from Combase.dll g_pMTAEmptyCtx: Read from Combase.dll pCallbackData->pfnCallback: Pick LoadLibraryW for our target What we need: ? Proxy of IRundown object from local server ? pCallbackData->pParam: Require to be a pointer point to user-controllable string
Getting a IRundown object proxy from local server
Client Side CoCreateInstance
Require IUnknown object proxy
"MEOW"
OBJREF Type
Sever Side
IID (lower 8 Bytes)
IID_IUnknown
IID (upper 8 Bytes)
Flags
Reference
Parsing OBJREF buffer Get IUnknown object proxy
Object Exporter ID (OXID) Object ID (OID)
Interface Pointer ID (IPID)
Return OBJREF buffer
IPID (upper 8 Bytes) Binding information
IPID_IUnknown
Getting a IRundown object proxy from local server
CoCreateInstance Get IUnknown Object Proxy CoMarshalInterface
"MEOW"
OBJREF Type
IID (lower 8 Bytes)
IID (upper 8 Bytes)
Flags
Reference
Object Exporter ID (OXID)
Object ID (OID)
Interface Pointer ID (IPID)
IPID (upper 8 Bytes)
Binding information
"MEOW" OBJREF Type IID_IRundown (lower 8 Bytes)
CoUnmarshalInterface
IID_IRundown (upper 8 Bytes)
Flags
Reference
Object Exporter ID (OXID)
Object ID (OID) IPID_IRundown (lower 8 Bytes)
IRundown Object Proxy
IPID_IRundown (upper 8 Bytes)
Binding information
Get the IPID of IRundown object
Object address Object IPID Object IID
Point pCallbackData->pParam to user-controllable string Step 1 Input DLL Path into local service
Step 2 Find the address of IWalletCustomProperty Object in server IWalletCustomProperty_object in client
pv is the address of the IWalletCustomProperty Object in the server
CoMarshalInterface
Compare IPID
Get IPID from OBJREF buffer
Point pCallbackData->pParam to user-controllable string Step 3 Find DLL Path string location *(Object address + 48) == &"C:\1\exp.dll"
Demo Time
Conclusion The thread safety of COM/WinRT is still an attack surface that deserves attention. 50+ memory corruption bugs we found associated with Race Condition. Hard to exploit Race Condition bugs stably. COM/WinRT still has a large attack surface for LPE bugs hunting.
Q & A Thanks for listening! Any Questions?