Авторы:
MozgC и FEUERRADER
 
ВСТУПЛЕНИЕ, ОГЛАВЛЕНИЕ
Оглавление:
  - НАЧАЛО И ОБЩИЕ ВОПРОСЫ
  - ИНСТРУМЕНТЫ
  - ТЕРМИНЫ
  - ВЗЛОМ
  - РАСПАКОВКА, ПРОТЕКТОРЫ
  - ОСТАЛЬНОЕ
Здравствуйте! Рады предствить Вам самый большой FAQ по взлому программ! FAQ Содерижит в себе около 130 вопросов (и что самое главное - еще и ответов =), и мы надеемся, что Вы найдете в нем то, что искали, а также узнаете для себя много нового и полезного, что поможет Вам в нелегком деле Cracking'a и Reversing'а. Прежде всего, если Вы встретите какой-либо незнакомый термин или определение, то рекомендуем ознакомиться с разделом термины. Также для полного понимания следует прочитать весь FAQ. И если какой-то вопрос не понятен, то вероятнее всего, что Вы окончательно разберетесь, прочитав ответы на остальные вопросы. Удачи и приятного чтения!


НАЧАЛО И ОБЩИЕ ВОПРОСЫ
Q: Легально ли ломать программы, распространять крэки, писать статьи о Reversing'e, ломать сайты и т.д. и т.п. ?
A: Согласно УК РФ, при совершении противоправных действий в сфере компьютерных технологий, Вам грозит:
Статья 272 УК РФ. Неправомерный доступ к компьютерной информации.
1) Неправомерный доступ к охраняемой законом компьютерной информации, то есть информации на машинном носителе, в электронно-вычислительной машине (ЭВМ), системе ЭВМ или их сети, если это деяние повлекло уничтожение, блокирование, модификацию либо копирование информации, нарушение работы ЭВМ, системы ЭВМ или их сети, наказывается штрафом в размере от двухсот до пятисот минимальных размеров оплаты труда или в размере заработной платы или иного дохода осужденного за период от двух до пяти месяцев, либо исправительными работами на срок от шести месяцев до одного года, либо лишением свободы на срок до двух лет.
2) То же деяние, совершенное группой лиц по предварительному сговору или организованной группой, либо лицом с использованием своего служебного положения, а равно имеющим доступ к ЭВМ, системе ЭВМ или их сети, наказывается штрафом в размере от пятисот до восьмисот минимальных размеров оплаты труда или в размере заработной платы, или иного дохода осужденного за период от пяти до восьми месяцев, либо исправительными работами на срок от одного года до двух лет, либо арестом на срок от трех до шести месяцев, либо лишением свободы на срок до пяти лет.

В принципе, ломать программы, делать крэки - это нарушение УК РФ. Правда исследовать программы дома, для себя, никто вам запретить не может. А вот распространение крэков или даже дизассемблированных листингов может повлечь отвественность.

Будьте бдительны!

Q: Я не знаю ассемблер, не знаю ни одного языка программирования высокого уровня, но в игры я играю хорошо, даже прошел весь Quake. Смогу ли я скоро научиться взламывать программы?
A: На данный момент нет. Для начала неплохо бы иметь хоть какой-то (а лучше неплохой =) опыт программирования. После этого стоит начать учить ассемблер (хотя бы необходимый минимум, это не так сложно, как кажется сначала, если конечно есть способности). А потом уже читать статьи по исследованию/взлому программ и практиковаться. Еще, я наверное многих огорчу, но если вы не чувствуете в себе скрытых (ну или не скрытых =) способностей, если вы с компьютером "на вы", то лучше либо (пока) не начинать, либо скорее всего вы далеко в этом деле не уйдете...

Q: Какую операционную систему лучше использовать для занятия реверсингом?
A: Лучше всего установить 2 ОС. Windows 98 и Windows 2000 или Windows XP. Этому есть причины:
1) некоторый софт для ревёрсинга не предназначен для использования на Win9x/ME.
2) проверка работоспособности программы (после ее модификации) на других ОС.

Q: Поставил себе SoftIce для Windows XP, но когда я его пытаюсь запустить и после этого нажать CTRL+D, то окно SoftIce'а на экране не появляется. Что мне делать?
A: Скорее всего проблема в том, что вы не поставили патч для SoftIce'а под Windows XP. В интернете можно найти много таких патчей, но на моем опыте сработал только один. Его (на момент написания FAQ'a) можно найти тут.

Q: С чего посоветуете начать обучение крэкингу?
A: C чтения рассылки Калашникова "Ассемблер? Это просто!", а также с последующего чтения статей для начинающих по взлому программ и постоянной практике на crackmes. Рассылку Калашникова "Ассемблер? Это просто!" можно скачать здесь.

Q: Не могли бы вы написать команды SoftIce'а, необходимые при исследовании программ?
A: Вот те команды, которые вам понадобятся:
1) "bpx function_name" или "bpx address" - установка брейкпоинта на вызов определенной функции или выполнения команды по определенному адресу. Примеры: "bpx MessageBoxA", "bpx 401000". (Здесь и далее двойные кавычки при вводе команд в SoftIce писать не надо).
2) "bpm address x" - аналогично первому пункту. Примеры: "bpm 401000 x", "bpm MessageBoxA x".
3) "bpm address" - установка брейкпоинта на запись или чтение данных с определенного адреса. Пример: "bpm 450768".
4) "bl" - показать список установленных брейкпоинтов
5) "bc nomer_breakpointa_v spiske" - удалить брейкпоинт. Примеры: "bc 0", "bc 2 4 6", "bc *" (удалить все).
6) "bd nomer_breakpointa_v spiske" - выключить брейкпоинт, не удаляя его.
7) "be nomer_breakpointa_v spiske" - включить брейкпоинт
8) "db address", "dw address", "dd address" - показать участок памяти начиная с указанного адреса и отделять участки памяти друг от друга соответственно по байту, двум байтам, четырем байтам. Примеры: "dd 450000", "dd esp", "db 401000", "dw ebx".
9) "eb (ew или ed) address newbytes" - изменить значение в памяти по указанному адресу. Примеры: "eb eip 55" - записать байт 55 по адресу хранящемуся в регистре eip, "eb MessageBoxA c3" - записать байт C3 по адресу первого байта функции MessageBoxA, "eb MessageBox+5 c3" - записать байт C3 по адресу функции MessageBoxA+5, "ed 412345 AABBCCDD" - записать 4 байта DDCCBBAA по адресу 412345 (запишутся в обратном порядке, т.е. по адресу 412345 окажется DDCCBBAA. Аналогично байты запишутся в обратном порядке при использовании ew например).
10) "u address" или "u function_name" - показать ассемблерный листинг программы начиная с адреса "address" или адреса функции "function_name". Примеры: "u 401000", "u MessageBoxA".
11) "r register newbytes" - записать новое значение в регистр. Примеры: "r al 1", "r eax 12FF", "r eip 494EA6".
12) "r fl flagname" - инвертировать значение флага. Пример: "r fl z" - изменить значение флага нуля на противоположное.
13) "addr PID" или "addr process_name" - сделать адресное пространство указанного процесса текущим. Чтобы узнать ID процесса (PID) или имя процесса, наберите просто команду "addr" и смотрите в списке. Примеры: "addr 130", "addr blueface". Данная команда используется когда нужно установить брейкпоинт на определенный адрес в программе или посмотреть определенный участок памяти программы (т.е. сначала делаем адресное пространство нужного процесса текущим, а потом делаем что хотим).

Q: Я хочу научиться взламывать программы. Где бы найти простенькие crackmes?
A: В свое время я (FEUERRADER) ломал crackmes от Fant0m. Мне они показались самыми интересными (пусть и легкими). Качал их отсюда. А я (MozgC) тренировался в основном на crackmes с сайта команды BiW. Скачать crackmes c их сайта можно по этой ссылке.

Q: Вот вчера скачал SoftIce, прочитал несколько статей, доходит с трудом, не знаю с чего начать. Посоветуйте какую-нибудь хорошую статью для новичка.
A: Советую прочитать две моих статьи: "Исследование программы BlueFace на предмет ее регистрации =)" и ее продолжение "Исследование алгоритма генерации кода в программе BlueFace и написание генератора правильных кодов". Если указанные ссылки не работают, то ищите мои статьи на сайтах http://www.xtin.org и http://cracklab.narod.ru.

Q: Вот уже неделю читаю все статьи подряд, все пробую и пробую, но ничего не получается. Что делать? Охото уже ХОТЬ ЧТО-ТО ВЗЛОМАТЬ.
A: Тут проблема либо в том, что вы пытаетесь взломать сложную для вашего уровня программу, либо читаете не те статьи =), либо ваше время еще не пришло =) В любом случае не стоит расстраиваться. Пробуйте исследовать crackme, задавайте вопросы в форумах у более опытных людей и наберитесь терпения.

Q: Уже неделю изучаю ассемблер, но никак не могу понять для чего служит команда test. Часто в программах вижу test eax, eax или test al, al.
A: Команда test ЧАЩЕ ВСЕГО используется для сравнения значения регистра с 0. Записывается так : test eax, eax . Тут может быть не eax а любой другой регистр, но чаще всего eax. Если eax равен 0, то устанавливается флаг нуля (флаг Z), т.е. он становится равным 1.

Q: Не могли бы вы объяснить для чего используется команда lea?
A: Команда lea используется для загрузки эффективного адреса. Например, если нам надо поместить в eax смещение массива Massiv для последующей работы с ним, то нужно написать так: lea eax, Massiv. Данная команда будет аналогична команде mov eax, offset Massiv. Также, если, например, необходимо получить адрес строки MsgText (предварительно объявленной так: "MsgText db "lalala",0", то можно написать: lea edx, MsgText. После этого в регистре edx окажется адрес, по которому хранится строка "lalala". Команду lea еще иногда используют для получения адреса какой-либо процедуры (например lea eax, ProcedureName). Иногда можно встретить, например, такое сочетание: lea ecx, dword ptr [edx+eax+01]. Для простоты скажу лишь, что эта команда приравняет ecx к edx+eax+1, т.е. после выполнения этой команды, ecx станет равным edx+eax+1. Аналогично, после выполнения команды "lea eax, dword ptr [ebx+ecx]", регистр eax станет равным ebx+ecx (eax = ebx + ecx). Ну вот вроде и все, что вам необходимо знать о команде lea для начала.

Q: Я уже во всю разбираюсь в reversing'е, но не пойму одной вещи: для чего нужны регистры?
A: Регистры используются для хранения различных данных, значений, адресов в памяти, для арифметических операций и т.д. Процессор имеет непосредственный (прямой) доступ к регистрам. Регистры - это часть процессора, поэтому все операции с регистрами происходят внутри процессора, без обращения к оперативной памяти, что позволяет достичь максимального быстродействия.

Q: Ну это понятно. А есть ли разница какие регистры использовать?
A: На этот вопрос нельзя ответить однозначно, все зависит от конкретного случая. Например если функция берет значение для какой-то своей работы из регистра eax (это только к примеру), то, если мы положим это значение в регистр ecx, функция об этом не узнает, и все равно возьмет значение из регистра eax. А что там будет лежать, если мы поместили нужное значение не в eax, а в ecx, только одному Богу известно. Но вот другой пример:

mov eax, address_of_function
call eax

В этом случае (если адрес функции помещается в eax только для того, чтобы сделать вызов этой функции и для примера значение регистра ebx в этот момент не нужно) то можно написать и так:

mov ebx, address_of_function
call ebx

Q: Чем отличается регистр eax от ax?
A: eax = Extended ax, т.е. расширенный регистр ax. eax, в отличие от ax, является 32-х разрядным регистром (ax - 16-ти разрядный регистр, хранит в себе 2 байта), т.е. способен хранить в себе 4 байта. ax является младшей частью регистра eax, т.е., при изменении регистра ax, регистр eax тоже будет меняться. Аналогичное ситуация и с другими регистрами (ebx, ecx, edx, esp, ebp и т.д.)

Q: А что значит младшая часть?
A: Регистр eax (беру eax просто для примера) является 32-х разрядным. Если представить его значение в двоичной системе счисления как последовательность из 32-х нулей и единиц, то, если взять правые 16 бит подряд, это и будет младшая часть регистра eax, которая будет определять значение регистра ax. Левые 16 бит подряд - это старшая часть регистра eax. Аналогично, 16-ти разрядный регистр ax делится на регистр ah и al, которые соответственно являются старшей и младшей частями регистра ax. Также регистр ebx (ecx, edx тоже) например делится на старшую часть и младшую часть. Младшая часть определяет значение регистра bx, который в свою очередь делится на bh и bl. Если вам что-то не понятно с разрядами и представлением в двоичной (и других) системе счисления, то почитайте про системы счисления.

Q: А как найти старшую часть расширенного регистра (eax, ebx, ..., esi, edi)?
A: Предлагаю два способа:

1) Например надо найти старшую часть регистра esi и поместить ее в ax. Это достигается следующей парой команд:

