Exploit-DB #42465
Description: Microsoft Edge Chakra - 'chakra!Js::GlobalObject' Integer overflow
Type: dos
Platform: windows
Date: 2017-08-17
Author: Huang Anwen

Exploit:
<!--
Report by Huang Anwen, He Xiaoxiao of ichunqiu Ker Team

There is a classic heap overflow when eval a string which large enough in Chakra!
This issue can be reproduced steadly in uptodate Edge in Win10 WIP.
An exception will occur immediatly when opening POC.html in Edge.



	//ChakraCore-master\lib\Runtime\Library\GlobalObject.cpp
	
    ScriptFunction* GlobalObject::DefaultEvalHelper(ScriptContext* scriptContext, const char16 *source, int sourceLength, ModuleID moduleID, uint32 grfscr, LPCOLESTR pszTitle, BOOL registerDocument, BOOL isIndirect, BOOL strictMode)
    {
        Assert(sourceLength >= 0);
        AnalysisAssert(scriptContext);
        if (scriptContext->GetThreadContext()->EvalDisabled())
        {
            throw Js::EvalDisabledException();
        }

#ifdef PROFILE_EXEC
        scriptContext->ProfileBegin(Js::EvalCompilePhase);
#endif
        void * frameAddr = nullptr;
        GET_CURRENT_FRAME_ID(frameAddr);

        HRESULT hr = S_OK;
        HRESULT hrParser = S_OK;
        HRESULT hrCodeGen = S_OK;
        CompileScriptException se;
        Js::ParseableFunctionInfo * funcBody = NULL;

        BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
        BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
        {
            uint cchSource = sourceLength;
            size_t cbUtf8Buffer = (cchSource + 1) * 3;		//OVERFLOW when cchSource large enough!!!

            ArenaAllocator tempArena(_u("EvalHelperArena"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
            LPUTF8 utf8Source = AnewArray(&tempArena, utf8char_t, cbUtf8Buffer);		//Allocate memory on Arena heap with a incorrect but smaller size

            Assert(cchSource < MAXLONG);
            size_t cbSource = utf8::EncodeIntoAndNullTerminate(utf8Source, source, static_cast< charcount_t >(cchSource));		//OOB write HERE!!!
            Assert(cbSource + 1 <= cbUtf8Buffer);

            SRCINFO const * pSrcInfo = scriptContext->GetModuleSrcInfo(moduleID);
			
            [...]

            LEAVE_PINNED_SCOPE();
        }
        END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
        END_LEAVE_SCRIPT_INTERNAL(scriptContext);


#ifdef PROFILE_EXEC
        scriptContext->ProfileEnd(Js::EvalCompilePhase);
#endif
        THROW_KNOWN_HRESULT_EXCEPTIONS(hr, scriptContext);

        if (!SUCCEEDED(hrParser))
        {
            JavascriptError::ThrowParserError(scriptContext, hrParser, &se);
        }
        else if (!SUCCEEDED(hrCodeGen))
        {
            [...]
        }
        else
        {

            [...]

            ScriptFunction* pfuncScript = funcBody->IsCoroutine() ?
                scriptContext->GetLibrary()->CreateGeneratorVirtualScriptFunction(funcBody) :
                scriptContext->GetLibrary()->CreateScriptFunction(funcBody);

            return pfuncScript;
        }
    }
	
	
	//ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
    __range(0, cch * 3)
    size_t EncodeIntoAndNullTerminate(__out_ecount(cch * 3 + 1) utf8char_t *buffer, __in_ecount(cch) const char16 *source, charcount_t cch)
    {
        size_t result = EncodeInto(buffer, source, cch);
        buffer[result] = 0;
        return result;
    }
	
	//ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
    __range(0, cch * 3)
        size_t EncodeInto(__out_ecount(cch * 3) LPUTF8 buffer, __in_ecount(cch) const char16 *source, charcount_t cch)
    {
        return EncodeIntoImpl<true>(buffer, source, cch);
    }
	
	//ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
	    template <bool cesu8Encoding>
    __range(0, cchIn * 3)
    size_t EncodeIntoImpl(__out_ecount(cchIn * 3) LPUTF8 buffer, __in_ecount(cchIn) const char16 *source, charcount_t cchIn)
    {
        charcount_t cch = cchIn; // SAL analysis gets confused by EncodeTrueUtf8's dest buffer requirement unless we alias cchIn with a local
        LPUTF8 dest = buffer;

        if (!ShouldFastPath(dest, source)) goto LSlowPath;

LFastPath:
        while (cch >= 4)
        {
            uint32 first = ((const uint32 *)source)[0];
            if ( (first & 0xFF80FF80) != 0) goto LSlowPath;
            uint32 second = ((const uint32 *)source)[1];
            if ( (second & 0xFF80FF80) != 0) goto LSlowPath;
            *(uint32 *)dest = (first & 0x0000007F) | ((first & 0x007F0000) >> 8) | ((second & 0x0000007f) << 16) | ((second & 0x007F0000) << 8);		//OOB write HERE finally!!!
            dest += 4;
            source += 4;
            cch -= 4;
        }

LSlowPath:
        if (cesu8Encoding)
        {
			[...]
        }
        else
        {
            [...]
        }

        return dest - buffer;
    }

Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

*** wait with pending attach
Symbol search path is: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00007ff6`26db0000 00007ff6`26dd5000   C:\Windows\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\MicrosoftEdgeCP.exe
ModLoad: 00007ffc`fc[PII_REDACTED]7ffc`fc23b000   C:\Windows\SYSTEM32\ntdll.dll
ModLoad: 00007ffc`fb9d0000 00007ffc`fba7e000   C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ffc`f90a0000 00007ffc`f92e9000   C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ffc`f6b90000 00007ffc`f6c0e000   C:\Windows\SYSTEM32\apphelp.dll
ModLoad: 00007ffc`fbbb0000 00007ffc`fbea9000   C:\Windows\System32\combase.dll
ModLoad: 00007ffc`f94c0000 00007ffc`f95b6000   C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ffc`fba80000 00007ffc`fbba5000   C:\Windows\System32\RPCRT4.dll
ModLoad: 00007ffc`f8[PII_REDACTED]7ffc`f868a000   C:\Windows\System32\bcryptPrimitives.dll
ModLoad: 00007ffc`fbfc0000 00007ffc`fc05d000   C:\Windows\System32\msvcrt.dll
ModLoad: 00007ffc`ebd60000 00007ffc`ebdc0000   C:\Windows\SYSTEM32\wincorlib.DLL
ModLoad: 00007ffc`fac50000 00007ffc`fad10000