Теоретические основы крэкинга

Вид материалаДокументы

Содержание


Дзен-крэкинг. Теория.
Орудия крэкера
Отладчики и дизассемблеры
Декомпиляторы и узкоспециализированные отладчики
Распаковщики и утилиты для дампинга процессов
Утилиты анализа файлов
Шестнадцатеричные редакторы и редакторы ресурсов
API-шпионы и другие утилиты мониторинга
Прочие утилиты
Почти начинаем ломать
Почти начинаем ломать
Переменные и константы
Куда попадают данные
Искусство разбивать окна.
И вновь продолжается бой…
Создание и уничтожение окон
Чтение и изменение текстов окон
Изменение видимости, позиции и прочих подобных свойств окна
Загрузка ресурсов
Отображение изображений и текстов на экране
...
Полное содержание
Подобный материал:
  1   2   3   4   5   6   7   8   9   10

Теоретические основы крэкинга


Что тебя смутит – то ложь

Е. Летов


За пять лет более или менее активного занятия крэкингом (а именно столько времени прошло с того знаменательного момента, как мне удалось впервые в жизни взломать программу) мне удалось выработать набор методов, позволяющих сравнительно быстро найти подход к большинству программ. Возьму на себя смелость утверждать, что именно эта система наиболее доступна для начинающих, поскольку она базируется не на раскрытии алгоритма работы защиты в целом, а на анализе сравнительно небольших участков кода и установлении взаимосвязи между ними.


Несмотря на то, что крэкеры, в большинстве своем, работают под одной хорошо известной операционной системой и пользуются сходными инструментами, я буду делать упор не на описание этих инструментов и правил работы с ними, а на универсальные идеи (хотя в качестве примеров я, понятное дело, буду приводить то, что наиболее доступно для самостоятельных экспериментов). Думаю, что Вы сами определитесь, какие инструменты Вам больше по душе.

Предлагаемую мной систему не следует воспринимать как единственно правильную, это не «истина в последней инстанции», но именно эта система помогла мне взломать десятки программ, так что ее эффективность неоднократно проверена и подтверждена длительной практикой. Моя точка зрения такова: одна лишь практическая эффективность может служить критерием того, какие идеи и технические приемы могут и должны применяться крэкером в его «профессиональной» деятельности. Именно поэтому я настоятельно рекомендую отрешиться от любых утверждений о «некрасивости» тех или иных приемов борьбы с защитами и ориентироваться лишь на достижение конечной цели – независимо от того, является ли этой целью раскрытие алгоритма работы какого-либо куска кода, или же простое снятие триальных ограничений в программе.


Так или иначе, статей от том, «что делать», то есть как взломать конкретную программу или тип защиты, во много раз больше, чем руководств «как и почему надо делать именно это». Образно говоря, статьи о том, «что делать» - это уровень начальной школы, «почему был выбран именно такой прием» - уровень выпускных классов. Но ведь есть еще и высшая школа - изучение идей, которые не привязаны к каким-либо программам и типам защит, но могут быть адаптированы для решения любой конкретной задачи. Выше – только «научная работа», то есть область чистого творчества, генерация оригинальных идей, и никакой «учебник» в этой области принципиально невозможен. По моему глубокому убеждению, основная проблема, возникающая у начинающих крэкеров, заключается в огромном количестве пособий уровня «делай, как я», совершенно не объясняющих, почему автор пособия поступил именно так. В результате начинающий крэкер «на ура» ломает новые версии одной и той же программы, но теряется перед подобной же защитой, но реализованной слегка иначе. Разумеется, существуют и весьма качественные «учебники», предлагающие именно систему, а не только набор технических приемов (те же +ORC Cracking Tutorialz или руководство от the Keyboard Caper’а) – но абсолютное большинство их них написаны на английском языке. Поскольку каждый человек имеет право получать необходимую информацию на своем родном языке (а для меня, как и для многих других, родным языком является русский), рано или поздно должны были появиться русскоязычные тексты, систематизирующие опыт крэкинга. Именно такой материал я и старался написать, а насколько хорошо это у меня получилось - решать вам.