mov eax, esi <--- Помещаем esi в eax
shr eax, 10h <--- Сдвигаем биты eax на 16 разрядов вправо.

Поясняю. Старшая часть регистра eax - это его левые (старшие) 16 разрядов. Если мы эти 16 разрядов сдвинем влево на 16 позиций, то они окажутся как раз на месте, где до этого были правые (младшие) 16 разрядов, т.е. в регистре ax. Все!

2) Например надо найти старшую часть регистра ebx. Для этого пишем:

rol ebx, 10h

После этого все разряды регистра ebx сдвинутся по кругу на 16 позиций вправо. Старшие 16 разрядов окажутся на месте младших 16 разрядов. А младшие 16 разрядов окажутся на месте старших =) Аналогично, в регистре bx окажется старшая часть предыдущего состояния регистра ebx. Надеюсь понятно =)

Q: А где почитать про системы счисления?
A: Учитесь пользоваться поисковиком. Вводим например в yandex'e "системы счисления" и вперед!

Q: Как узнать какие параметры передаются функции и какие значения она возвращает?
A: Параметры передаются функции обычно через стек, либо через регистры (например в программах, написанных на Delphi). Функция обычно возвращает значение в регистре eax, либо тоже через стек. Для примера возьмем функцию GetWindowTextA:

push 00000100
push dword ptr [esp+04]
push dword ptr [ebx+30]
Call user32.GetWindowTextA

Параметры передаются функции "как бы" в обратном порядке. Т.е. последним в стек помещается значение, которое функция берет первым. В нашем примере push 100 кладет в стек число 100h - максимальная длина считываемой текстовой строки. push dword ptr [esp+04] помещает в стек адрес, по которому функция GetWindowTextA поместит считанную строку. push dword ptr [ebx+30] помещает в стек handle элемента окна, из которого будет считываться текст. call user32.GetWindowTextA вызывает саму функцию.

Q: Ну вроде более менее понятно, но что такое handle?
A: Handle - это уникальный идентификатор, который представляет собой целое 32-х битное (4-х байтное) число. Handle позволяет обращаться к чему-либо в системе не по имени (или еще чему там можно придумать), а по соответствующему уникальному идентификатору. Например каждый элемент окна имеет свой handle. Все значения идентификаторов разные, т.е. уникальные. Если есть два одинаковых окна, то элементы этих окон все равно будут иметь разные идентификаторы. Понятие handle используется не только для идентификации элементов окна, но и например для файлов, процессов, потоков (threads) и т.д. На самом деле ОС работает с файлами, процессами, потоками (threads) не по их имени, а по их идентификатору.

Q: И что так всегда будет push 100, push dword ptr [esp+04] и т.д. перед вызовом функции GetWindowTextA?
A: Нет не всегда. Это был просто пример. Этой функции всегда будут передаваться 3 параметра через стек. А что будет передаваться конкретно (максимальна длина строки, адрес буфера для текста, handle элемента окна) может каждый раз быть разным.

Q: А где я могу взять информацию с описанием API функций Windows? Мне нужно знать, что они делают, что и как им нужно передавать в качестве параметров, что и как они возвращают и т.д.
A: Для этого необходимо достать Microsoft® Win32® Programmer's Reference. Это руководство программиста, которое оформлено в виде help-файла win32.hlp. Его можно найти в комплекте с Delphi/C++ Builder. Скачать его на момент написания FAQ'a можно тут.

Q: А что это за "А" или "W" в конце имени многих функций?
A: Сейчас используются только функции с "W" в конце своего имени, т.е. функции, которые работают со строками в Unicode (на хранение одного символа требуется два байта, а точнее 11 бит). A - означает ASCII, W - WideChar (Unicode). Если глянуть в kernel32.dll в 2K/XP/NT, то можно увидеть, что любая API функция с буквой A в конце на самом деле является переходником к API функции с буквой W. Как, по-вашему, реализуется многоязыковая поддержка? Только благодаря unicode.

Q: Если функции с "A" на конце являются переходниками на функции с "W" на конце, то почему тогда при появлении MessageBox'a не срабатывает функция MessageBoxW или при вызове функции CreateProcessA не срабатывает CreateProcessW?
A: Не надо понимать так дословно. Переход на функции с "W" на конце происходит не сразу. Например функция CreateProcessA внутри себя вызывает функцию CreateProcessInternalA, а та уже в свою очередь переводит текстовую строку из ASCII в Unicode и вызывает функцию CreateProcessInternalW. Еще, для примера, функция MessageBoxA вызывает функцию MessageBoxExA, а та, в зависимости от ядра ОС, вызывает либо MessageBoxExW либо MessageBoxTimeOutA, которая, в свою очередь, вызывает функцию MessageBoxTimeOutW =) В любом случае мы видим, что в итоге вызывается функция с "W" на конце. Т.е. подтверждается предыдущий ответ, что сейчас в конечном итоге используются функции, которые работают со строками в Unicode, т.е. функции с "W" на конце.

Q: Где я могу задать свой вопрос? Посоветуйте пожалуйста какой-нибудь хороший форум.
A: На момент написания этого FAQа мне (MozgC) больше всего нравится вот этот форум. Еще есть форум сайта reversing.net.

 


ИНСТРУМЕНТЫ
Q: Я решил заняться крэкерством (ну или называйте как хотите), чувствую в себе способности и думаю у меня все получится. Какие инструменты (и не только инструменты) мне нужны для начала?
A: Из отладчиков: SoftIce (можно TRW2000 если у вас Win9x) ; из дизассемблеров: IDA Pro, W32Dasm; еще понадобится шестнадцатеричный редактор (я использую Hex Workshop, Hiew, QView); PEid, для того, чтобы знать на каком языке написана программа или каким упаковщиком/протектором она запакована; справочник по API функциям Windows и по командам ассемблера; когда вы начнете распаковывать программы то понадобятся PE Tools (и/или ProcDump, LordPE) для снятия дампа, редактирования PE-заголовка, остановки на Entry Point и т.д; ImpREC (и/или Revirgin) для восстановления импорта программы при распаковке; утилиты для отслеживания обращений исследуемой программы к файлам/реестру - FileMon и RegMon; редактор ресурсов типа eXeScope, Restorator, ResHacker; ну и небольшой набор автоматических распаковщиков, например UPX, Caspr, AsPackDie.

Q: А где скачать все эти нужные инструменты?
A: На момент написания этого FAQ скачать большинство нужных программ, можно на http://protools.cjb.net , http://wasm.ru , http://reversing.kulichki.net

Q: Можно ли найти все эти инструменты на одном диске?
A: Я могу выслать вам компакт-диск со всеми имеющимися у меня последними версиями инструментов + что захотите по вашему желанию. Диск обойдется вам в 150 рублей включая доставку. Я вышлю диск на следующий день после оплаты. Время пересылки диска: 3-10 дней. Если вы заинтересовались таким предложением, напишите мне письмо по адресу MozgCnoSpam@avtograd.ru.

Q: Что такое IceExt, FrogsIce, IceDump?
A: 1) IceExt - это плагин для SoftIce, дающий дополнительные команды (типа дампа памяти, экрана, смены шрифта, остановки процесса и т.д.), а также позволяющий надежно скрыть SoftIce от программ с антиотладочными приемами, которые отказываются работать при обнаружении SoftIce (например некоторые протекторы). Работает только под Windows 2K/XP.
2) FrogsIce - это драйвер, позволяющий скрыть SoftIce от программ, отказывающихся работать при запущенном отладчике. Также показывает всю информацию о том, как программа проверяет наличие загруженного SoftIce. Работает только под Windows 9x/Me.
3) IceDump - это тоже драйвер, который как и FrogsIce скрывает SoftIce от обнаружения, а также вводит новые команды (типа дампа памяти на диск и т.д.). Работает в Windows 9x/Me/2K/XP.
Отмечу, что IceExt наиболее надежно скрывает SoftIce, да и мне (MozgC) он нравится больше всего. Жалко только что работает только в Windows 2K/XP.

Q: Как установить FrogsIce ? Проинструктируйте пожалуйста!
A: Откройте папку с FrogsIce. Здесь увидите вложенные три папки: win95, win98, winME. Откройте нужную (какая у вас ОС, такую папку и откройте =)). Скопируйте лежащий там файл frogsice.vxd в папку с FPloader.exe. Все. Теперь запускайте программу. FrogsIce работает только под Win9x/ME!

Q: Как выгрузить IceDump и FrogsIce из памяти, не перезагружая компьютер?
A: В FrogsIce достаточно найти кнопочку Exit. Чтобы выгрузить IceDump в Win9x надо его запустить с параметром "u", т.е. "icedump u". В Win2K/XP IceDump выгрузить вообще нельзя.

Q: Какая достойная альтернатива существует PEiD?
A: Можно порекомендовать PESniffer (из пакета PETools by NEOx). Немаловажно, что открыты сигнатуры, по которым все определяется. Также можно использовать PE-Scan. Ему до PEiD далеко, но если ему попадется знакомый пакер, то он может сразу сам предложить Вам его распаковать. Удобно.

Q: Существует много различных генераторов патчей. Каким воспользоваться?
A: В общих случаях рекомендуется использовать генератор патчей CodeFusion. Он имеет много возможностей и подходит для создания большинства патчей. Конечно, можно использовать и что-то иное, но это "по вкусу". Также удобен Embryo Patch Maker. Дизайн создаваемых им патчей многим может понравиться. Для патча запакованных программ можно использовать DZAPatcher. Этот патчер может сделать крэк для большинства пакеров и даже некоторых протекторов (например для TElock).

Q: Какую программу посоветуете для снятия дампа, а то их так много!?
A: Да, их действительно много, но на моем опыте мне больше всего приглянулась программа PE Tools. Вот только недавно LordPE и ProcDump не могли корректно сдампить кое-какую прогу, а PE Tools справился без проблем. Иногда в опциях необходимо будет поставить галочку Full Dump: paste header from disk.

Q: Как пользоваться CoolDump?
A: CoolDump предназначен для автоматического снятия дампа. Он работает из командной строки и использует LordPE Dumper Server (типа плагина для LordPE). Вот алгоритм действий:

