копаемся в броне КРИС КАСПЕРСКИ АКА МЫЩЪХ Спецвыпуск: Хакер, номер #066, стр. 066-062-5 Комментарии, как говорится, излишни. Господа программисты! Если хотите защититься, не пишите слишком «навороченных» процедур. Хакер все равно расколет их. Ну и пусть функция растянется хоть на тысячу строк — будет легче локализовать ее. несколько серийных номеров в одном Как обычно ломают программы? Ищут процедуру, сравнивающую введенный серийный номер с эталонным, затем либо правят код, либо пишут генератор серийных номеров. Если же разные части программы в различное время будут проверять различные части одного и того же ключа, то взломщику придется очень сильно поднапрячься, прежде чем он доведет взлом до ума. Допустим, программа спрашивает серийник на запуске и до осуществления ввода не пускает никуда дальше. Хакер быстро «отламывает» защитный код (пишет генератор серийных номеров) и программа как будто бы запускается, но при расчете таблицы (попытке записать файл на диск) проверяет другую часть серийного номера с помощью дополнительной защитной функции, которую взломщик благополучно «проморгал» на первой стадии взлома. Хакер вновь берет отладчик в руки и дорабатывает свой генератор (отламывает вторую проверочную процедуру). И вот программа работает уже в полный рост, только при выводе на печать… Ну, в общем, ты понял. Если крэкер ломает программу «для себя», он будет долго материться, в конце концов это дело настолько надоест ему, что он все-таки купит ее (или доломает из спортивного интереса). Если же программа ломается «на сторону» по спецзаказу, то после первых двух-трех промахов клиент пошлет крэкера и предпочтет заплатить, а не мучиться. Один момент. Серийный номер ни в коем случае не должен храниться в секции данных как глобальная переменная, иначе перекрестные ссылки и аппаратные точки останова выдадут функции проверки с головой. Всегда передавай серийный номер по цепочке локальных переменных тысячам посторонних функций программы. Тогда взломщик никак не сможет отследить, какие именно функции реально проверяют серийный номер, а какие только передают его по транзиту. детерминированная логика Редкая программа ломается в один присест, и взломщику для преодоления защиты приходится предпринимать серию последовательных наступлений, рокировок и отступлений, планомерно продвигающих его вглубь, все ближе и ближе к сердцу защиты. При этом ставятся точки останова, картографируется маршрут трассировки, с каждым прогоном взломщик чувствует себя все увереннее и увереннее. Начинающие ломатели вообще ограничиваются тем, что планомерно хачат один условный переход за другим и тешат в себе надежду найти тот единственный, нужный им (часто он и есть единственный). Ситуация значительно усложняется, если программист применяет оружие недетерминированной логики, или, проще говоря, вызывает различные проверочные функции в случайное время из произвольных мест, используя функцию rand() или другой генератор подобного типа. В этом случае взломщик не сможет повторить однажды пройденный маршрут: при следующем запуске программа пойдет совсем другим путем. Допустим, в прошлый раз крэкер дотрассировал программу до точки А и понял, что свернул не на том повороте (проскочил условный переход) и что сворачивать нужно было гораздо раньше, а теперь защитная функция уже позади и дальше трассировать некуда. Он перезапускает отладчик и… с превеликим удивлением обнаруживает, что его занесло совсем в другие места, незнакомые ему… |