u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) { u16 v; __outdword(PCI_CONFIG_ADDRESS, 0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset); v = __inword(PCI_CONFIG_DATA + (offset&2)); return v; }
// Perform IO instruction according with parameters _Use_decl_annotations_ static void VmmpIoWrapper(bool to_memory, bool is_string, SIZE_T size_of_access, unsigned short port, void *address, unsigned long count) { NT_ASSERT(size_of_access == 1 || size_of_access == 2 || size_of_access == 4); // Update CR3 with that of the guest since below code is going to access // memory. const auto guest_cr3 = UtilVmRead(VmcsField::kGuestCr3); const auto vmm_cr3 = __readcr3(); __writecr3(guest_cr3); // clang-format off if (to_memory) { if (is_string) { // IN switch (size_of_access) { case 1: *reinterpret_cast<UCHAR*>(address) = __inbyte(port); break; case 2: *reinterpret_cast<USHORT*>(address) = __inword(port); break; case 4: *reinterpret_cast<ULONG*>(address) = __indword(port); break; } } else { // INS switch (size_of_access) { case 1: __inbytestring(port, reinterpret_cast<UCHAR*>(address), count); break; case 2: __inwordstring(port, reinterpret_cast<USHORT*>(address), count); break; case 4: __indwordstring(port, reinterpret_cast<ULONG*>(address), count); break; } } } else { if (is_string) { // OUT switch (size_of_access) { case 1: __outbyte(port, *reinterpret_cast<UCHAR*>(address)); break; case 2: __outword(port, *reinterpret_cast<USHORT*>(address)); break; case 4: __outdword(port, *reinterpret_cast<ULONG*>(address)); break; } } else { // OUTS switch (size_of_access) { case 1: __outbytestring(port, reinterpret_cast<UCHAR*>(address), count); break; case 2: __outwordstring(port, reinterpret_cast<USHORT*>(address), count); break; case 4: __outdwordstring(port, reinterpret_cast<ULONG*>(address), count); break; } } } // clang-format on __writecr3(vmm_cr3); }
NTSTATUS __fastcall DispatchIOCTL(IN PIOCTL_INFO RequestInfo, OUT PULONG ResponseLength) { NTSTATUS Status = STATUS_SUCCESS; #define INPUT(Type) ((Type)(RequestInfo->InputBuffer)) #define OUTPUT(Type) ((Type)(RequestInfo->OutputBuffer)) #define SET_RESPONSE_LENGTH(Length) if (ResponseLength != NULL) {*ResponseLength = (Length);} switch (RequestInfo->ControlCode) { // DriverFunctions: case GET_HANDLES_COUNT: *OUTPUT(PULONG) = GetHandlesCount(); SET_RESPONSE_LENGTH(sizeof(ULONG)); break; // NativeFunctions: case START_BEEPER: __outbyte(0x61, __inbyte(0x61) | 3); break; case STOP_BEEPER: __outbyte(0x61, __inbyte(0x61) & 252); break; case SET_BEEPER_REGIME: __outbyte(0x43, 0xB6); break; case SET_BEEPER_OUT: __outbyte(0x61, __inbyte(0x61) | 2); break; case SET_BEEPER_IN: __outbyte(0x61, __inbyte(0x61) & 253); break; case SET_BEEPER_DIVIDER: SetBeeperDivider(*INPUT(PWORD)); break; case SET_BEEPER_FREQUENCY: SetBeeperFrequency(*INPUT(PWORD)); break; case READ_IO_PORT_BYTE: *OUTPUT(PBYTE) = __inbyte(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(BYTE)); break; case READ_IO_PORT_WORD: *OUTPUT(PWORD) = __inword(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(WORD)); break; case READ_IO_PORT_DWORD: *OUTPUT(PDWORD32) = __indword(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(DWORD)); break; case WRITE_IO_PORT_BYTE: __outbyte( INPUT(PWRITE_IO_PORT_BYTE_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_BYTE_INPUT)->Data ); break; case WRITE_IO_PORT_WORD: __outword( INPUT(PWRITE_IO_PORT_WORD_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_WORD_INPUT)->Data ); break; case WRITE_IO_PORT_DWORD: __outdword( INPUT(PWRITE_IO_PORT_DWORD_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_DWORD_INPUT)->Data ); break; case RDPMC: *OUTPUT(PULONGLONG) = __readpmc(*INPUT(PULONG)); SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); break; case RDMSR: *OUTPUT(PULONGLONG) = __readmsr(*INPUT(PULONG)); SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); break; case WRMSR: __writemsr(INPUT(PWRMSR_INPUT)->Index, INPUT(PWRMSR_INPUT)->Data); break; // MemoryUtils: case ALLOC_KERNEL_MEMORY: *OUTPUT(PUINT64) = (SIZE_T)GetMem(*INPUT(PSIZE_T)); SET_RESPONSE_LENGTH(sizeof(UINT64)); break; case FREE_KERNEL_MEMORY: FreeMem((PVOID)*INPUT(PUINT64)); break; case COPY_MEMORY: RtlCopyMemory( (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Destination, (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Source, (SIZE_T)INPUT(PCOPY_MEMORY_INPUT)->Size ); break; case FILL_MEMORY: RtlFillMemory( (PVOID)INPUT(PFILL_MEMORY_INPUT)->Destination, (SIZE_T)INPUT(PFILL_MEMORY_INPUT)->Size, (BYTE)INPUT(PFILL_MEMORY_INPUT)->FillingByte ); break; case ALLOC_PHYSICAL_MEMORY: *OUTPUT(PUINT64) = (SIZE_T)AllocPhysicalMemory( INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (SIZE_T)INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->Size ); SET_RESPONSE_LENGTH(sizeof(UINT64)); break; case FREE_PHYSICAL_MEMORY: FreePhysicalMemory((PVOID)*INPUT(PUINT64)); break; case GET_PHYSICAL_ADDRESS: *OUTPUT(PPHYSICAL_ADDRESS) = GetPhysicalAddressInProcess( (HANDLE)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->ProcessID, (PVOID)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(PHYSICAL_ADDRESS)); break; case READ_PHYSICAL_MEMORY: *OUTPUT(PBOOL) = ReadPhysicalMemory( INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (PVOID)INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->Buffer, INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->BufferSize ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case WRITE_PHYSICAL_MEMORY: *OUTPUT(PBOOL) = WritePhysicalMemory( INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (PVOID)INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->Buffer, INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->BufferSize ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case READ_DMI_MEMORY: ReadDmiMemory((PVOID)*INPUT(PUINT64), DMI_SIZE); SET_RESPONSE_LENGTH(DMI_SIZE); break; // ShellCode: case EXECUTE_SHELL_CODE: *OUTPUT(PSHELL_STATUS) = ExecuteShell( (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->EntryPoint, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->CodeBlock, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->InputData, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->OutputData, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->Result ); SET_RESPONSE_LENGTH(sizeof(SHELL_STATUS)); break; // ProcessesUtils: case ALLOC_VIRTUAL_MEMORY: OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->Status = VirtualAllocInProcess( (HANDLE)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->ProcessId, (SIZE_T)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->Size, (PVOID*)&OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(ALLOC_VIRTUAL_MEMORY_OUTPUT)); break; case FREE_VIRTUAL_MEMORY: *OUTPUT(PNTSTATUS) = VirtualFreeInProcess( (HANDLE)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); break; case MAP_VIRTUAL_MEMORY: OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->MappedMemory = MapVirtualMemory( (HANDLE)INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->ProcessId, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->VirtualAddress, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->MapToVirtualAddress, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->Size, UserMode, (PMDL*)&(OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->Mdl) ); SET_RESPONSE_LENGTH(sizeof(MAP_VIRTUAL_MEMORY_OUTPUT)); break; case UNMAP_VIRTUAL_MEMORY: UnmapVirtualMemory( INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->Mdl, INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->MappedMemory ); break; case READ_PROCESS_MEMORY: *OUTPUT(PBOOL) = ReadProcessMemory( (HANDLE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->VirtualAddress, (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->Buffer, INPUT(PREAD_PROCESS_MEMORY_INPUT)->BytesToRead, TRUE, (MEMORY_ACCESS_TYPE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->AccessType ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case WRITE_PROCESS_MEMORY: *OUTPUT(PBOOL) = WriteProcessMemory( (HANDLE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->VirtualAddress, (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->Buffer, INPUT(PWRITE_PROCESS_MEMORY_INPUT)->BytesToWrite, TRUE, (MEMORY_ACCESS_TYPE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->AccessType ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case RAISE_IOPL_BY_TF: #ifdef _AMD64_ RaiseIOPLByTrapFrame(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPL_BY_TF: #ifdef _AMD64_ ResetIOPLByTrapFrame(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RAISE_IOPL_BY_TF_SCAN: RaiseIOPLByTrapFrameScan(); break; case RESET_IOPL_BY_TF_SCAN: ResetIOPLByTrapFrameScan(); break; case RAISE_IOPL_BY_TSS: #ifdef _X86_ RaiseIOPLByTSS(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPL_BY_TSS: #ifdef _x86_ ResetIOPLByTSS(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RAISE_IOPM: #ifdef _X86_ *OUTPUT(PNTSTATUS) = RaiseIOPM((HANDLE)*INPUT(PUINT64)); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPM: #ifdef _X86_ *OUTPUT(PNTSTATUS) = ResetIOPM((HANDLE)*INPUT(PUINT64)); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; // PCI: case READ_PCI_CONFIG: OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->Status = ReadPciConfig( INPUT(PREAD_PCI_CONFIG_INPUT)->PciAddress, INPUT(PREAD_PCI_CONFIG_INPUT)->PciOffset, (PVOID)INPUT(PREAD_PCI_CONFIG_INPUT)->Buffer, INPUT(PREAD_PCI_CONFIG_INPUT)->BufferSize, &OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->BytesRead ); SET_RESPONSE_LENGTH(sizeof(READ_PCI_CONFIG_OUTPUT)); break; case WRITE_PCI_CONFIG: OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->Status = WritePciConfig( INPUT(PWRITE_PCI_CONFIG_INPUT)->PciAddress, INPUT(PWRITE_PCI_CONFIG_INPUT)->PciOffset, (PVOID)INPUT(PWRITE_PCI_CONFIG_INPUT)->Buffer, INPUT(PWRITE_PCI_CONFIG_INPUT)->BufferSize, &OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->BytesWritten ); SET_RESPONSE_LENGTH(sizeof(WRITE_PCI_CONFIG_OUTPUT)); break; default: Status = STATUS_NOT_IMPLEMENTED; break; } return Status; #undef INPUT #undef OUTPUT #undef SET_RESPONSE_LENGTH }