Сразу покажу пример, чтобы не мусолить (тестировал на последнем Хроме, который у меня был):
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;
}
)
Очевидно, что с ее помощью гугл Хроум выдает нам саггешены, которые будут показаны в выпадающем меню при вводе текста в консоли.
Можете смело переопределять возвращаемые функцией Object.getOwnPropertyNames значения, и вставлять туда всякий мусор, если захотите. Так же вы просто можете реагировать на ввод пользователя в консоли. (В примере мы просто выводим ту самую функцию хрома).
Все :)
Репозиторий вот
Комментарии (37)
leorush
24.05.2017 08:46+1Что помешает
остановить ваш код в дебаггере?mitinsvyat
24.05.2017 09:26+1Мой код очень легко остановить в дебагере, потому что его никто не обфрусцировал.
Если ты хочешь основательно прятать свой код, то можно его обфрусцировать, динамически менять, подкачивать как попало и т.д.
Тут я это не описовал, потому что статья не про это.
На счет "код виден" я не очень понял, что имеете ввиду, показывая скриншот.
На нем показано, как моя программа вывела функцию, которую использует хром, чтобы получить сагешеныleorush
24.05.2017 10:14+1Прошу прощения, не посмотрел код. Ожидал что будет как на скрине у вас:
Подумал что это браузер ) Надо завязвать писать комменты после бессонной ночи.
По теме — возможно этот способ дополнит ваш код?
Revisiting Disable JavaScript Execution From Console
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
Может, можно дополнить, но в целом, это на ваше усмотрение, думаю.
Оба трюка не сильно взаимосвязаны, как понял.
ertaquo
24.05.2017 15:25Есть способы нехило подвесить браузер. Некоторые даже нельзя остановить дебаггером.
Например, можно одновременно загрузить все шрифты, установленные в системе. Правда, тут нужно использовать Flash, без него список шрифтов получить нельзя (разве только жестко вшить).goiliago
24.05.2017 17:20Сам недавно случайно наткнулся, что при скачивании большого количества файлов с помощью javascript браузер виснет и падает. Правда в хроме нужно иногда разрешить сайту скачивать много файлов, но это не всегда помогает, т.к. хром качает их в фоне. Протестировать можно здесь: https://iliakonnov.github.io/chromeCrash/index.html
pewpew
24.05.2017 09:17+1Видел примерно такую «тихую» реализацию:
var oldf=console.log; console.log=function(){ store.push(arguments); oldf.apply(console, arguments); };
Подозреваю, что можно чуток допилить, переопределив console.log на пустую функцию и будет счастье. Ну то есть не очень понятно в чём именно это счастье, но будет.Goodkat
24.05.2017 10:57А у нас примерно так и сделано.
После того, как мы пару раз забыли удалить вызовы console.log() и выкатили релиз, где у юзеров файрфокса всё поломалось из-за отсутствия у них console, мы переопределяем объект console и все его функции в продуктивной версии.mayorovp
24.05.2017 12:20Ну зачем же с именно переопределять-то?
if (!window.console) window.console = { log: function() {} };
Zenitchik
24.05.2017 12:51+3Это в какой версии ФФ было?
Я с 11 года пишу (отлаживаю во всех более-менее встречающихся браузерах), и ни разу не сталкивался, чтобы где-то кроме IE могло не быть console.Goodkat
24.05.2017 15:47+1Не знаю версию, но это точно был Firefox и версия скорей всего больше 2.0, возможно до 3.6., я не помню уже за давностью лет.
Но история коммитов всё помнит: 11.11.11 в 9:37 я коммитнул переопределение консоли :)
A стажем меня не надо пугать, я писал и отлаживал ещё под Mozilla, который не Firefox :-)Zenitchik
24.05.2017 16:17+2Пугать? Что Вы! Я только отметил, что в 11 году, когда я начал заниматься этим профессионально и у меня на машине появились все актуальные браузеры (две версии FF, две версии Оперы, Гугл, IE, естественно, кажется, Сафари для винды, но могу уже не помнить), подобная проблема нигде кроме ИЕ не встречалась.
vlreshet
24.05.2017 09:21+2Изменять suggestions, конечно, прикольно, но чтобы просто обнаружить факт открытия консоли — есть способ попроще. console.log(x.y), где «х» — это объект у которого навешен геттер на поле «у». Как только сработал геттер — значит юзер открыл devtools :)
mitinsvyat
24.05.2017 09:36Я немного запyтался. Идея с гетерами мне понятна, но я не очень понял про значение console.log(x.y)
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);
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);
mayorovp
24.05.2017 10:40+1Если писать
console.log(x.y)
, то полеy
будет получено сразу же. Что бы отловить именно обращение к полю из консоли, надо писатьconsole.log(x)
devalone
24.05.2017 16:44-3mitinsvyat
24.05.2017 17:17+2Я чисто случайно нашел эту фичу.
А троллейбус мы всегда знаем, как собрать.
Думаешь, фича никому не будет интересна совсем?
Mingun
24.05.2017 19:03А меня вот интересует другое. Как можно (и можно ли вообще) вырезать принудительные точки останова по ключевому слову
debugger;
. Натыкался на такую защиту от отладки на некоторых сайтах — постоянно в «цикле» (поsetTimeout()
, кажется) динамически генерируется функция, снова устанавливающая тот же самый таймер и содержащая инструкциюdebugger;
. Соответственно, мало того, что от такой «защиты» сайт очень скоро начинал безбожно тормозить и подвешивать интерфейс браузера, так ещё и в инструменты разработчика было не зайти, поскольку они безусловно останавливались на инструкцииdebugger;
, пропустить которую нет никакой возможности. Так вот, есть ли какой-то способ отключить её к чертям хотя бы в каком-то браузере?Aingis
24.05.2017 20:29Есть же кнопка «Deactivate breakpoints (Ctrl+F8)» в хром-дев-тулзах.
Mingun
24.05.2017 23:24Она работает только с теми точками останова, что поставил сам, через инструменты разработчика. Если в коде встречается инструкция
debugger;
, отладчик останавливается (останавливался, когда я последний раз смотрел) на ней независимо от состояния этой кнопки.
trapwalker
24.05.2017 22:06+1Детектить факты захода юзера а девтулз полезно, например, когда нужно бороться с хитрожопыми читерами в браузерных играх. Только вот детектить нужно максимально скрытно и ни в коем случае не реагировать явно на такого рода действия пользователя. Просто ставим галочку в скрытой части профиля пользователя, и имеем её в виду как дополнительный штрих при поиске более надёжных свидетельств читерства.
devalone
26.05.2017 03:02+2Хреновый способ, имхо, будто читы без захода в консоль не работают, можно написать дополнение для браузера, можно модифицировать движок или просто перехватывать и подменять трафик. Чем городить такие «защиты» лучше перенести большую часть логики на сервер.
trapwalker
26.05.2017 18:55Вы не поняли суть моего комментария, как и mayorovp. Я не предлагал только по факту захода в консоль определять читеров. Ни один признак в этом вопросе не должен быть однозначно определяющим и обязательным. Это всегда бесконечное противостояние брони и пули, в котором обе стороны вынуждены постоянно придумывать что-то новое и окончательной победы не будет.
Я предлагал факт, частоту и характер использования консоли тихо добавлять в поведенческий портрет пользователя наряду с максимальным количеством разных других признаков. По совокупности этих признаков различные эвристики (которые со временем будут добавляться, изменяться и устаревать) проклассифицируют пользователей по степени риска читерства. В любом случае нужны дополнительные проверки и правила.
yulllll
25.05.2017 10:41+1Пока смотрела как все вышеописанное работает в консоли, случайно обнаружила масштабирование для devtools. С учетом того, что у меня все страницы выставлены на 150%… это прелесть)
Почаще бы такие случайности!
floatbreaker2
А какие плюсы от этой этой фичи?
mitinsvyat
Если сайт твой и, может, ты не любишь, когда твой сайт отлаживают, можешь выключать консоль через это:
А в целом я не знаю, почему так сделано, и как еще этим можно воспользоваться.
vyrkmod
Ну так консоль рисуется тем же движком что рендерит сайты. Хотя по-хорошему стоило б её изолировать как остальной интерфейс браузера, а не делать частью страницы.
k0ldbl00d
Целых три — lol, kek и azaaza.