fuckadblock插件的分析与绕过
0x01 简介
最近在访问csdn的时候,总是弹出您正在使用adblock。我日你娘,老子用插件还烦我?于是打开F12,开始分析一波
我认为吧,对于这种js,chrome动态打断点+静态分析,多锻炼自然会了。权当抛砖引玉啦,大神们看看就好
0x02 check-adblock.js
这个js的内容比较短,直接贴出代码就好
!
function() {
var c, e;
function t() {
console.log("AdBlock is not enabled")
}
function n() {
var c, e, t;
console.log("Adblock is enabled"),
c = "adblock",
e = {
step: "install"
},
t = window.location.protocol + "//statistic.csdn.net/",
$.get(t + c, e);
var n; !
function() {
var c = document.createElement("div");
c.innerHTML = '<div class="adblock"><img src="https://g.csdnimg.cn/check-adblock/1.0.0/img/monkey@2x.png"/><span>亲爱的用户,您使用了广告屏蔽软件,广告是CSDN向您免费提供服务与产品的重要支持,希望您将csdn.net加入AdBlock Plus<a class="check_a" href="https://bbs.csdn.net/topics/392458005" target="_blank">白名单</a>,感谢支持!</span><em class="check_close"><svg t="1539053811268" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7199" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 438.378667L806.506667 143.893333a52.032 52.032 0 1 1 73.6 73.621334L585.621333 512l294.485334 294.485333a52.074667 52.074667 0 0 1-73.6 73.642667L512 585.621333 217.514667 880.128a52.053333 52.053333 0 1 1-73.621334-73.642667L438.378667 512 143.893333 217.514667a52.053333 52.053333 0 1 1 73.621334-73.621334L512 438.378667z" fill="#8a8a8a" p-id="7200"></path></svg></div>';
var e = document.body.firstChild;
document.body.insertBefore(c, e)
} (),
$(".check_close").length && $(".check_close").on("click",
function(c) {
c.stopPropagation(),
$(this).parents(".adblock").remove(),
"function" == typeof window.csdn.insertcallbackBlock && window.csdn.insertcallbackBlock()
}),
(n = new Date).setDate(n.getDate() + 7),
document.cookie = "c_adb=1; expires=" + n.toGMTString() + "; domain=csdn.net; path=/",
"function" == typeof window.csdn.insertcallbackBlock && window.csdn.insertcallbackBlock()
}
if (void 0 === window.csdn && (window.csdn = {}), c = "https://g.csdnimg.cn/check-adblock/1.0.8/css/check-adblock.css", (e = document.createElement("link")).rel = "stylesheet", e.type = "text/css", e.href = c, document.getElementsByTagName("head")[0].appendChild(e), "undefined" != typeof fuckAdBlock || "undefined" != typeof FuckAdBlock)
n();
else {
var o = document.createElement("script");
o.onload = function() {
fuckAdBlock.onDetected(n),
fuckAdBlock.onNotDetected(t)
},
o.onerror = function() {
n()
},
o.type = "text/javascript",
o.src = "https://g.csdnimg.cn/lib/fuckadblock/3.2.1/fuckadblock.min.js",
document.head.appendChild(o)
}
} ();
这个js会运行(废话)。函数t与函数n的作用很明显,t是未检测到adblock时运行的函数,函数n时检测到adblock时运行的函数。在函数t中,主要行为是:
- 访问https://statistic.csdn.net/adblock?step=install,推测是上报并统计adblock的数量
- 在网页最顶端创建一个div,用以提示用户,你正在使用adblock
- 创建一个key为c_adb的cookie
该函数首先会从第33行的if开始运行。而且,那行比较长的代码,其实都是if中判断语句。
void 0 === window.csdn && (window.csdn = {}), c = "https://g.csdnimg.cn/check-adblock/1.0.8/css/check-adblock.css", (e = document.createElement("link")).rel = "stylesheet", e.type = "text/css", e.href = c, document.getElementsByTagName("head")[0].appendChild(e), "undefined" != typeof fuckAdBlock || "undefined" != typeof FuckAdBlock
按照逗号,一个一个的执行,然后检查fuckAdBlock这个对象。
这行作用是,创建一个adblock一定会拦截的css,然后检查。如果检测到fuckAdBlock这个对象,说明存在adblock,然后提示用户。这个判断主要是在页面完全加载后,如果再有判断adblock的任务,则无需调用检测,直接就可以完成。
如果是页面刚加载的时候,是会绕过这个if的。所以,会创建一个script标签,src是fuckadblock的代码。然后创建一个onload事件,去调用fuckAdBlock。
0x03 fuckadblock.min.js
这个代码有点长,直接截图分析吧。。。
这个代码会创建一个FuckAdBlock的类,也就是图中的e。首先会执行构造函数(深受java荼毒,不太会描述)。设置window的onload事件,也就是等待页面加载完之后再执行check函数。在onload的o函数中,再延迟1秒钟执行check函数,推测是为了更准确的检测adblock,防止出现页面未加载完而导致的判断失效。
然后开始分析check函数。check函数混淆的比较严重,我精简了一下。该函数的主要作用是:
- 调用_checkBait创建一个页面上不可见,但是一定会被adblock拦截的div
- 调用setTimeout,设置1秒钟后调用_checkBai函数,检测刚才创建的div对象是否还存在。
我们可以通过动态调试的方式,看一下_checkBait所创建的div是什么样子的。
1. _checkBai函数
这个嘛,先通过getComputedStyle获取刚才创建的div的css,然后对比一下。然后调用emitEvent返回结果。
可以看一下if语句中的内容
null !== t.document.body.getAttribute("abp") || null === this._var.bait.offsetParent || 0 == this._var.bait.offsetHeight || 0 == this._var.bait.offsetLeft || 0 == this._var.bait.offsetTop || 0 == this._var.bait.offsetWidth || 0 == this._var.bait.clientHeight || 0 == this._var.bait.clientWidth) && (i = !0), void 0 !== t.getComputedStyle
如果找到创建的这个div对象,说明没有adblock。设置变量i为false。否则,就是已经被adblock拦截。设置i为true。在最后一行代码,判断i,并调用emitEvent。
2. emitEvent函数
e.prototype.emitEvent = function (t) {
this._options.debug === !0 && this._log("emitEvent", "An event with a " + (t === !0 ? "positive" : "negative") + " detection was called");
var e = this._var.event[t === true ? "detected" : "notDetected"];
for (var i in e) this._options.debug === !0 && this._log("emitEvent", "Call function " + (parseInt(i) + 1) + "/" + e.length),
e.hasOwnProperty(i) && e[i]();
return this._options.resetOnEnd === !0 && this.clearEvent(),
this
}
该函数作用根据上一步的结果,调用相应的函数。可以看一下this._var.event里面的内容。如图
可以明了哇,如果detected有多个函数的话,则分别调用。有点像观察者模式了。那么现在有个疑问,detected是啥时候设置的呢?我们要回到开头check-adblock.js中创建script时设置的onload时间
fuckAdBlock.onDetected(n),
fuckAdBlock.onNotDetected(t)
然后看一下fuckAdBlock.onDetected函数
e.prototype.on = function(t, e) {
return this._var.event[t === !0 ? "detected": "notDetected"].push(e),
this._options.debug === !0 && this._log("on", 'A type of event "' + (t === !0 ? "detected": "notDetected") + '" was added'),
this
},
e.prototype.onDetected = function(t) {
return this.on(!0, t)
},
e.prototype.onNotDetected = function(t) {
return this.on(!1, t)
},
主要是根据相应的事件,添加到对应的数组里,其中,e.prototype.on的第一行代码this._var.event[t === !0 ? "detected": "notDetected"].push(e)
中的push是关键,其中,e是对应事件的处理函数。
至此,就分析完流程了。下面讲一下如何bypass
0x04 tampermonky插件
tampermonky插件可以通过安装各类脚本对网站进行定制。我们只需要写一个脚本就行啦。
-
右键添加新脚本
-
在弹出的界面中输入以下代码
// ==UserScript== // @name Fuck FuckAdblock // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author Potatso // @match *://blog.csdn.net/* // match 是设置该脚本适用的网站 // @grant none // ==/UserScript== (function() { 'use strict'; // 等待window加载完,将FuckAdBlock的check函数替换为我们自己的函数 window.addEventListener('load', function() { FuckAdBlock.prototype.check = function(t) {} }, false); })();
-
然后点击文件,保存即可
检查一下,完成