package extract import "fmt" // An IOCTL code is a 32-bit value laid out by the CTL_CODE macro: // // (DeviceType << 16) | (Access << 14) | (Function << 2) | Method // // Bits 0-1 are the transfer method, bits 2-13 the function code, bits 14-15 // the access, and bits 16-31 the device type. // IoctlCode is a decoded IOCTL control code. type IoctlCode struct { Code uint32 DeviceType uint16 Function uint16 Method uint8 Access uint8 Confidence string // "high", "medium", or "low" Source string // "disasm" or "data" RVA uint32 // where the value was found (0 if unknown) Note string // optional annotation (e.g. "ambiguous: NTSTATUS range") } // DecodeIoctl splits a raw 32-bit value into its CTL_CODE components. func DecodeIoctl(code uint32) (deviceType uint16, function uint16, method, access uint8) { method = uint8(code & 0x3) function = uint16((code >> 2) & 0xFFF) access = uint8((code >> 14) & 0x3) deviceType = uint16((code >> 16) & 0xFFFF) return } // MethodName returns the human-readable name for a transfer method. func MethodName(m uint8) string { switch m { case 0: return "METHOD_BUFFERED" case 1: return "METHOD_IN_DIRECT" case 2: return "METHOD_OUT_DIRECT" case 3: return "METHOD_NEITHER" default: return fmt.Sprintf("METHOD_%d", m) } } // AccessName returns the human-readable name for an access value. func AccessName(a uint8) string { switch a { case 0: return "FILE_ANY_ACCESS" case 1: return "FILE_READ_ACCESS" case 2: return "FILE_WRITE_ACCESS" case 3: return "FILE_READ_ACCESS|FILE_WRITE_ACCESS" default: return fmt.Sprintf("ACCESS_%d", a) } } // deviceTypeNames maps common FILE_DEVICE_* values to their symbolic names. var deviceTypeNames = map[uint16]string{ 0x0001: "FILE_DEVICE_BEEP", 0x0002: "FILE_DEVICE_CD_ROM", 0x0003: "FILE_DEVICE_CD_ROM_FILE_SYSTEM", 0x0004: "FILE_DEVICE_CONTROLLER", 0x0005: "FILE_DEVICE_DATALINK", 0x0006: "FILE_DEVICE_DFS", 0x0007: "FILE_DEVICE_DISK", 0x0008: "FILE_DEVICE_DISK_FILE_SYSTEM", 0x0009: "FILE_DEVICE_FILE_SYSTEM", 0x000A: "FILE_DEVICE_INPORT_PORT", 0x000B: "FILE_DEVICE_KEYBOARD", 0x000C: "FILE_DEVICE_MAILSLOT", 0x000D: "FILE_DEVICE_MIDI_IN", 0x000E: "FILE_DEVICE_MIDI_OUT", 0x000F: "FILE_DEVICE_MOUSE", 0x0010: "FILE_DEVICE_MULTI_UNC_PROVIDER", 0x0011: "FILE_DEVICE_NAMED_PIPE", 0x0012: "FILE_DEVICE_NETWORK", 0x0013: "FILE_DEVICE_NETWORK_BROWSER", 0x0014: "FILE_DEVICE_NETWORK_FILE_SYSTEM", 0x0015: "FILE_DEVICE_NULL", 0x0016: "FILE_DEVICE_PARALLEL_PORT", 0x0017: "FILE_DEVICE_PHYSICAL_NETCARD", 0x0018: "FILE_DEVICE_PRINTER", 0x0019: "FILE_DEVICE_SCANNER", 0x001A: "FILE_DEVICE_SERIAL_MOUSE_PORT", 0x001B: "FILE_DEVICE_SERIAL_PORT", 0x001C: "FILE_DEVICE_SCREEN", 0x001D: "FILE_DEVICE_SOUND", 0x001E: "FILE_DEVICE_STREAMS", 0x001F: "FILE_DEVICE_TAPE", 0x0020: "FILE_DEVICE_TAPE_FILE_SYSTEM", 0x0021: "FILE_DEVICE_TRANSPORT", 0x0022: "FILE_DEVICE_UNKNOWN", 0x0023: "FILE_DEVICE_VIDEO", 0x0024: "FILE_DEVICE_VIRTUAL_DISK", 0x0025: "FILE_DEVICE_WAVE_IN", 0x0026: "FILE_DEVICE_WAVE_OUT", 0x0027: "FILE_DEVICE_8042_PORT", 0x0028: "FILE_DEVICE_NETWORK_REDIRECTOR", 0x0029: "FILE_DEVICE_BATTERY", 0x002A: "FILE_DEVICE_BUS_EXTENDER", 0x002B: "FILE_DEVICE_MODEM", 0x002C: "FILE_DEVICE_VDM", 0x002D: "FILE_DEVICE_MASS_STORAGE", 0x002E: "FILE_DEVICE_SMB", 0x002F: "FILE_DEVICE_KS", 0x0030: "FILE_DEVICE_CHANGER", 0x0031: "FILE_DEVICE_SMARTCARD", 0x0032: "FILE_DEVICE_ACPI", 0x0033: "FILE_DEVICE_DVD", 0x0034: "FILE_DEVICE_FULLSCREEN_VIDEO", 0x0035: "FILE_DEVICE_DFS_FILE_SYSTEM", 0x0036: "FILE_DEVICE_DFS_VOLUME", 0x0037: "FILE_DEVICE_SERENUM", 0x0038: "FILE_DEVICE_TERMSRV", 0x0039: "FILE_DEVICE_KSEC", 0x003A: "FILE_DEVICE_FIPS", 0x003B: "FILE_DEVICE_INFINIBAND", 0x003C: "FILE_DEVICE_VMBUS", 0x003D: "FILE_DEVICE_CRYPT_PROVIDER", 0x003E: "FILE_DEVICE_WPD", 0x003F: "FILE_DEVICE_BLUETOOTH", 0x0040: "FILE_DEVICE_MT_COMPOSITE", 0x0041: "FILE_DEVICE_MT_TRANSPORT", 0x0042: "FILE_DEVICE_BIOMETRIC", 0x0043: "FILE_DEVICE_PMI", 0x0044: "FILE_DEVICE_EHSTOR", 0x0045: "FILE_DEVICE_DEVAPI", 0x0046: "FILE_DEVICE_GPIO", 0x0047: "FILE_DEVICE_USBEX", 0x0048: "FILE_DEVICE_CONSOLE", 0x0049: "FILE_DEVICE_NFP", 0x004A: "FILE_DEVICE_SYSENV", 0x004B: "FILE_DEVICE_VIRTUAL_BLOCK", 0x004C: "FILE_DEVICE_POINT_OF_SERVICE", 0x004D: "FILE_DEVICE_STORAGE_REPLICATION", 0x004E: "FILE_DEVICE_TRUST_ENV", 0x004F: "FILE_DEVICE_UCM", 0x0050: "FILE_DEVICE_UCMTCPCI", 0x0051: "FILE_DEVICE_PERSISTENT_MEMORY", 0x0052: "FILE_DEVICE_NVDIMM", 0x0053: "FILE_DEVICE_HOLOGRAPHIC", 0x0054: "FILE_DEVICE_SDFXHCI", 0x0055: "FILE_DEVICE_HVDEV", } // DeviceTypeName returns the symbolic name for a device type, or "" if unknown. func DeviceTypeName(dt uint16) string { return deviceTypeNames[dt] } // knownNTSTATUS is a small set of common NTSTATUS values that frequently appear // as CMP immediates in driver dispatch code. They are return-value comparisons, // not IOCTL codes, and are filtered out to reduce false positives. var knownNTSTATUS = map[uint32]bool{ 0x00000000: true, // STATUS_SUCCESS 0x00000103: true, // STATUS_PENDING 0x40000003: true, // STATUS_OBJECT_NAME_EXISTS (informational) 0x80000005: true, // STATUS_BUFFER_OVERFLOW 0x8000000A: true, // STATUS_NO_MORE_FILES 0x8000001A: true, // STATUS_NO_MORE_ENTRIES 0xC0000001: true, // STATUS_UNSUCCESSFUL 0xC0000002: true, // STATUS_NOT_IMPLEMENTED 0xC0000004: true, // STATUS_INFO_LENGTH_MISMATCH 0xC0000005: true, // STATUS_ACCESS_VIOLATION 0xC0000008: true, // STATUS_INVALID_HANDLE 0xC000000D: true, // STATUS_INVALID_PARAMETER 0xC000000E: true, // STATUS_NO_SUCH_DEVICE 0xC000000F: true, // STATUS_NO_SUCH_FILE 0xC0000010: true, // STATUS_INVALID_DEVICE_REQUEST 0xC0000011: true, // STATUS_END_OF_FILE 0xC0000013: true, // STATUS_NO_MEDIA_IN_DEVICE 0xC0000017: true, // STATUS_NO_MEMORY 0xC000001C: true, // STATUS_BUFFER_TOO_SMALL 0xC0000022: true, // STATUS_ACCESS_DENIED 0xC0000023: true, // STATUS_BUFFER_TOO_SMALL (dup) 0xC0000024: true, // STATUS_OBJECT_TYPE_MISMATCH 0xC0000034: true, // STATUS_OBJECT_NAME_NOT_FOUND 0xC0000035: true, // STATUS_OBJECT_NAME_COLLISION 0xC0000039: true, // STATUS_OBJECT_PATH_INVALID 0xC000003A: true, // STATUS_OBJECT_PATH_NOT_FOUND 0xC0000043: true, // STATUS_SHARING_VIOLATION 0xC0000045: true, // STATUS_INVALID_PAGE_PROTECTION 0xC000007B: true, // STATUS_INVALID_IMAGE_FORMAT 0xC000009A: true, // STATUS_INSUFFICIENT_RESOURCES 0xC00000BB: true, // STATUS_NOT_SUPPORTED 0xC00000C0: true, // STATUS_DEVICE_NOT_CONNECTED 0xC00000CC: true, // STATUS_BAD_NETWORK_NAME 0xC00000D0: true, // STATUS_DRIVER_UNABLE_TO_LOAD 0xC000010E: true, // STATUS_IMAGE_ALREADY_LOADED 0xC0000135: true, // STATUS_DLL_NOT_FOUND 0xC0000142: true, // STATUS_DLL_INIT_FAILED 0xC000014B: true, // STATUS_PIPE_BROKEN 0xC0000205: true, // STATUS_INSUFFICIENT_RESOURCES 0xC0000225: true, // STATUS_NOT_FOUND 0xC00000E5: true, // STATUS_FLT_NO_HANDLER_DEFINED } // plausibleIoctl reports whether a raw 32-bit value is a plausible IOCTL code // rather than a status code, flag, or size constant. It returns the reason for // rejection (empty string means "plausible"). func plausibleIoctl(code uint32) (ok bool, note string) { if code == 0 { return false, "zero" } if code == 0xFFFFFFFF { return false, "0xFFFFFFFF" } // A real IOCTL has a non-zero device type in bits 16-31, so the value is // >= 0x10000. Smaller values are flags, sizes, or synthetic IDs (e.g. the // nanga driver's SSNs 0x777/0x888/0x999), not IOCTLs. if code < 0x10000 { return false, "device type zero (< 0x10000)" } if knownNTSTATUS[code] { return false, "known NTSTATUS" } dt, fn, m, a := DecodeIoctl(code) // A value that is exactly device_type<<16 (function/method/access all zero) // is a degenerate IOCTL and far more likely a size or alignment constant // (e.g. 0x10000 = 64 KiB). if fn == 0 && m == 0 && a == 0 { return false, "degenerate (function/method/access all zero)" } // NTSTATUS error codes occupy 0xC0000000-0xFFFFFFFF. A value whose device // type falls in 0xC000-0xFFFF is almost certainly a status code, not an // IOCTL (custom vendor device types are conventionally 0x8000-0xBFFF). if dt >= 0xC000 { return false, "NTSTATUS error range" } if dt >= 0x8000 { // Custom vendor device type. Genuinely ambiguous with NTSTATUS warning // codes, so keep it but flag it. return true, "ambiguous: vendor device type overlaps NTSTATUS warning range" } return true, "" }