-
-
[原创]借鉴CVE-2017-0213思路,挖掘到另外一种方法成功获取到System的Token,新的0day
-
发表于: 2018-3-16 19:01 5478
-
我讲一下我的实现思路, 在打满所有补丁的server2008或win7下情况下IBackgroundCopyJob->SetNotifyInterface根据CVE-2017-0213的原理会加载一个指定com组件的typelib(以sysytem权限),可以指定任意typlelib然后bits服务调用loadregtypelib这个ole32下函数,然后loadregtypelib会把com组件的typelib中指定的文件名作为一个filemoniker解析(调用),因为文件被锁定了(见使用方法),所以它loadregtypelib调用mkpaersedisplayname来createfilemoniker失败,同时我在poc中实现了一个和这个filemoniker相同displaynmame的moniker并在Running Object Table注册一个自定义的typelib,所以mkpaersedisplayname失败后会把在Running Object Table注册的moniker指定的typlelib对象(可以是任意对象)作为filemoniker应该调用bindtoobject返回的对象(也就是替换),然后bits服务会调用这个指定的typlelib对象上的一些方法,这个时候在我的typlelib上调用coimpersonateclient返回的token就是system的,和截图一样,但是这个token模拟级别是SecurityIdentification类型的无法创建新进程无法操作文件(返回1346错误),另外说一点,我分析到是,通过修改注册表中typelib对于的文件名路径,如果bits服务调用loadregtypelib对应typelib指定的文件名是一个scrptletmoniker是可以直接启动一个system的cmd.exe,问题是注册表非管理员无法修改,这个只是验证说明调用方确实是system的bits服务,暂时得出的结论是如果bits服务调用loadregtypelib返回的scrptletmoniker是在他自己本身内部实现的所以启动cmd.exe是可行的,
,我认识到了SecurityIdentification模拟等级的token利用的相关知识,另外一种利用方式是在调用方发起一个导致代码执行的反序列化,我通过逆向ole32的代码发现确实有类似回调对象的东西,有关微软官方文档https://msdn.microsoft.com/en-us/library/windows/desktop/ms686628(v=vs.85).aspx其中说到If riid is set to IID_IEnterActivityWithNoLock, the function is executed without an activity lock.是否意味着只要是unmarshal 的objref中可以序列还出来这种类型iid的回调就可以绕过com代理不同套间(apartment)的限制,以下我是逆向ole32的结果,不知道是否有可行性:
HRESULT __stdcall UnmarshalObjRef(tagOBJREF *objref, void **ppv, int fBypassActLock, CStdMarshal **ppStdMarshal)
{
HRESULT v4; // eax
CObjectContext *v5; // eax
tagOBJREF *v7; // edi
HRESULT v8; // esi
CStdMarshal *v9; // esi
CStdIdentity *v10; // eax
void **v11; // edi
tagStdUnmarshalData StdData; // [esp+Ch] [ebp-1Ch]
int fLightNAProxy; // [esp+24h] [ebp-4h]
v7 = objref;
fLightNAProxy = CrossAptRefToNA(objref);
v8 = FindStdMarshal(v7, 0, (CStdMarshal **)&objref, fLightNAProxy);
if ( v8 < 0 )
{
if ( v7->u_objref.u_standard.std.cPublicRefs )
ReleaseMarshalObjRef(v7);
}
else
{
v9 = (CStdMarshal *)objref;
v10 = *(CStdIdentity **)objref->iid.Data4;
StdData.pobjref = v7;
v11 = ppv;
StdData.pStdID = v10;
StdData.ppv = ppv;
StdData.pClientCtx = GetCurrentContext();
if ( ppStdMarshal )
{
*ppStdMarshal = v9;
v9->vfptr->AddRef((IUnknown *)&v9->vfptr);
}
v5 = CStdMarshal::ServerObjectCallable(v9);
if ( v5 )
{
StdData.fCreateWrapper = v11 != 0;
if ( fBypassActLock )
v4 = PerformCallback(v5, UnmarshalSwitch, &StdData, &IID_IEnterActivityWithNoLock, 2u, 0);
else
v4 = PerformCallback(v5, UnmarshalSwitch, &StdData, &IID_IMarshal, 6u, 0);
}
else
{
StdData.fCreateWrapper = fLightNAProxy;
v4 = UnmarshalSwitch(&StdData);
}
v8 = v4;
}
return v8;
}
这个有一个fBypassActLock是安全主体的构造验证
UnmarshalSwitch是可以序列化出来的回掉函数
具体序列还方式 是:
HRESULT __stdcall UnmarshalSwitch(void *pv)
{
void **v1; // eax
int v2; // edi
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)