1) Запускаем LordPE. Жмем Dumper Server.
2) Запускаем cooldump со следующими параметрами: "cooldump.exe programname OEP Bytes", где
"programname" - имя упакованной программы
"OEP" - ОЕР программы. Используется GenOEP.dll (что и в PEiD). Можно написать свой или оставить пустым.
"Bytes" - 2 байта с ОЕР. Можно оставить пустым.
3) Ждем. По необходимости нажимаем любую клавишу (это понадобится сделать 2 раза и об этом будет написано). В конце появится сообщение, если все прошло ОК. Сдампленная программа будет сохранена с тем же именем, но расширением ".ex_". Импорт надо будет восстанавливать отдельно.

Q: Как мне восстановить импорт с помощью Revirgin?
A: Вот алгоритм действий:

1) Делаем дамп программы.
2) Запускаем запакованную программу.
3) Запускаем Revirgin.
4) Выбираем в списке процессов Revirgin'а эту запакованную программу и вводим OEP.
5) Жмем Fetch IAT. Revirgin найдет адрес начала и размер IAT.
6) Жмем IAT Resolver. Revirgin будет искать функции импорта.
7) После этого нажимаем Resolve again (когда полоска дойдет до конца жмем Stop).
8) Выбираем в списке Show Unresolved (показать нераспознанные функции).
9) Если есть нераспознанные функции, то необходимо их распознать (об этом читайте в статьях по восстановлению импорта), после чего в выпадающем меню выбрать "Edit" и вписать адреса уже распознанных функций в поле Address.
10) После того, как вписаны адреса всех функций, жмем Resolve again (когда полоска дойдет до конца жмем Stop). Начнут появляться нормальные названия функций и их адреса в системе.
11) Жмем Generate, выбираем полученный перед этим дамп, после этого еще выбираем имя .bin файла (можно задать любое, "от косяка". Это сама таблица импорта, но она нам не понадобится) и получаем восстановленный дамп с нормальной таблицей импорта.
12) Можно нажать Save resolved и сохранить информацию об импорте.

Q: Вот прочитал в статье про распаковку, что в конце надо изменить Entry Point. Как это сделать?
A:
1) Если используем ProcDump, то нажимаем кнопку PE Editor -> Выбираем файл -> Меняем значение Entry Point (пишем RVA Entry Point. Что такое RVA читайте в этом же FAQ'е) -> OK
2) Если используем LordPE, то нажимаем кнопку PE Editor -> Выбираем файл -> Меняем значение Entry Point (тоже RVA) -> Save -> OK
3) Если используем PE Tools, то в меню Tools -> PE Editor -> Выбираем файл -> Optional Header -> Меняем значение Entry Point (тоже RVA) -> OK -> OK

Q: Что делает Rebuild PE из LordPE (и др.)?
A: Оптимизируется PE-заголовок файла, что может уменьшить размер файла на несколько килобайт. Это можно сделать для оптимизации внутренней структуры и расположения данных в файле. Можно воспользоваться им после восстановления файла после протекторов/упаковщиков.

Q: Существуют ли программы для автоматического/ручного создания .nfo?
A: Конечно. Для автоматического создания могу порекомендовать NFOmakeR v1.0, Feuer's NFO File Maker 1.6. Для рисования - NFO Builder2000, ASCII Art Studio.


ТЕРМИНЫ
Q: Что такое "reversing"?
A: Reversing - это совокупность действий, дающих, так сказать, обратный ход. Это если переводить с английского. Что же мы реверсируем? Конечно же алгоритмы программ. Reversing подразумевает под собой разбор программы с целью изменения ее работы, параметров, интерфейса, встраивание дополнительных функций и т.д. Эти действия могут включать в себя нахождение алгоритма генерации/проверки кода, пароля, алгоритма организации защиты и т.д. Совокупность этих действий, как я уже сказал, и называется Reversing.

Q: Что такое crackme (крэкми, крякми)?
A: Crackme (переводится как "взломай меня") - это специальная программка для тренировки взлома. Обычно защита в таких программках довольно простая (хотя есть и сложные crackme), но для новичков, которые ТОЛЬКО НАЧАЛИ заниматься крэкингом это идеальный способ потренироваться.

Q: А что такое флаг?
A: Флаг - это регистр (на самом деле это один бит регистра флагов, но чтобы вам было легче понять, можете представлять флаг как отдельный регистр), который может принимать значение либо 0, либо 1 (если флаг равен 1, то говорят, что флаг установлен или выставлен). Флаг нуля, например, показывает результат предыдущего сравнения или некоторых других команд.

Q: А что такое стек?
A: Стек - это специально отведенная область памяти для хранения промежуточных данных. Новичку работа со стеком может показаться сложной, но на самом деле это не так. Когда мы помещаем что-то в стек (обычно это адрес, или какое-то значение, которое нужно передать функции или сохранить на время), то это значит что указатель вершины стека (регистр esp) уменьшается на размер помещаемого в стек элемента и по адресу esp в стек записывается этот элемент. При выталкивании элемента из стека, берется значение по адресу esp, после чего указатель вершины стека (регистр esp) увеличивается на размер полученного элемента стека. Важно помнить две вещи:

1) Cтек растет в сторону уменьшения адреса в памяти.
2) При использовании команд push и pop нужно быть осторожным, потому что если элемент был помещен в стек последним, то из стека он будет вытолкнут первым.

Рассмотрим пример работы со стеком на небольшой задаче. Допустим, нам необходимо сохранить значения регистров eax, ebx и edx в стеке, потом произвести с ними необходимые действия и вернуть исходные значения этих регистров. На ассемблере это будет выглядеть так:

push eax // Помещаем в стек значение регистра eax. При этом указатель стека (esp) уменьшится на размер регистра eax, т.е. на 4 байта (значение esp уменьшится на 4)
push ebx // Аналогично, только в стек поместится значение регистра ebx
push edx // То же самое, только в стек помещается значение регистра edx
........... // Тут производим какие-то действия с регистрами eax, ebx, edx так, что значения этих регистров изменяются
........... // Тут тоже
........... // И тут =)
pop edx // Берем значение из стека (по адресу esp) и помещаем это значение в регистр edx. В edx окажется его исходное сохраненное значение. Как видите если мы с помощью команды push edx помещали значение регистра edx в стек последним, то для возвращения значения регистра edx, команда pop edx должна идти первой. Так что действует принцип "последним зашел - первым вышел". После того, как значение получено из стека и помещено в регистр edx, указатель вершины стека (регистр esp) увеличивается на размер регистра edx, т.е. на 4.
pop ebx // Аналогично берем из стека значение по адресу esp и помещаем его в регистр ebx. esp опять же увеличивается на 4.
pop eax // Сами догадайтесь =)

Надеюсь основы работы стека из примера вам понятны. Вот еще один небольшой пример:

push eax
pop ebx

Как вы думаете, что получится после выполнения данного кода? Конечно же значение регистра eax поместится в регистр ebx! Почему? Все очень просто. Команда push eax поместит значение регистра eax в стек. Команда pop ebx возьмет из стека последнее помещенное в него значение и поместит его в регистр ebx. А что было помещено в стек последним? Значение регистра eax! Таким образом ebx станет равным eax. Ну теперь все понятно?

Q: Что такое "брейкпоинт" (breakpoint)?
A: Брейкпоинт (breakpoint, бряк, BP...) - это точка останова программы, т.е. та точка, в которой программа прервет свое выполнение, и мы попадем в отладчик (отладчик получит управление над прерванной программой). В софтайсе брейкпоинт ставится с помощью команды: "bpx имя_функции" . Где имя_функции - это название функции, перед выполнением которой программа остановится. Или же можно поставить брейкпоинт на адрес командой "bpx XXXXXXXX", где XXXXXXXX - это адрес, дойдя до которого программа прервется, и вылезет окно СофтАйса. В этот момент мы будем находиться как раз на адресе XXXXXXXX. Как узнать какая функция нам нужна, если мы ставим брейкпоинт на функцию? Вначале можно где-нибудь посмотреть список стандартных функций, которые могут пригодиться при отладке. Остальное очень быстро придет с опытом.

Q: А что такое MessageBox ?
A: MessageBox - это либо функция, либо окно. Когда говорят, что выводится MessageBox, то имеют в виду стандартное окно, небольшого размера, которое содержит в себе только информационное сообщение (обычно очень короткое) и 1-3 кнопки для выбора дальнейших действий (например ОК, или ОК и Отмена). Когда говорят поставить брейкпоинт на MessageBox, то имеют в виду функцию MessageBox, которая выводит это окошко.

Q: Что такое EP и OEP?
A: EP - это сокращение от Entry Point, что переводится как Точка Входа. Под EP подразумевается адрес в программе, по которому находится команда, которая будет выполнена первой при старте программы. Аналогично, OEP - это сокращение от Original Entry Point, что переводится как Оригинальная Точка Входа. Термин OEP применяется когда речь идет об упакованной программе. Иными словами OEP - это адрес, с которого бы начинала выполняться программа, если бы не была упакована. Может возникнуть вопрос, а с какого же тогда адреса будет выполняться упакованная программа? Она будет выполняться с EP, только после упаковки по адресу EP находится первая команда распаковщика/протектора. Упаковщик либо протектор добавляет в программу свой код, который получает управление первым и распаковывает программу в памяти, после чего делает переход на OEP.

Q: А что вообще такое decompiler (декомпилятор) ?
A: Это программа, позволяющая получить из набора машинных инструкций исходный код программы на том языке, на котором она была написана.

Q: А мне не понятны многие простые термины, например что такое shareware программа?
A: Shareware программа - это условно бесплатная программа. Это значит, что программа будет работать даже если вы ее не будете регистрировать. Но в этом случае она будет работать ограниченное время (к примеру 30 дней или 100 запусков) и/или будет иметь ограничения в своей работе, т.е. например некоторые функции программы будут доступны только в зарегистрированной версии.

Q: И как ее зарегистрировать?
A: Читайте FAQ сначала и полностью =)

Q: Что значит RVA?
A: RVA - это сокращение от Relative Virtual Address, т.е. относительный виртуальный адрес. "Относительно чего?" - спросите вы. "Относительно Image Base" - отвечу я. Например, если какая-либо строка хранится в памяти по адресу 450000h, и Image Base = 400000h, то RVA этой строки равен 450000h - 400000h = 50000h

Q: Что такое Image Base?
A: Это адрес в памяти, начиная с которого программа загружена в память. Естественно подразумевается виртуальный адрес. Чтобы вам было понятнее, приведу пример. Вы наверное все знаете, что в заголовке .exe файла (например) сначала идет сигнатура MZ (4D 5A). Так вот после запуска программы по адресу Image Base окажется именно MZ. Однако необязательно, что дальше программа в памяти после загрузки является точной копией программы на диске. Это происходит из-за различных смещений секций программы.

Q: Что означают все эти термины, которые мы видим при показе секций файла программами типа ProcDump, LordPE (на примере ProcDump): Name, Virtual Size, Virtual Offset, Raw Size, Raw Offset, Characteristics ?
A: Name в данном случае - это имя секции. Оно может быть любым (максимальная длина - 8 символов), и его смена в общем случае не повлияет на работоспособность программы.
Virtual Size - это размер данной секции в памяти.
Virtual Offset - это смещение данной секции в памяти относительно Image Base, иными словами - это RVA этой секции.
Raw Size - это размер данной секции в файле на диске.
Raw Offset - это смещение данной секции в файле на диске относительно начала файла.
Characteristics - это 4х байтное число, определяющее характеристику секции, ее свойства. Это число показывает является ли секция секцией исполняемого кода или нет, возможно ли чтение данных с этой секции, запись данных в эту секцию и т.д.

Q: Что такое сигнатура?
A: В нашем контексте под словом "сигнатура" понимается последовательность байт в файле, которая позволяет узнать необходимую информацию о файле. Например сигнатура "PE", расположенная по определенному адресу в файле (просто два байта - "P" и "E" :) - это один из признаков того, что данный файл - PE файл. Когда говорят про сигнатуры, по которым определяется, чем упакована программа, или на каком языке программирования она была написана, то имеют ввиду некоторые байты в файле, позволяющие определить указанную выше информацию.

Q: Что такое Dumpfixer (фикс дампа)?
A: Не думайте, что это какая-то программа! Это термин. Dumpfixer - это установка параметра Raw Offset, каждой секции файла, равному Virtual Offset. Проще говоря, это нужно для того, чтобы смещение секции в памяти соответствовало смещению данной секции в файле.

Q: Я так понял брутфорсер (BruteForcer) - это программа перебирающая все возможные варианты кода?
A: Почти. В нашем случае брутфорсер должен представлять из себя процедуру, которая перебирала бы все возможные варианты кода и, после получения каждого нового варианта, делала бы переход на процедуру проверки кода. Эта процедура вставляется в тело программы в каком-либо свободном месте, например отдельной секцией или в конце какой-либо секции (в конце секций обычно много нулей, вот туда и можно вставлять свою процедуру). В месте кода, который выполняется при определении неправильности пароля/кода, ставится команда перехода на нашу процедуру перебора. Та получает новый вариант кода, делает переход на процедуру проверки, и так по кругу, пока не найдется правильный пароль/код, либо пока не кончатся все варианты.

Q: Что такое Loader (Лоадер)?
A: Loader - это программа, которая запускает определенную программу (которую надо пропатчить) и после ее запуска меняет (патчит) нужные байты в адресном пространстве запускаемой программы. Loader'ы применяются в том случае, когда программа упакована, и нет времени (или возможности) ее распаковывать и патчить. В этом случае Loader патчит программу уже в памяти, когда она уже распакована.

Q: Постоянно слышу термин SEH. Что это такое, и как это мешает отладке?
A: SEH - это сокращение от Structured Exception Handling, т.е. структурированная обработка исключительных ситуаций. Примерами исключительных ситуаций (далее - ИС) могут быть деление на ноль, попытка доступа к невыделенной области памяти, попытка записи в системную область памяти, недопустимые арифметические операции (например попытка вычисления логарифма от нуля) и т.д. Обработчик операционной системы (далее - ОС) получает управление при возникновении ИС и решает что дальше делать, после чего либо завершает программу, либо выполняет необходимые действия и передает управление обратно программе. Программа может сама указать свой обработчик ИС, однако этот обработчик будет получать управление уже из обработчика исключительной ситуации ОС. Как это мешает отладке? Программа, которая хочет помешать своей отладке устанавливает свой собственный обработчик ИС, после чего создает исключительную ситуацию. Если мы будем проходить по участку кода, где будет создаваться исключительная ситуация, то в этот момент попадем в обработчик ИС операционной системы. Переход на обработчик ИС, который был установлен из программы, произойдет в одном из call'ов внутри обработчика ИС ОС =) А если мы будем идти в отладчике, нажимая F10 (т.е. не входя в вызовы процедур и функций), то проскочим переход в обработчик, установленный программой, и возврат в программу, т.е. так сказать потеряемся =) В этом и трудность. Как с этим бороться читайте например в статьях Hex'a (http://www.xtin.org).

Q: Что такое защита электронным ключем, dongle (донгл) ?
A: Dongle (донгл) - это и есть ключ, который представляет из себя микросхему, помещенную в корпус. Донглы используются для защиты от нелицензионного использования и распространения программ. Донглы втыкаются либо в LPT либо в USB разъем на вашей материнской плате. В случае LPT варианта, донгл похож на разъем от принтера (ну или по другому штекер от принтера, который втыкается в LPT вход), размером примерно со спичечный коробок. В случае USB, донгл напоминает USB Flash память (кто видел, тот поймет). Сначала считалось, что защита с помощью электронных ключей - неломаема, ведь если не воткнуть донгл в LPT или USB программа просто не будет работать. Но позже и эту защиту научились обходить. Однако и сейчас защита электронными ключами представляет из себя довольно надежное средство против нелицензионного использования и копирования программного обеспечения и может отсечь многих начинающих, средних и даже опытных крэкеров.

Q: Что значит PE файл?
A: PE - это сокращение от Portable Executable, т.е. переносимый (универсальный) исполняемый файл =) Этот формат появился еще в поздние времена Windows 3.11, но настоящее распространение получил с расцветом Windows 95. Можно сказать, что сейчас на компьютерах с Windows 9x/2K/XP 95% исполняемых (exe, dll) файлов - это PE файлы.

Q: Не могли бы вы вкратце, по-минимуму, описать формат PE файла?
A: PE файл имеет свою структуру. Очень вкратце я ее постараюсь описать. Вначале файла идет DOS заголовок, который включает в себя DOS MZ-заголовок и DOS-stub. DOS-stub, фактически, является полноценным exe, котоpый запускается опеpационной системой, не знающей о PE-фоpмате. Обычно в этом случае он пpосто отобpажает стpоку вpоде "This program cannot be run in DOS mode" или типа того =) Если же ОС - Windows, то DOS-stub не выполняется. Далее идет PE-заголовок (на самом деле между DOS заголовком и PE заголовком есть еще кое что, но я это описывать не буду, т.к. для начального понимания формата PE это не нужно). PE заголовок начинается с 4-х байтной сигнатуры, которая представляет из себя 2 байта - "PE" (4550h) и 2 байта равные 0. Далее идут различные данные, которые я описывать не буду. Их очень много и подробно вы можете посмотреть в cтандартном описании формата PE файлов. После PE заголовка идет таблица секций файла (Object Table), которая описывает параметры секций файла (секции кода, данных, ресурсов и т.д.), т.е. имя секции, ее Virtual Size, RVA, размер секции в файле, смещение секции в файле, характеристику секции. Количество таких структур в таблице секций равно количеству секций. Количество секций хранится в PE заголовке. После таблицы секций, идут страницы образов секций, т.е., попросту говоря, сами секции одна за другой.

Q: А что такое секция?
A: В данном контексте, секция - это просто блок данных с одинаковыми атрибутами (под одинаковыми атрибутами подразумевается, что все данные в одной секции являются либо кодом, либо данными, либо все они доступны только для чтения/записи и т.д.). Когда я говорю, что секция - это блок данных, не надо понимать это прямо. А то подумаете например, что исполняемый код программы в этом случае к данным не относится. Секции могут быть разными: секция кода, данных, ресурсов, импорта и т.д. Соответственно в секции кода находится исполняемый код программы, в секции данных - сами данные, которые будут использоваться в программе: определенные и неопределенные переменные и т.д., в секции ресурсов - ресурсы используемые в программе: изображения, звуки, формы, строки и т.д.

Q: Что такое TLS?
A: TLS (Thread Local Storage) - Это 24-х (18h) байтная структура, причем 8 последних байт забито нулями, но это не принципиально. Родное место этой структуры в секции .rdata (по крайней мере, для программ, написанных на Delphi). Thread Local Storage используется для выделения областей памяти, используемых потоками (threads) для хранения данных.

Q: Не могли бы вы подробно объяснить, что такое таблица импорта?
A: В официальном описании формата PE нет конкретно понятия таблица импорта, есть понятие Import Directory Table, что можно перевести как каталог импорта. Обычно когда говорят Import Table (Таблица импорта, сокращенно IT) имеют в виду каталог импорта. Вообще полностью информация об импорте, т.е. об импортируемых функциях, складывается из трех структур:
1) Каталог импорта (Import Directory Table)
2) Таблица просмотра импорта (Import LookUp Table)
3) Таблица адресов импорта (Import Address Table, сокращенно IAT)

Каталог импорта представляет из себя последовательность однотипных структур. Каждая такая структура называется Thunk и представляет из себя последовательность 4х байтных полей:

OriginalFirstThunk
TimeDateStamp
ForwarderChain
Name
FirstThunk

Поле OriginalFirstThunk хранит в себе RVA поля в массиве адресов имен функций. Адрес в этом поле указывает на первое поле (для соотвествующей DLL) в таблице просмотра импорта, в которой хранятся имена функций из какой либо DLL (каждый Thunk относится к отдельной DLL).
TimeDateStamp хранит в себе отметку о времени создания Thunk'a (часто содержит 0 или 0FFFFFFFFh).
ForwarderChain точно не известно для чего, но часто значение его равно 0 или 0FFFFFFFFh.
Name хранит в себе RVA имени DLL.
Поле FirstThunk аналогично полю OriginalFirstThunk

Таблица просмотра импорта (Import LookUp Table), как я уже написал выше, представляет из себя массив, в котором последовательно хранятся имена функций какой-либо DLL.

При запуске программы загрузчик ОС получает адреса используемых в программе функций и записывает их в массив адресов имен функций, на который ссылаются поля FirstThunk, и в котором до этого были RVA, ссылающиеся на имена соответствующих функций. После того, как этот массив заполнен адресами функций, он называется Таблицей Адресов Импорта (Import Address Table, сокращенно IAT).

После того, как IAT заполнена адресами нужных функций, программа может начать работу. Хоть мы и видим в дизассемблере например call MessageBoxA, на самом деле этот call вызывает функцию по адресу, хранящемуся в таблице адресов импорта. Т.е. на самом деле этот call выглядит так: call dword ptr [xxxxxx], где по адресу xxxxxx (это адрес в IAT) хранится адрес функции MessageBoxA в системе.

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

У вас может возникнуть вопрос: "А зачем нужны два поля OriginalFirstThunk и FirstThunk, которые фактически одинаковы, т.е. которые в итоге приводят к одинаковым именам функций?". Дело в том, что когда PE-файл загружается в память, и загрузчик ОС заполняет IAT (где до этого были RVA имен функций) адресами соответствующих функций, то если потребуется найти имена функций, то их можно будет найти с помощью полей OriginalFirstThunk, которые указывают на массив, в котором хранятся RVA этих имен функций. Т.е. OriginalFirstThunk, в отличие от FirstThunk, указывает на массив адресов имен функций, который остается нетронутым, исходным, оригинальным так сказать. Поэтому это поле и называется OriginalFirstThunk. Иногда поле OriginalFirstThunk содержит в себе 0. В этом случае найти имена функций уже будет невозможно, только если считывать их из файла на диске.

Поясняющую схему, которую я (MozgC) вырисовывал в PaintBrush'e =), можете посмотреть тут.

Надеюсь, что хоть что-то из этого вы поняли. Если нет - не расстраивайтесь. Все-таки это вопрос не для полных новичков. А добавил я его в этот FAQ по многочисленным просьбам. Если не понятно, то могу лишь порекомендовать еще раз все внимательно прочитать и проверить все на практике (значения в каталоге импорта можете посмотреть с помощью PE Tools: PE Editor -> Directories -> Import Directory).


ВЗЛОМ
Q: Какие вообще существуют способы взлома программ?
A: Вопрос сам по себе странный, на него нельзя ответить однозначно, и никто не сможет ответить универсально. Но раз такой вопрос возник, я постараюсь ответить. Часто проще всего оказывается пропатчить программу (такой способ взлома называется битхаком), т.е. изменить определенные байты таким образом, чтобы программа думала, что она зарегистрирована либо чтобы просто не выполнялись ненужные нам функции (например появления раздражающих окон с напоминанием о необходимости регистрации). Потом можно найти место сравнения правильного пароля с введенным и подсмотреть этот правильный пароль. Можно найти процедуру генерации/проверки правильного кода и разобраться с алгоритмом, а потом уже и флаг в руки. Можно попытаться найти правильный код в памяти программы рядом с введенным кодом. Если программа запакована можно сделать лоадер. На крайний случай можно сделать bruteforcer, т.е. попытаться подобрать регистрационный код, либо ключ для расшифровки. Еще есть защита электронными ключами, где пишется эмулятор функции проверки либо генератор ключа. Подробнее на этот вопрос ответить нельзя, для этого существуют конкретные статьи.

Q: Я только начал заниматься reversing'ом, и есть вопрос. Программа для регистрации просит ввести код. Как поймать место, когда она его будет считывать, чтобы потом можно было узнать, что она делает с введенным кодом, и где идет проверка.
A: Нужно попробовать поставить breakpoint на функции GetWindowTextA, GetDlgItemTextA. Если они не сработают и код представляет собой какое-то число, то надо попробовать GetWindowLongA. Если и она не сработает, то попробуйте поставить брейкпоинт на функцию hmemcpy/memcpy. Хотя часто оказывается проще искать по сообщению об ошибке, т.е. искать в дизассемблере ссылку на строку-сообщение об ошибке. Ведь не обязательно, что программа будет использовать хоть одну из этих API функций: например если программа написана на VB или Clarion.

Q: Не подскажете какой-нибудь легкий способ взлома?
A: Можно попробовать выделить адресное пространство ломаемой программы, после чего сделать поиск введенного пароля в памяти (предварительно ввести пароль и нажать ОК или Регистрация и т.д.) с помощью команды в SoftIce "s 0 l -1 "пароль который вы ввели"". Если пароль найдется в памяти, то посмотрите близлежащие области памяти: возможно рядом будет настоящий пароль. Это можно сделать нажимая мышкой на полосы прокрутки в окне данных, где найдется введенный пароль, либо Alt + вверх или вниз. Однако на практике такое наврятли сработает. Разве что в crackme каком-нибудь.

Q: А почему так надо писать - s 0 l -1 "что_найти" ?
A:
s - означает поиск, от слова search.
0 - c какого адреса в памяти искать
l - сокращение от слова length (длина)
-1 - размер области памяти в которой искать (-1 = FFFFFFFF)


Q: А если существует несколько искомых строк, как продолжить поиск, что-то типа "найти далее"?
A: После того, как нашли первый раз, вводите просто "s" для продолжения поиска.

Q: А еще какой-нить легкий способ взлома?
A: Ну например если программа выводит MessageBoxA, то ставим брейкпоинт на MessageBoxA и вводим код (или делаем что нужно) и жмем ОК (ну или что там в программе надо нажать для регистрации). Должны будем сразу же прерваться в отладчике в начале функции MessageBoxA (она должны будет вывести окно с сообщением о неправильном пароле и т.п.). Для выхода из функции жмем F12 (после чего надо будет нажать ОК в появившемся MessageBox'e) и оказываемся на следующей, после вызова MessageBoxA, команде. Смотрим выше и ищем условный переход типа je, jne, jz, jnz (je - это то же самое, что и jz, а jne - то же самое, что и jnz). Если нашли, то можно попробовать поставить брейкпоинт на адрес этого условного перехода и еще раз попытаться зарегистрироваться. Скорее всего остановимся на этом адресе. Теперь попробуйте изменить соответствующий флаг. Например если там je, jne, jz, jnz то эти команды перехода зависят от флага нуля (zf - флаг нуля). Пишем r fl "флаг", в нашем примере - "r fl z", для смены значения флага на противоположное и нажимаем F5. Возможно программа выведет сообщением о верной регистрации. А почему так? Потому что скорее всего эта команда условного перехода (jz, jnz и т.д.) делает переход на вывод сообщения об успешной регистрации, либо о неуспешной. Если это так, то в нашем случае она должна будет выполнить переход на сообщение о неверном коде, и если мы сменим соответствующий регистр флагов, то изменится и действие этой команды, и мы направимся на вывод сообщения об успешной регистрации.

Q: Ну а еще какой-нибудь легкий способ? =)
A: Можно улучшить предыдущий способ (про установку брейкпоинта на функцию MessageBoxA) использованием программы W32Dasm. Начало такое же. Узнаем адрес например следующей после вызовы MessageBox команды. Открываем исследуюмую программу в W32Dasm'e и ищем этот адрес. Выше (это может быть на 5-10-20 строк выше) скорее всего будет одно из двух:

1) Такая строка:

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00XXXXXX(C)

В этом случае перейдите на адрес XXXXXX и там скорее всего будет команда условного перехода (jn, jnz и т.д. - уже устал писать =). Тогда попробуйте изменить этот условный переход на противоположный одним из известных способов (например с помощью отладчика поставить брейкпоинт на адрес этой команды и изменить соответствующий флаг на противоположный, как было описано выше; либо изменить соотвествующую команду на противоположную в файле)
2) Условный переход типа jz, jnz, je, jne. Как и в предыдущем случае, попробуйте изменить этот переход.

Q: Я дизассемблировал исследуемую программу и думаю, что нашел место где происходит проверка введенного кода, но когда я пишу в SoftIce "bpx 12345678" (12345678 - адрес "этого места"), то breakpoint никогда не срабатывает. Что делать?
A: Возможно код по этому адресу просто не выполняется, но скорее всего дело в том, что вы не выделили адресное пространство процесса. Прежде чем ставить breakpoint на какой-то адрес в исследуемой программе необходимо выделить адресное пространство этого процесса. Это делается командой "addr PROCESSNAME" в отладчике. Если имя процесса слишком длинное или сложное, можете написать "addr PID", где PID - Process ID - идентификатор процесса. Его можно узнать просто набрав команду "addr" и в появившемся списке посмотреть значение в колонке PID напротив нужного процесса. Еще можно после того, как команда "addr" выведет информацию о текущих процессах, выделить мышкой имя нужного процесса, нажать правую кнопку и затем "copy", после чего нажатием правой кнопки и выбором "paste" можно будет вставлять имя процесса из буфера.

Вот пример того, что можно увидеть после ввода команды "addr":

CR3         Addr        PID     NAME
........    ........    ....    .........
xxxxxxxx    xxxxxxxx    1234    BlueFace
xxxxxxxx    xxxxxxxx    0000    Idle
Теперь, чтобы, например, выделить процесс BlueFace, можно написать "addr 1234" или "addr blueface".

Q: Программа работает нормально и без ограничений, но выводит раздражающее сообщение о том, что она не зарегистрирована. Как можно убрать это сообщение?

A: Это сообщение скорее всего выводится какой-либо процедурой или функцией. Надо найти вызов этой процедуры или функции и занопить его. Вся проблема сводится к тому, как найти этот вызов. Если раздражающее окно - это MessageBox, то ставьте брейкпоинт на функцию MessageBoxA, и когда он сработает жмите F12, выше увидете вызов функции MessageBoxA. Запомните адрес этого вызова. После чего занопьте его и четыре команды push перед ним. Если вызываемое окно - не messagebox, то будет труднее. Можно попробовать поискать с помощью дизассемблера обращение к выводимой в раздражающем сообщении строке и рядом будет вызов процедуры, которая выведет это сообщение, либо обращение будет происходить уже внутри этой процедуры. В этом случае найдите начало процедуры/функции и поставьте туда команду ret (байт C3h) - возврат из функции. Т.е. как только эта функции будет вызываться для вывода сообщения, будет просто происходить мгновенный возврат и ничего выводиться не будет. Только в этом случае не забудьте восстановить стек! Т.е. если параметры для передачи функции помещались в стек, то перед тем, как писать команду ret, необходимо вынуть эти параметры из стека, точнее освободить стек (можно просто сдвинуть стек на нужное число. Например если функции передавалось два 4-х байтных параметра, то для того что-бы освободить стек от этих параметров, указатель вершины стека надо увеличить на 4x2=8. Т.е. написать add esp,8 , а уже потом ret). Если вам что-то не понятно, то это придет с опытом. Я лишь дал "наводку". Тут нет универсального способа, только практика вам поможет.

Q: Как узнать машинный код определенной инструкции? Я хочу пропатчить программу.
A: Я для этого использую QView: запускаем, жмем Tab, пишем любую инструкцию, жмем Enter и смотрим слева ее машинный код. Только чтобы потом не сохранить изменения в памяти, жмем два раза ESC и выбираем Discard (отменить изменения). Также легко можно это сделать в HieW: открываем любой файл, выбираем режим показа ASM. Затем жмем F3 и F2. Пишем нужную инструкцию и смотрим ее машинный код.

Q: В программе есть какая-либо команда, и мне нужно сделать так, чтобы она не выполнялась. Как это сделать?
A: Самый простой способ это занопить команду. Это значит, что на место этой команды надо вписать необходимое количество команд nop (байт 90h). Команда nop (сокращение от no operand) ничего не далает. Так и написано в официальной документации: "This is a do nothing instruction".

Q: Всмысле необходимое количество команд nop? Почему просто не заменить одну ненужную команду, одной командой nop?
A: Команда, которую вам нужно отключить, в машинных кодах может занимать более одного байта (обычно так и бывает). А команда nop в машинном коде выглядит как один байт - 90h. Если заменить команду, машинный код которой занимает больше чем 1 байт, на 1 команду nop, то после команды nop (байта 90h) считаются следующие байты для обработки и выполнения, но эти байты будут просто остатками от заменяемой команды, поэтому их выполнение приведет к ошибке в программе. Поэтому, если нужно сделать так, чтобы какая-то команда не выполнялась, то ее надо заменить на столько команд nop, сколько байтов занимает эта команда. Например команда call 00450000 занимает 5 байтов, соответсвенно ее надо будет заменить на последовательность из 5 команд nop.

Q: А как это сделать? И вообще как пропатчить исполняемый файл программы?
A: Открываете файл, который собираетесь патчить в любом шестнадцатеричном редакторе (я использую Hex WorkShop), находите нужную команду или нужное место по соответствующему смещению (адресу относительно начала файла) в файле и изменяете ее как хотите.

Q: Я знаю адрес команды, которую мне надо изменить, в памяти. Как мне узнать, по какому смещению (адресу) относительно начала файла находится эта команда в файле?
A: Лично я смотрю смещение нужной команды в файле с помощью IDA Pro или W32Dasm. В обеих этих программах смещение выделенной команды/адреса в файле показывается в строке состояния (такая панелька в самом низу окна программы). Например в W32Dasm'e, если вам надо найти смещение нужной команды в памяти, выделите эту команду и в строке состояния смотрите такую строку: @Offset 00XXXXXX in File . Это значит что по смещению XXXXXX относительно начала файла и находится машинный код вашей команды. Аналогично в IDA Pro смотрите искомое смещение в строке состояния слева от текущего адреса. Также смещение нужной команды в файле, зная ее (даже и виртуальный) адрес, можно найти с помощью своеобразного калькулятора в PE Tools (кнопка FLC).

Q: Мне нужно изменить работу программы для своих целей. Я хочу вставить на место инструкций, которые хочу изменить, свои инструкции. Но "не хватает места", т.е. мои инструкции занимают больше места, чем те, которые нужно заменить. Что делать?
A: В этом случае составляем нужный нам код (процедуру). В конце кода добавляем команду ret. Создаем новую секцию (с помощью LordPE или ProcDump'a) и помещаем наш код в эту секцию. В начале инструкций, которые нам надо изменить, ставим вызов добавленной процедуры (call), оставшиеся ненужные инструкции, до начала нужных, забиваем командами "nop". Все. Только нужно будет быть внимательным с адресами, их надо будет смотреть в отладчике. Еще можно не добавлять новую секцию, а написать свой код (процедуру) в конец последней секции файла (там обычно есть много нулей), и дальше делать так, как я написал выше. Если в конце файла нет нулей, можно их дописать и расширить raw и virtual size последней секции, и не забыть исправить Image Size (увеличить все эти параметры на длину дописанного кода).

Q: При запуске программы, которую я хочу отладить, она пишет, что запущен отладчик и отказывается работать дальше. Что делать?
A: Можно конечно попытаться вручную найти где проходит проверка на наличие отладчика, но зачастую это сложно и можно использовать для этого специальные plugin'ы для SoftIce'а. Под Windows 9x это FrogsIce, под Windows 2K/XP это IceExt. В большинстве случаев они позволяют "скрыть" отладчик, и программа должна будет запуститься без проблем. Замечу, что IceExt на данный момент является одним из самых продвинутых plugin'ов в этой области и помимо скрытия отладчика имеет еще много полезных функций. Хотя я рекомендую все-таки разобраться как происходит отлов отладчика и учиться обходить это самому (вручную).

Q: Мне необходимо взломать программу, написанную на Visual Basic. При вводе неправильного пароля выскакивает табличка с соотвествующим сообщением, но я не могу найти это сообщение в дизассемблере.
A: Строки в программах, написанных на Visual Basic, хранятся в unicod'e т.е. на хранение одного символа уходит 2 байта. Для начала можно использовать патчи для W32Dasm типа Win32Dasm++ или SDR Enabler for VB Apps. Также дизассемблер IDA Pro может распознавать строки в unicode (Options -> ASCII String Style -> Unicode). Еще для исследования VB программ можно использовать NuMega SmartCheck.

Q: Программа написана на Дельфи. Вроде выводит MessageBox, но когда ставлю брейкпоинт на MessageBox, то он не срабатывает. Что делать?
A: Часто в Дельфи для вывода сообщения используют не MessageBox, а "самодельную" функцию ShowMessage. Если это дельфовский ShowMessage, то я думаю проще всего в IDA PRO сделать поиск функции ShowMessage либо прямо поиск строки, скорее всего ее смещение будет загружаться в eax, т.е. будет что-то типа
mov eax, offset _str_STROKA.Text
call XXXXXXXXX , где XXXXXXXX - либо адрес либо название функции. Ну и конечно еще на помощь придет программа DeDe.

Q: Есть программы, в которых серийный номер (рег. код) тщательно зашифрован, т.е. вместо пароля (рег. кода) ты видишь %^@#*& или просто что-то неосмысленное... Как такое дело расшифровать?
A: Если есть уверенность, что это зашифрованный пароль, то просто надо смотреть алгоритм, по которому он получается из введенного. В этом случае, когда вводится пароль, он должен будет шифроваться (преобразовываться) по точно такому же алгоритму, как и настоящий пароль, из которого получилась данная зашифрованная строка (%^@#*&). Ну вот и нужно реверсировать алгоритм, разбираться с ним. Еще необходимо помнить, что если дело слишком запутанно и сложно, то просто иногда легче не находить пароль, а просто пропатчить программу, чтобы она приняла любой пароль и зарегистрировалась.

Q: Что делать, если текст в MessageBox выводится на русском языке: я не могу найти его в дизассемблере, т.к. русский язык не поддерживается?
A: Тут есть два варианта:
1) С помощью Hex-редактора найти смещение (адрес относительно начала файла) этой строки в файле. Загрузить файл в IDA Pro, найти это адрес, выделить его и нажать "N", после чего ввести новое имя для этого адреса (латинскими буквами). Теперь нажимаете Alt+T для поиска и вводите указанное имя. Когда строка найдется, для продолжения поиска жмите Ctrl+T.
2) Если у вас нет IDA Pro или вы не любите пользоваться этим дизассемблером, то найдите аналогично искомую строку на русском языке в файле и замените ее на любую строку на английском языке, хоть на abcdefghijk... (это можно сделать также с помощью любого hex-редактора), после чего загружайте свой файл в дизассемблер (например W32Dasm) и ищите новую строку.

Q: Как взломать программу, в которой кнопка ОК не работает, пока не введешь правильный рег. код? Т.е. кнопка есть, но ее нельзя нажать!
A: Тут надо подумать логически. Ясно, что каждый раз когда просто вводится символ, то запускается процедура, которая это дело проверяет. (Это событие ОnСhange. Кто программирует на чем-нибудь типа Delphi, C++ Builder и т.д., тот знает). Чтобы проверять каждый раз введенный пароль при вводе нового символа, его надо считать из Edit'a, так ? Ну и как он будет считываться ? Как обычно. Ставим брейкпоинт на GetWindowTextA, GetDlgItemTextA и вперед. Тоже самое, как если бы мы нажали ОК. Только тут брейкпоинт должен будет сработать при вводе нового символа. Если программа написана на Delphi, то можно использовать DeDe для облегчения. Надо будет найти в списке форм нужную форму и в списке процедур выбрать OnChange, а дальше уже смотреть что происходит в процедуре.

Q: Программа имеет ограничение в незарегистрированной версии такое, что выходит после 10 минут своей работы. Что посоветуете?
A: Обычно такое ограничение делается одним из двух способов:

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

2) Запускается таймер с заданным временем (например 600000 мс = 10 минут) и, когда таймер срабатывает, программа завершает свою работу. В этом случае необходимо ставить брейкпоинт на функцию SetTimer. Установка Timer'а функцией SetTimer на ассемблере будет выглядеть так:

push XXXXXX // XXXXXX - адрес процедуры, которая будет выполнена при срабатывании таймера.
push YYYYYY // YYYYYY - время, через которое будет срабатывать таймер.
push ZZZZ // ZZZZ - идентификатор таймера. Иногда может быть нулем.
push XYXY // XYXY - handle окна, которому будут передаваться сообщения от таймера. Иногда может быть нулем.
call SetTimer

Тут можно поступить двумя способами. Например увеличить время срабатывания таймера, (т.е. второй push заменить на push FFFFFFFh например) либо занопить все это, чтобы таймер не запускался (занопить начиная с первого push'а и по команду call SetTimer, либо вместо первого push'а поставить прыжок на следующую после call SetTimer команду). Ну вот вроде и все, что нужно знать для начала. Пробуйте!

Q: Перебрал все известные мне способы взлома, но программа имеет хорошую защиту и сложный алгоритм генерации кода, и я так и не смог ее взломать. Что попробовать напоследок?
A: Обычно последней стадией, когда все уже перепробовано и ничего не вышло, является написание bruteforcer'а. Если код состоит из относительно небольшого числа символов, или если можно ввести дополнительные условия, сокращающие перебор, то брутфорсер становится довольно реальным и действенным вариантом.

Q: Какие существуют способы взлома защиты CD от копирования на винчестер?
A: Вот несколько полезных советов для начала:
1) Ставим брейкпоинт "bpx GetDriveTypeA" и запускаем игру, перед этим скопировав ее на винчестер. Функция GetDriveTypeA возвращает в eax тип указанного диска. Нас интересуют только 2 возможных возвращаемых значения:
Если указанный диск - диск винчестера, то возвращаемое значение в eax равно 3.
Если указанный диск - CD, то в eax возвратится 5.
Ниже должна будет идти проверка возвращаемого значения (типа если не "5", то значит игру скопировали, и произойдет переход на выход, либо на сообщение о том, что CD не вставлен в CD-ROM), которую надо будет изменить под свои цели.
2) Если предыдущий способ не помог, то используем брейкпоинт "bpx GetVolumeInformation". Функция GetVolumeInformation обычно используется для проверки метки диска: после вызова функции, скорее всего будет идти сравнение метки. Это надо отследить и исправить, т.е. сделать так, чтобы при любой метке игра запускалась.
3) Еще можно попробовать ставить брейкпоинты на функции GetDiskFreeSpace и GetFileAttributesA. Из названия вы можете догадаться для чего нужны эти функции. Используйте это в своих целях.
4) Игра также может делать проверку на запись файла на диск, с которого она запускается. На CD, как вы понимаете, запись не должна получиться. Если же файл запишется, значит игру запускают с винчестера. В этом случае используйте брейкпоинты на функции CreateFileA и WriteFile, чтобы найти проверку на запись.

Q: Как взломать запароленный zip/arj архив?
A: Т.к. при криптовании запароленного zip/arj архива используется необратимый алгоритм, то вскрыть такой архив можно только двумя способами
1) Простой подбор пароля (перебор всех возможных вариантов паролей специальными программами) - рекомендую программу AAPR (Advanced Archive Password Recovery) или AZPR (Advanced Zip Password Recovery).
2) Так называемая plain-text атака. Для этого вам надо найти хотя бы один файл, точь-в-точь такой же, какой есть в запароленном архиве. После этого вы архивируете этот файл, а из запароленного архива удаляете все файлы (естественно из копии =) кроме этого. Далее я вам объяснять не буду. Просто используйте plain-text атаку в программе AAPR или AZPR (поисковик - вперед!)

Q: Как взломать запароленный rar архив?
A: Смотрите предыдущий вопрос и используйте перебор с помощью программы AAPR. plain-text атака в этом случае не прокатывает, т.к. работает только для ZIP/ARJ архивов.


РАСПАКОВКА, ПРОТЕКТОРЫ
Q: Для чего применяются упаковщики и протекторы исполняемых файлов?
A: Упаковщики применяются для уменьшения размера исполняемого файла и, частично, для защиты программы от взлома (что может помешать только крэкеру, с опытом не более 2х недель =). Упаковщик сжимает исполняемый код программы, а также ее ресурсы и данные, и добавляет к программе свой код, который при запуске получает управление первым, распаковывает программу в памяти и передает управление распакованной программе, т.е. делает переход на OEP. Протекторы служат не столько для уменьшения размера исполняемого файла (хотя некоторые протекторы еще и упаковывают программу), сколько для защиты программы от взлома. Протекторы в простейшем случае работают как упаковщики, только добавляют различные действия, которые мешают распаковке и взлому. Например: защита от отладчика, криптование некоторых частей кода программы, создают проблемы с таблицей импорта программы, производят действия для затруднения получения работоспособной распакованной программы и т.д.

Q: Как узнать чем упакована программа?
A: Проще всего воспользоваться программой PEid.

Q: Мне попалась программа, которая запакована одним из известных упаковщиков, но автоматический распаковщик ее не распаковывает. Что делать?
A: Учиться распаковывать самому.

Q: Когда я загружаю исследуемую программу в W32Dasm, то там "пусто": нет никаких ассемблерных команд. Почему так?
A: Скорее всего программа запакована/защищена каким-либо упаковщиком/протектором, который изменил параметры секций программы. Также это может быть и уже после распаковки. В любом случае, необходимо выставить характеристику секции кода в значение E0000020. Если вы не знаете, какая из секций программы является секцией кода, то это обычно первая и самая большая по размеру секция, а также OEP (или EP если файл не запакован) находится внутри этой секции. Изменить характеристику секции можно например с помощью PE Tools:
1) В меню Tools выбираете PE Editor
2) Затем указываете нужный файл
3) Жмете кнопку Sections
4) Выбираете секцию кода
5) Кликаете по ней правой кнопкой и в появившемся меню выбираете Edit Section Header
6) В поле Characteristics вписываете E0000020
7) Закрываете все окна нажатиями кнопок ОК =)
Это все. Теперь загружайте программу в W32Dasm и делайте что хотите =)

