Created
March 26, 2021 14:00
-
-
Save uf0o/c74adbc7f274014da9f1772b2a8b294b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import sys | |
def auto_int(x): | |
return int(x, 0) | |
# Modded by Matteo 'uf0' Malvica - 2021 | |
# The following code is taken from | |
# https://github.com/mwrlabs/win_driver_plugin/blob/master/win_driver_plugin/ioctl_decoder.py | |
# which in turn used the code from | |
# https://github.com/tandasat/WinIoCtlDecoder/blob/master/plugins/WinIoCtlDecoder.py | |
def error(): | |
print("[!] Error while Encoding...") | |
parser.print_help() | |
sys.exit() | |
def get_device(ioctl_code): | |
""" | |
Returns the correct device name for a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
device_name_unknown = '<UNKNOWN>' | |
device_names = [ | |
device_name_unknown, # 0x00000000 | |
'FILE_DEVICE_BEEP', # 0x00000001 | |
'FILE_DEVICE_CD_ROM', # 0x00000002 | |
'FILE_DEVICE_CD_ROM_FILE_SYSTEM', # 0x00000003 | |
'FILE_DEVICE_CONTROLLER', # 0x00000004 | |
'FILE_DEVICE_DATALINK', # 0x00000005 | |
'FILE_DEVICE_DFS', # 0x00000006 | |
'FILE_DEVICE_DISK', # 0x00000007 | |
'FILE_DEVICE_DISK_FILE_SYSTEM', # 0x00000008 | |
'FILE_DEVICE_FILE_SYSTEM', # 0x00000009 | |
'FILE_DEVICE_INPORT_PORT', # 0x0000000a | |
'FILE_DEVICE_KEYBOARD', # 0x0000000b | |
'FILE_DEVICE_MAILSLOT', # 0x0000000c | |
'FILE_DEVICE_MIDI_IN', # 0x0000000d | |
'FILE_DEVICE_MIDI_OUT', # 0x0000000e | |
'FILE_DEVICE_MOUSE', # 0x0000000f | |
'FILE_DEVICE_MULTI_UNC_PROVIDER', # 0x00000010 | |
'FILE_DEVICE_NAMED_PIPE', # 0x00000011 | |
'FILE_DEVICE_NETWORK', # 0x00000012 | |
'FILE_DEVICE_NETWORK_BROWSER', # 0x00000013 | |
'FILE_DEVICE_NETWORK_FILE_SYSTEM', # 0x00000014 | |
'FILE_DEVICE_NULL', # 0x00000015 | |
'FILE_DEVICE_PARALLEL_PORT', # 0x00000016 | |
'FILE_DEVICE_PHYSICAL_NETCARD', # 0x00000017 | |
'FILE_DEVICE_PRINTER', # 0x00000018 | |
'FILE_DEVICE_SCANNER', # 0x00000019 | |
'FILE_DEVICE_SERIAL_MOUSE_PORT', # 0x0000001a | |
'FILE_DEVICE_SERIAL_PORT', # 0x0000001b | |
'FILE_DEVICE_SCREEN', # 0x0000001c | |
'FILE_DEVICE_SOUND', # 0x0000001d | |
'FILE_DEVICE_STREAMS', # 0x0000001e | |
'FILE_DEVICE_TAPE', # 0x0000001f | |
'FILE_DEVICE_TAPE_FILE_SYSTEM', # 0x00000020 | |
'FILE_DEVICE_TRANSPORT', # 0x00000021 | |
'FILE_DEVICE_UNKNOWN', # 0x00000022 | |
'FILE_DEVICE_VIDEO', # 0x00000023 | |
'FILE_DEVICE_VIRTUAL_DISK', # 0x00000024 | |
'FILE_DEVICE_WAVE_IN', # 0x00000025 | |
'FILE_DEVICE_WAVE_OUT', # 0x00000026 | |
'FILE_DEVICE_8042_PORT', # 0x00000027 | |
'FILE_DEVICE_NETWORK_REDIRECTOR', # 0x00000028 | |
'FILE_DEVICE_BATTERY', # 0x00000029 | |
'FILE_DEVICE_BUS_EXTENDER', # 0x0000002a | |
'FILE_DEVICE_MODEM', # 0x0000002b | |
'FILE_DEVICE_VDM', # 0x0000002c | |
'FILE_DEVICE_MASS_STORAGE', # 0x0000002d | |
'FILE_DEVICE_SMB', # 0x0000002e | |
'FILE_DEVICE_KS', # 0x0000002f | |
'FILE_DEVICE_CHANGER', # 0x00000030 | |
'FILE_DEVICE_SMARTCARD', # 0x00000031 | |
'FILE_DEVICE_ACPI', # 0x00000032 | |
'FILE_DEVICE_DVD', # 0x00000033 | |
'FILE_DEVICE_FULLSCREEN_VIDEO', # 0x00000034 | |
'FILE_DEVICE_DFS_FILE_SYSTEM', # 0x00000035 | |
'FILE_DEVICE_DFS_VOLUME', # 0x00000036 | |
'FILE_DEVICE_SERENUM', # 0x00000037 | |
'FILE_DEVICE_TERMSRV', # 0x00000038 | |
'FILE_DEVICE_KSEC', # 0x00000039 | |
'FILE_DEVICE_FIPS', # 0x0000003A | |
'FILE_DEVICE_INFINIBAND', # 0x0000003B | |
device_name_unknown, # 0x0000003C | |
device_name_unknown, # 0x0000003D | |
'FILE_DEVICE_VMBUS', # 0x0000003E | |
'FILE_DEVICE_CRYPT_PROVIDER', # 0x0000003F | |
'FILE_DEVICE_WPD', # 0x00000040 | |
'FILE_DEVICE_BLUETOOTH', # 0x00000041 | |
'FILE_DEVICE_MT_COMPOSITE', # 0x00000042 | |
'FILE_DEVICE_MT_TRANSPORT', # 0x00000043 | |
'FILE_DEVICE_BIOMETRIC', # 0x00000044 | |
'FILE_DEVICE_PMI', # 0x00000045 | |
] | |
device_names2 = [ | |
{'name': 'MOUNTMGRCONTROLTYPE', 'code': 0x0000006d}, | |
] | |
device = (ioctl_code >> 16) & 0xffff | |
if device >= len(device_names): | |
device_name = device_name_unknown | |
for dev in device_names2: | |
if device == dev['code']: | |
device_name = dev['name'] | |
break | |
else: | |
device_name = device_names[device] | |
return device_name, device | |
def get_device_encode(ioctl_code): | |
device_types = {'FILE_DEVICE_8042_PORT':0x00000027, | |
'FILE_DEVICE_ACPI':0x00000032, | |
'FILE_DEVICE_BATTERY':0x00000029, | |
'FILE_DEVICE_BEEP':0x00000001, | |
'FILE_DEVICE_BUS_EXTENDER':0x0000002a, | |
'FILE_DEVICE_CD_ROM':0x00000002, | |
'FILE_DEVICE_CD_ROM_FILE_SYSTEM':0x00000003, | |
'FILE_DEVICE_CHANGER':0x00000030, | |
'FILE_DEVICE_CONTROLLER':0x00000004, | |
'FILE_DEVICE_DATALINK':0x00000005, | |
'FILE_DEVICE_DFS':0x00000006, | |
'FILE_DEVICE_DFS_FILE_SYSTEM':0x00000035, | |
'FILE_DEVICE_DFS_VOLUME':0x00000036, | |
'FILE_DEVICE_DISK':0x00000007, | |
'FILE_DEVICE_DISK_FILE_SYSTEM':0x00000008, | |
'FILE_DEVICE_DVD':0x00000033, | |
'FILE_DEVICE_FILE_SYSTEM':0x00000009, | |
'FILE_DEVICE_FIPS':0x0000003a, | |
'FILE_DEVICE_FULLSCREEN_VIDEO':0x00000034, | |
'FILE_DEVICE_INPORT_PORT':0x0000000a, | |
'FILE_DEVICE_KEYBOARD':0x0000000b, | |
'FILE_DEVICE_KS':0x0000002f, | |
'FILE_DEVICE_KSEC':0x00000039, | |
'FILE_DEVICE_MAILSLOT':0x0000000c, | |
'FILE_DEVICE_MASS_STORAGE':0x0000002d, | |
'FILE_DEVICE_MIDI_IN':0x0000000d, | |
'FILE_DEVICE_MIDI_OUT':0x0000000e, | |
'FILE_DEVICE_MODEM':0x0000002b, | |
'FILE_DEVICE_MOUSE':0x0000000f, | |
'FILE_DEVICE_MULTI_UNC_PROVIDER':0x00000010, | |
'FILE_DEVICE_NAMED_PIPE':0x00000011, | |
'FILE_DEVICE_NETWORK':0x00000012, | |
'FILE_DEVICE_NETWORK_BROWSER':0x00000013, | |
'FILE_DEVICE_NETWORK_FILE_SYSTEM':0x00000014, | |
'FILE_DEVICE_NETWORK_REDIRECTOR':0x00000028, | |
'FILE_DEVICE_NULL':0x00000015, | |
'FILE_DEVICE_PARALLEL_PORT':0x00000016, | |
'FILE_DEVICE_PHYSICAL_NETCARD':0x00000017, | |
'FILE_DEVICE_PRINTER':0x00000018, | |
'FILE_DEVICE_SCANNER':0x00000019, | |
'FILE_DEVICE_SCREEN':0x0000001c, | |
'FILE_DEVICE_SERENUM':0x00000037, | |
'FILE_DEVICE_SERIAL_MOUSE_PORT':0x0000001a, | |
'FILE_DEVICE_SERIAL_PORT':0x0000001b, | |
'FILE_DEVICE_SMARTCARD':0x00000031, | |
'FILE_DEVICE_SMB':0x0000002e, | |
'FILE_DEVICE_SOUND':0x0000001d, | |
'FILE_DEVICE_STREAMS':0x0000001e, | |
'FILE_DEVICE_TAPE':0x0000001f, | |
'FILE_DEVICE_TAPE_FILE_SYSTEM':0x00000020, | |
'FILE_DEVICE_TERMSRV':0x00000038, | |
'FILE_DEVICE_TRANSPORT':0x00000021, | |
'FILE_DEVICE_UNKNOWN':0x00000022, | |
'FILE_DEVICE_VDM':0x0000002c, | |
'FILE_DEVICE_VIDEO':0x00000023, | |
'FILE_DEVICE_VIRTUAL_DISK':0x00000024, | |
'FILE_DEVICE_WAVE_IN':0x00000025, | |
'FILE_DEVICE_WAVE_OUT':0x00000026} | |
for k,v in device_types.items(): | |
if k == ioctl_code: | |
device_name = v | |
return device_name | |
def get_method(ioctl_code): | |
""" | |
Returns the correct method type name for a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
method_names = [ | |
'METHOD_BUFFERED', | |
'METHOD_IN_DIRECT', | |
'METHOD_OUT_DIRECT', | |
'METHOD_NEITHER', | |
] | |
method = ioctl_code & 3 | |
return method_names[method], method | |
def get_method_encode(ioctl_code): | |
""" | |
Returns the correct method type name for a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
method_names = [ | |
'METHOD_BUFFERED', | |
'METHOD_IN_DIRECT', | |
'METHOD_OUT_DIRECT', | |
'METHOD_NEITHER', | |
] | |
for i,method in enumerate(method_names): | |
if ioctl_code in method: | |
return i | |
def get_access(ioctl_code): | |
""" | |
Returns the correct access type name for a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
access_names = [ | |
'FILE_ANY_ACCESS', | |
'FILE_READ_ACCESS', | |
'FILE_WRITE_ACCESS', | |
'FILE_READ_ACCESS | FILE_WRITE_ACCESS', | |
] | |
access = (ioctl_code >> 14) & 3 | |
return access_names[access], access | |
def get_access_encode(ioctl_code): | |
""" | |
Returns the correct access type name for a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
access_names = [ | |
'FILE_ANY_ACCESS', | |
'FILE_READ_ACCESS', | |
'FILE_WRITE_ACCESS', | |
'FILE_READ_ACCESS | FILE_WRITE_ACCESS', | |
] | |
access_encoded = 0 | |
for i,access in enumerate(access_names): | |
if ioctl_code == access: | |
access_encoded = i | |
if not access_encoded: | |
error() | |
return access_encoded | |
def get_function(ioctl_code): | |
""" | |
Calculates the function code from a 32 bit IOCTL code | |
:param ioctl_code: ioctl code | |
""" | |
return (ioctl_code >> 2) & 0xfff | |
def get_function_encode(ioctl_code): | |
function_encode = int(ioctl_code,16) | |
return function_encode | |
def get_define_decode(ioctl_code): | |
""" | |
Decodes an ioctl code and returns a C define for it using the CTL_CODE macro | |
:param ioctl_code: ioctl code | |
""" | |
function = get_function(ioctl_code) | |
device_name, device_code = get_device(ioctl_code) | |
method_name, method_code = get_method(ioctl_code) | |
access_name, access_code = get_access(ioctl_code) | |
return "IOCTL: 0x%X -> CTL_CODE(%s, 0x%X, %s, %s)" % (ioctl_code, device_name, function, method_name, access_name) | |
def get_define_encode(ioctl_code): | |
""" | |
Decodes an ioctl code and returns a C define for it using the CTL_CODE macro | |
:param ioctl_code: ioctl code | |
""" | |
device_name= (ioctl_code.split(',')[0]).split('(')[1].strip(' ') | |
function_name = ioctl_code.split(',')[1].strip(' ') | |
method_name = ioctl_code.split(',')[2].strip(' ') | |
access_name = ioctl_code.split(',')[3].strip(' ').strip(')').rstrip('\x00').rstrip('\x20') | |
method = get_method_encode(method_name) | |
function = get_function_encode(function_name) << 2 | |
access = get_access_encode(access_name) << 14 | |
device = get_device_encode(device_name) << 16 | |
result = device + access + function + method | |
return "IOCTL: 0x%x" % (result) | |
if __name__ == "__main__": | |
example_text = '''Example: | |
python ioctltranslator.py -d 0x124004 | |
python ioctltranslator.py -e "CTL_CODE(FILE_DEVICE_NETWORK, 0x1, METHOD_BUFFERED, FILE_READ_ACCESS)" | |
''' | |
parser = argparse.ArgumentParser(description="IOCTL decoder - Provide either a flag '-e' for encoding or '-d' for decoding the IOCTL",epilog=example_text, | |
formatter_class=argparse.RawDescriptionHelpFormatter) | |
parser.add_argument( | |
"-i", "--ioctl", help="IOCTL value", action="store", type=auto_int, required=False | |
) | |
group = parser.add_mutually_exclusive_group() | |
group.add_argument('-e','--encode', type=str, help="encode IOCTL") | |
group.add_argument('-d','--decode', type=auto_int, help="decode IOCTL") | |
args = parser.parse_args() | |
encoded_ioctl = args.decode | |
decoded_ioctl = args.encode | |
if len(sys.argv) < 3: | |
parser.print_help() | |
sys.exit() | |
if args.decode: | |
print(get_define_decode(encoded_ioctl)) | |
if args.encode: | |
try: | |
print(get_define_encode(decoded_ioctl)) | |
except IndexError: | |
print("[!] Wrong IOCTL Format\n") | |
parser.print_help() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment