Si usa bloqueadores de anuncios, puede encontrar BlockAdBlock . Este script detecta su bloqueador y no lo permite en el sitio hasta que lo desactive. Pero me preguntaba cómo funciona. ¿Cómo detecta los bloqueadores los anti-bloqueadores? ¿Y cómo reaccionan los bloqueadores a esto y cómo bloquean los anti-bloqueadores?Historia de la ingeniería inversa.
Lo primero que hice fue mirar su sitio . BlockAdBlock ofrece un configurador con configuraciones: el intervalo de espera y cómo se verá la advertencia, generando diferentes versiones del script.Esto me hizo pensar en versiones. ¿Qué pasaría si no pudiera ver una versión, y todas a la vez? Así que lo hice. Regresé en el tiempo usando la máquina Wayback . Después de eso, descargué todas las versiones de BlockAdBlock y las procesé.Lista de todas las versiones de BlockAdBlock, con sha1sum
6d5eafab2ca816ccd049ad8f796358c0a7a43cf3 20151007203811.js
065b4aa813b219abbce76ad20a3216b3481b11bb 20151113115955.js
d5dec97a775b2e563f3e4359e4f8f1c3645ba0e5 20160121132336.js
8add06cbb79bc25114bd7a2083067ceea9fbb354 20160318193101.js
8add06cbb79bc25114bd7a2083067ceea9fbb354 20160319042810.js
8add06cbb79bc25114bd7a2083067ceea9fbb354 20160331051645.js
8add06cbb79bc25114bd7a2083067ceea9fbb354 20160406061855.js
8add06cbb79bc25114bd7a2083067ceea9fbb354 20160408025028.js
555637904dc9e4bfc6f08bdcae92f0ba0f443ebf 20160415083215.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20161120215354.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170525201720.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170606090847.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170703211338.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170707211652.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170813090718.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20170915094808.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171005180631.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171019162109.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171109101135.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171127113945.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171211042454.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20171227031408.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20180202000800.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20180412213253.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20180419060636.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20180530223228.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20180815042610.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20181029233809.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20181122190948.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20181122205748.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20190324081812.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20190420155244.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20190424200651.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20190903121933.js
d8986247cad3bbc2dd92c3a2a06ac1540da6b286 20200112084838.js
Solo seis versiones difieren entre sí, y la última de ellas se refiere a 2016, aunque algunos sitios todavía usan BlockAdBlock. Esto es genial, porque será suficiente para nosotros aplicar ingeniería inversa a la única versión, y luego invertir las diferencias. Spoiler: veremos el desarrollo de ideas e incluso los restos del código de depuración. Publiquétodas las versiones en GitHub . Si desea ver diffs, en este repositorio cada confirmación es una nueva versión.Desempacando
El código del script no está minimizado, sino que está empaquetado por un JS-packer de Dean Edwards con cambios cosméticos y sin ninguna modificación de la lógica 1.eval(function(p, a, c, k, e, d) {
e = function(c) {
return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
};
if (!''.replace(/^/, String)) {
while (c--) {
d[e(c)] = k[c] || e(c)
}
k = [function(e) {
return d[e]
}];
e = function() {
return '\\w+'
};
c = 1
};
while (c--) {
if (k[c]) {
p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c])
}
}
return p
}('0.1("2 3 4 5 6 7 8\'d. 9, h? a b c d e f g");i j=\'a\'+\'k\'+\'e\'+\'l\'+\'n\'+\'m\'+\'e\';',24,24,
'console|log|This|code|will|get|unpacked|then|eval|Cool||||||||huh|let|you|w|s||o'.split('|'),0,{}))
Afortunadamente, esto no es un problema para nosotros. La debilidad del empacador es que todo el código durante el desempaquetado se pasa a eval()
. Si reemplazamos eval()
con algo así console.log()
, de repente obtenemos todo el código fuente, y el empacador es derrotado 2.Una vez hecho esto para cada versión, podemos examinar cada una de ellas y ver qué funciones se agregaron allí con el tiempo.v1 :? - Noviembre de 2015: guión inicial
Código fuenteComencemos con un estudio 20151007203811.js
publicado alrededor de noviembre de 2015 3. Aunque esta primera versión no bloquea muy bien los bloqueadores, le permite evaluar la arquitectura BlockAdBlock sin la basura que se ha acumulado a lo largo de los años.Arquitectura
En tres oraciones:- BlockAdBlock es un cierre que devuelve un objeto con tres funciones:
bab()
pone el cebo y llama un cheque check
check()
comprueba si el bloqueador ha bloqueado el cebo, causando arm
arm()
cubrir
- El punto de entrada
bab()
comienza luego de un período de tiempo especificado.
- Se generan tres funciones con argumentos que se establecen en el configurador BlockAdBlock .
El código se construye alrededor de un cierre asignado a un objeto global con un nombre aleatorio.var randomID = '',
e = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 12; i++) randomID +=
e.charAt(Math.floor(Math.random() * e.length));
var setTimeoutDelay = 7;
window['' + randomID + ''] = ...
El autor proporcionó una aleatorización exhaustiva para evitar el bloqueo estático.A continuación, devuelve un objeto con tres funciones: bab
, check
y arm
.window['' + randomID + ''] = (function() {
var eid = ...
return {
bab: function(check, passed_eid) {},
check: function(checkPredicate, unused) {},
arm: function() {}
}
})();
Estos son mis propios nombres. Todas las variables están minimizadas, y algunas están especialmente ofuscadas.Se bab()
llama al punto de entrada setTimeout()
.setTimeout('window[\'\' + randomID + \'\'] \
.bab(window[\'\' + randomID + \'\'].check, \
window[\'\' + randomID + \'\'].bab_elementid)', setTimeoutDelay * 1000)
bab_elementid
No se utiliza en ninguna versión del código. setTimeout
pasado como una cuerda.Un cierre tiene variables externas. Dos de ellos se usan para guardar el estado en un script:adblockDetected
igual a 1 si se detecta un bloqueador de anuncios.
nagMode
- Esta es una opción de configuración. Si está instalado, el script no bloquea el acceso a la página, sino que solo se enciende una vez.
Otras variables para controlar la apariencia y el comportamiento se establecen en el configurador .var eid = ' ad_box',
__u1 = 1,
overlayColor = '#EEEEEE',
textColor = '#777777',
buttonBackgroundColor = '#adb8ff',
buttonColor = '#FFFFFF',
__u2 = '',
welcomeText = 'Sorry for the interruption...',
primaryText = 'It looks like you\'re using an ad blocker. That\'s okay. Who doesn\'t?',
subtextText = 'But without advertising-income, we can\'t keep making this site awesome.',
buttonText = 'I understand, I have disabled my ad blocker. Let me in!',
adblockDetected = 0,
nagMode = 0,
bab_domain = 'moc.kcolbdakcolb';
bab_domain
establecido aquí en un intento de ofuscar el dominio BlockAdBlock.bab: crea un banner de señuelo
El método principal de trabajar con BlockAdBlock es crear "cebo" o "cebo" a partir de elementos publicitarios que parecen pancartas reales. Luego verifica si su bloqueador ha bloqueado.Esto crea un señuelo: un div falso que finge ser un anuncio pero está oculto a la vista.bab: function(check, passed_eid) {
if (typeof document.body == 'undefined') {
return
};
var delay = '0.1',
passed_eid = eid ? eid : 'banner_ad',
bait = document.createElement('DIV');
bait.id = passed_eid;
bait.style.position = 'absolute';
bait.style.left = '-999px';
bait.appendChild(document.createTextNode(' '));
document.body.appendChild(bait);
...
Aparentemente, está passed_eid
destinado a configurar el identificador del cebo, pero no se utiliza.Después de eso, se verifica si el cebo ha sido eliminado por el bloque de anuncios. ...
setTimeout(function() {
if (bait) {
check((bait.clientHeight == 0), delay);
check((bait.clientWidth == 0), delay);
check((bait.display == 'hidden'), delay);
check((bait.visibility == 'none'), delay);
check((bait.opacity == 0), delay);
check((bait.left < 1000), delay);
check((bait.top < 1000), delay)
} else {
check(true, delay)
}
}, 125)
}
Si el cebo ya no existe, el elemento se elimina (y comenzamos la superposición).La función check
funcionará si Predicate
devuelve un valor true
y comienza arm
.check: function(checkPredicate, unused) {
if ((checkPredicate) && (adblockDetected == 0)) {
adblockDetected = 1;
window['' + randomID + ''].arm()
} else {}
}
Como la prueba se check
dispara varias veces, como se muestra arriba, se adblockDetected
establece en la primera prueba correcta para evitar disparos repetidos arm
.Modo gruñido
El script tiene una función llamada "modo molesto": en este modo, BlockAdBlock solo dirá una vez para deshabilitar el bloqueador de anuncios, pero no lo bloqueará cada vez que lo visite. Esto se hace configurando el elemento localStorage
en la primera visita.Si pudiéramos instalar este elemento nosotros mismos, ¿podríamos desactivar el bloqueo para siempre? Desafortunadamente, BlockAdBlock verifica de antemano si la secuencia de comandos se configuró para modo molesto, por lo que este método no funcionará cuando funcione en modo predeterminado, es decir, con bloqueo de acceso.arm: function() {
if (nagMode == 1) {
var babNag = sessionStorage.getItem('babn');
if (babNag > 0) {
return true
} else {
sessionStorage.setItem('babn', (Math.random() + 1) * 1000)
}
};
...
Desafortunadamente, está nagMode
instalado en el configurador, y por defecto es igual 0
.BlockAdBlock versión 1
Los bloqueadores de anuncios usan los llamados filtros: líneas de código que pueden bloquear solicitudes de red y ocultar elementos en la página. Al crear elementos de cebo, BlockAdBlock lanza específicamente estos filtros.Con esta defensa simple, BlockAdBlock es efectivo contra todos los principales bloqueadores de anuncios como uBlock Origin, AdBlock Plus y Ghostery. Para contrarrestar esto, debemos escribir nuestro propio filtro, que se activa solo en los sitios que ejecutan BlockAdBlock.Escribir filtros para un bloqueador es un poco complicado. Necesitamos un filtro de contenido que bloquee los elementos de la página generados después de la carga. Como el cebo tiene un identificador banner_ad
, creamos una excepción para ocultar elementosmarcado #@#
para todos los elementos #
con un identificador banner_ad
y ponerlo en la lista de filtros de usuario de nuestro bloqueador.El resultado es el siguiente:localhost#@# #banner_ad
Tengo localhost aquí para demostración, puede reemplazarlo con su URL.Esto desactiva correctamente BlockAdBlock. La solución puede parecer simple, pero lleva mucho tiempo funcionando con éxito en la lista de filtros Anti-AdBlock-Killer .Versión 2 (noviembre de 2015 - enero de 2016): varias mejoras
Diferencia de código fuentev1 / v2Creación de cebo: menos errores
Hay un error sutil en la primera versión de crear el cebo: el div creado no tiene contenido, por lo que se genera un div con una altura de 0 y un ancho de 0. Más tarde, el código verifica si el div se elimina al verificar su altura y ancho. Pero como tenía una altura cero, BlockAdBlock siempre funcionó 4.Se corrigió el error de un div vacío.bab: function(...) {
bait = document.createElement('DIV');
...
bait.appendChild(document.createTextNode('Â '));
Se crea un div hijo con algún contenido.Detección de bloqueadores a través de pancartas gráficas falsas
En este método, creamos una imagen falsa con un nombre aleatorio doubleclick.net
. Los bloqueadores de anuncios bloquearán la imagen, pensando que es un banner publicitario. Pero esto no requiere ningún cambio en nuestro filtro.bab: function(...) {
bait = document.createElement('DIV');
bait.innerHTML = '<img src="http://doubleclick.net/' + randomStr() + '.jpg">';
...
randomStr()
genera una cadena de longitud arbitraria.Otra diferencia notable fue el uso de un temporizador en setInterval
lugar de una simple verificación única para ver si hay un disparador instalado. Vuelve a verificar si se muestra el banner gráfico y si no se cambia su atributo src
, verificando el contenido del cebo.Nuevo setInterval
y verifique la disponibilidad de la imagen: ...
checkCallback = setInterval(function() {
if (bait) {
check((bait.clientHeight == 0), delay);
check((bait.clientWidth == 0), delay);
check((bait.display == 'hidden'), delay);
check((bait.visibility == 'none'), delay);
check((bait.opacity == 0), delay);
try {
check((document.getElementById('banner_ad').innerHTML.indexOf('click') == -1), delay)
} catch (e) {}
} else {
check(true, delay)
}
}, 1000
¿Por qué indexof ('click')
? Debido a la fuente de la imagen src="doubleclick.net/abcdefg.jpg"
y verificamos si se conserva el fragmento de la cadena click
.Versión 3 (noviembre de 2015 - marzo de 2016): cebo generalizado
Diferencia de código fuentev2 / v3Creación de cebo: identificadores aleatorios
El único cambio en esta versión, aunque significativo, es la aparición de identificadores aleatorios para el cebo. El nuevo identificador se toma de la lista de identificadores al cargar la página y se usa para el cebo, que ahora se coloca en el medio de la página.Una larga lista de identificadores aleatorios demuestra un buen conocimiento del área temática.var baitIDs = [
"ad-left",
"adBannerWrap",
"ad-frame",
"ad-header",
"ad-img",
"ad-inner",
"ad-label",
"ad-lb",
"ad-footer",
"ad-container",
"ad-container-1",
"ad-container-2",
"Ad300x145",
"Ad300x250",
"Ad728x90",
"AdArea",
"AdFrame1",
"AdFrame2",
"AdFrame3",
"AdFrame4",
"AdLayer1",
"AdLayer2",
"Ads_google_01",
"Ads_google_02",
"Ads_google_03",
"Ads_google_04",
"DivAd",
"DivAd1",
"DivAd2",
"DivAd3",
"DivAdA",
"DivAdB",
"DivAdC",
"AdImage",
"AdDiv",
"AdBox160",
"AdContainer",
"glinkswrapper",
"adTeaser",
"banner_ad",
"adBanner",
"adbanner",
"adAd",
"bannerad",
" ad_box",
" ad_channel",
" adserver",
" bannerid",
"adslot",
"popupad",
"adsense",
"google_ad",
"outbrain-paid",
"sponsored_link"
];
Generación de identificación aleatoria
randomBaitID = baitIDs[ Math.floor(Math.random() * baitIDs.length) ],
...
var passed_eid = randomBaitID;
bait = document.createElement('DIV');
bait.id = passed_eid;
Como esto funciona en cada arranque, el identificador será diferente cada vez.BlockAdBlock, penúltima versión
BlockAdBlock explota el punto ciego de los bloqueadores de anuncios: si un filtro omite todos los identificadores anteriores, también omitirá los anuncios reales. Por lo tanto, BlockAdBlock obliga al bloqueador de anuncios a volverse inútil .En los bloqueadores, podemos ejecutar scripts arbitrarios antes de cargar la página. Puede intentar eliminar el objeto BlockAdBlock de antemano. Pero para esto necesitamos el nombre del objeto BlockAdBlock, que se aleatoriza cada vez que se inicia.uBlock Origin tomó un enfoque diferente. Dado que el código es ejecutado por una función eval
, podemos definir nuestra propia función eval
que bloqueará la ejecución si encontramos BlockAdBlock. En JS, un objeto es capaz de esto Proxy
: puede reemplazar cualquier propiedad y método en cualquier objeto.Esto se puede evitar al no pasar la carga útil inicial de BlockAdBlock eval
, sino al usarla directamente, por lo que también representamos el punto de entrada: la llamada setTimeout
. Como lo setTimeout
pasa una cadena, no una función, verificamos esta cadena.Implementación en uBlock Origin ( fuente ):const signatures = [
[ 'blockadblock' ],
[ 'babasbm' ],
[ /getItem\('babn'\)/ ],
[
'getElementById',
'String.fromCharCode',
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
'charAt',
'DOMContentLoaded',
'AdBlock',
'addEventListener',
'doScroll',
'fromCharCode',
'<<2|r>>4',
'sessionStorage',
'clientWidth',
'localStorage',
'Math',
'random'
],
];
const check = function(s) {
};
Lista de firmas: definición de plantillas de código. La función check
verifica la cadena después eval
para el cumplimiento de estos patrones.A continuación, delegue las funciones eval
y setTimeout
.window.eval = new Proxy(window.eval, {
apply: function(target, thisArg, args) {
const a = args[0];
if ( typeof a !== 'string' || !check(a) ) {
return target.apply(thisArg, args);
}
if ( document.body ) {
document.body.style.removeProperty('visibility');
}
let el = document.getElementById('babasbmsgx');
if ( el ) {
el.parentNode.removeChild(el);
}
}
});
window.setTimeout = new Proxy(window.setTimeout, {
apply: function(target, thisArg, args) {
const a = args[0];
if (
typeof a !== 'string' ||
/\.bab_elementid.$/.test(a) === false
) {
return target.apply(thisArg, args);
}
}
});
Como ahora estamos usando un scriptlet , un fragmento de código personalizado especial ejecutado por el bloqueador, el filtro cambia un poco:localhost## +js(nobab)
No se inicia de manera predeterminada en todos los sitios por razones de rendimiento, por lo que debe asignarlo a cada sitio mediante un script.Versión 4 (enero de 2016 - abril de 2016): funciones experimentales
Diferencia de código fuente v3 / v4El método descrito para bloquear los anti-bloqueadores se desarrolló en enero de 2016, de acuerdo con la historia de los compromisos de uBlock Origin , y no ha cambiado conceptualmente desde su inicio. BlockAdBlock nunca intentó evitar este filtro cambiando su arquitectura. En cambio, continuó desarrollando nuevas características. Y cuando vamos a la página BlockAdBlock, vemos una pestaña interesante: "¿Necesita más poder antibloqueo?"
Aunque estos métodos de protección están disponibles solo a través de una pestaña especial, se incluyen en todos los scripts y se ejecutan a través de variables con los nombres correspondientes. La cuarta versión implementa dos métodos:aDefOne
, "Protección específica para sitios adsense"
aDefTwo
, "Característica de seguridad especial"
Comentarios de depuración aleatorios
Antes de despedirme, debo mencionar una cosa más. En el proceso de ingeniería inversa, una función me llamó la atención: ¡Depuración console.log()
directamente en el código!function consolelog(e) {
if (window.consolelog == 1) {
console.log(e)
}
};
Esto solo se hace si se establece global consolelog
, por ejemplo window.consolelog = 1
.Los comentarios de depuración solo están disponibles en esta versión. Si no hubiera revertido todas las versiones, nunca las habría notado. Proporcionan información valiosa sobre cómo funciona el código.Seguridad avanzada: AdSense
Todos estos métodos de protección especiales están codificados en check
, no en arm
, como sugiere la arquitectura. Quizás un nuevo desarrollador que no esté familiarizado con el código base haya comenzado a trabajar en el producto.Si AdSense está activo en la página, buscamos anuncios. Si desaparecieron debido a un bloqueador, BlockAdBlock se activa.function check() {
...
var q = 'ins.adsbygoogle',
adsbygoogleQuery = document.querySelector(q);
if ((adsbygoogleQuery) && (adblockDetected == 0)) {
if (aDefOne == 'yes') {
consolelog('case2: standard bait says ads are NOT blocked.');
var adsbygoogle = '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
if (scriptExists(adsbygoogle)) {
consolelog('case2: And Adsense pre-exists.');
if (adsbygoogleQuery.innerHTML.replace(/\s/g, '').length == 0) {
consolelog('case2: Ads are blocked.');
window['' + randomID + ''].arm()
}
}
};
adblockDetected = 1
}
...
scriptExists
busca en la página completa un script con una URL dada. En este caso, el script de AdSense 5.La URL de la secuencia de comandos se compara con todas las secuencias de comandos de la página. Por alguna razón, la URL se trunca a 15 caracteres.function scriptExists(href) {
if (href) href = href.substr(href.length - 15);
var scripts = document.getElementsByTagName('script');
for (var i = scripts.length; i--;) {
var src = String(scripts[i].src);
if (src) src = src.substr(src.length - 15);
if (src === href) return true
};
return false
};
Protección avanzada: elemento especial
A diferencia del primero, este método va acompañado de un descargo de responsabilidad: "Realice una prueba después de la instalación para garantizar la compatibilidad con su sitio".Esta protección especial solo funciona si no se encuentra un bloqueador y no hay un script de AdSense en la página. Aquí está el fragmento de código relevante check
:check: function(checkPredicate, unused) {
if ((checkPredicate) && (adblockDetected == 0)) {
} else {
var q = 'ins.adsbygoogle',
adsbygoogleQuery = document.querySelector(q);
if ((adsbygoogleQuery) && (adblockDetected == 0)) {
if (aDefOne == 'yes') {
};
} else {
if (adblockDetected == 0) {
if (aDefTwo == 'yes') {
}
}
}
}
El método supone que los propietarios de sitios usan solo AdSense: si no existe un script de AdSense, entonces algo está mal.¿Por qué hubo una advertencia? Este método intenta habilitar el script de AdSense. Si no se carga, lo más probable es que el bloqueador haya bloqueado la solicitud de red, por lo tanto, se activa BlockAdBlock. Pero esto puede arruinar algunos sitios, de ahí la advertencia.Si AdSense no se ha cargado, se inicia la superposición.if (aDefTwo == 'yes') {
var googleAdCode = '//static.doubleclick.net/instream/ad_status.js';
consolelog('case3: standard bait says ads are NOT blocked. Maybe ???\
No Adsense is found. Attempting to add Google ad code to head...');
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', googleAdCode);
script.onerror = function() {
window['' + randomID + ''].arm()
};
adblockDetected = 1;
if (!scriptExists(googleAdCode)) {
document.getElementsByTagName('head')[0].appendChild(script)
};
adsbygoogleQuery = 0;
window['' + randomID + ''].check = function() {
return
}
}
Cuando ocurre una falla a nivel de red, funciona onerror
, como con un bloqueador de anuncios.De hecho, la mayoría de los bloqueadores de anuncios responden a esto y bloquean la solicitud. Pero hay un bloqueador que aún no he mencionado. Habla sobre el navegador Brave .Respuesta valiente del navegador
Hasta ahora, hemos estado estudiando cómo se detecta el antibloqueo en uBlock Origin. Y funciona, solo se requiere un filtro específico para cada sitio donde está instalado BlockAdBlock. El navegador Brave es impresionante porque detecta y omite BlockAdBlock de todas las versiones sin ninguna acción necesaria por parte del usuario. Para hacer esto, falsifica la solicitud directamente en la capa de red 6.En lugar de bloquear la solicitud, ad_status.js
la omite, pero carga Google Ads falsos de 0 bytes de tamaño . Este truco engañoso engaña a BlockAdBlock, porque onerror
solo funciona si la solicitud de red falla.Versión 5 (marzo de 2016 - noviembre de 2016)
Diferencia de código fuentev4 / v5Protección avanzada: favicons de spam
El único cambio en esta versión es que la segunda protección extendida se reescribió, aunque todavía se adhiere al mismo principio básico: verificar las solicitudes de red que serán bloqueadas por el bloqueador. Pero ahora se están cargando favicons en lugar de AdSense.Valiente evade este ataque de la misma manera. No bloquea las solicitudes, pero crea imágenes falsas 1 × 1.if (aDefTwo == 'yes') {
if (! window['' + randomID + ''].ranAlready) {/
var favicons = [
"//www.google.com/adsense/start/images/favicon.ico",
"//www.gstatic.com/adx/doubleclick.ico",
"//advertising.yahoo.com/favicon.ico",
"//ads.twitter.com/favicon.ico",
"//www.doubleclickbygoogle.com/favicon.ico"
],
len = favicons.length,
img = favicons[Math.floor(Math.random() * len)],
...
baitImages(Math.floor(Math.random() * 2) + 1);
var m = new Image();
m.onerror = function() {
baitImages(Math.floor(Math.random() * 2) + 1);
c.src = imgCopy;
baitImages(Math.floor(Math.random() * 2) + 1)
};
c.onerror = function() {
adblockDetected = 1;
baitImages(Math.floor(Math.random() * 3) + 1);
window['' + randomID + ''].arm()
};
m.src = img;
baitImages(Math.floor(Math.random() * 3) + 1);
window['' + randomID + ''].ranAlready = true
};
}
La función baitImages
se puede llamar con frecuencia, con un número aleatorio de imágenes, para evitar bloqueadores estáticos.Versión 6 (abril de 2016 - noviembre de 2016): Brave lock
Diferencia de código fuente v5 / v6Los métodos BlockAdBlock, aunque simples a primera vista, gradualmente se volvieron más complejos y más eficientes. Pero el último enemigo invicto permaneció: el navegador Brave.Protección avanzada: definición de un falso icono
¿Por qué BlockAdBlock cambió de intentar cargar un script para cargar imágenes (favicons)? La respuesta está en el código que se agrega a la protección a través de favicons de spam y que se activa contra la protección de Brave.Verificando la respuesta para una imagen falsa:if (aDefTwo == 'yes') {
baitImages(Math.floor(Math.random() * 3) + 1);
var m = new Image();
if ((aDefThree % 3) == 0) {
m.onload = function() {
if ((m.width < 8) && (m.width > 0)) {
window['' + randomID + ''].arm()
}
}
};
}
Si el tamaño del favicon es inferior a 8 × 8, entonces esto es probablemente falso del navegador Brave.Con este truco, BlockAdBlock evita el disfraz de Brave y otros bloqueadores que ejecutan este código (la mayoría, como uBlock Origin, lo bloquea primero).Después de esta actualización, a fines de noviembre de 2016, BlockAdBlock desapareció de Internet. Aunque sus "métodos de seguridad avanzados" funcionan, nunca se han activado para la mayoría de los usuarios. Esta fue la última actualización. La última publicación en Twitter y en el sitio se publicó en algún lugar a fines de 2017.Sin embargo, el legado de BlockAdBlock sigue vivo. Aunque es trivial bloquearlo en estos días, algunos sitios modernos todavía usan este script.Conclusión
¿Quién ganará la carrera armamentista entre los bloqueadores de anuncios y los antibloqueadores que bloquean los bloqueadores de anuncios? Sólo el tiempo dirá. A medida que se desarrolle la carrera armamentista, los antibloqueadores tendrán que usar métodos más sofisticados y códigos especiales, como lo demuestra la evolución de BlockAdBlock.Por otro lado, los bloqueadores tienen la ventaja de sistemas estables y potentes herramientas de filtrado a través de listas de filtros, así como acceso a JavaScript. Con dicho sistema, es suficiente que una persona entienda cómo vencer al enemigo y actualice la lista de filtros con nuevos sitios.Al analizar la evolución de BlockAdBlock, así como las diversas respuestas de los bloqueadores de anuncios, pudimos pintar una imagen de una pequeña guerra entre BlockAdBlock y los bloqueadores. En el proceso, aprendimos qué métodos se usan en las hostilidades.Mi código de ingeniería inversa se publica en GitHub . Gracias por leer.
1. Si desea tener una idea de cómo funciona esto, intente pegar el siguiente ejemplo en la consola JS y luego mire el código. Si está interesado en su funcionamiento interno, aquí está el código fuente . ︎ [volver]2. ¿No lo crees? Intenta cambiar eval
a console.log
en la primera línea.[regresar]3. La marca de tiempo dice 201510
, entonces quizás octubre. Pero no sabemos cuándo cambió el guión. Todo lo que sabemos:- 2015-10, se guardó una versión:
20151007203811.js
- 2015-11 hay una nueva versión:
20151113115955.js
Hasta donde sabemos, el script podría cambiarse el día anterior a la segunda marca de tiempo. Por lo tanto, me acerco conservadoramente a las citas. ︎ [volver]4. Durante la corrección de este error se desarrollaron pruebas para v1. ︎ [volver]5. Gracias a McStroyer en Reddit, que llamó la atención sobre esto. ︎ [volver]6. El componente bloqueador de anuncios Brave está abierto, por lo que podemos ver el código fuente para tener una idea de cómo funciona.Gracias a François Marie por señalar el código fuente de Brave. ︎ [volver]