Q: Программа запакована протектором. Я хочу лишь посмотреть/вытащить ресурсы ее. Нужно ли мне распаковывать программу?
A: Не обязательно. При запуске программы все равно идет инициализация ресурсов, и они находятся распакованными в памяти. Достаточно сделать дамп работающей программы! Естественно дамп будет нерабочий, но ресурсы (справедливо не для всех протекторов и не всегда!) будут восстановлены.

Q: Я более менее научился взламывать маленькие программки, но мне почему-то постоянно попадаются программы, которые чем-либо запакованы. Я так понимаю надо учиться распаковывать программы? Если да, то с чего начать? Есть ли автоматические распаковщики?
A: Любой начинающий крэкер рано или поздно сталкивается с тем, что приходится учиться распаковывать программы, ибо примерно половина shareware программ чем-либо да и упакованы/защищены. Так что учиться конечно надо, или в будущем это будет большим препятствием. Что по поводу "c чего начать", то лично я начинал с AsProtect 1.2x. Помню я тогда довольно долго мучался, читал много статей на эту тему, спрашивал у более опытных людей и наконец СМОГ =) Однако не знаю, стоит ли советовать вам начинать с AsProtect. Если вы оцениваете свой уровень как довольно неплохой (не в отношении распаковки конечно =), то можете попробовать заняться AsProtect. Качайте кучу статей, найдите кого-нибудь поопытнее, кто бы мог помочь если что, и вперед! Если же вы оцениваете свой уровень как низкий (не надо этого стыдиться и самому себе врать =), то можете начать с распаковки UPX или AsPack. Они распаковываются за 2 минуты, если знать, что делать. Так что с ними трудностей возникнуть не должно. Что насчет автоматических распаковщиков, то конечно таковые имеются. Например для распаковки UPX распаковщиком является сам же UPX =). Для AsPack - Caspr, AsPackDie. Для AsProtect 1.1-1.2 - Caspr. Еще есть ASPRStripperXP, который многие хвалят (только под Win 2K/XP), но на моем опыте он распаковал только 2 программы, защищенные ASProtect 1.2x, из 15 . Но можете попробовать. Хотя уточню все-таки, что для понимания происходящего лучше начинать с UPX. Надо не только дойти до OEP, но и просто посмотреть каким образом реализуется распаковка. Иначе - это все бесполезно: любой другой упаковщик приведет вас в полное недоумение. Необязательно понимать каждую команду, нужно просто смотреть и понять общий принцип.

Q: Какие упаковщики и протекторы наиболее популярны?
A: Наиболее популярные упаковщики - это UPX и AsPack. Из протекторов резко выделяется AsProtect, который я (да и многие другие) однако не считаю очень уж хорошим протектором. Хотя если правильно его использовать, то можно довольно хорошо защитить программу. Еще можно назвать такие протекторы как Armadillo, PC-Guard, Obsidium, SVK Protector, VBox и т.д.

Q: Какие протекторы наиболее хорошо защищают программу?
A: Мне кажется это Armadillo при использовании наномитов, CopyMem II + Debug Blocker, Enchanced SoftIce Detection, и криптования отдельных процедур, а также протектор Obsidium, который я сам не разбирал, но отзывы о нем очень хорошие.

Q: Где найти зарегистрированный ASProtect 1.23? Где скачать свежий ASProtect 1.23?
A: Зарегистрированный ASProtect 1.23 RC1 можно скачать здесь. ASProtect v.1.23 RC4 build 07.15 demo можно скачать отсюда.

Q: Где можно скачать Armadillo?
A: На момент написания FAQ'a, относительно свежую версию Armadillo (v3.10) с ключом для регистрации можно скачать здесь.

Q: А вот все говорят, что упакованные программы, или программы защищенные протекторами необходимо распаковывать. Зачем это нужно?
A: Это делается для того, чтобы после распаковки получить возможность дизассемблировать и патчить программу. Еще многие протекторы типа AsProtect, Armadillo и др. предоставляют для защиты программ специальные функции, с помощью которых осуществляется и проверяется регистрация программы. Если автор программы при использовании этих протекторов использовал только эти функции, а не писал свои, то после распаковки и убирания зависимости программы от протектора (это для примера, на самом деле еще кое-что надо будет подправить) она будет считать себя зарегистрированной.

Q: Существует ли универсальный, автоматический распаковщик программ?
A: Существует. Его название Generic Unpacker Win32. Он универсален тем, что сам ищет ОЕР (ошибается не часто) и дампит программу (в том числе и импорт восстанавливает). Таким образом, распаковывает большинство упаковщиков. Протекторы не берет! Программу можно скачать тут.

Q: Что значить "dump", "дамп", "сдампить", "сделать дамп", "снять dump"?
A: Слово dump (дамп) может быть и существительным и глаголом. В первом случае, дамп означает - область (часть) памяти. Во втором случае, сдампить, снять дамп - значит сохранить нужную область памяти на жесткий диск. Часто дамп нужно снимать при распаковке программ. Это надо для того, чтобы получить распакованную программу. Ведь когда запакованная программа запускается, то она распаковывается в памяти. В этот момент распакованный код программы нужно сохранить на жесткий диск.

Q: Зачем находить ОЕР еще как-то, если можно воспользоваться OEP Module из PEiD?
A: Реализованная в PEiD функция по нахождению ОЕР не всегда работает. Бывает, что она и вовсе не определяет ОЕР или показывает вообще не правильно. Очень часто можно доверять ей, если ЕХЕ упакован простыми упаковщиками. Бывает, что ОЕР оказывается верен даже у протекторов, но не нужно ему часто доверять.

Q: Зачем нужно зацикливать программу перед переходом на OEP либо прямо на OEP?
A: Это необходимо для того, чтобы остановить выполнение программы и сделать дамп в тот момент, когда программа находится в своем исходном состоянии. Если сдампить программу, просто запустив ее, то, возможно, секции данных и кода будут уже изменены и отличаться от исходных. Это может повлиять на работоспособность дампа (распакованной программы).

Q: Очень интересует меня распаковка протекторов и пакеров. Если не трудно, хотел бы увидеть пару инструкций распаковки несложных пакеров, типа UPX.
A: Ну если пару инструкций, то вот пример распаковки UPX:
Прерываемся на EP. Первой командой будет pushad.
Ставим breakpoint "bpm esp-4" и жмем F5. Прерываемся тут:

POPAD
JMP XXXXXX <--- Мы находимся тут

XXXXXX - это OEP! Для зацикливания программы вводим в SoftIce:

a <--- Начать ввод опкодов (ассемблерных команд)
jmp eip <--- Прыгать на eip, т.е. на текущий адрес (получается цикл)
"enter" <--- Прекратить ввод опкодов

После чего выходим из отладчика (F5) и снимаем дамп. Для этого я использую PE Tools (LordPE или ProcDump тоже подойдут). В списке процессов выбираем наш исследуемый процесс, правой кнопкой мыши по нему =) и в появившемся меню нажимаем Dump Full. Сохраняем дамп в какой-нибудь файл и завершаем процесс (Kill Task во всплывающем меню или выделите процесс и нажмите DEL). Запускаeм программу, которую надо распаковать, заново. Теперь запускаем программу для восстановления таблицы импорта. Это ImpREC либо Revirgin. ImpREC попроще, поэтому для примера возьмем его. В списке процессов выбираем нужный процесс, вводим OEP который мы получили, жмем Get Imports и затем Fix Dump. Выбираем наш дамп. Новый файл с восстановленной таблицей импорта будет иметь символ "_" после имени. Теперь все можно закрыть и запустить PE Tools (ProcDump или LordPE как я уже говорил тоже подойдут, но PE Tools мне нравится больше и иногда работает надежнее). В меню Tools выбираем PE Editor, указываем полученный новый дамп, затем нажимаем Optional Header и исправляем Entry Point. Вписываем значение равное OEP - (минус) Image Base. Например если мы нашли OEP 45FEC8h и Image Base = 400000h, то EP укажем 45FEC8h - 400000h = 5FEC8h. Жмем ОК, запускаем полученный файл и радуемся распакованной программе.

Q: А как прерваться на EP?
A: Я обычно это делаю одним из двух способов:
1) Запускаю программу. В отладчике пишу "addr NAME", где name - имя исследуемой программы (процесса), после этого пишу "bpm 12345678 x", где вместо 12345678 подставляем значение EP (вместе с Image Base) и перезапускаем программу. Произойдет остановка на EP.
2) Запускаю PE Tools. В меню Tools выбираю Break & Enter и выбираю нужную программу. После этого появится сообщение о том, что необходимо поставить брейкпоинт "bpint 3" и, после его срабатывания, написать "e eip 0xYY". После срабатывания брейкпоинта в СофтАйсе надо будет написать не "e eip 0xYY" (YY - это какой-то байт, который был заменен на вызов третьего прерывания). После этого флаг вам руки, делайте дальше что нужно.

Q: А как узнать адрес Entry Point (EP) ?
A: Тут существует куча способов. Проще всего воспользоваться для этого любой из этих программок: PeID, PETools, ProcDump, LordPE.

Q: Читал статьи по распаковке программ, в частности по распаковке AsProtect, и там почему-то пишут, что надо ставить breakpoint на esp-4 или esp-24 для нахождения OEP. Почему?
A: Привожу отрывок из своей статьи (MozgC):

"Для нахождения OEP используем тот факт, что при старте программы в Windows, указатель на верхушку стека (esp) практически всегда один и тот же. Это не обязательно, но это стандарт. Например, в Windows 2K/XP, esp при старте программы ПОЧТИ ВСЕГДА равен 12FFC4h. Хотя, конечно, если изменить esp вручную, ради интереса, находясь на EP, то ничего страшного не произойдет. Однако, повторюсь, такой стандарт сохраняется, и мы его используем для нахождения OEP. При запуске программы, упакованной ASProtect'ом, esp равен этому стандартному значению. Так как ASProtect во время своей работы следит за стеком (т.е. сколько поместил в стек, столько потом и достал из стека), то, перед переходом на OEP, esp должен быть опять равен этому "стандартному значению". Например в ранних версиях ASProtect'a, когда ASProtect восстанавливал стек перед переходом на OEP, считывалось значение в стеке по адресу esp-4 (имеется ввиду что esp = "стандартному значению") следующий элемент стека уже был по адресу esp, и ASProtect его трогать не должен, т.к. не он ложил этот элемент в стек. Т.е. используя тот факт, что последним будет считываться значение по адресу esp-4, можно поставить брейкпоинт на тот момент, когда это будет происходить (bpm esp-4), и, когда этот брейкпоинт сработает последний раз перед непосредственным запуском программы, мы окажемся перед переходом на OEP"

Если вам трудно это понять, не расстраивайтесь. С опытом вы это поймете. Это действительно сложно объяснять, но я старался как мог.

Q: Почему автоматические распаковщики не могут распаковать программу защищенную AsProtect 1.2x ? Хотя многие из них распаковывают AsProtect 1.2. Какие между ними различия?
A: Я перечислю только главные различия:
1) Кража байтов (команд) с OEP.
2) Эмуляция некоторых Windows API функций таким образом, что программы для восстановления импорта не могут определить эти функции (правда есть дополнительные плагины для этого дела, но я всегда все стараюсь делать вручную).
3) Улучшенная защита от отладчика.
Подробнее узнать и увидеть разницу можете в статьях по распаковке программ защищенных AsProtect 1.2x.