Глава 0.

Дзен-крэкинг. Теория.


Основной идеей дзен-крэкинга (именно это название широко используется на сайте Fravia для обозначения той системы крэкинга, о которой я рассказываю) стало: «я не знаю, как это работает, но я могу это сломать». Разумеется, речь не идет об абсолютном незнании того, как функционирует программа – знание команд ассемблера, способов передачи параметров в функции и процедуры, назначения системных вызовов ОС, особенностей кодогенерации определенных компиляторов и многого другого, несомненно, является обязательным. Более того, это основы, без которых любое изучение внутренностей программ в принципе невозможно – нельзя получить информацию из книги, не понимая языка, на котором она написана. «Не знаю, как работает» следует понимать в том смысле, что очень часто для успешного взлома программы совершенно необязательно проводить доскональный анализ всех защитных процедур. Иметь возможность сказать: «я знаю, для чего нужен каждый байт в этой программе» - это, конечно, хорошо, но на практике вполне успешно работает модель «черного ящика», когда нам известно назначение отдельных процедур, взаимосвязь между ними и то, какие эффекты вызывает передача тех или иных параметров на входы «черного ящика».


В крэкинге есть два пути. Первый – путь глубокого анализа, изучения и достижения понимания того, как работает программа. Этот путь весьма надежен, но для получения гарантированного результата он требует много времени, усилий и практического опыта. В наше время главным критерием является эффективность и скорость взлома, а не «правильность», которая интересна лишь «гуру» и вечно недовольным теоретикам. К тому же, если Вы только начали обучаться крэкингу, у Вас может просто не оказаться нужных знаний и опыта, чтобы знать, в каком направлении нужно двигаться. Итак – налицо парадокс: чтобы приобрести опыт, нужно ломать программы, причем ломать успешно, и чем больше – тем лучше, а ломать их не получается из-за недостатка опыта. Но существует второй путь – исследовать программы, исходя из предположений, которые, в свою очередь, строятся на наблюдении за внешними эффектами, производимыми программой. То есть Вы не сразу начинаете выяснять, что и как происходит в недрах кода программы, а сначала строите предположения, «на что это может быть похоже», «как это может быть реализовано» и «как бы я добился такого эффекта, будь я на месте автора программы». Как ни странно, при использовании этого метода, успех зависит не только от знаний, но и от того, насколько богато Ваше воображение. Эффективность дзен-крэкинга опирается, прежде всего, на наблюдения и смелые предположения. Поэтому не надейтесь, что авторы защит будут применять избитые приемы, которые можно аккуратно переписать на бумажку и составить «инструкцию по взлому». Ожидайте неожиданного!


Однако Вы не можете строить предположения о работе программы на пустом месте – Вам нужен некий стартовый набор знаний. Поэтому Вы должны собрать как можно больше информации о самой программе – выяснить, упакована она или нет, какие ограничения содержатся в незарегистрированной программе и как выглядит процесс регистрации; узнать, что будет, если Вы попытаетесь использовать программу дольше, чем это предусмотрено триальными ограничениями; проанализировать, какие текстовые строки и ресурсы содержатся внутри программы; поинтересоваться, к каким файлам и ключам реестра программа обращается при запуске, и многое другое. Не поленитесь заглянуть в справочную систему программы – там Вы можете найти описания различий между зарегистрированной и незарегистрированной версией. Значительная часть этой информации Вам скорее всего не пригодится, но Вы не можете знать заранее, какой путь окажется наиболее удобным и какие знания о программе Вам понадобятся. Более того, почти наверняка все необходимые данные о работе программы Вы с первой попытки не соберете, и уже в процессе изучения кода Вам придется возвращаться к этому этапу, чтобы узнать, например, сколько с какими параметрами программа в заданной точке вызывает функцию создания файла, куда считываются введенные серийные номера, сколько раз и откуда программа вызывает функцию проверки регистрации и т.п. А потому – собирайте информацию!


