Advisory NTIADV0808 (Accelerated Disclosure)
SiSoftware Sandra (sandra.sys) Multiple Vulnerabilities
VendorSiSoftware Ltd.
Affected SoftwareSiSoftware Sandra < = 16.10.2010.1
Affected DriverSandra Device Driver (x86)(Unicode) - sandra.sys < = 15.18.1.1
Sandra Device Driver (x64)(Unicode) - sandra.sys < = 15.18.1.1
Date Reported2008-10-17
Release Date2010-01-23
StatusPartially Fixed
ExploitSandra_Exp.zip - Local Privilege Escalation Exploit (unavailable)
Disclosure Timeline 2008-10-17 - Vulnerability reported to vendor
2008-10-21 - Vendor response
2008-11-15 - Status update request
2008-11-20 - Vendor response
2008-12-12 - Status update request
2008-12-12 - Vendor response
2008-12-16 - Partial update released by the vendor
2008-12-16 - Vulnerability reported to vendor a second time
2008-12-16 - Vendor response
2009-01-27 - Status update request (no response)
2009-02-27 - Status update request (no response)
2009-01-26 - Second update released by the vendor
2010-01-23 - Full technical details released to general public
Description
SiSoftware Sandra contains signed drivers, one for x86 and one for x64 systems. Both modules are prone to a local privilege escalation vulnerabilities that occurs in the sandra.sys driver.
Details
SiSoftware Sandra's modules include functionality that can be abused to copy user supplied data into Model-Specific Registers. This allows malicious users to crash the system or inject arbitrary code into the kernel. In order to use this vulnerability, an Administrator must lunch the SiSoftware Sandra application or load the sandra.sys driver manually.

Fixed (restricted access to some MSR registers)

		.text:00011948 ; int __stdcall WriteMsr(int SystemBuffer)
		.text:00011948 WriteMsr proc near
		.text:00011948
		.text:00011948 SystemBuffer = dword ptr  8
		.text:00011948
		.text:00011948                 mov     edi, edi
		.text:0001194A                 push    ebp
		.text:0001194B                 mov     ebp, esp
		.text:0001194D                 push    esi
		.text:0001194E                 mov     esi, [ebp+SystemBuffer]
		.text:00011951                 push    dword ptr [esi]                ; SystemBuffer[0] -> AffinityMask
		.text:00011953                 call    SetThreadAffinityMask
		.text:00011958                 test    al, al
		.text:0001195A                 jz      short @@return
		.text:0001195C                 mov     eax, [esi+8]                   ; SystemBuffer[2] -> LowOrderMsr
		.text:0001195F                 mov     ecx, [esi+4]                   ; SystemBuffer[1] -> Msr Number
		.text:00011962                 mov     edx, [esi+0Ch]                 ; SystemBuffer[3] -> HighOrderMsr
		.text:00011965                 wrmsr
		.text:00011967                 mov     al, 1
		.text:00011969
		.text:00011969 @@return:
		.text:00011969                 pop     esi
		.text:0001196A                 pop     ebp
		.text:0001196B                 retn    4
		.text:0001196B WriteMsr	       endp
		