Q: Я считал себя уже не совсем начинающим крэкером, но вот столкнулся с программой защищенной новым AsProtect, и я не могу запустить эту программу вместе с отладчиком (SoftIce), т.к. программа ругается на активный отладчик. У меня Windows 98, FrogsIce не помогает.
A: Думаю тут остается только два варианта.
1) Попробовать разобраться вручную, что бывает сложно даже для некоторых опытных крэкеров
2) Использовать программу AsLoad, которую можно скачать тут.

Пользователям Windows 2K/XP/NT в аналогичной ситуации рекомендую использовать IceExt.

Q: Я хочу отлаживать программу, защищенную ASProtect на TRW2000. Но почему-то программа не прерывается на брейкпоинтах. К тому же для TRW2000 нет никаких дополнительных плагинов (типа icedump для softice). Что делать?
A: Дело в том, что ASProtect не дает ставить брейкпоинты. Это не зависит от отладчика. Существует программа SuperBPM (запустить и поставить галочку на Erase), которая позволит ставить брейкпоинты на программы ASProtect. Теперь в любом отладчике можно ставить обычные BPX на адреса программ, защищенных ASProtect.

Q: Чем можно восстановить импорт?
A: Лучше воспользоваться ImpRec или Revirgin. В ImpRec 1.6 FINAL плагин для ASProtect может справиться с большинством функций, которые раньше приходилось обрабатывать вручную. Но не стоит на него надеяться, учитесь сами распознавать функции! Благо, статей по этому поводу немало. Кстати, если, вдруг, ImpRec не определил много функций, попробуйте воспользоваться Revirgin'ом. Аналогично, если вы всегда используете Revirgin, но он, вдруг, не распознает много функций, или не будет работать как надо, то попробуйте ImpRec.

Q: У меня Windows XP. После того как я ImpREC'ом восстановил импорт при распаковке программы, то программа не работает на Win9x, хотя у меня на Win XP она работает без проблем. При запуске в Win9x, программа пишет, что не найдена функция RestoreLastError из библиотеки kernel32.dll. Что делать?
A: Дело вот в чем. В Win 2K/XP есть функция RestoreLastError, полностью идентичная функции SetLastError. В Win9x нет функции RestoreLastError, а функция SetLastError есть. Не знаю как с этой проблемой дела у Revirgin'a, но при восстановлении импорта ImpREC'ом в Win 2K/XP, ImpREC при нахождении такой функции определяет ее как RestoreLastError. Ну а так как такой функции в Win9x нет, то и программа потом не запускается в win9x. Что делать? Просто в списке определенных функциий, в окне ImpREC'a, найти функцию RestoreLastError и заменить ее на SetLastError, после чего можно восстанавливать импорт сдампленному файлу.

Q: Можно ли не ломать программы, защищенные ASProtect, а подобрать к ним ключ?
A: Наврятли =). ASProtect использует для создания ключа особый криптостойкий алгоритм c длиной ключа как минимум 173 символа. Так что подобрать в домашних условиях - нереально.проще распаковать и взломать программу, чем подбирать ключ.

Q: А можно ли подобрать рег. инфу к программе, защищенной Armadillo?
A: На подборе ключей для Armadillo специализируется команда DreamTeam. Видимо, они нашли слабое место у Armadillo, т.к. находят ключ даже к самым последним его версиям! Но дело в том, что когда это сделала только одна команда/человек в мире, то вряд ли стоит надеяться на это.

Q: Почему нигде не пишут, что надо удалять секции простых упаковщиков (UPX, ASPack..)?
A: В принципе, возможно удалить секции, но они, как правило, малы. Поэтому это не имеет смысла.

Q: Как распаковать DLL?
A: Распаковка DLL практически не отличается от распаковки EXE файла. У DLL как и у EXE есть точка входа (ЕР), и если она упакована, то есть и ОЕР. О подробностях читайте в одной из статей НЕХ'а (www.xtin.org).

Q: Почему распакованные файлы иногда запускаются медленнее, чем упакованные (ведь распаковка же отнимает процессорное время, а в распакованном файле ее нет) ?
A: При больших размерах файла возникает такой парадокс: к примеру размер сжатого файла 1 Мб, а расжатого - 3.5 Мб. Так вот получается, что на быстрых компьютерах скорость распаковки в памяти намного выше, чем скорость загрузки с винчестера. Поэтому быстрее загрузить 1 Мб, а потом разжать его в памяти, чем грузить 3.5 Мб с винчестера.


ОСТАЛЬНОЕ
Q: У меня не ставится breakpoint на функцию hmemcpy. Почему и что делать?
A: Скорее всего проблема в том, что у вас Windows 2K/XP. Там нет функции hmemcpy. Но не расстраивайтесь: в 99% случаев есть более удобные пути.

Q: Как мне сохранить содержимое окна SoftIce в текстовый или графический файл?
A: Под Windows 9x рекомендую использовать IceDump (добавка к SoftIce), под Windows 2K/XP - IceExt. Качайте один из этих плагинов, в зависимости от вашей операционной системы, и смотрите подробности в документации к этим плагинам.

Q: Мне необходимо отладить программу, написанную на Delphi, но в дизассемблированном коде трудно разобраться. Существуют ли декомпиляторы для Delphi?
A: Декомпиляторов, позволяющих получить исходный текст программы на Delphi, не существует. Но довольно неплохо тут может помочь программка DeDe. Рассказывать про нее не буду. Просто скачайте и не пожалеете (поисковик вам поможет).

Q: Можно ли защититься от анализаторов типа PEiD?
A: В принципе можно, но на практике это нелегко. Вы можете изучить как работает тот или иной анализатор и каким-либо образом от него защититься (простым изменением байт, например). Но существует немало анализаторов, и у них могут быть разные способы вычисления. Вам будет трудно защититься от них, т.к. будет сложно узнать по каким байтам анализатор вычисляет чем упакована или защищена программа. Еще это зависит от анализатора. Некоторые анализаторы можно ввести в заблуждение простой сменой пары байтов. Других же (типа PEid) так уже не проведешь =).

Q: Какие существуют способы защиты программ? И что они из себя представляют?
A: На этот вопрос нельзя ответить в рамках этого FAQ'а. Можно лишь дать несколько советов. Но если соберетесь делать серьезную защиту, то конечно надо будет читать статьи на эту тему, пробовать, просить крэкеров взломать защиту и т.д. В общем начну с того, что если вы ленивы делать свою защиту, то можете воспользоваться протектором, который защитит (все конечно относительно, и насколько он защитит будет зависеть от крэкера, от автора программы и от протектора =) вашу программу. Только не надо использовать ТОЛЬКО функции защиты предоставляемые протектором. Всегда используйте возможности протектора по максимуму, не бойтесь написать автору протектора письмо и расспросить его как нужно воспользоваться его протектором для лучшей защиты (я так делал на примере протектора Armadillo). Теперь по поводу защиты, которую будете делать лично вы. Во-первых, постарайтесь не хранить важные текстовые строки открытым текстом. Во-вторых, постарайтесь сделать действительно сложный алгоритм проверки кода. В-третьих, как я уже сказал, можете использовать протектор. В-четвертых, сделайте проверку целостности кода (подробнее - ищите статьи по организации CRC). Делайте проверку программы на зарегистрированность из разных мест в программе. Например при запуске, при вводе рег. кода, через определенные промежутки времени. Для вывода сообщения о правильном/неправильном рег. коде не используйте функцию MessageBox. Можете зашифровать или вообще исключить в незарегистрированной версии функции программы, которые будут доступны после регистрации. Приводить примеров можно до бесконечности. Я привел лишь основные и несложные для реализации.

Q: Можно ли заработать на взломе программ?
A: Вообще, если у вас неплохой уровень, то заработать конечно можно (если найдется заказчик). Только учтите, что это незаконно. Обычно берут от 10% до 25% от стоимости одной копии программы. Только в этом деле надо быть очень осторожным, чтобы вас, так сказать, не "кинули". Например в интернете существует много объявлений нековоего Rudym'a (Rudym@iquebec.com). Он якобы ищет крэкеров для взлома программ на заказ. Но потом "кидает" их. Причем первую небольшую сумму (он говорит, что высылает деньги только после получения крэка) он может выслать, но потом ставит условия так, что невыгодно высылать деньги маленькими суммами; говорит, что когда накопиться сумма побольше, то он вышлет ее. Вы можете "наломать" ему программ, но когда накопиться нормальная сумма, и вы захотите получить свои деньги - он вас кинет. Так попался и мой друг, которого он кинул на 20$. Будьте осторожны: если увидите его объявление и решите "подзаработать", то не связывайтесь с ним. В любом другом случае и любым другим заказчиком будьте не менее осторожны. Никогда не высылайте крэки первыми, только после получения денег. Если же заказчик сильно настаивает, то защитите крэкнутый .exe (не патч, а именно уже пропатченный крэкнутый .ехе. В этом случае заказчику придется каждый раз для запуска программы запускать этот .exe) с помощью armadillo так, чтобы программа могла запуститься только 10 раз например, и только после этого можете отослать запакованный крэкнутый .exe заказчику. Он увидит, что программа "взломана", но не сможет воспользоваться ей более чем 10 раз например, и, соответственно, не сможет вас "кинуть". После этого пусть пересылает деньги, а вы отошлете ему уже нормальный крэк. За надежность армадилло можно не беспокоиться: в 95% случаев распаковать программу, защищенную армадилло, будет труднее, чем взломать программу, которую вам заказали. Ну вроде все. Будьте предельно осторожны!

Q: Я сломал shareware программу. Как мне разослать крэк по всему миру?
A: Можно например послать крэк на сайты http://www.cracks.am, http://www.serials.ws, http://keygen.us. Об условиях смотрите там. Но лично мое (MozgC) мнение, что это неправильно. Взламывать программу для себя или для друзей - это одно дело. А наносить автору программы большой ущерб, рассылая крэк по всему миру - это другое дело.

Q: Не могу взломать такую-то программу. А крэк к ней нужен. Где можно его взять?
A: Существуют огромные базы данных со всевозможными кряками, серийными номерами, кейгенами и т.д. Вот полезные ссылки:
http://astalavista.box.sk (производит поиск по многим сайтам - хранилищам крэков)
http://www.cracks.am
http://www.serials.ws
http://keygen.us
http://www.thebugs.ws

Q: Не могу найти ответ на свой вопрос. Спрашивал на форуме - там не ответили или не смогли ответить. Что делать?
A: Можете написать мне письмо по адресу MozgCnoSpam@avtograd.ru, и я постараюсь вам помочь. Только просьба слать мне письма в крайнем случае, когда вопрос действительно важен для вас и, на форуме ответ на него вы не нашли.


БЛАГОДАРНОСТИ
Авторы благодарят за любую помощь, оказанную при написании данного FAQ'a, и передают приветы следующим людям: MoonShiner'у, Hex'у, freeExec'у, Bad_guy'ю, DiveSlip'у, DeMoNiX'у, ::: XD :::, Dragon'у, EGOiST'у, Sten'у, а также всем, кто проявлял активность на форуме при тестировании и написании FAQ'a, и всем тем, кого мы забыли упомянуть в этом списке!


НУ И НАПОСЛЕДОК...
Вы можете послать свои отзывы и комментарии нам по адресам MozgCnoSpam@avtograd.ru и feuerrader(at)pisem.net. Мы постараемся ответить на любой ваш отзыв или предложение!

 

Copyright © 2002-2003 hack4joy



Hosted by uCoz