Когда Вы сгенерировали идеи о том, как именно могут работать интересующие Вас механизмы в программе, перед Вами встанет задача добраться до кода, который эти механизмы реализует. Для этого Вам нужно проанализировать все предполагаемые варианты и найти, к чему можно «прицепиться» в каждом случае. Иными словами, Вы должны представить, чем может отличаться интересующий Вас кусок кода от множества других кусков, и чем более явными будут эти отличия, тем легче Вам будет этот код найти. Например, если программа выводит nag-screen, можно «прицепиться» к функциям создания и отображения окон; если предполагается проверка CRC файла, результатом будет либо многократное чтение небольших блоков, либо загрузка или отображение всего файла в память; если в заголовке окна программы большими буквами написано UNREGISTERED, можно поискать эту строчку в программе и выяснить, откуда и при каких условиях происходит обращение к этой надписи.


И, наконец, Вам придется разработать практические приемы, при помощи которых можно добраться до интересующих Вас кусков кода, выбрать подходящий инструмент из своего арсенала и правильно его применить.


Как это работает на практике? Представьте себе программу, которая делает нечто. Например, отказывается запускаться после 30 дней использования, выдавая стандартное окошко с сообщением (широко известное как MessageBox). Чтож, у нас есть первое наблюдение. Простой перевод системного времени не помогает – обмануть программу и заставить ее работать дольше, чем положено, не удается. Это второе наблюдение. Из него следует, что программа проверяет текущую дату не на основе показаний внутренних часов Windows. Предполагаем, что программа либо уже сделала пометку «больше не запускаться» где-нибудь в реестре или на диске, либо все-таки определяет текущее время, но каким-либо хитрым способом. Например, читая дату последнего доступа или модификации какого-либо файла. У нас уже есть целых два смелых предположения, которые можно брать за основу в дальнейшем расследовании вредительской деятельности защиты. Если программа не просто «задумывается» при запуске, но еще и шуршит винчестером, вероятность второго варианта сильно повышается. Теперь начинаем проверять эти варианты. В первом случае нам однозначно проще докопаться до истины, установив точки останова на все виды MessageBox’ов и выяснять, какой из условных переходов позволяет избежать появления этого сообщения. Во втором случае в качестве отправной точки можно использовать всевозможные GetFileTime, CompareFileTime (а чем не способ – сравнить дату создания файла программы, т.е. дату инсталляции с датой последней модификации какого-либо файла) и FindFirstFile/FindNextFile (они ведь тоже способны читать временные характеристики файлов).


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


Теперь, когда мы знаем, что нам нужно искать, осталось только определить, как выглядят эти уязвимости. Наиболее «удобные» для крэкера дыры – это прежде всего глобальные переменные, в которых хранится состояние программы («зарегистрирована - не зарегистрирована»), функции, возвращающее критичное для защиты значение (число запусков или дней до истечение триала, результат проверки серийного номера на правильность) и процедуры, выводящие сообщение об успешной или неуспешной попытке регистрации, а также об истечении триального срока программы. Одним из величайших «шедевров», встреченным мной, была глобальная переменная в секции инициализированных данных. По умолчанию ее значение было равно нулю, и менялось на единицу если серийный номер, извлекаемый из реестра, был верен. Исправление одного-единственного бита превратило программу в зарегистрированную. Другим перспективным приемом, который, правда, эффективен в основном против ограничений максимального/минимального значения какого-либо числового параметра (количества обрабатываемых документов, числа запусков и т.п.) является поиск константы, с которой производится сравнение, и модификация либо самой константы, либо условия проверки. Более подробно о том, как обращаться с переменными и константами, я расскажу в соответствующей главе.


«Регистрация» программ, где защитная функция возвращает единственное несколько сложнее – в этом случае требуется выявить все точки, в которых функция возвращает какое-либо значение, и подправить это значение. Нужно только помнить, что куски кода вроде


xor eax,eax



ret


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