.text:0001191A ; int __stdcall ReadMsr(int InputBuffer,int OutputBuffer) .text:0001191A ReadMsr proc near .text:0001191A .text:0001191A InputBuffer = dword ptr 8 .text:0001191A OutputBuffer = dword ptr 0Ch .text:0001191A .text:0001191A mov edi, edi .text:0001191C push ebp .text:0001191D mov ebp, esp .text:0001191F push esi .text:00011920 mov esi, [ebp+InputBuffer] .text:00011923 push dword ptr [esi] ; InputBuffer[0] -> AffinityMask .text:00011925 call SetThreadAffinityMask .text:0001192A test al, al .text:0001192C jz short @@return .text:0001192E mov ecx, [esi+4] .text:00011931 rdmsr .text:00011933 mov ecx, [ebp+OutputBuffer] .text:00011936 mov [ecx+8], eax ; OutputBuffer[2] <- LowOrderMsr .text:00011939 mov [ecx+0Ch], edx ; OutputBuffer[3] <- HighOrderMsr .text:0001193C mov al, 1 .text:0001193E .text:0001193E @@return: .text:0001193E pop esi .text:0001193F pop ebp .text:00011940 retn 8 .text:00011940 ReadMsr endp
.text:0000000000012262 @@0x22A424_IOCTL_WRITE_MSR: .text:0000000000012262 cmp rbx, rdi .text:0000000000012265 jz @@invalid_buffer_size .text:000000000001226B cmp r9d, 10h ; InputBufferSize >= 0x10 ? .text:000000000001226F jb @@invalid_buffer_size .text:0000000000012275 mov ecx, [rbx] ; SystemBuffer[0] -> AffinityMask .text:0000000000012277 call SetThreadAffinityMask .text:000000000001227C cmp al, dil .text:000000000001227F jz @@unsuccessful .text:0000000000012285 mov rdx, [rbx+8] ; SystemBuffer[3] -> HighOrderMsr .text:0000000000012289 mov ecx, [rbx+4] ; SystemBuffer[1] -> Msr Number .text:000000000001228C mov eax, [rbx+8] ; SystemBuffer[2] -> LowOrderMsr .text:000000000001228F shr rdx, 20h .text:0000000000012293 wrmsr .text:0000000000012295 jmp @@complete_request

SiSoftware Sandra supports functionality that allows to unrestricted I/O access by supplying a specially crafted Irp to the IOCTL handler.

		
.text:00011258 ; int __stdcall ReadPort(int,int) .text:00011258 ReadPort proc near .text:00011258 .text:00011258 InputBuffer = dword ptr 8 .text:00011258 OutputBuffer = dword ptr 0Ch .text:00011258 .text:00011258 mov edi, edi .text:0001125A push ebp .text:0001125B mov ebp, esp .text:0001125D push esi .text:0001125E mov esi, [ebp+InputBuffer] .text:00011261 mov eax, [esi+8] ; InputBuffer[2] .text:00011264 sub eax, 0 .text:00011267 jz short @@read_port_uchar .text:00011269 dec eax .text:0001126A jz short @@read_port_ushort .text:0001126C dec eax .text:0001126D jz short @@read_port_ulong .text:0001126F dec eax .text:00011270 jnz short @@exit .text:00011272 push ebx .text:00011273 push edi .text:00011274 push dword ptr [esi] .text:00011276 mov edi, ds:READ_PORT_ULONG .text:0001127C call edi ; READ_PORT_ULONG .text:0001127E mov ebx, [ebp+OutputBuffer] .text:00011281 mov [ebx+10h], eax .text:00011284 mov eax, [esi] .text:00011286 add eax, 4 .text:00011289 push eax .text:0001128A call edi ; READ_PORT_ULONG .text:0001128C pop edi .text:0001128D mov [ebx+14h], eax .text:00011290 pop ebx .text:00011291 jmp short @@exit .text:00011293 .text:00011293 @@read_port_ulong: .text:00011293 push dword ptr [esi] .text:00011295 call ds:READ_PORT_ULONG .text:0001129B mov ecx, [ebp+OutputBuffer] .text:0001129E mov [ecx+10h], eax .text:000112A1 jmp short @@exit .text:000112A3 .text:000112A3 @@read_port_ushort: .text:000112A3 push dword ptr [esi] .text:000112A5 call ds:READ_PORT_USHORT .text:000112AB mov ecx, [ebp+OutputBuffer] .text:000112AE mov [ecx+10h], ax .text:000112B2 jmp short @@exit .text:000112B4 .text:000112B4 @@read_port_uchar: .text:000112B4 push dword ptr [esi] ; Port <- InputBuffer[0] .text:000112B6 call ds:READ_PORT_UCHAR .text:000112BC mov ecx, [ebp+OutputBuffer] .text:000112BF mov [ecx+10h], al ; OutputBuffer[4] <- Value .text:000112C2 .text:000112C2 @@exit: .text:000112C2 mov al, 1 .text:000112C4 pop esi .text:000112C5 pop ebp .text:000112C6 retn 8 .text:000112C6 ReadPort endp
.text:000112CE ; int __stdcall WritePort(int) .text:000112CE WritePort proc near .text:000112CE .text:000112CE SystemBuffer = dword ptr 8 .text:000112CE .text:000112CE mov edi, edi .text:000112D0 push ebp .text:000112D1 mov ebp, esp .text:000112D3 push esi .text:000112D4 mov esi, [ebp+SystemBuffer] .text:000112D7 mov eax, [esi+8] ; SystemBuffer[2] .text:000112DA sub eax, 0 .text:000112DD jz short @@write_port_uchar .text:000112DF dec eax .text:000112E0 jz short @@write_port_ushort .text:000112E2 dec eax .text:000112E3 jz short @@write_port_ulong .text:000112E5 dec eax .text:000112E6 jnz short @@exit .text:000112E8 push edi .text:000112E9 push dword ptr [esi+10h] .text:000112EC mov edi, ds:WRITE_PORT_ULONG .text:000112F2 push dword ptr [esi] .text:000112F4 call edi ; WRITE_PORT_ULONG .text:000112F6 mov eax, [esi] .text:000112F8 push dword ptr [esi+14h] .text:000112FB add eax, 4 .text:000112FE push eax .text:000112FF call edi ; WRITE_PORT_ULONG .text:00011301 pop edi .text:00011302 jmp short @@exit .text:00011304 .text:00011304 @@write_port_ulong: .text:00011304 push dword ptr [esi+10h] .text:00011307 push dword ptr [esi] .text:00011309 call ds:WRITE_PORT_ULONG .text:0001130F jmp short @@exit .text:00011311 .text:00011311 @@write_port_ushort: .text:00011311 movzx eax, word ptr [esi+10h] .text:00011315 push eax .text:00011316 push dword ptr [esi] .text:00011318 call ds:WRITE_PORT_USHORT .text:0001131E jmp short @@exit .text:00011320 .text:00011320 @@write_port_uchar: .text:00011320 movzx eax, byte ptr [esi+10h] .text:00011324 push eax ; Value <- SystemBuffer[4] .text:00011325 push dword ptr [esi] ; Port <- SystemBuffer[0] .text:00011327 call ds:WRITE_PORT_UCHAR .text:0001132D @@exit: .text:0001132D mov al, 1 .text:0001132F pop esi .text:00011330 pop ebp .text:00011331 retn 4 .text:00011331 WritePort endp

