Skip to content

Instantly share code, notes, and snippets.

@fuzzamos
Forked from herrcore/quick_ioctl_decoder.py
Created July 12, 2019 18:21
Show Gist options
  • Save fuzzamos/139f187e201574c858bde27dbf0c8ba7 to your computer and use it in GitHub Desktop.
Save fuzzamos/139f187e201574c858bde27dbf0c8ba7 to your computer and use it in GitHub Desktop.

Revisions

  1. @herrcore herrcore created this gist Aug 14, 2016.
    211 changes: 211 additions & 0 deletions quick_ioctl_decoder.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,211 @@
    ############################################################################################
    ##
    ## 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()