Другая проблема для программистов защит, которая сильно облегчает жизнь крэкерам (вот уж воистину «что русскому хорошо, то немцу - смерть») это «проблема условного перехода». Эта проблема заключается в том, реализовать проверку какого-либо условия, не использовав команду условного перехода, не так уж просто. Чем же так выделяются команды условных переходов? А тем, что любой такой переход очень просто превратить в такой же, но с противоположным условием – обычно для этого достаточно исправить ровно один бит! Несмотря на техническую простоту, правка условных переходов все-таки менее предпочтительна, чем модификация функций. Причина этого в том, что условных переходов, имеющих отношение к защите, в программе может быть довольно много (обычно – заметно больше, чем кусков кода, отвечающих за возврат результата функции), и их поиск требует особой внимательности. К тому же, если защита вместо обычных функций использует inline-функции или макросы, разбросанные по всей программе, защитный механизм выглядит как длинный и внешне однородный кусок кода, поиск «плохих» переходов внутри которого несколько затруднителен. С другой стороны, если в таких защитных вставках используются вызовы каких-либо «нормальных» (не inline) функций, особенно функций WinAPI, найти такие идентичные куски становится не так уж сложно. В таком блоке кода почти наверняка есть комбинации команд, по которым такой кусок кода можно идентифицировать – так что поможет либо поиск в двоичном файле программы с использованием маски, либо в дизассемблированном тексте - с использованием регулярных выражений. Если запастись терпением, можно даже проверить все подозрительные участки программы вручную, это вполне реально, если таких участков в программе не больше двух десятков.


Теперь Вам известны наиболее часто встречающиеся в защитах дыры, в выявлении которых заключена половина успеха крэкера. Пришло время рассмотреть трудности и «подводные камни», которые могут ожидать Вас в нелегком кэкерском труде. Прежде всего это проблема неверной интерпретации собранной информации. Например, Вы обнаружили, что программа поддерживает использование плагинов и при запуске сканирует все файлы с расширением DLL в собственной директории. Вы вполне логично предполагаете, что программа строит список плагинов для дальнейшей загрузки и подключения. А потом Вы можете очень долго искать механизм определения даты первого запуска – и не найти его. Потому что он уже отработал – как раз при поиске плагинов. Как такое может быть? Да очень просто: в комплект программы включается как минимум один плагин. Далее – обычная привязка к дате последней модификации файла этого плагина; саму дату модификации файла несложно получить в ходе поиска через FindFirst/FindNext. Вот так иногда авторы защит прячут свой вредительский код, что называется, «на самом видном месте».


Другой пример неверной интерпретации собранных данных встречается еще чаще; более того, это неизбежное следствие подхода, принятого в дзен-крэкинге. Если Вы нашли условный переход, который начисто «выключает» все сообщения о незарегистрированности программы, из этого не обязательно следует, что программа будет вести себя в точности как зарегистрированная. Убедиться в стопроцентной надежности (или принципиальной неправильности) исправления этого перехода – подчас задача много более сложная, чем найти этот самый условный переход. Что интересно, это утверждение работает и в обратную сторону: если Вы что-то сделали, но не увидели результат, это совершенно не означает того, что Вы ошиблись. Создатели защит не так уж редко создают многоуровневую оборону, и для одержания победы недостаточно разрушить внешние рубежи защитного кода. Если вы что-то сделали, но не получили желаемого результата, не стоит сразу же бросать избранный путь; возможно, что Вы абсолютно правы и необходимо двигаться тем же путем и дальше. Даже если после Ваших манипуляций подопытная программа рушится с «ужасным» GPF, этот GPF может быть всего лишь еще одной, еще не выявленной уловкой создателя защиты.


Глава -1.

Орудия крэкера.


Ваше слово, товарищ «Маузер»

В. Маяковский


