############################################################################################ ## ## Quick IOCTL Decoder! ## ## All credit for actual IOCTL decode logic: ## http://www.osronline.com/article.cfm?article=229 ## ## ## To install: ## Copy script into plugins directory, i.e: C:\Program Files\IDA 6.8\plugins ## ## To run: ## Highlight IOCTL then right click and select "Decode IOCTL" or press PLUGIN_HOTKEY ## The decoded IOCTL data will be added as a comment and displayed in the IDA cli ## ############################################################################################ __VERSION__ = '0.1' __AUTHOR__ = '@herrcore' PLUGIN_NAME = "Quick IOCTL Decoder" PLUGIN_HOTKEY = 'Ctrl-Alt-I' import idaapi class IOCTL_Decoder(): DEVICE = [None]*55 DEVICE[1]="BEEP" DEVICE[2]="CD_ROM" DEVICE[3]="CD_ROM_FILE_SYSTEM" DEVICE[4]="CONTROLLER" DEVICE[5]="DATALINK" DEVICE[6]="DFS" DEVICE[7]="DISK" DEVICE[8]="DISK_FILE_SYSTEM" DEVICE[9]="FILE_SYSTEM" DEVICE[10]="INPORT_PORT" DEVICE[11]="KEYBOARD" DEVICE[12]="MAILSLOT" DEVICE[13]="MIDI_IN" DEVICE[14]="MIDI_OUT" DEVICE[15]="MOUSE" DEVICE[16]="MULTI_UNC_PROVIDER" DEVICE[17]="NAMED_PIPE" DEVICE[18]="NETWORK" DEVICE[19]="NETWORK_BROWSER" DEVICE[20]="NETWORK_FILE_SYSTEM" DEVICE[21]="NULL" DEVICE[22]="PARALLEL_PORT" DEVICE[23]="PHYSICAL_NETCARD" DEVICE[24]="PRINTER" DEVICE[25]="SCANNER" DEVICE[26]="SERIAL_MOUSE_PORT" DEVICE[27]="SERIAL_PORT" DEVICE[28]="SCREEN" DEVICE[29]="SOUND" DEVICE[30]="STREAMS" DEVICE[31]="TAPE" DEVICE[32]="TAPE_FILE_SYSTEM" DEVICE[33]="TRANSPORT" DEVICE[34]="UNKNOWN" DEVICE[35]="VIDEO" DEVICE[36]="VIRTUAL_DISK" DEVICE[37]="WAVE_IN" DEVICE[38]="WAVE_OUT" DEVICE[39]="8042_PORT" DEVICE[40]="NETWORK_REDIRECTOR" DEVICE[41]="BATTERY" DEVICE[42]="BUS_EXTENDER" DEVICE[43]="MODEM" DEVICE[44]="VDM" DEVICE[45]="MASS_STORAGE" DEVICE[46]="SMB" DEVICE[47]="KS" DEVICE[48]="CHANGER" DEVICE[49]="SMARTCARD" DEVICE[50]="ACPI" DEVICE[51]="DVD" DEVICE[52]="FULLSCREEN_VIDEO" DEVICE[53]="DFS_FILE_SYSTEM" DEVICE[54]="DFS_VOLUME" def __init__(self, control_code): self.control_code = control_code def decode(self): out={} device_val = (self.control_code >> 16) & 0xFFF funcVal = (self.control_code >> 2) & 0xFFF if (device_val <= 54) and (device_val != 0): device_string = self.DEVICE[device_val]+ " ("+hex(device_val)+")" else: device_string = hex(device_val) function_string = hex(funcVal) out["device"] = device_string out["function"] = function_string access = (self.control_code >> 14) & 3 method = self.control_code & 3 access_string = "" if access == 0: access_string = "FILE_ANY_ACCESS" elif access == 1: access_string = "FILE_READ_ACCESS" elif access == 2: access_string = "FILE_WRITE_ACCESS" elif access == 3: access_string = "Read and Write" method_string = "" if method == 0: method_string = "METHOD_BUFFERED" elif method == 1: method_string = "METHOD_IN_DIRECT" elif method == 2: method_string = "METHOD_OUT_DIRECT" elif method == 3: method_string = "METHOD_NEITHER" out["access"] = access_string out["method"] = method_string return out class IDAIOCTLDecoder(): @staticmethod def decode(): ea = ScreenEA() if ea == idaapi.BADADDR: idaapi.msg(PLUGIN_NAME + " ERROR: Could not get get_screen_ea()") return str_id = idaapi.get_highlighted_identifier() if not str_id: idaapi.msg(PLUGIN_NAME + " ERROR: No Ioctl Code highlighted!") return try: if str_id[-1] == 'h': code = int(str_id[:-1], 16) elif str_id[-1] == 'o': code = int(str_id[:-1], 8) elif str_id[-1] == 'b': code = int(str_id[:-1], 2) else: code = int(str_id) except ValueError: idaapi.msg(PLUGIN_NAME + " ERROR: Not a valid Ioctl Code: " + str(str_id)) return try: decoder = IOCTL_Decoder(code) ioctl_data = decoder.decode() #print decoded IOCTL to cli msg_string = "That IOCTL decodes to: \n\tDevice: %s \n\tFunction: %s \n\tAccess: %s \n\tMethod: %s" idaapi.msg(msg_string % (ioctl_data["device"], ioctl_data["function"], ioctl_data["access"], ioctl_data["method"])) #add decoded IOCTL as comment comment_string = "dwIoControlCode: \n\t\tDevice: %s \n\t\tFunction: %s \n\t\tAccess: %s \n\t\tMethod: %s" idaapi.set_cmt(ea, comment_string % (ioctl_data["device"], ioctl_data["function"], ioctl_data["access"], ioctl_data["method"]), 0) except Exception as e: idaapi.msg(PLUGIN_NAME + " ERROR: " + str(e)) return class IOCTLDecodeHandler(idaapi.action_handler_t): def activate(self, ctx): IDAIOCTLDecoder.decode() def update(self, ctx): return idaapi.AST_ENABLE_ALWAYS class QuickIOCTLDecoderHooks(idaapi.UI_Hooks): def finish_populating_tform_popup(self, form, popup): tft = idaapi.get_tform_type(form) if tft == idaapi.BWN_DISASM: # Note the 'None' as action name (1st parameter). # That's because the action will be deleted immediately # after the context menu is hidden anyway, so there's # really no need giving it a valid ID. desc = idaapi.action_desc_t(None, 'Decode IOCTL', IOCTLDecodeHandler()) idaapi.attach_dynamic_action_to_popup(form, popup, desc, None) class QuickIOCTLDecoder(idaapi.plugin_t): flags = idaapi.PLUGIN_UNL comment = "Decode IOCTL codes!" help = "Highlight IOCTL and right-click 'Decode IOCTL'" wanted_name = PLUGIN_NAME wanted_hotkey = PLUGIN_HOTKEY def init(self): idaapi.msg("Initializing: %s\n" % PLUGIN_NAME) global hooks hooks = QuickIOCTLDecoderHooks() re = hooks.hook() return idaapi.PLUGIN_OK def run(self, arg): IDAIOCTLDecoder.decode() pass def term(self): pass def PLUGIN_ENTRY(): return QuickIOCTLDecoder()