Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

[CB20]-U25 Automated Hunting for Cross-Server Xrefs in Microsoft RPC and COM by Sai Cheng, Yongqing He and Zhimin Wang

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.

  • Be the first to comment

  • Be the first to like this

[CB20]-U25 Automated Hunting for Cross-Server Xrefs in Microsoft RPC and COM by Sai Cheng, Yongqing He and Zhimin Wang

  1. 1. Automated Hunting for Cross-Server Xrefs in Microsoft RPC and COM
  2. 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.,
  3. 3. Who We Are? Penetration Testing & Security Training Many Clients of energy sector
  4. 4. Who We Are? Syclover We focus on Cyber Security
  5. 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. 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
  7. 7. Microsoft RPC Interface Func() Routine 2 Routine 3 Routine 4 Server ProcessClient Process Runtime Library Application Code HRESULT Func(void); Stub Translates to Client Server
  8. 8. Microsoft RPC myinterface.idl myinterface_c.c myinterface_s.cmyinterface_s.h MIDL Compiler Application Code Client Stub Server Stub
  9. 9. “MEOW, MEOW. I’m a cat, please feed me OBJREF”
  10. 10. Component Object Model(COM)  Vtable Pointer QueryInterface() Pointer AddRef() Pointer Release() Pointer Method1() Pointer Method2() Pointer COM Object Data Human IUnknown IWork Inherits from IUnknown ISleep ICsgo Client Interactive with Interface Interface Methods
  11. 11. Apartment in COM •Single-Threaded Apartment(STA) •Multi-Threaded Apartment(MTA) •Neutral-Threaded Apartment(NTA) Instance Apartment Process Thread Apartment 1 Apartment 2 InstanceProxy Cross-Apartment
  12. 12. Single-Threaded Apartment STA Thread 1 Affinity Instance Process STA Thread 2 Instance STA Thread 3 Instance
  13. 13. Multi-Threaded Apartment Instance Thread 1 Thread 2 MTA Process
  14. 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. 15. Case Study of Logic Bug: CVE-2020-0773 •Time-of-Check to Time-of-Use
  16. 16. Common Call Chain Searching Server Process Func() Sub() Blah() CopyFileW A piece of cake. Disassembler
  17. 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
  18. 18. Cross-Server Xrefs RPC/COM Server RPC/COM Server Client COM Server RPC ServerClient
  19. 19. Cross-Apartment Xrefs in COM MTA STA Proxy COM Object Proxy COM Object Client Application
  20. 20. Impersonation Client Server Thread 1 ImpersonatedCall Client Server Thread 1 Without Impersonation Call *Different colors for different identities
  21. 21. Impersonation Client RPC Server Thread 1 Impersonated Thread 1 RPC Server Client RPC Server Thread 1 Impersonated Thread 1 RPC Server Without Impersonation Impersonated *Different colors for different identities
  22. 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. 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. 24. Impersonation in COM Client COM Server Thread 1 Impersonated COM Server Thread 1 Impersonated Without Cloaking *Different colors for different identities
  25. 25. Impersonation in COM Client COM Server Thread 1 Impersonated COM Server Thread 1 Impersonated With Cloaking *Different colors for different identities
  26. 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
  27. 27. Cloaking •Types •Static Cloaking(EOAC_STATIC_CLOAKING) •Dynamic Cloaking(EOAC_DYNAMIC_CLOAKING) •Configuration • CoInitializeSecurity • CoSetProxyBlanket(Wrapper function of IClientSecurity::SetBlanket) •Not useful without impersonation •Not set by default •Pick up thread token(if it has one), otherwise process token
  28. 28. Cloaking IMyIface Proxy ProxyManager IBlah Proxy As Client COM Object Proxy Identity Call CoInitializeSecurity CoSetProxyBlanket Process-Wide
  29. 29. Static Cloaking •Cached Identity Method1()Application First call Proxy Method1()Application First call Proxy Pick up thread/process token Method1()Application Subsequent call Proxy Fixed Identity CoInitializeSecurity
  30. 30. Static Cloaking •Cached Identity ProxyCoSetProxyBlanket Set blanket CoSetProxyBlanket Set blanket Pick up thread/process token Method1()Application Subsequent call Proxy Fixed Identity CoSetProxyBlanket Proxy
  31. 31. Dynamic Cloaking ProxyApplication Call ProxyApplication Call •Pick up token on each call
  32. 32. Traps in Cloaking •Using CoInitializeSecurity 0x831728 0x831728 Same interface proxy
  33. 33. Traps in Cloaking 0x831728 •Using CoInitializeSecurity
  34. 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
  35. 35. Automated search for Cross-Server Xrefs
  36. 36. Finding RPC Server Routines(interpreted mode) typedef struct _RPC_SERVER_INTERFACE { unsigned int Length; RPC_SYNTAX_IDENTIFIER InterfaceId; RPC_SYNTAX_IDENTIFIER TransferSyntax; PRPC_DISPATCH_TABLE DispatchTable; unsigned int RpcProtseqEndpointCount; PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint; RPC_MGR_EPV *DefaultManagerEpv; void const *InterpreterInfo; unsigned int Flags ; } RPC_SERVER_INTERFACE, * PRPC_SERVER_INTERFACE; typedef struct { unsigned int DispatchTableCount; RPC_DISPATCH_FUNCTION __RPC_FAR * DispatchTable; LONG_PTR Reserved; } RPC_DISPATCH_TABLE, __RPC_FAR * PRPC_DISPATCH_TABLE; typedef struct _MIDL_SERVER_INFO_ { PMIDL_STUB_DESC pStubDesc; const SERVER_ROUTINE * DispatchTable; PFORMAT_STRING ProcString; const unsigned short * FmtStringOffset; const STUB_THUNK * ThunkTable; PRPC_SYNTAX_IDENTIFIER pTransferSyntax; ULONG_PTR nCount; PMIDL_SYNTAX_INFO pSyntaxInfo; } MIDL_SERVER_INFO, *PMIDL_SERVER_INFO; typedef struct _RPC_PROTSEQ_ENDPOINT { unsigned char * RpcProtocolSequence; unsigned char * Endpoint; } RPC_PROTSEQ_ENDPOINT, * PRPC_PROTSEQ_ENDPOINT; Routine 1 Pointer Routine 2 Pointer Routine 3 Pointer Routine 4 Pointer [ uuid(4F12331F-FC50-4E96-940A-3882DC8F971E), endpoint(“ncacn_np:[pipemyendpoint]”) ] sizeof(RPC_SERVER_INTERFACE) Count
  37. 37. Analyzing MIDL Switch Options For Server typedef struct { unsigned int DispatchTableCount; RPC_DISPATCH_FUNCTION __RPC_FAR * DispatchTable; LONG_PTR Reserved; } RPC_DISPATCH_TABLE, __RPC_FAR * PRPC_DISPATCH_TABLE; NdrServerCall2 NdrServerCall NdrServerCallNdr64 0 … /Oi(c)f /Oi(c) /protocol ndr64 64-bit environment typedef struct _RPC_SERVER_INTERFACE { unsigned int Length; … void const *InterpreterInfo; unsigned int Flags ; } RPC_SERVER_INTERFACE, * PRPC_SERVER_INTERFACE; If null pointer Inline stub(/Os mode) Contradictory with /protocol ndr64|all
  38. 38. Analyzing MIDL Switch Options For Server typedef struct _RPC_SERVER_INTERFACE { unsigned int Length; … … void const *InterpreterInfo; unsigned int Flags ; } RPC_SERVER_INTERFACE, * PRPC_SERVER_INTERFACE; 0x6000000 typedef struct _MIDL_SERVER_INFO_ { PMIDL_STUB_DESC pStubDesc; … PFORMAT_STRING ProcString; … PRPC_SYNTAX_IDENTIFIER pTransferSyntax; ULONG_PTR nCount; PMIDL_SYNTAX_INFO pSyntaxInfo; } MIDL_SERVER_INFO, *PMIDL_SERVER_INFO; typedef struct _MIDL_SYNTAX_INFO { RPC_SYNTAX_IDENTIFIER TransferSyntax; RPC_DISPATCH_TABLE * DispatchTable; … … } MIDL_SYNTAX_INFO, *PMIDL_SYNTAX_INFO; NdrServerCallAll … … … >>= 2 •/protocol all with 64-bit environment
  39. 39. Finding RPC Client Routines(/Oicf mode)
  40. 40. Finding RPC Client Routines(/Oicf mode) Client routine RPC_CLIENT_INTERFACE MIDL_STUB_DESC PROC_FORMAT_STRING ? ? ?
  41. 41. Backtracking technique in Metasm require 'metasm' include Metasm sc = <<<--EOS push eax mov eax, 0x4c mov ebx, 0x21 sub eax, 1 sub ebx, 0x4 push edx push ecx add eax, 0x3c inc ebx sub eax, ebx jmp eax EOS dasm = Metasm:::Shellcode.assemble(Metasm:::Ia32.new, sc).init_disassembler dasm.disassemble(0) block = dasm.block_at(0) block.list.each do |di| puts "Instruction: " + di.instruction.to_s bt_binding = di.backtrace_binding bt_binding.map {{|k, v| puts "##{k} =>= ##{v}"} puts end puts "Result of backtracking expression 'eax': " puts dasm.backtrace(Expression[:eax], block.list.last.address).first.to_s Our test shellcode Backtrack symbolic expression “eax” from instruction “jmp eax”
  42. 42. Backtracking technique in Metasm
  43. 43. Backtracking technique in Metasm
  44. 44. SWEET technique… Return non-symbolic value after backtracking static const
  45. 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. 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. 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. 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. 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. 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. 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. 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
  53. 53. Talk is cheap And Show me the TOOL!
  54. 54. About TurboRex •A Ruby gem •RPC Server/Client routines locator •COM interface methods locator •Cross-Server Xrefs searcher •ALPC Server && Client •COM Client •COM Fuzzer(in progress)
  55. 55. https://github.com/existXFx/TurboRex
  56. 56. Sorry there is no live demo
  57. 57. Acknowledgement(in no particular order) •James Forshaw(@tiraniddo) •k0shl(@KeyZ3r0) •Ox9A82(@Ox9A82) •0xmuhe(@0xmuhe) •Yoann GUILLOT(developer of Metasm) •Code Blue Official •Other people who helped us
  58. 58. Thanks!
  59. 59. Q & A

×