Осмелюсь предположить, что Вы читаете этот текст не из праздного интереса или ради абстрактного «знания», а хотите научиться применять эти знания на практике. То есть ломать программы. И хотя это пособие носит название «Теоретические основы…», Вы не замедлите применить эти «основы» на практике. А поскольку крэкинг отнюдь не ограничивается теорией, Вам потребуются «рычаги», при помощи которых Вы сможете перевернуть код. И именно об этих «рычагах» и пойдет речь в данной главе. Раз обучение крэкингу требует постоянной и разнообразной практики, было бы логично начать с перечисления того, что Вам потребуется для «практических занятий». Но, с другой стороны, вряд ли Вы сможете выбрать наилучшие инструменты, не зная хотя бы в общих чертах особенностей Вашей будущей деятельности. И именно поэтому глава носит номер «минус один», но следует за «нулевой» главой, в которой я попытался объяснить, чем Вы будете заниматься и какие трудности могут Вас ожидать.


Инструменты – это материальная основа крэкинга, без инструментов в крэкинге – никуда, но сами по себе инструменты – не более чем набор байтов, и лишь человеческая мысль оживляет их, заставляя творить чудеса. Для использования этих программ, как правило, требуются соответствующие знания. Насколько будет Вам полезен лучший отладчик в мире, если Вы не знаете, что означают те хитрые цифры и буквы, которые он показывает на экране? Поэтому прежде чем задать программе вопрос, Вы должны быть уверены, что сможете понять ответ.

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

К вашему счастью, инструментов, пригодных для использования в крэкинге, не так уж мало, и проблема состоит не в том, чтобы их раздобыть, а в том, чтобы отобрать из них наилучшие, изучить их возможности и определить для себя, в какой ситуации тот или иной инструмент лучше всего применить. Поясню эту мысль на примере: на данный момент наиболее мощным из дизассемблеров является IDA Pro, которая способен не просто дизассемблировать код, но и находить в нем вызовы стандартных функций тех или иных компиляторов. Однако если мне необходимо покопаться в программе, написанной на Delphi версии выше третьей, я наверняка не буду использовать IDA Pro, предпочтя ему Delphi Decompiler. Почему? Во-первых, скорость работы IDA Pro и DeDe различается в десятки раз в пользу последнего; используя DeDe, я скорее всего получу желаемый результат раньше, чем закончилось бы дизассемблирование в IDA Pro. Во-вторых, DeDe позволяет анализировать работающие процессы «на лету», что позволяет анализировать сжатые программы, не отвлекаясь на распаковку, восстановление таблицы импорта и прочие вспомогательные действия. Не углубляясь в дальнейшее перечисление достоинств DeDe, начисто отсутствующих в IDA, скажу, что в большинстве случаев специализированная программа позволяет решать свой «родной» класс задач значительно эффективнее, чем программы «общего назначения», ориентированные на ручную работу. Конечно, никто не запретит вам распаковывать программы, вручную копируя секции из памяти в файл, но не проще ли воспользоваться дампером?


Наверняка найдутся те, кто возразит, что широкое использование готовых утилит якобы мешает самостоятельному мышлению, чрезмерно упрощает процесс взлома и вообще «настоящие хакеры дизассемблируют в уме». Так вот, мое принципиальное мнение по этому поводу такое: используйте все программы, какие только сочтете нужными, если это поможет вам добиться желаемого. В конце-концов, цель крэкера обычно состоит в получении работающей программы, а никак не в тренировке памяти или демонстрации собственной крутизны. А всем «настоящим хакерам» посоветуйте дизассемблировать в уме winword.exe из состава самого последнего MS Office, и до тех пор, пока они это не сделают, не беспокоить вас древними суевериями. Разумеется, рано или поздно Вы перейдете от использования чужих программ к написанию собственных патчеров, распаковщиков, дамперов и прочих утилит – но такой переход должен быть продиктован насущной необходимостью, а не обезьяним «чтобы быть не хуже других». В конце-концов, большинство программ было написано именно для того, чтобы люди ими пользовались.


