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

Сразу покажу пример, чтобы не мусолить (тестировал на последнем Хроме, который у меня был):

var gn = Object.getOwnPropertyNames.bind(Object)

var f = function(o) {
    if(f.caller && f.caller.toString && 
       f.caller.toString().indexOf('object&&ArrayBuffer.isView(o)&&o.length>9999') > 0) {
        console.log(f.caller)
    }
    return gn(o);
}
Object.getOwnPropertyNames = f

Если начать что-то вводить в консоль после запуска кода выше, то при вводе в консоль начнет выпадать какая-то функция.

Вот эта:

(function getCompletions(type) {
    var object;
    if (type === 'string')
        object = new String('');
    else if (type === 'number')
        object = new Number(0);
    else if (type === 'boolean')
        object = new Boolean(false);
    else
        object = this;
    var result = [];
    try {
        for (var o = object; o; o = Object.getPrototypeOf(o)) {
            if ((type === 'array' || type === 'typedarray') && o === object && ArrayBuffer.isView(o) && o.length > 9999)
                continue;
            var group = {
                items: [],
                __proto__: null
            };
            try {
                if (typeof o === 'object' && o.constructor && o.constructor.name)
                    group.title = o.constructor.name;
            } catch (ee) {}
            result[result.length] = group;
            var names = Object.getOwnPropertyNames(o);
            var isArray = Array.isArray(o);
            for (var i = 0; i < names.length; ++i) {
                if (isArray && /^[0-9]/.test(names[i]))
                    continue;
                group.items[group.items.length] = names[i];
            }
        }
    } catch (e) {}
    return result;
}
)

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

image
Можете смело переопределять возвращаемые функцией Object.getOwnPropertyNames значения, и вставлять туда всякий мусор, если захотите. Так же вы просто можете реагировать на ввод пользователя в консоли. (В примере мы просто выводим ту самую функцию хрома).

image

Все :)

image

