Before diving into the analysis of CVE-2018-4878, a quick reminder that this is the continuation of our previous post, which provided background on CVE-2018-4878, including a video of how Morphisec prevents any attacks leveraging this Flash vulnerability. Morphisec prevents the attack at all phases and components in the attack chain – during the exploit, the shellcode, as well as the malware which is executed using wbscript.exe with additional in-memory command control code.
At the time of the previous post, the vulnerability was still a zero-day. Adobe released a new version that fixed the flaw yesterday. With that fix available, Morphisec is now free to release technical details of the attack.
Set-up of Analysis
Although in this overview we focus mainly on the 32 bit exploitation flow, the original exploit was implemented to support both 32 and 64 bit browsers. The exploit included adaptation of offsets for shellcode to cope with the difference in the file header structures (e.g. Import Address table pointer is with a higher offset for 64 bit process from the NT header) as well as many other adaptations during the pointer leakage.
It is also important to mention that the exploit writers didn’t delete debug symbols from the Flash and therefore it was much easier to de-obfuscate the object.
We will not focus on the malspam document that delivered a Flash wrapper; this Flash object is now inactive due to the fact that the decryption key for the inner exploit presented here was only delivered during the activity of the C2.
This document focuses solely on the already fully decrypted working exploit. For those interested, Proof of Concept details can be found in a separate section toward the end of this report.
After decrypting the exploit from the encrypted Flash wrapper, we identified action script files to handle 32 and 64 bit browsers. We also identified 2 blobs relevant for the 32 and 64 bit shellcodes (in our walkthrough we deleted the 64 bit files and blob to make it easier for the reader, we also renamed many of the variables for the same reason).
In this stripped and de-obfuscated form, the exploit is well structured. It, starts from the Main class that initializes the shellcode blob to a local variable and forwards the flow to the next stage of utilizing the vulnerability by triggering Use After Free on a DRM Operation object (UAF).
As shown in the screenshot, first a DRM Listener object is created and pointed to by “var_13”- eventually this pointer points to a “free” memory (as part of use after free – this one is usable).
Then the attacker creates a MediaPlayer and initializes the player’s DRM manager with a new DRM operation listener object. Immediately after, it triggers the “free” of the DRM object by assigning it a null value, while the Media player DRM manager points to it.
The previous operation causes the “free” of the “var_13” DRM, while the pointer now points to a new allocated array object. Since we are not going into the Reversing of the BUG here (this deserves a blog by itself) we will call this condition “magic.”
Each time a timer is triggered, there is a verification of the first parameter in the original “var_13” DRM_obj. When the value changes, it means that the UAF was successfully triggered.
As soon as the array is allocated and pointed to by the DRM object, the size of the array is modified to 0Xffffffff to cover the full process memory. Next a basic validation on the array and the OS is executed.
In the screenshot below, the size is compared to 0Xffffffff and a verification is performed that the exploit is running on Windows (“flash72”).
In the screenshot below we can clearly see the read primitive and write primitive that perform sanity verification of the index to point solely to user memory (should be lower than 0Xc0000000 and higher than 0x1000 in order to not risk triggering null page guard or kernel memory assets):
Locating Gadgets in Memory
Now that the exploit gained read and write primitive and is able to fully control the flow, it needs to bypass DEP by changing the shellcode memory protection to “Execute,” and then executing the shellcode.
In the screenshot below, the shellcode blob is copied to a vector. The exploit then locates the Kernel32!VirtualProtect and Kernel32!CreateProcessA functions, executes the functions, and jumps to the in-memory shellcode execution.
In the screenshot below, we see how the attackers use the byte array to locate the different functions.
This post exploit technique is very standard
- Locating of the MZ by aligning to 64k alignment and then going back up by 0x10000 until MZ magic number is located -> this indicates the base address of the flash module.
- Locating the NT_Header and then the Import table through PEB traversal.
- Locating the kernel32.dll module name by regular comparison of names with maximum length of 12.
- Locating the VirtualAlloc and CreateProcessA functions through Original First Thunk.
CMD.exe is created using the CreateProcessA. Next, to bypass any possible whitelisting solutions, a shellcode is injected directly into the memory of the cmd.exe process, again by using a very standard technique of CreateRemoteThread with a written shellcode inside the process.
After additional decryption in CMD.exe process memory, the same shellcode eventually downloads and executes an executable from the C2, in this case a Remote Access Trojan.
CVE-2018-4878 Proof of Concept:
While we were in possession of the malicious exploit, we noticed that the shellcode that is remotely injected into the CMD.exe process after the process creation resides in the blob without any encryption. Accordingly, we chose to create the PoC the easy way by simply replacing the malicious shellcode with a calculator shellcode.
Note that we complicated the calculator shellcode slightly to temporarily limit the number of solutions triggered just based on the shellcode. In the real exploit, there is a number of stages of self-modifying shellcode that eventually perform a reflective loading (much more complicated although still fully decrypted, plainly written to the blob).
Below is the screenshot for the results from VirusTotal for the uploaded PoC:
VirusTotal results for the same PoC after compressing and embedding into Excel:
As demonstrated in this analysis, CVE-2018-4878 can be easily manipulated and adapted to additional attack scenarios. Given this, we predict that this vulnerability will soon become a staple of exploit kits and one of the most exploited vulnerabilities of 2018.
The threat group attributed to this attack, known as Group123 or TEMP.Reaper, constantly evolves its attack methods and techniques. In tracing their development over the last year and a half, we see a markedly increased sophistication in this latest attack. On the other hand, our analysis also reveals carelessness in hiding their traces.
Morphisec customers were and are protected against all variants of this attack, starting from the first version one and half years ago to this latest one leveraging CVE-2018-4878 (which, until yesterday, was a zero-day).