day & night

Огромный FAQ по взлому программ, Хак! Ломать не строить - это уметь надо
Дата обновления: , перейти к новому сообщению
#1
tyomik89



Unregistered














Источник:http://www.cracklab.ru/
Огромный FAQ по взлому программ
MozgC & FEUERRADER, 2003-09-28


Авторы: 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 дней. Если вы заинтересовались таким предложением, напишите мне письмо по адресу MozgCstopSpam @ 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" smile.gif - это один из признаков того, что данный файл - 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. Если они не сработают, то попробуйте поставить брейкпоинт на функцию 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 ©onditional Jump at Addresses:
|:00XXXXXX©

В этом случае перейдите на адрес 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 или LordPE (PE Editor -> 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, а
Go topGo end
 

Ответов(1 - 1)
31.08.2004 - 15:13
#2
Paladin



профи!
Group Icon

Группа: Наши Люди
Сообщений: 944
Регистрация: 7.03.2004
Из: г. Абакан
Пользователь №: 303


Респектов: 11
-----X----




Faq не законченный, нет кучи ссылок.
User is offline
Go topGo end

Topic Options
Сейчас: 29.03.2024 - 1:47
Мобильная версия | Lite версия