DevTools
DevTools (сокр. от Developer Tools, оно же «инструменты разработчика», «консоль», «эта хреновина по F12») — специальный набор утилит, встроенный в твой браузер, который превращает обычного юзера, кликающего на смешные картинки, в почти-что-хакера, способного копипастить, ломать и кромсать веб-странички в реальном времени. Для веб-разработчика — это священный грааль, скальпель и стетоскоп в одном флаконе. Для владельца сайта, особенно если сайт про браузерную игру про боевых хомяков или торгует уникальным контентом — это Око Саурона, которое нужно немедленно выжечь каленым железом.
А нахрена?[править]
Казалось бы, кому какое дело, что ты там ковыряешь на его сайте? Но чувство собственной важности у иного веб-мастера раздуто до таких масштабов, что сама мысль о том, что какой-то анон залезет в его божественный HTML и увидит там div class="div-for-div-wrapper-content-1" вызывает у него жгучую боль пониже спины. Основных причин для паранойи несколько:
- Борьба с читерами. Самая, пожалуй, адекватная причина. Если твой сайт — это очередная кликалка, где за каждый клик по хомяку тебе начисляют крипто-фантики, то любой школьник с помощью DevTools может найти заветную функцию addCoins(999999) и стать виртуальным миллионером, обрушив хрупкую экономику игры.
- Защита от копипасты. Когда владелец говносайтика уверен, что его рерайт статьи с Википедии является интеллектуальной собственностью, он будет до последнего защищать свои сокровища от наглых плагиаторов.
- Сокрытие «бизнес-логики». Некоторые наивно полагают, что если спрятать AJAX-запросы от глаз юзера, то никто не догадается, как работает их гениальная система. Спойлер: догадаются.
- Просто потому что могут. Чистый, незамутненный синдром вахтера. Мой сайт — мои правила. Нечего тут своими отладчиками шастать!
Как это работает, %username%?[править]
Методы детекта варьируются от примитивных, как палка-копалка, до весьма изощренных, заставляющих попотеть даже опытного реверс-инженера. Рассмотрим классику, которую ты можешь встретить в дикой природе.
Дедовский метод: линейка и глазомер[править]
Самый древний и тупой, как пробка, способ — это замерять размеры окна. Суть проста: у объекта window есть свойства innerWidth и innerHeight (видимая область страницы) и outerWidth / outerHeight (размер всего окна браузера). Когда ты открываешь пристыкованную панель DevTools (сбоку или снизу), она отжирает кусок видимой области.
const widthDiff = window.outerWidth - window.innerWidth;
const heightDiff = window.outerHeight - window.innerHeight;
if (widthDiff > 150 || heightDiff > 150) {
// Алярм! У нас тут хацкер!
console.log("Попался, голубчик!");
}
Казалось бы, винрар. Но есть нюанс, и не один. Во-первых, масштабирование. Любой юзер, нажавший `Ctrl`+`+` чтобы разглядеть твой мелкий шрифт, тут же будет помечен как злоумышленник, потому что браузеры (особенно Firefox) начинают творить с этими значениями полную дичь. Во-вторых, панель закладок или боковые панели самого браузера тоже меняют размеры, что приводит к ложноположительным срабатываниям. Ну и в-третьих, если хацкер откроет DevTools в отдельном окне, этот метод с треском провалится, так как на размеры окна страницы это никак не повлияет. FAIL.
Ловушка для любопытной Варвары[править]
Более изящный способ — это так называемые «ловушки для отладчика». Самая известная — это ключевое слово debugger.
const startTime = new Date();
debugger;
const endTime = new Date();
if (endTime - startTime > 100) {
// Ага! Консоль открыта, и ты нажал "продолжить"!
// Сажаем на бутылку.
}
Как это работает? Оператор `debugger` ставит выполнение скрипта на паузу, но только если открыта консоль. Если консоль закрыта, он просто игнорируется. Мы ставим метку времени до него и после. Если разница во времени превышает некий порог (например, 100 миллисекунд), значит, скрипт был на паузе, а юзер, чтобы продолжить, тыкнул на кнопочку в отладчике. Поздравляем, вас поймали за жопу.
Еще один хитрый трюк из этой же оперы — переопределение геттеров.
А что, если мы создадим объект и выведем его в консоль? Сама консоль, чтобы его отобразить, полезет читать его свойства. И вот тут-то мы ее и поймаем!
Создается невинный с виду объект, но у одного из его свойств (например, `id`) через `Object.defineProperty()` переопределяется `get`-тер. Как только `console.log(myTrapObject)` попытается прочитать это свойство, сработает наша функция, которая и поднимет тревогу. Анонимуса, который просто хотел посмотреть на объект, ждет неприятный сюрприз.
Как нагнуть систему?[править]
Естественно, на каждую хитрую гайку найдется свой болт с левой резьбой. Большинство примитивных методов обходятся элементарно:
- Открепи окно DevTools. Самый простой способ обойти проверку по размеру.
- Отключи брейкпоинты. В DevTools есть кнопка, которая деактивирует все точки останова, включая debugger.
- Переопредели переопределенное. Если сайт меняет console.log, то ты можешь переопределить его обратно через какой-нибудь Tampermonkey.
- Не лезь в консоль, когда не просят. Если видишь, что сайт ведет себя странно, не спеши выводить все подряд объекты в лог. Возможно, один из них — троянский конь.
Мораль[править]
Вся эта возня с детектом DevTools — не более чем бесконечная война правок между копирастами и пиратами, разработчиками игр и читерами. С каждым днем методы становятся все изощреннее: проверка стека вызовов, сложные рекурсивные ловушки на debugger, анализ поведения через CDP… Но и способы обхода не стоят на месте. В конечном счете, все, что исполняется на машине клиента, может и будет взломано, отлажено и скопипащено. А все эти защиты — лишь способ потешить эго разработчика и слегка усложнить жизнь начинающим «хакерам».