Last week a major zero-day vulnerability was found in Adobe Flash Player. Over the weekend, Adobe released an update to fix the vulnerability: users who have enabled auto-update already received the newest version (184.108.40.2066). Our analysis has confirmed that the vulnerable code has been modified.
The update will be available for manual download later this week. Users of Chrome and newer versions of Internet Explorer will receive updates for their included versions of Flash Player at around the same time.
Looking into the samples we acquired, we found that the actual Flash file was embedded within the malicious .SWF file. In addition, the actual file was heavily obfuscated.
Once we removed the obfuscation, we were able to analyze the vulnerability in full and find out how the exploit works. Before going into the details, we will point out one curious little fact: some of the code fragments are similar to exploits targeting CVE-2014-8439. It is possible that the same person is responsible for both exploits.
Vulnerability Root Cause
Our analysis found that this is a use-after-free (UAF) type of vulnerability. In this case, the memory referenced by domainMemory is freed. This vulnerability can be used to read and write into memory, and an attacker can use this ability to run arbitrary code.
This vulnerability is triggered by the following steps:
- Create a new ByteArray, and write lots of data to it, then compress the contents.
Figure 1. ByteArray creation code
- Overwrite the ByteArray compressed data from position 0x200 and set ByteArray to domainMemory.
Figure 2. Overwriting ByteArray
- Uncompress the ByteArray data. Because of the actions in the previous step, this will result in an IOError exception. The code catches the exception, then uses another ByteArray to hold the freed memory’s place, this ByteArray is buffered with 0xBBBBBBBB.
Figure 3. IOError and catching the exception
- Clear the place holder data in ByteArray.
Figure 4. Freeing the 0xBBBBBBBB ByteArray memory
Why Does domainMemory Still Reference The Uncompressed Data Buffer?
In the AvmPlus project code, we found that the bug is in the ByteArray::UncompressViaZlibVariant function. The function is designed this way: it will allocate a new buffer for storing the uncompressed data first. If the decompression is successful, it will notify domainMemory to use the new buffer. If the decompression fails, it will not notify domainMemory to use the new buffer, and instead, it will free the newly created buffer.
This seems correct, but in the decompression process, the allocation for the new buffer will grow bigger. The class Grower will handle the buffer’s dynamic growth. After this growth is complete, the destruction of class Grower will notify domainMemory to use the expanded buffer. What we end up with is domainMemory using the new buffer during the decompression process. If this fails, the newly created buffer is freed. This breaks the original logic of ByteArray::UncompressViaZlibVariant: even if the decompression fails, domainMemory uses the new buffer.
This is why after performing the above steps, domainMemory now points to a freed memory space filled with 0xBBBBBBBB, the exploit can now use intrinsic instructions to read and write the freed memory space.
Figure 5. Reading the freed memory space
Like most recent Adobe Flash exploits, the exploit code controls the memory layout and put vectors beside the freed memory. This allows the vector length to be overwritten, which allows the attacker to arbitrarily read and write into the memory.
Figure 6. Overwriting memory
We can see the memory layout changing during uncompression, up to the vector length being overwritten in the following pictures. The use-after-free memory address is 0x05120000 in my debug environment.
Figure 7. The memory layout after uncompressing (the header data is successfully uncompressed)
Figure 8. The memory layout after allocated the 0xBBBBBBBB ByteArray
Figure 9. The memory lay out after freed the 0xBBBBBBBB ByteArray and sprayed Vectors
Figure 10. The memory layout after overwrite vector length
After the vector length has been overwritten to 0x40000000, the sample code can now read and write into arbitrary memory; this capability can be used by exploits to run arbitrary code. The exploit just triggers a fake virtual function call to execute shellcode.
Trend Micro Solutions
Trend Micro’s dynamic script emulation technology is able to successfully analyze even heavily obfuscated Flash files. This allows us to extract embedded .SWF files and monitor the vector heap spray behavior. As a result, we are able to provide a more complete analysis of exploits and provide complete protection to our users in a relatively short period of time.
Our initial post contains details on our available solutions for this threat.