If user buffer is carefully crafted it is possible to overwrite an arbitrary memory location.

		
.text:00011E4A ; int __stdcall UnmapAndFree(int) .text:00011E4A UnmapAndFree proc near .text:00011E4A .text:00011E4A SystemBuffer = dword ptr 8 .text:00011E4A .text:00011E4A mov edi, edi .text:00011E4C push ebp .text:00011E4D mov ebp, esp .text:00011E4F push esi .text:00011E50 mov esi, [ebp+SystemBuffer] .text:00011E53 mov ecx, [esi+30h] ; SystemBuffer[12] .text:00011E56 test ecx, ecx .text:00011E58 jz short @@unmap_io_space .text:00011E5A mov eax, [esi+20h] ; SystemBuffer[8] .text:00011E5D test eax, eax .text:00011E5F jz short @@unmap_io_space .text:00011E61 push eax ; MemoryDescriptorList .text:00011E62 push ecx ; BaseAddress .text:00011E63 call ds:MmUnmapLockedPages .text:00011E69 push dword ptr [esi+20h] ; Mdl .text:00011E6C call ds:IoFreeMdl .text:00011E72 .text:00011E72 @@unmap_io_space: .text:00011E72 mov eax, [esi+28h] ; SystemBuffer[10] .text:00011E75 test eax, eax .text:00011E77 jz short @@exit .text:00011E79 push dword ptr [esi+10h] ; NumberOfBytes .text:00011E7C push eax ; BaseAddress .text:00011E7D call ds:MmUnmapIoSpace .text:00011E83 .text:00011E83 @@exit: .text:00011E83 mov al, 1 .text:00011E85 pop esi .text:00011E86 pop ebp .text:00011E87 retn 4 .text:00011E87 UnmapAndFree endp
Copyright © 2oo8-2oo9 NT Internals. All rights reserved.