There may be some logic bugs in the COM and RPC servers built in Windows OS.In order to find these bugs automatically, the commonly used algorithm is to search for the call chain between functions and Win32 APIs that perform sensitive operations, but if you only rely on the xrefs of the disassembler to generate the call chain, you cannot handle calls across process boundaries. To solve this problem to a certain extent, we propose "Cross-Server Xrefs" in COM and RPC and introduce an automated algorithm to search for this scenario, the key to this algorithm is to use the Backtrace function of Metasm(the Ruby assembly manipulation suite). We will also introduce other attack surfaces in "Cross-Server Xrefs" and use our methods to find examples. Finally, we release an open source tool to help researchers explore the things described in this presentation.
2. Who We Are?
•Founder partner of MeetSec Technology Co., Ltd.,
•Leader of security department,
•A memeber of SycloverSecurity team.
•Penetration testing,Cyber Security researching,Web&OS programing.
ZhiMin Wang
YongQing He
•Security Researcher
•A member of SycloverSecurity
•Penetration testing & Coding
•Employee of MeetSec Technology Co., Ltd.,
Sai Cheng
•A member of SycloverSecurity
•Windows Security & Web Security
•Employee of MeetSec Technology Co., Ltd.,
5. Agenda
•Overview of MSRPC and COM
•Introducing Cross-Server Xrefs(CSX)
•Searching call chains to find logic bugs
•Disadvantages of common call chain searching — Missing the CSX
•Some attack surfaces in CSX
•An automated approach to find CSX and its limitation
•About Backtrack in Metasm
•Using Backtrack to implement our algorithm
•The limitation
•Demo
6. Microsoft RPC
•A kind of Remote Procedure Call
•Client-Server model
•Server exposes interfaces, which contain routines
•Client calls functions in its own address space, translated by
runtime library and stubs into remote server routines
•Many built-in privileged RPC servers in Windows
14. In-Proc and Out-of-Proc Server
Process
Instance
Client
Process A
Client
Process B
Instance
ORPC or other channel
In Process
Out of Process
15. Case Study of Logic Bug: CVE-2020-0773
•Time-of-Check to Time-of-Use
16. Common Call Chain Searching
Server Process
Func()
Sub()
Blah()
CopyFileW
A piece of cake.
Disassembler
17. But if across process boundary…
Server Process 1
Func()
Sub()
Blah()
RemoteCall()
Server Process 2
Sub()
CopyFileW
As COM/RPC Client
Cross-Server Xrefs
22. RPC Security Callback Function Bypass
Security
Callback
Client
Thread 1
Impersonated
RPC Server 1
Interface
Client
PassFirst time
Second time
RPC_STATUS RpcServerRegisterIf2(
RPC_IF_HANDLE IfSpec,
UUID *MgrTypeUuid,
RPC_MGR_EPV *MgrEpv,
unsigned int Flags,
unsigned int MaxCalls,
unsigned int MaxRpcSize,
RPC_IF_CALLBACK_FN *IfCallbackFn
);
#define RPC_IF_AUTOLISTEN 0x0001
#define RPC_IF_OLE 0x0002
#define RPC_IF_ALLOW_UNKNOWN_AUTHORITY 0x0004
#define RPC_IF_ALLOW_SECURE_ONLY 0x0008
#define RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH 0x0010
#define RPC_IF_ALLOW_LOCAL_ONLY 0x0020
#define RPC_IF_SEC_NO_CACHE 0x0040
#if (NTDDI_VERSION >>= NTDDI_VISTA)
#define RPC_IF_SEC_CACHE_PER_PROC 0x0080
#define RPC_IF_ASYNC_CALLBACK 0x0100
#endif /// (NTDDI_VERSION >>= NTDDI_VISTA)
Disables security callback caching,
forcing a security callback for each
RPC call on a given interface.
Cache enabled by default!
23. RPC Security Callback Function Bypass
Attacker
Thread 1
Impersonated
RPC Server 1
Application
Attacker
PassFirst time
Second time
Is the client
PID same
as RPC
Server 1?
24. Impersonation in COM
Client
COM Server
Thread 1
Impersonated
COM Server
Thread 1
Impersonated
Without Cloaking
*Different colors for different identities
25. Impersonation in COM
Client
COM Server
Thread 1
Impersonated
COM Server
Thread 1
Impersonated
With Cloaking
*Different colors for different identities
26. Review of Cross-Apartment
MTA STA
Proxy
COM Object
Proxy COM Object
Client
Application
Impersonated
Thread 1 Thread 1
Impersonated
*Different colors for different identities
34. Traps in Cloaking
COM Server
•Using CoInitializeSecurity
Proxy
0x831728
CMyClass:Call1()Client
Projects identity
Client
First call
Subsequent call
Note: Not all coclasses have this behavior
*Different colors for different identities
45. Backtracking for key information
typedef struct _MIDL_STUB_DESC
{
void * RpcInterfaceInformation;
.....
.....
} MIDL_STUB_DESC;
RPC_CLIENT_INTERFACE
Same layout as RPC_SERVER_INTERFACE
Get interface identifier
and Transfer syntax
•Interface information
46. Backtracking for key information
Routine 1
Routine 2
…
…
Proc Number 0
Proc Number 1
NdrClientCall(…, PFORMAT_STRING pFormat, …)
NdrClientCall2(…, PFORMAT_STRING pFormat, …)
NdrClientCall3(…, unsigned long nProcNum, …)
NdrClientCall4(…, PFORMAT_STRING pFormat, …)
•Procedure Number
Decompile
NDR procedure format string
Backtracking parameter
Stubless proxy
/protocol all with 64-bit env
47. Decompile NDR Format String
Header Descriptor
Param A Descriptor
Param B Descriptor
Param C Descriptor
Procedure Format String
Handle type
Oi Flags
RPC Flags(optional)
Procnum
Stack size
…
Common /Oif mode
That’s what we need!
48. Another Example:
Backtracking RPC Security Callback Function
•RpcServerRegisterIf2/RpcServerRegisterIf3/RpcServerRegisterIfEx
RPCServerRegisterIf2(
RPC_IF_HANDLE IfSpec,
UUID *MgrTypeUuid,
RPC_MGR_EPV *MgrEpv,
unsigned int Flags,
unsigned int MaxCalls,
unsigned int MaxRpcSize,
RPC_IF_CALLBACK_FN *IfCallbackFn
)
Server interface
Check if the cache is disabled
Function address
49. Another Example:
Backtracking RPC Security Callback Function
•Security Callback Function Checks Caller's PID
RPCServerRegisterIf2(
RPC_IF_HANDLE IfSpec,
UUID *MgrTypeUuid,
RPC_MGR_EPV *MgrEpv,
unsigned int Flags,
unsigned int MaxCalls,
unsigned int MaxRpcSize,
RPC_IF_CALLBACK_FN *IfCallbackFn
)
Security Callback
I_RpcBindingInqLocalClientPID
RpcServerInqCallAttributes
Calls
50. Finding COM Interface Methods
•Hooking NdrStubCall2/NdrStubCall3 for standard marshaler
•Casting pThis parameter to pointer of CStdStubBuffer
•Get member variable pvServerObject
•Event Tracing for Windows(ETW)
•Provider Name: Microsoft-Windows-COM-Perf
•GUID: b8d6861b-d20f-4eec-bbae-87e0dd80602b
•Event ServerSyncCallStart/ServerAsyncCallStart
•Parsing internally maintained database in COM server(OleViewDotNet)
51. Finding COM Client
•Backtracking COM Object Activation API
HRESULT CoCreateInstance(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID *ppv
);
Example: CoCreateInstance
Get Class Id
Get Interface Id
But interface pointer
is symbolic value
lea rax, [rsp+ppv]
mov qword ptr [rsp+arg], rax
…
…
call CoCreateInstance
…
…
mov rcx, [rsp+ppv]
mov rax, [rcx]
call qword ptr [rax+28h] ; Calling interface method
Backtracking from here
[[rsp+32]]
Symbolic value
52. Finding COM Client
•Backtracking COM Object Activation API
Example: CoCreateInstance
lea rax, [rsp+ppv]
mov qword ptr [rsp+arg], rax
…
…
call CoCreateInstance
…
…
mov rcx, [rsp+ppv]
mov rax, [rcx]
call qword ptr [rax+28h]
Vtable pointer
Backtracking rax
for last known value
qword ptr [qword ptr [rsp+50h]]
Object Pointer
Backtracking
[[rsp+32]]
for last known value
Interface Pointer
Is it equal?
We know which
interface method
was called
True
Offset to fptr
Meow(ICat * This, …)
*Without CFG