On April 14th 2015, Adobe patched CVE-2015-0359 in APSB15-06. On April 17th, just 3 days later, a new version of the Angler Exploit Kit (EK) was released that targets the patched vulnerability. Following the previous Flash security patch in March, exploit kits (initially Nuclear, and then Angler) incorporated a newly patched vulnerability (CVE-2015-0336) seven days after the patch was released to the public. EK’s recent adoption of newly patched vulnerabilities has both shortened the time between patch and exploit and increased the regularity with which vulnerabilities are exploited. This sets a worrying trend for the security community that is compounded by the effectiveness of basic Flash obfuscation.
In addition to EK’s timeliness with adding CVEs, they are also quick to adopt new exploitation standards. Core Security’s technique to bypass Microsoft’s Control Flow Guard (CFG) exploit mitigation was posted on March 25th, and is already being used in this attack.
The exploit mostly follows established Flash exploitation standards. It checks the environment before attempting the exploit, and chooses whether to deliver CVE-2015-0313 and CVE-2015-0359, which are similar vulnerabilities related to concurrency issues with ByteArrays. The Flash file does not need to be recompiled to serve a new payload since the shellcode is taken from flashvars (paramaters passed from HTML/JS). The SWF is packed, but once unpacked the exploit is wholly unobfuscated.
The exploit uses a Vector spray, from which the vulnerability trigger will corrupt one vector’s length field. The corrupted vector can access the rest of program memory, and is used to build a corrupted ByteArray object containing a modified vtable, ROP chain, and shellcode. The modified toString method of the ByteArray’s vtable object is called from ActionScript, which transfers control to the attacker. The details from this last step from AS3 are specifically from Core Security’s technique to bypass CFG
1. Assert target is vulnerable
2. Allocate attacking_buffer and fill it with 0xAAAAAAAA
3. Set attacking_buffer as shareable
4. Create worker thread with a message channel, and start() it
1. Allocate written_buffer and fill it with 0xABABABAB
2. Decrypt shellcode from flashvar “exec”
1. ApplicationDomain.currentDomain.domainMemory = this.attacking_buffer;
1. Spray Vector objects
2. if CVE-2015-0313: attacking_buffer.clear()
3. else (CVE-2015-0359): attacking_buffer.write(written_buffer)
4. Resize sprayed Vector objects
1. Search attacking_buffer for the length attribute of a Vector
2. Overwrite the length of the Vector
1. Search Vectors for the corrupted Vector object. This corrupted Vector is used for subsequent out-of-bounds memory accesses
2. Create a victim ByteArray, and fill it with a magic value
3. Find victim bytearray by scanning memory for the magic value
4. Save the address of the victim bytearray’s vtable pointer
5. Find the base address of an executable module, and scan it for ROP gadgets
6. Build fake vtable, ROP chain, and shellcode in memory inside the victim bytearray
7. Overwrite unprotected address of toString method in vtable object
8. Call .toString() to pivot to ROP -> shellcode -> payload
9. Repair bytearray for continuation of execution
A big thank you to Peleus Uhley (Adobe) for working with us on this issue.