Репозиторий вот
Поделиться с друзьями
-->

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


  1. floatbreaker2
    24.05.2017 06:03

    А какие плюсы от этой этой фичи?


    1. mitinsvyat
      24.05.2017 06:07
      +1

      Можете смело переопределять возвращаемые функцией Object.getOwnPropertyNames значения, и вставлять туда всякий мусор, если захотите. Так же вы просто можете реагировать на ввод пользователя в консоле. (В примере мы просто выводим ту самую функцию хрома).

      Если сайт твой и, может, ты не любишь, когда твой сайт отлаживают, можешь выключать консоль через это:
      while(1);

      А в целом я не знаю, почему так сделано, и как еще этим можно воспользоваться.


      1. vyrkmod
        24.05.2017 09:41
        +1

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


    1. k0ldbl00d
      24.05.2017 16:36

      Целых три — lol, kek и azaaza.


  1. leorush
    24.05.2017 08:46
    +1

    Что помешает

    остановить ваш код в дебаггере?
    image


    1. mitinsvyat
      24.05.2017 09:26
      +1

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


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


      1. leorush
        24.05.2017 10:14
        +1

        Прошу прощения, не посмотрел код. Ожидал что будет как на скрине у вас:
        image
        Подумал что это браузер ) Надо завязвать писать комменты после бессонной ночи.

        По теме — возможно этот способ дополнит ваш код?
        Revisiting Disable JavaScript Execution From Console



        1. mitinsvyat
          24.05.2017 15:05

          Так можно вставлять белеберду:

          var gn = Object.getOwnPropertyNames.bind(Object)
          
          var f = function(o) {
              if(f.caller && f.caller.toString && 
                 f.caller.toString().indexOf('object&&ArrayBuffer.isView(o)&&o.length>9999') > 0) {
                  return ['azaza', 'kek', 'lol']
              }
              return gn(o);
          }
          Object.getOwnPropertyNames = f
          

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


      1. stas404
        25.05.2017 01:15
        +1

        «Обфускация» же.


    1. ertaquo
      24.05.2017 15:25

      Есть способы нехило подвесить браузер. Некоторые даже нельзя остановить дебаггером.
      Например, можно одновременно загрузить все шрифты, установленные в системе. Правда, тут нужно использовать Flash, без него список шрифтов получить нельзя (разве только жестко вшить).


      1. goiliago
        24.05.2017 17:20

        Сам недавно случайно наткнулся, что при скачивании большого количества файлов с помощью javascript браузер виснет и падает. Правда в хроме нужно иногда разрешить сайту скачивать много файлов, но это не всегда помогает, т.к. хром качает их в фоне. Протестировать можно здесь: https://iliakonnov.github.io/chromeCrash/index.html


  1. pewpew
    24.05.2017 09:17
    +1

    Видел примерно такую «тихую» реализацию:

    var oldf=console.log;
    console.log=function(){
    store.push(arguments);
    oldf.apply(console, arguments);
    };
    


    Подозреваю, что можно чуток допилить, переопределив console.log на пустую функцию и будет счастье. Ну то есть не очень понятно в чём именно это счастье, но будет.


    1. mitinsvyat
      24.05.2017 09:28

      Можно извратиться, и перехватывать все на свете, но так никто не делает.


    1. Goodkat
      24.05.2017 10:57

      А у нас примерно так и сделано.
      После того, как мы пару раз забыли удалить вызовы console.log() и выкатили релиз, где у юзеров файрфокса всё поломалось из-за отсутствия у них console, мы переопределяем объект console и все его функции в продуктивной версии.


      1. mayorovp
        24.05.2017 12:20

        Ну зачем же с именно переопределять-то?


        if (!window.console) window.console = { log: function() {} };


      1. Zenitchik
        24.05.2017 12:51
        +3

        Это в какой версии ФФ было?
        Я с 11 года пишу (отлаживаю во всех более-менее встречающихся браузерах), и ни разу не сталкивался, чтобы где-то кроме IE могло не быть console.


        1. Goodkat
          24.05.2017 15:47
          +1

          Не знаю версию, но это точно был Firefox и версия скорей всего больше 2.0, возможно до 3.6., я не помню уже за давностью лет.
          Но история коммитов всё помнит: 11.11.11 в 9:37 я коммитнул переопределение консоли :)

          A стажем меня не надо пугать, я писал и отлаживал ещё под Mozilla, который не Firefox :-)


          1. Zenitchik
            24.05.2017 16:17
            +2

            Пугать? Что Вы! Я только отметил, что в 11 году, когда я начал заниматься этим профессионально и у меня на машине появились все актуальные браузеры (две версии FF, две версии Оперы, Гугл, IE, естественно, кажется, Сафари для винды, но могу уже не помнить), подобная проблема нигде кроме ИЕ не встречалась.


          1. vitvad
            24.05.2017 18:52

            а в document.title для IE «по быстрому» отладчик не прикручивали? :)


  1. vlreshet
    24.05.2017 09:21
    +2

    Изменять suggestions, конечно, прикольно, но чтобы просто обнаружить факт открытия консоли — есть способ попроще. console.log(x.y), где «х» — это объект у которого навешен геттер на поле «у». Как только сработал геттер — значит юзер открыл devtools :)


    1. mitinsvyat
      24.05.2017 09:36

      Я немного запyтался. Идея с гетерами мне понятна, но я не очень понял про значение console.log(x.y)


      1. vlreshet
        24.05.2017 10:04
        +1

        Блин, сейчас проверил — а уже, походу, зафиксили. Жаль. Ещё прошлым летом работало, я писал небольшую игру и защищал её разными извращёнными способами, этим в том числе. Если вкратце — было так: по факту console.log срабатывала не в момент вызова, а в момент открытия консоли. Иными словами, если написать console.log, в самом начале большого кода, то срабатывал он всё равно только после того как devtools был открыт.
        Если я всё правильно помню — то рабочим был примерно вот такой вот код:

        var test = {};
        
        Object.defineProperty(test, "console", {
          get: function() {
            alert('You are dirty hacker!');
          }
        });
        
        console.log(test.console);
        


      1. vlreshet
        24.05.2017 10:10
        +10

        А, нет, не зафиксили, это меня память подвела)

        Рабочий код выглядел вот так (честно стырен со стековерфлоу)

        var element = new Image();
        Object.defineProperty(element, 'id', {
          get: function () {
            alert('Devtool has been opened!');
          }
        });
        console.log('%cHello', element);
        


        1. mitinsvyat
          24.05.2017 14:56

          Спасибо, вкурил.


    1. mayorovp
      24.05.2017 10:40
      +1

      Если писать console.log(x.y), то поле y будет получено сразу же. Что бы отловить именно обращение к полю из консоли, надо писать console.log(x)


  1. devalone
    24.05.2017 16:44
    -3

    image


    1. mitinsvyat
      24.05.2017 17:17
      +2

      Я чисто случайно нашел эту фичу.
      А троллейбус мы всегда знаем, как собрать.
      Думаешь, фича никому не будет интересна совсем?


  1. Mingun
    24.05.2017 19:03

    А меня вот интересует другое. Как можно (и можно ли вообще) вырезать принудительные точки останова по ключевому слову debugger;. Натыкался на такую защиту от отладки на некоторых сайтах — постоянно в «цикле» (по setTimeout(), кажется) динамически генерируется функция, снова устанавливающая тот же самый таймер и содержащая инструкцию debugger;. Соответственно, мало того, что от такой «защиты» сайт очень скоро начинал безбожно тормозить и подвешивать интерфейс браузера, так ещё и в инструменты разработчика было не зайти, поскольку они безусловно останавливались на инструкции debugger;, пропустить которую нет никакой возможности. Так вот, есть ли какой-то способ отключить её к чертям хотя бы в каком-то браузере?


    1. Aingis
      24.05.2017 20:29

      Есть же кнопка «Deactivate breakpoints (Ctrl+F8)» в хром-дев-тулзах.


      1. Mingun
        24.05.2017 23:24

        Она работает только с теми точками останова, что поставил сам, через инструменты разработчика. Если в коде встречается инструкция debugger;, отладчик останавливается (останавливался, когда я последний раз смотрел) на ней независимо от состояния этой кнопки.


        1. Aingis
          25.05.2017 10:09

          Странно, нам помогала (есть любители наставить debugger в коде при отладке).


          1. Mingun
            25.05.2017 18:00

            Может быть, уже что-то и изменилось. Я довольно давно смотрел, тогда не работало.


  1. trapwalker
    24.05.2017 22:06
    +1

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


    1. mayorovp
      25.05.2017 12:17
      -1

      Угу. Посмотрел сертификат SSL — записали в читеры! :-)


    1. devalone
      26.05.2017 03:02
      +2

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


      1. trapwalker
        26.05.2017 18:55

        Вы не поняли суть моего комментария, как и mayorovp. Я не предлагал только по факту захода в консоль определять читеров. Ни один признак в этом вопросе не должен быть однозначно определяющим и обязательным. Это всегда бесконечное противостояние брони и пули, в котором обе стороны вынуждены постоянно придумывать что-то новое и окончательной победы не будет.
        Я предлагал факт, частоту и характер использования консоли тихо добавлять в поведенческий портрет пользователя наряду с максимальным количеством разных других признаков. По совокупности этих признаков различные эвристики (которые со временем будут добавляться, изменяться и устаревать) проклассифицируют пользователей по степени риска читерства. В любом случае нужны дополнительные проверки и правила.


  1. yulllll
    25.05.2017 10:41
    +1

    Пока смотрела как все вышеописанное работает в консоли, случайно обнаружила масштабирование для devtools. С учетом того, что у меня все страницы выставлены на 150%… это прелесть)
    Почаще бы такие случайности!