Overflow Analysis of CVE-2013-0077 Reactor

Keywords: Google

It took a long time to find that this environment is easier to build and analyze.

  • Environmental Science:
    • System - Win XP SP3
    • Vulnerability program: QQPlayer 3.7.892.400
    • Error DLL: quartz.dll 6.5.2600.5512
    • Debugging tool: x32db+gflag.exe
  • Process:
    • First gflag sets the heap debugging property of QQPlayer.exe, "gflag.exe-i QQPlayer.exe+hpa", where the overflow in the heap page check heap replication is added.
    • Start Q QQPlayer.exe, and then attach x32dbg to the QQQPlayer process to debug, so that the heap allocation mechanism of the debugged program executes properly. Then the poc.m2p file is dragged into QQQPlayer, and the x32dbg captures the error (EXCEPTION_ACCESS_VIOLATION) and stops at the rep movsd instruction.
    • At this point, we can see that the current error instruction is located in quartz.dll. We use IDA Pro to analyze quartz.dll and get the following results.
    • signed int __stdcall sub_7D0706CC(int src_addr, unsigned int count, int a3)
      {
        signed int result; // eax@2
        int v4; // eax@3
        unsigned __int8 v5; // al@3
        unsigned int v6; // ebx@7
        int v7; // ecx@7
        int v8; // ST00_4@7
        unsigned int v9; // eax@7
        signed int v10; // eax@10
      
        if ( *(_BYTE *)(src_addr + 10) & 0x20 )
        {
          v4 = (*(_BYTE *)(src_addr + 6) + ((*(_BYTE *)(src_addr + 5) + (*(_BYTE *)(src_addr + 4) << 8)) << 8)) & 0xFFF;
          *(_DWORD *)a3 = (*(_BYTE *)(src_addr + 6)
                         + ((*(_BYTE *)(src_addr + 5) + ((unsigned int)*(_BYTE *)(src_addr + 4) << 8)) << 8)) >> 12;
          *(_DWORD *)(a3 + 4) = v4;
          v5 = *(_BYTE *)(src_addr + 7);
          if ( (*(_BYTE *)(src_addr + 7) & 0xFu) > 8 )
            v5 &= 0xF7u;
          if ( v5 & 0xF0 && v5 & 0xF )
          {
            v6 = v5;
            v7 = v5 & 0xF;
            *(_QWORD *)(a3 + 16) = dword_7D0707F8[v7];
            v8 = *(_DWORD *)(a3 + 16);
            *(_DWORD *)(a3 + 24) = dword_7D070838[v7];
            *(_DWORD *)(a3 + 28) = MulDiv(v8, 9, 1000);
            v9 = (*(_BYTE *)(src_addr + 10) + ((*(_BYTE *)(src_addr + 9) + ((unsigned int)*(_BYTE *)(src_addr + 8) << 8)) << 8)) >> 6;
            *(_DWORD *)(a3 + 32) = v9;
            if ( v9 == 0x3FFFF )
              *(_DWORD *)(a3 + 32) = 0;
            else
              *(_DWORD *)(a3 + 32) = 400 * v9;
            *(_DWORD *)(a3 + 40) = 2000;
            *(_DWORD *)(a3 + 36) = dword_7D070860[v6 >> 4];
            v10 = (((unsigned int)*(_BYTE *)(src_addr + 11) >> 3) | 32 * (*(_BYTE *)(src_addr + 10) & 0x1F)) << 11;
            *(_DWORD *)(a3 + 8) = v10;
            if ( *(_BYTE *)(src_addr + 11) & 4 )
            {
              if ( v10 > 40960 )
                *(_DWORD *)(a3 + 8) = 40960;
            }
            *(_DWORD *)(a3 + 48) = count;
         //Here qmemcpy copies count bytes from src_addr to the heap as an error instruction, assuming count is not checked, resulting in an overflow
         //See here the starting content of src_addr is 0x000001B3
            qmemcpy((void *)(a3 + 52), (const void *)src_addr, count);
            result = 1;
          }
          else
          {
            result = 0;
          }
        }
        else
        {
          result = 0;
        }
        return result;
      }

      Returning to x32dbg and debugging this function, we found that the starting content at src_addr is 0x000001B3 and count is 0x000000C3.

    • Find "0x000001B3" in poc.m2p file, and after "0x000001B3" offset 0xC3, the content is "0x00000100". At this time, we do not know what the hexadecimal sequence has special meaning, but for the time being, consider it as a start sign. After that, Google MPEG-2 Data Structure It is found that "0x000001B3" is the starting flag of Video Sequence and "0x00000100" is the starting flag of Picture Header. Therefore, the function of this function is to copy the contents between Video Sequence and Picture Header into the heap, because there is not enough space in the heap, resulting in overflow errors.

    • Finally, let's explore the exact length of the spill.The heap start address before replication is 0x027A6F64, the error time is 0x027A7000, 0x027A7000-0x027A6F64=0x9C, so the heap space allocated here is 0x9C byte, while the actual replication content is 0xC3 byte, which exceeds all the space, resulting in overflow error.

  • Summary: The heap overflow and stack overflow here are basically similar, because the number of replicas is not checked and the overflow is caused by the different address space of different attributes, because the address space has different characteristics; debuggers such as x32dbg are not friendly to heap debugging, and there is no strong support of windbg for heap debugging, which is a problem that needs to be solved in the future. At the same time, a heap overflow error was found, but there is still a long way to go to achieve exp.
  • To be continued: Looking forward to the sequel EXP...

Posted by SlyOne on Fri, 17 May 2019 18:31:02 -0700