Итак, какие инструменты и для чего нам потребуются?

  1. Отладчики и дизассемблеры. Традиционно оба этих инструмента используются в паре, поскольку дизассемблер выдает лишь «чистый код», хотя современные дизассемблеры способны также распознать вызовы стандартных функций, выделить локальные переменные в процедурах и предоставляют прочий подобный сервис. Пользуясь дизассемблером, Вы можете лишь догадываться о том, какие данные получает та или иная функция в качестве параметров и что они означают; чтобы выяснить это, чаще всего требуется изучения если не всей программы, то довольно значительной ее части. Отладчики выполняют принципиально иные функции, они позволяют анализировать код в процессе его работы, отслеживать и изменять состояние регистров и стека, править код «на лету» - в общем, наблюдать за «личной жизнью» программы и даже активно в нее вмешиваться. Обратной стороной медали является «неинтеллектуальность» многих отладчиков – их врожденные способности к анализу кода редко простираются дальше определения направления перехода. SoftIce, «лучший отладчик всех времен и народов», например, ничего не знает о типах данных и не способен отличить обычный DWORD от указателя на ASCIIZ-строку, хотя и предоставляет пользователю возможность проверить это вручную. Впрочем, вполне реальны отладчики, сочетающие высокое качество дизассемблирования и анализа кода с широкими возможностями по его отладке. Примером может служить OllyDebug, выполняющий эвристический анализ кода, выделяющий локальные переменные, «знающий» о типах данных, передаваемых функциям WinAPI и при этом способный во многих случаях автоматически отличить обычное число от указателя на строку.
  2. Декомпиляторы и узкоспециализированные отладчики. С ростом мощности ЭВМ довольно широкое распространение получили компиляторы, создающие не «чистый» машинный код, а некий набор условных инструкций, который выполняется при помощи интерпретатора. Интерпретатор может как поставляться отдельно (Java), так и быть «прикрепленным» к самой программе (хотя формально не интерпретатор прикрепляется к программе, а программа к интерпретатору. Примером может служить Visual Basic при компиляции в p-code). Возможны и более экзотические варианты, например, применяемый в Форте «шитый код»; компиляция программы в цепочку команд push\call или преобразование текста программы в такую цепочку непосредственно при запуске этой программы. Интерпретаторами являются практически все инсталляторы (в их основе лежит интерпретатор инсталляционного скрипта, хотя сам процесс создания такого скрипта может быть скрыт при помощи использования визуальных средств). Да и «обычные» компилирующие языки могут создавать код, прямой анализ которого весьма затруднителен. Для анализа таких программ используются специализированные утилиты, переводящие код, понятный лишь интерпретатору, в форму, более удобную для понимания человеком. Также некоторые декомпиляторы могут извлекать информацию об элементах интерфейса, созданных визуальными средствами. В любом случае, не следует ожидать от декомпиляторов восстановления исходного текста программы; если декомпилированная программа успешно компилируется и сохраняет работоспособность – это исключение, а не правило.
  3. Распаковщики и утилиты для дампинга процессов. Дизассемблировать запакованную или зашифрованную программу невозможно, но если очень хочется получить хоть какой-то листинг, можно попытаться извлечь из памяти компьютера «снимок» (дамп) программы в момент ее работы. Этот дамп уже можно более или менее успешно дизассемблировать. Более того, на основе дампа можно воссоздать исполняемый файл программы, причем этот файл будет успешно загружаться, запускаться и работать. Именно на этом принципе и основана работа большинства современных распаковщиков: подопытная программа запускается под управлением распаковщика; распаковщик ждет некоторого события, говорящего о том, что программа полностью распаковалась, и тут же «замораживает» программу и сбрасывает ее дамп на диск. Защитные системы нередко пытаются противодействовать получению работоспособного дампа при помощи манипуляций с сегментами и таблицами импорта-экспорта. В этих случаях приходится PE-реконструкторы, т.е. утилиты, обнаруживающие в дампе некорректные ссылки на функции и пытающиеся их восстановить. Многие продвинутые дамперы и распаковщики имеют встроенные средства восстановления секций импорта.
  4. Утилиты анализа файлов. Очень часто требуется быстро узнать, каким упаковщиком или защитным софтом обработана та или иная программа, найти все текстовые строки в дампе памяти, просмотреть содержимое файла в виде таблицы записей, вывести в файл список импортируемых и экспортируемых программой функций и многое другое. Для всех этих целей существует огромное количество специализированных утилит, позволяющих быстро проанализировать файл на наличие тех или иных признаков. Эти утилиты, как правило, не являются жизненно необходимыми, но, при надлежащем качестве, способны сэкономить огромное количество времени и сил.
  5. Шестнадцатеричные редакторы и редакторы ресурсов. Это, несомненно, наиболее древние (по идее, но не обязательно по исполнению) из программистских инструментов, ведущие свою славную историю с тех времен, когда программисты еще умели «читать» и править исполняемый код, не прибегая к помощи дизассемблеров. Тайное искусство чтения кода еще сохранилось в отдаленных уголках Вселенной, но в последние годы практически утратило актуальность. И теперь лишь крэкеры практикуют этот мистический обряд, в соответствии со священной традицией исправляя в неправильных программах идеологически чуждый опкод 75h на истинный и совершенный 0EBh. Редакторы ресурсов, в принципе, занимаются тем же самым, но по отношению к прилинкованным к исполняемому файлу ресурсам. Именно при помощи редакторов ресурсов выполняется значительная часть работ по «независимой» русификации программ и доработке интерфейсов. Рука об руку с редакторами идут всевозможные патчеры, которые позволяют создать небольшой исполняемый файл, автоматически вносящий изменения в оригинальный файл программы либо в код этой программы непосредственно в памяти.
  6. API-шпионы и другие утилиты мониторинга. Очень часто бывает нужно узнать, какие именно действия выполняет та или иная программа, откуда читает и куда записывает данные, какие стандартные функции и с какими параметрами она вызывает. Получить эти знания как раз и помогают утилиты мониторинга. Такие утилиты делятся на две большие группы: те, которые отслеживают сам факт возникновения каких-либо событий и те, которые позволяют выявить один или несколько специфических типов изменений, произошедших в системе за некий промежуток времени. К первой группе относятся всевозможные API-шпионы, перехватывающие вызовы системных (а более продвинутые - и не только системных) функций, хорошо известные утилиты Reg-, File-, PortMon и т.д., перехватчики системных сообщений и многие другие. Эти утилиты, как правило, предоставляют весьма подробную информацию об отслеживаемых событиях, но генерируют весьма объемные и неудобные для анализа логи, если отслеживаемые события происходят достаточно часто. Вторая группа представлена всевозможными программами, создающими снимки реестра, жесткого диска, системных файлов и т.п. Эти программы позволяют сравнить состояние компьютера «до» и «после» некоего события, построить список различий между состояниями и на основе этого списка сделать определенные выводы. Основная проблема при работе с такими утилитами хорошо описывается словами “«после» – не значит «вследствие»” (т.е. кроме интересующей Вас деятельности программы Вы можете получить лог «жизнедеятельности» других параллельно работающих программ и операционной системы).
  7. Прочие утилиты. Существует огромное количество утилит, не вписывающихся в приведенные выше категории или попадающие в несколько категорий. Одна лишь полная классификация этих инструментов потребовала бы значительных усилий, но моя цель не в том, чтобы плодить «мертвые буквы», а в том, чтобы дать Вам знания и навыки, достаточные для самостоятельных занятий. Крэкинг – занятие весьма многогранное, и столь же многогранны инструменты, в нем используемые. Более того, некоторые из утилит, которые могут быть полезны для крэкера, создавались для совершенно иных целей (хорошим примером может служить программа GameWizard32, которая вообще-то была предназначена, чтобы мухлевать в компьютерных играх, но оказалась полезна при вскрытии программы с ограничением на максимальное число вводимых записей). Поэтому еще раз обращу Ваше внимание: важно не только качество инструмента, но и умение творчески и нетривиально его применить.