From 41fcc10ad3c324dded4777535e3c55b1da7a9335 Mon Sep 17 00:00:00 2001 From: xd4rker Date: Sun, 8 Oct 2017 23:16:29 +0100 Subject: [PATCH] Added feature to block inline scripts (coinhive), Added crypto-loot filter --- assets/filters.txt | 3 +- js/background.js | 34 ++++++-- js/content.js | 31 +++++++ js/minerkill.js | 31 +++++++ js/options.js | 74 ++++++++-------- js/utils.js | 208 ++++++++++++++++++++++----------------------- manifest.json | 14 ++- options.html | 2 +- popup.html | 2 +- 9 files changed, 248 insertions(+), 151 deletions(-) create mode 100644 js/content.js create mode 100644 js/minerkill.js diff --git a/assets/filters.txt b/assets/filters.txt index 98fd07a..d58831a 100644 --- a/assets/filters.txt +++ b/assets/filters.txt @@ -12,4 +12,5 @@ *://*.coinhive.com/proxy* *://*.coinhive.com/captcha* *://*.minemytraffic.com/lib* -*://*.2giga.link/js* \ No newline at end of file +*://*.2giga.link/js* +*://*.crypto-loot.com/lib* \ No newline at end of file diff --git a/js/background.js b/js/background.js index 29f318a..7c297bc 100644 --- a/js/background.js +++ b/js/background.js @@ -1,8 +1,5 @@ 'use strict'; -//utils.clearSettings(); -//return; - var pauseIcon = 'icons/icon_off.png', startIcon = 'icons/icon.png', mbTabs = {}, @@ -116,6 +113,17 @@ function updateBadge(mcount, tabId) { }); } +function addmbTab(tabId, rootDomain) { + if(tabId in mbTabs) { + if(mbTabs[tabId].indexOf(rootDomain) === -1) { + mbTabs[tabId].push(rootDomain); + } + + } else { + mbTabs[tabId] = [rootDomain]; + } +} + function handleOnUpdatedListener(tabId, changeInfo, tab) { let tabwIndex = mbwTabs.indexOf(tabId); @@ -153,7 +161,7 @@ function handleOnBeforeRequest(details) { } let rootDomain = utils.getRootDomain(details.url); - if(details.tabId in mbTabs) { + if(details.tabId in mbTabs) { if(mbTabs[details.tabId].indexOf(rootDomain) === -1) { mbTabs[details.tabId].push(rootDomain); } @@ -219,11 +227,27 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { mbwTabs.splice(tabwIndex, 1); } - } else if(message.action == 'optionUpdated') { urls = []; mbwTabs = []; initBackground(); + + } else if(message.action == 'minerBlockedFromContent') { + + addmbTab(sender.tab.id, message.minerUrl); + + if(mbSettings['mbShowCount']) { + updateBadge(mbTabs[sender.tab.id].length, sender.tab.id); + } + + } else if(message.action == 'getmKillStatus') { + if(mbSettings['mbRunStatus'] === false) { + sendResponse({mKillStatus: false}); + + } else { + let isUrlwListed = utils.checkWhiteList(utils.getRootDomain(message.url), mbSettings['mbWhiteList']); + sendResponse({mKillStatus: !isUrlwListed}); + } } }); diff --git a/js/content.js b/js/content.js new file mode 100644 index 0000000..db7ea67 --- /dev/null +++ b/js/content.js @@ -0,0 +1,31 @@ +(function () { + + 'use strict'; + + function injectmKiller(status) { + if(status) { + var node = document.getElementsByTagName('body')[0]; + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.setAttribute('src', chrome.extension.getURL('js/minerkill.js')); + node.appendChild(script); + } + } + + function initmKiller() { + chrome.runtime.sendMessage({action: 'getmKillStatus', url: location.host}, function(res) { + injectmKiller(res.mKillStatus); + }); + } + + document.onreadystatechange = function () { + if (document.readyState === "complete") { + initmKiller(); + } + } + + document.addEventListener('minerBlocked', function(e) { + chrome.runtime.sendMessage({action: 'minerBlockedFromContent', minerUrl: e.detail.minerUrl}, function() {}); + }, false); + +}()); \ No newline at end of file diff --git a/js/minerkill.js b/js/minerkill.js new file mode 100644 index 0000000..736c91d --- /dev/null +++ b/js/minerkill.js @@ -0,0 +1,31 @@ +'use strict'; + +function triggerEvent(miner) { + let event = new CustomEvent('minerBlocked', { + detail: { + minerUrl: miner + } + }); + document.dispatchEvent(event); +} + +let event = new Event('minerBlocked'); + +for(let name in this) { + + if(name === 'webkitStorageInfo') { + continue; + } + + // Check coinhive miner + + if( this[name] + && typeof this[name] !== 'undefined' + && typeof this[name].isRunning === 'function' + && typeof this[name].stop === 'function') { + console.log('[+] Coinhive miner found, stopping...'); + this[name].stop(); + this[name] = null; + triggerEvent('coinhive.com'); + } +} \ No newline at end of file diff --git a/js/options.js b/js/options.js index a444734..55df0dc 100644 --- a/js/options.js +++ b/js/options.js @@ -11,23 +11,23 @@ function initOptionPage() { - utils = chrome.extension.getBackgroundPage().utils; + utils = chrome.extension.getBackgroundPage().utils; selectElement = document.getElementById('mbWhiteList'); - toggleTab(document.getElementsByClassName('tablinks')[0], 0); - loopEls('tablinks', addTabClickListener); + toggleTab(document.getElementsByClassName('tablinks')[0], 0); + loopEls('tablinks', addTabClickListener); - loopEls('opt', function(e) { + loopEls('opt', function(e) { - utils.getOption(e.id, function(value) { - updateOption(e, value); - }); + utils.getOption(e.id, function(value) { + updateOption(e, value); + }); if(e.tagName === 'INPUT' && e.getAttribute('type') === 'checkbox') { e.addEventListener('click', toggleCheckBox); } - }); + }); loopEls('btn', function(e) { if(e.id === 'mbUserFiltersSave') { @@ -121,7 +121,7 @@ function populateSelect(e, value) { e.innerHTML = ''; - let prop; + let prop; for(prop in value) { let optTag = document.createElement("option"); optTag.value = prop; @@ -131,49 +131,49 @@ } function updateOption(e, value) { - if(e.tagName === 'INPUT' && e.getAttribute('type') === 'checkbox') { - e.checked = value; + if(e.tagName === 'INPUT' && e.getAttribute('type') === 'checkbox') { + e.checked = value; - } else if(e.tagName === 'TEXTAREA') { + } else if(e.tagName === 'TEXTAREA') { if(value !== null) { e.value = value.join('\n'); } - } else if (e.tagName === 'SELECT') { - populateSelect(e, value); + } else if (e.tagName === 'SELECT') { + populateSelect(e, value); - } + } } function addTabClickListener(el ,index) { - el.addEventListener('click', function () { - toggleTab(el, index); - }); + el.addEventListener('click', function () { + toggleTab(el, index); + }); } function toggleContainers(activeIndex) { - loopEls('tab-cnt', function(e, i) { - if(i === activeIndex) { - e.style.display = 'block'; - } else { - e.style.display = 'none'; - } - }); + loopEls('tab-cnt', function(e, i) { + if(i === activeIndex) { + e.style.display = 'block'; + } else { + e.style.display = 'none'; + } + }); } function toggleTab(elm, elIndex) { - elm.style.backgroundColor = '#fff'; - elm.style.borderBottom = '1px solid #fff'; - - loopEls('tablinks', function(el, index) { - if(index === elIndex) { - return; - } - el.style.backgroundColor = '#eee'; - el.style.borderBottom = '1px solid #ccc'; - toggleContainers(elIndex); - - }); + elm.style.backgroundColor = '#fff'; + elm.style.borderBottom = '1px solid #fff'; + + loopEls('tablinks', function(el, index) { + if(index === elIndex) { + return; + } + el.style.backgroundColor = '#eee'; + el.style.borderBottom = '1px solid #ccc'; + toggleContainers(elIndex); + + }); } function notifyBackground() { diff --git a/js/utils.js b/js/utils.js index 8fd516b..522a041 100644 --- a/js/utils.js +++ b/js/utils.js @@ -4,110 +4,110 @@ var utils = { - noop: function() {}, - - getDefaultSettings: function() { - - let dfSettings = {}; - dfSettings['mbShowCount'] = true; - dfSettings['mbShowAlert'] = false; - dfSettings['mbRunStatus'] = true; - dfSettings['mbFilters'] = true; - dfSettings['mbWhiteList'] = []; - dfSettings['mbUserFilters'] = []; - - return dfSettings; - }, - - getSettings: function(callback) { - let self = this; - chrome.storage.local.get('mbSettings', function(res) { - if((Object.keys(res).length) === 0) { - res = self.getDefaultSettings(); - self.setSettings(res); - callback(res); - } else { - callback(res.mbSettings); - } - }); - - }, - - setSettings: function(settings, callback) { - callback = (callback === undefined) ? this.noop : callback; - chrome.storage.local.set({'mbSettings' : settings}, callback); - }, - - clearSettings: function(callback) { - callback = (callback === undefined) ? this.noop : callback; - chrome.storage.local.clear(callback); - }, - - setOption: function(option, value, callback) { - let self = this; - this.getSettings(function(res) { - res[option] = value; - self.setSettings(res, callback); - }); - }, - - getOption: function(option, callback) { - let self = this; - this.getSettings(function(res) { - if(typeof(res[option]) === 'undefined') { - let dfSettings = self.getDefaultSettings(); - res[option] = dfSettings[option]; - self.setOption(option, dfSettings[option], function() { - callback(dfSettings[option]); - }); - } else { - callback(res[option]); - } - }); - }, - - cleanArray: function(arr) { - return arr.map(function(e){ - return e.trim(); - }).filter(function(str) { - return /\S/.test(str); - }); - }, - - isValidFilter: function(filter) { - return /^\*:\/\/\*\..*\/.*?\*$/.test(filter); - }, - - getRootDomain: function(url) { - // https://stackoverflow.com/a/23945027 (forgive my laziness -.-) - var hostname, - domain, - splitArr, - arrLen; - if (url.indexOf("://") > -1) { - hostname = url.split('/')[2]; - } else { - hostname = url.split('/')[0]; - } - hostname = hostname.split(':')[0]; - hostname = hostname.split('?')[0]; - - domain = hostname; - splitArr = domain.split('.'); - arrLen = splitArr.length; - if(arrLen > 2) { - domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; - } - return domain; - }, - - checkWhiteList: function(url, array) { - if(array === null) { - return false; - } else { - return (array.indexOf(url) > -1); - } - }, + noop: function() {}, + + getDefaultSettings: function() { + + let dfSettings = {}; + dfSettings['mbShowCount'] = true; + dfSettings['mbShowAlert'] = false; + dfSettings['mbRunStatus'] = true; + dfSettings['mbFilters'] = true; + dfSettings['mbWhiteList'] = []; + dfSettings['mbUserFilters'] = []; + + return dfSettings; + }, + + getSettings: function(callback) { + let self = this; + chrome.storage.local.get('mbSettings', function(res) { + if((Object.keys(res).length) === 0) { + res = self.getDefaultSettings(); + self.setSettings(res); + callback(res); + } else { + callback(res.mbSettings); + } + }); + + }, + + setSettings: function(settings, callback) { + callback = (callback === undefined) ? this.noop : callback; + chrome.storage.local.set({'mbSettings' : settings}, callback); + }, + + clearSettings: function(callback) { + callback = (callback === undefined) ? this.noop : callback; + chrome.storage.local.clear(callback); + }, + + setOption: function(option, value, callback) { + let self = this; + this.getSettings(function(res) { + res[option] = value; + self.setSettings(res, callback); + }); + }, + + getOption: function(option, callback) { + let self = this; + this.getSettings(function(res) { + if(typeof(res[option]) === 'undefined') { + let dfSettings = self.getDefaultSettings(); + res[option] = dfSettings[option]; + self.setOption(option, dfSettings[option], function() { + callback(dfSettings[option]); + }); + } else { + callback(res[option]); + } + }); + }, + + cleanArray: function(arr) { + return arr.map(function(e){ + return e.trim(); + }).filter(function(str) { + return /\S/.test(str); + }); + }, + + isValidFilter: function(filter) { + return /^\*:\/\/\*\..*\/.*?\*$/.test(filter); + }, + + getRootDomain: function(url) { + // https://stackoverflow.com/a/23945027 (forgive my laziness -.-) + var hostname, + domain, + splitArr, + arrLen; + if (url.indexOf("://") > -1) { + hostname = url.split('/')[2]; + } else { + hostname = url.split('/')[0]; + } + hostname = hostname.split(':')[0]; + hostname = hostname.split('?')[0]; + + domain = hostname; + splitArr = domain.split('.'); + arrLen = splitArr.length; + if(arrLen > 2) { + domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; + } + return domain; + }, + + checkWhiteList: function(url, array) { + if(array === null) { + return false; + } else { + return (array.indexOf(url) > -1); + } + }, }; diff --git a/manifest.json b/manifest.json index 8274896..411bcb5 100644 --- a/manifest.json +++ b/manifest.json @@ -2,12 +2,19 @@ "manifest_version": 2, "name": "minerBlock", "description": "Blocks cryptocurrency miners all over the web.", - "version": "0.4.3", + "version": "0.4.5", "options_page": "options.html", "background": { "scripts": ["js/utils.js", "js/background.js"], "persistent": true }, + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["js/content.js"], + "run_at": "document_start" + } + ], "icons": { "19": "icons/icon.png", "48": "icons/icon_48.png", @@ -26,5 +33,8 @@ "webRequest", "webRequestBlocking", "" + ], + "web_accessible_resources": [ + "js/minerkill.js" ] -} +} \ No newline at end of file diff --git a/options.html b/options.html index 547efa2..0065ced 100644 --- a/options.html +++ b/options.html @@ -63,7 +63,7 @@

-

MinerBlock v0.4.3

+

MinerBlock v0.4.5

Please email your feedback to cryptominedev@gmail.com.


diff --git a/popup.html b/popup.html index bf3c218..dd3f2bd 100644 --- a/popup.html +++ b/popup.html @@ -9,7 +9,7 @@
-
MinerBlock
Version 0.4.3
+
MinerBlock
Version 0.4.5