Skip to content

Instantly share code, notes, and snippets.

@uf0o
Created March 26, 2021 14:00
Show Gist options
  • Save uf0o/c74adbc7f274014da9f1772b2a8b294b to your computer and use it in GitHub Desktop.
Save uf0o/c74adbc7f274014da9f1772b2a8b294b to your computer and use it in GitHub Desktop.
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