|
| 1 | +// C/C++ standard headers |
| 2 | +// Other external headers |
| 3 | +#pragma warning(push, 0) |
| 4 | +#include <hexrays.hpp> |
| 5 | +#pragma warning(pop) |
| 6 | + |
| 7 | + |
| 8 | +// Windows headers |
| 9 | +// Original headers |
| 10 | + |
| 11 | + |
| 12 | +//////////////////////////////////////////////////////////////////////////////// |
| 13 | +// |
| 14 | +// macro utilities |
| 15 | +// |
| 16 | + |
| 17 | + |
| 18 | +//////////////////////////////////////////////////////////////////////////////// |
| 19 | +// |
| 20 | +// constants and macros |
| 21 | +// |
| 22 | + |
| 23 | +static const char COMMENT[] = |
| 24 | + "Decodes Windows Device I/O control code into " |
| 25 | + "DeviceType, FunctionCode, AccessType and MethodType."; |
| 26 | + |
| 27 | + |
| 28 | +//////////////////////////////////////////////////////////////////////////////// |
| 29 | +// |
| 30 | +// types |
| 31 | +// |
| 32 | + |
| 33 | + |
| 34 | +//////////////////////////////////////////////////////////////////////////////// |
| 35 | +// |
| 36 | +// prototypes |
| 37 | +// |
| 38 | + |
| 39 | +int idaapi plugin_init(); |
| 40 | + |
| 41 | +void idaapi plugin_term(); |
| 42 | + |
| 43 | +void idaapi plugin_run( |
| 44 | + int arg); |
| 45 | + |
| 46 | +int idaapi plugin_callback( |
| 47 | + void* ud, |
| 48 | + hexrays_event_t event, |
| 49 | + va_list va); |
| 50 | + |
| 51 | +bool idaapi plugin_on_decode_code( |
| 52 | + void *ud); |
| 53 | + |
| 54 | +void decode( |
| 55 | + uint32 ioctl_code); |
| 56 | + |
| 57 | + |
| 58 | +//////////////////////////////////////////////////////////////////////////////// |
| 59 | +// |
| 60 | +// variables |
| 61 | +// |
| 62 | + |
| 63 | +hexdsp_t *hexdsp = nullptr; // Hex-Rays API pointer |
| 64 | +plugin_t PLUGIN = |
| 65 | +{ |
| 66 | + IDP_INTERFACE_VERSION, |
| 67 | + PLUGIN_HIDE, // plugin flags |
| 68 | + plugin_init, // initialize |
| 69 | + plugin_term, // terminate. this pointer may be nullptr. |
| 70 | + plugin_run, // invoke plugin |
| 71 | + COMMENT, // long comment about the plugin |
| 72 | + // it could appear in the status line or as a hint |
| 73 | + "", // multiline help about the plugin |
| 74 | + "Windows IOCTL code decoder", // the preferred short name of the plugin |
| 75 | + "" // the preferred hotkey to run the plugin |
| 76 | +}; |
| 77 | + |
| 78 | + |
| 79 | +static bool g_plugin_initialized = false; |
| 80 | + |
| 81 | + |
| 82 | +//////////////////////////////////////////////////////////////////////////////// |
| 83 | +// |
| 84 | +// implementations |
| 85 | +// |
| 86 | + |
| 87 | +// Initialization handler called when the decompiler starts |
| 88 | +int idaapi plugin_init() |
| 89 | +{ |
| 90 | + if (!init_hexrays_plugin()) |
| 91 | + { |
| 92 | + return PLUGIN_SKIP; // no decompiler |
| 93 | + } |
| 94 | + |
| 95 | + if (!install_hexrays_callback(plugin_callback, nullptr)) |
| 96 | + { |
| 97 | + return PLUGIN_SKIP; |
| 98 | + } |
| 99 | + |
| 100 | + msg("%s ready to use.\n", PLUGIN.wanted_name); |
| 101 | + g_plugin_initialized = true; |
| 102 | + return PLUGIN_KEEP; |
| 103 | +} |
| 104 | + |
| 105 | + |
| 106 | +// Termination handler |
| 107 | +void idaapi plugin_term() |
| 108 | +{ |
| 109 | + if (!g_plugin_initialized) |
| 110 | + { |
| 111 | + return; |
| 112 | + } |
| 113 | + |
| 114 | + remove_hexrays_callback(plugin_callback, nullptr); |
| 115 | + term_hexrays_plugin(); |
| 116 | + g_plugin_initialized = false; |
| 117 | +} |
| 118 | + |
| 119 | + |
| 120 | +// The handler invoked via Edit/Plugins/* or Hot-key |
| 121 | +void idaapi plugin_run( |
| 122 | + int /*arg*/) |
| 123 | +{ |
| 124 | + // Never called because this plugin is markded as PLUGIN_HIDE, |
| 125 | + // and has no hot-key registration. |
| 126 | +} |
| 127 | + |
| 128 | + |
| 129 | +int idaapi plugin_callback( |
| 130 | + void* /*ud*/, |
| 131 | + hexrays_event_t event, |
| 132 | + va_list va) |
| 133 | +{ |
| 134 | + switch (event) |
| 135 | + { |
| 136 | + case hxe_right_click: |
| 137 | + { |
| 138 | + // If the current item is non zero const, then add the menu item |
| 139 | + auto window = va_arg(va, vdui_t*); |
| 140 | + if (window->item.is_citem() |
| 141 | + && window->item.e->is_non_zero_const()) |
| 142 | + { |
| 143 | + add_custom_viewer_popup_item( |
| 144 | + window->ct, |
| 145 | + "Decode as an IOCTL code", |
| 146 | + "", |
| 147 | + plugin_on_decode_code, |
| 148 | + window); |
| 149 | + } |
| 150 | + } |
| 151 | + break; |
| 152 | + |
| 153 | + default: |
| 154 | + break; |
| 155 | + } |
| 156 | + return 0; |
| 157 | +} |
| 158 | + |
| 159 | + |
| 160 | +bool idaapi plugin_on_decode_code( |
| 161 | + void *ud) |
| 162 | +{ |
| 163 | + const auto window = static_cast<vdui_t*>(ud); |
| 164 | + const auto number_obj = window->get_number(); |
| 165 | + if (!number_obj) |
| 166 | + { |
| 167 | + return true; |
| 168 | + } |
| 169 | + // It is not IOCTL code if it is larger than the max 32bit value. |
| 170 | + if (number_obj->_value > std::numeric_limits<uint32>::max()) |
| 171 | + { |
| 172 | + return true; |
| 173 | + } |
| 174 | + decode(static_cast<uint32>(number_obj->_value)); |
| 175 | + return true; |
| 176 | +} |
| 177 | + |
| 178 | + |
| 179 | +// Decodes IOCTL code and prints it. |
| 180 | +void decode( |
| 181 | + uint32 ioctl_code) |
| 182 | +{ |
| 183 | + const char* ACCESS_NAMES[] = |
| 184 | + { |
| 185 | + "FILE_ANY_ACCESS", |
| 186 | + "FILE_READ_ACCESS", |
| 187 | + "FILE_WRITE_ACCESS", |
| 188 | + "FILE_READ_ACCESS | FILE_WRITE_ACCESS", |
| 189 | + }; |
| 190 | + const char* METHOD_NAMES[] = |
| 191 | + { |
| 192 | + "METHOD_BUFFERED", |
| 193 | + "METHOD_IN_DIRECT", |
| 194 | + "METHOD_OUT_DIRECT", |
| 195 | + "METHOD_NEITHER", |
| 196 | + }; |
| 197 | + const char DEVICE_NAME_UNKNOWN[] = "<UNKNOWN>"; |
| 198 | + const char* DEVICE_NAMES[] = |
| 199 | + { |
| 200 | + DEVICE_NAME_UNKNOWN, // 0x00000000 |
| 201 | + "FILE_DEVICE_BEEP", // 0x00000001 |
| 202 | + "FILE_DEVICE_CD_ROM", // 0x00000002 |
| 203 | + "FILE_DEVICE_CD_ROM_FILE_SYSTEM", // 0x00000003 |
| 204 | + "FILE_DEVICE_CONTROLLER", // 0x00000004 |
| 205 | + "FILE_DEVICE_DATALINK", // 0x00000005 |
| 206 | + "FILE_DEVICE_DFS", // 0x00000006 |
| 207 | + "FILE_DEVICE_DISK", // 0x00000007 |
| 208 | + "FILE_DEVICE_DISK_FILE_SYSTEM", // 0x00000008 |
| 209 | + "FILE_DEVICE_FILE_SYSTEM", // 0x00000009 |
| 210 | + "FILE_DEVICE_INPORT_PORT", // 0x0000000a |
| 211 | + "FILE_DEVICE_KEYBOARD", // 0x0000000b |
| 212 | + "FILE_DEVICE_MAILSLOT", // 0x0000000c |
| 213 | + "FILE_DEVICE_MIDI_IN", // 0x0000000d |
| 214 | + "FILE_DEVICE_MIDI_OUT", // 0x0000000e |
| 215 | + "FILE_DEVICE_MOUSE", // 0x0000000f |
| 216 | + "FILE_DEVICE_MULTI_UNC_PROVIDER", // 0x00000010 |
| 217 | + "FILE_DEVICE_NAMED_PIPE", // 0x00000011 |
| 218 | + "FILE_DEVICE_NETWORK", // 0x00000012 |
| 219 | + "FILE_DEVICE_NETWORK_BROWSER", // 0x00000013 |
| 220 | + "FILE_DEVICE_NETWORK_FILE_SYSTEM", // 0x00000014 |
| 221 | + "FILE_DEVICE_NULL", // 0x00000015 |
| 222 | + "FILE_DEVICE_PARALLEL_PORT", // 0x00000016 |
| 223 | + "FILE_DEVICE_PHYSICAL_NETCARD", // 0x00000017 |
| 224 | + "FILE_DEVICE_PRINTER", // 0x00000018 |
| 225 | + "FILE_DEVICE_SCANNER", // 0x00000019 |
| 226 | + "FILE_DEVICE_SERIAL_MOUSE_PORT", // 0x0000001a |
| 227 | + "FILE_DEVICE_SERIAL_PORT", // 0x0000001b |
| 228 | + "FILE_DEVICE_SCREEN", // 0x0000001c |
| 229 | + "FILE_DEVICE_SOUND", // 0x0000001d |
| 230 | + "FILE_DEVICE_STREAMS", // 0x0000001e |
| 231 | + "FILE_DEVICE_TAPE", // 0x0000001f |
| 232 | + "FILE_DEVICE_TAPE_FILE_SYSTEM", // 0x00000020 |
| 233 | + "FILE_DEVICE_TRANSPORT", // 0x00000021 |
| 234 | + "FILE_DEVICE_UNKNOWN", // 0x00000022 |
| 235 | + "FILE_DEVICE_VIDEO", // 0x00000023 |
| 236 | + "FILE_DEVICE_VIRTUAL_DISK", // 0x00000024 |
| 237 | + "FILE_DEVICE_WAVE_IN", // 0x00000025 |
| 238 | + "FILE_DEVICE_WAVE_OUT", // 0x00000026 |
| 239 | + "FILE_DEVICE_8042_PORT", // 0x00000027 |
| 240 | + "FILE_DEVICE_NETWORK_REDIRECTOR", // 0x00000028 |
| 241 | + "FILE_DEVICE_BATTERY", // 0x00000029 |
| 242 | + "FILE_DEVICE_BUS_EXTENDER", // 0x0000002a |
| 243 | + "FILE_DEVICE_MODEM", // 0x0000002b |
| 244 | + "FILE_DEVICE_VDM", // 0x0000002c |
| 245 | + "FILE_DEVICE_MASS_STORAGE", // 0x0000002d |
| 246 | + "FILE_DEVICE_SMB", // 0x0000002e |
| 247 | + "FILE_DEVICE_KS", // 0x0000002f |
| 248 | + "FILE_DEVICE_CHANGER", // 0x00000030 |
| 249 | + "FILE_DEVICE_SMARTCARD", // 0x00000031 |
| 250 | + "FILE_DEVICE_ACPI", // 0x00000032 |
| 251 | + "FILE_DEVICE_DVD", // 0x00000033 |
| 252 | + "FILE_DEVICE_FULLSCREEN_VIDEO", // 0x00000034 |
| 253 | + "FILE_DEVICE_DFS_FILE_SYSTEM", // 0x00000035 |
| 254 | + "FILE_DEVICE_DFS_VOLUME", // 0x00000036 |
| 255 | + "FILE_DEVICE_SERENUM", // 0x00000037 |
| 256 | + "FILE_DEVICE_TERMSRV", // 0x00000038 |
| 257 | + "FILE_DEVICE_KSEC", // 0x00000039 |
| 258 | + "FILE_DEVICE_FIPS", // 0x0000003A |
| 259 | + "FILE_DEVICE_INFINIBAND", // 0x0000003B |
| 260 | + DEVICE_NAME_UNKNOWN, // 0x0000003C |
| 261 | + DEVICE_NAME_UNKNOWN, // 0x0000003D |
| 262 | + "FILE_DEVICE_VMBUS", // 0x0000003E |
| 263 | + "FILE_DEVICE_CRYPT_PROVIDER", // 0x0000003F |
| 264 | + "FILE_DEVICE_WPD", // 0x00000040 |
| 265 | + "FILE_DEVICE_BLUETOOTH", // 0x00000041 |
| 266 | + "FILE_DEVICE_MT_COMPOSITE", // 0x00000042 |
| 267 | + "FILE_DEVICE_MT_TRANSPORT", // 0x00000043 |
| 268 | + "FILE_DEVICE_BIOMETRIC", // 0x00000044 |
| 269 | + "FILE_DEVICE_PMI", // 0x00000045 |
| 270 | + }; |
| 271 | + |
| 272 | + const auto device = (ioctl_code >> 16) & 0xffff; |
| 273 | + const auto access = (ioctl_code >> 14) & 3; |
| 274 | + const auto function = (ioctl_code >> 2) & 0xfff; |
| 275 | + const auto method = ioctl_code & 3; |
| 276 | + |
| 277 | + const char* device_name = nullptr; |
| 278 | + if (device >= _countof(DEVICE_NAMES)) |
| 279 | + { |
| 280 | + device_name = DEVICE_NAME_UNKNOWN; |
| 281 | + } |
| 282 | + else |
| 283 | + { |
| 284 | + device_name = DEVICE_NAMES[device]; |
| 285 | + } |
| 286 | + |
| 287 | + msg("Code = 0x%08X\n", ioctl_code); |
| 288 | + msg("Device : %s (0x%X)\n", device_name, device); |
| 289 | + msg("Function : 0x%X\n", function); |
| 290 | + msg("Method : %s (%d)\n", METHOD_NAMES[method], method); |
| 291 | + msg("Access : %s (%d)\n", ACCESS_NAMES[access], access); |
| 292 | +} |
| 293 | + |
0 commit comments