Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Кодим Dll во сне и на яву или таинство встраивания кода

Обсудить статью на форуме

Хорошая подборка видеоуроков, инструментов крэкера, книг и статей - здесь.

Автор: ARCHANGEL <crazyangel88@mail.ru>

Начало

Начало у этой истории было, как всегда, достаточно простое. Как-то после утомительного набора
очередного реферата на компе решил я поразвлекаться и отправился в компьютерный клуб посмотреть,
как (и во что) народ играет, и себя показать. После часа напряжённого отстреливания козлов-
контров стрелялки мне порядком надоели (я вообще не любитель игр), но тут моё внимание
перекочевало на экран рядом сидящего типа, который напряжённо пытался выиграть у компа в шашки,
а когда ему это, наконец, удалось,то девчонка на экране(на которую я до этого вообще внимания не
обратил) начала потихоньку(ну, очень потихоньку:) раздеваться. Шашки на раздевание - прикольно,
но тут была одна проблема - шашки я не любил и не умел в них играть, поэтому решил найти игру
наподобие(ну, в смысле, чтоб девчонки раздевались:) без шашек, шахмат и подобной ерунды, а,
на пример, "Сапер на рездевание", и ещё хотелось бы, чтоб игрушка бесплатной была. Хотелось бы...
Ко всей этой истории хорошо подходит старый анекдот:

Вовочка в школе пишет сочинение. Училка говорит:"Дети, тема сочинения - свободная, но есть одно
условие:вы обязательно должны начать сочинение с эпиграфа". Вовочка начинает:
В качестве эпиграфа хотелось бы вспомнить слова А.С.Пушкина... Хотелось бы, но вспомнить
не могу...

Так и в моей истории - хотелось бы найти бесплатную прогу, но, похоже, авторы таких прог
считают, что все люди, играющие в такие игры - маньяки-извращенцы и будут платить любые бабки
за фотки голых девушек, вбитые в игру. Им не понять, что в эти игры могут играть для прикола,
а когда играют для прикола, то не хотят платить. Но суть не в этом, а в том, что пришлось
выбирать что-то из Sharaware. Выбор был невелик. С одной стороны, сайт небезызвестного
Хорина Макса http://sweetgames.narod.ru/, но сайт этот мне не очень понравился. Щас раскажу,
в чём дело.
Меня как-то просил друг сломать оттуда одну прогу, вроде бы, "Дурак на раздевание" или что-то
в этом роде. Ну, я её скачал, скачал к ней архив с фотками(для проверки, действительно ли
она сломалась), всё это дело установил и начал реверсить. Распаковал aspack, восстановил
ресурсы(всё по науке:) и начал изучать. Дело в том, что там кнопка "Регистрация" имела
свойство Enabled = False и нажать её нельзя было, а значит, и зарегиться тоже никак. В
Restorator'е если изменить это свойство, то прога вылетала с ошибкой. Поэтому пришлось его
править с помощью Hex Workshop. После этого я запустил подправленный ехе, нажал на заветную
кнопку "Регистрация" и...Ничего не произошло, потому что это была демка!!! Эти с?"№№!%
(в общем, не очень хорошие люди:) подсунули демку и ничего об этом не сказали. После этого
с сайта Хорина я ничего не качаю(а вы - как хотите).
Был ещё один вариант - воспользоваться поисковиком. Я так и сделал. Поисковик(уже не помню,
какой, да это и не важно) подумал и выдал кучу ссылок. Я долго по ним перемещался, пока меня
не закинуло так далеко, что я уже не знал, в И-нете ли я:). На каком-то из сайтов я кликнул
мышью по ссылке и... что-то начало качаться. А когда это "что-то" докачалось, то я обнаружил,
что скачал самое оно.

Самое оно

В общем, скачал то, что я и хотел скачать - "Сапер SEX-бомба"(сапер на раздевание). Всё было
просто - выбираешь девчонку и начинаешь играть. Если правильно расставил флажки по минам,
значит выиграл и девчонка что-то с себя снимет:). В Sharaware-версии ограничения:
открыты 2 из 6 девушек, остальные станут доступны после регистрации;
прога показывает баннер и надпись о том, что она не зарегистрирована;
Кстати, прога на вид не вчера написана, но если захотите, попытайтесь её найти на сайте
http://www.fmi.narod.ru/saper.

Взлом, взлом и ещё раз взлом

Итак, будем ломать. Для этого нам понадобятся:

1. OllyDebug v1.10+CommandBar - отладчик для исследований
2. PeID v0.93 и старше - для анализа подопытной проги
3. DeDe v 3.50 by DaFixer - в этот раз вместо IDA
4. LordPe Deluxe by Yoda - (не поверите) для редактирования таблицы импорта
5. Borland Delphi 6.0 и старше - для написания dll(позже поймёте, какой)

Начнём. Первым делом натравим на нашу цель PeID, а он нам выдаст такую инфу:
Borland Delphi 6.0 - 7.0
Отлично, не придётся распаковывать, да и можно декомпилировать. Так и сделаем - грузим прогу
в DeDe. Теперь настраиваем мозг на декомпиляцию и начинаем думать. В окне просмотрщика
ресурсов найдём форму с подозрительным названием TRegisterForm, ищем там ресурсы, которые
бы соответствовали кнопкам. И не просто кнопкам, а кнопке с заголовком ОК. Почему? Как
почему? Для того, чтоб сработала процедура проверки ключа, который мы ввели, нужно нажать эту
кнопку. Нашли? Её ресурсы должны выглядеть так:

 object BitBtn1: TBitBtn
    Left = 120
    Top = 96
    Width = 75
    Height = 25
    Caption = 'OK'
    Default = True
    ModalResult = 1
    TabOrder = 2
    OnClick = BitBtn1Click
    NumGlyphs = 2
  end

Из всего этого нас интересует ответ на вопрос: "Какая процедура выполнится при нажатии на
кнопку?". И вот он - ответ:

OnClick = BitBtn1Click

В декомпиляторе переходим на вкладку Procedures, слева в Unit name у нас Register, а справа
выбираем BitBtn1Click и дважды кликаем. Появляется код процедуры, которая нас так интересовала.
Запомним или запишем адрес первой инструкции этой процедуры - именно на него мы и поставим
бряк. Запускаем прогу под отладчиком и в CommandBar пишем:
bp 00487BB8
Дальше начнётся отладка. Перед этим хотелось бы сказать, что вышеописанное руководство по
декомпиляции отнюдь не претендует на уникальность или первенство, просто я всегда
придерживаюсь мнения, что тьтютор надо делать максимально понятным для всех, а не для узкого
круга избранных. Те же, кто чувствует себя великим крэкером, просто подождите, впереди ещё
будут разные финты ушами:)


Поиски ключа а также другие приятные и неприятные моменты

Так вот, мы остановились на том, что поставили бряк на адрес 00487BB8. Отлично, теперь давим
F9, заходим в окно регистрации, вводим ЛЮБОЙ ключ и нажимаем ОК. Прервёмся на нашем бряке.
Далее всё банально и просто - идёт по F8 и смотрим в регистры. Доходим до такого места:

 00487C15   8B952CFEFFFF           mov     edx, [ebp+$FFFFFE2C]  запись правильного ключа в EDX
 00487C1B   58                     pop     eax                   запись нами введенного ключа в EAX

Элементарщина! Мы нашли ключ! "Стоп" - скажет модератор. "Если здесь всё так примитивно,
то какого ... этот ARCHANGEL свой тьютор прислал, тут таких(и гораздо круче) навалом!" Да
и многие так скажут. Но вы поторопились со своими суждениями, есть тут одно маленькое, но
очень неприятное Но. Вы заметили, что когда вводили ключ, над полем для ввода ключа
красовалось ещё одно с заголовком ID. И были там какие-то циферки. Так вот, это - псевдослучайная
последовательность символов, которая в каждой системе будет разной, а по этим циферкам и
генерируется наш регистрационный ключ. У меня, к примеру, этот ключ выглядит так:
2107623611131523
Но вам от этого ни холодно, ни жарко, потому что вы с этим ключом не зарегистрируетесь.
Тут есть несколько вариантов, и вначале я хотел пойти по пути наименьшего сопротивления,
т.е. сделать патч. (Ведь юзать прогу дома - это хорошо, а дать прогу друзьям - ещё лучше).
Вопрос "что патчить?" здесь абсолютно неуместен, нужно просто посмотреть, куда бы мы
попали при удачной регистрации. Сделать это можно даже в DeDe:

00487C21   7573                   jnz     00487C96     если ключ был правильный, то переход не выполнится
00487C23   8D9528FEFFFF           lea     edx, [ebp+$FFFFFE28]

* Reference to control Edit2 : TEdit
|
00487C29   8B83F8020000           mov     eax, [ebx+$02F8]

* Reference to: Controls.TControl.GetText(TControl):TCaption;
|
00487C2F   E8B840FBFF             call    0043BCEC
00487C34   8B9528FEFFFF           mov     edx, [ebp+$FFFFFE28]
00487C3A   B844FD4B00             mov     eax, $004BFD44

* Reference to: System.@LStrAsg(void;void;void;void);
|
00487C3F   E894CBF7FF             call    004047D8

* Possible String Reference to: 'reginfo.txt'
|
00487C44   BADC7C4800             mov     edx, $00487CDC
00487C49   8D8534FEFFFF           lea     eax, [ebp+$FFFFFE34]

* Reference to: System.@Assign(TTextRec;TTextRec;String):Integer;
|
00487C4F   E848B1F7FF             call    00402D9C
00487C54   8D8534FEFFFF           lea     eax, [ebp+$FFFFFE34]

* Reference to: System.@RewritText(TTextRec;TTextRec):Integer;
|
00487C5A   E8D9AEF7FF             call    00402B38

|
00487C5F   E804ADF7FF             call    00402968
00487C64   8B1544FD4B00           mov     edx, [$004BFD44]
00487C6A   8D8534FEFFFF           lea     eax, [ebp+$FFFFFE34]

* Reference to: Classes.TWriter.WriteRootComponent(TWriter;TComponent);
|           or: CopyPrsr.TCopyParser.SkipToken(TCopyParser;Boolean):Char;
|           or: DB.TWideStringField.GetAsWideString(TWideStringField):WideString;
|           or: DB.TDateTimeField.GetValue(TDateTimeField;TDateTime;TDateTime):Boolean;
|           or: DB.TSQLTimeStampField.GetValue(TSQLTimeStampField;TSQLTimeStamp;TSQLTimeStamp):Boolean;
|           or: DB.TSQLTimeStampField.SetAsSQLTimeStamp(TSQLTimeStampField;TSQLTimeStamp;TSQLTimeStamp);
|
00487C70   E8DBD1F7FF             call    00404E50

* Reference to: System.@WriteLn(TTextRec;TTextRec):Pointer;
|
00487C75   E812B8F7FF             call    0040348C

|
00487C7A   E8E9ACF7FF             call    00402968
00487C7F   8D8534FEFFFF           lea     eax, [ebp+$FFFFFE34]

* Reference to: System.@Close(TTextRec;TTextRec):Integer;
|
00487C85   E8DAB1F7FF             call    00402E64

|
00487C8A   E8D9ACF7FF             call    00402968
00487C8F   C60564D84B0001         mov     byte ptr [$004BD864], $01  СТРАННАЯ ИНСТРУКЦИЯ
00487C96   33C0                   xor     eax, eax
00487C98   5A                     pop     edx
00487C99   59                     pop     ecx
00487C9A   59                     pop     ecx
00487C9B   648910                 mov     fs:[eax], edx

Помеченная в листинге инструкция наводит на мысль о конструкции типа если по этому адресу
01, то прога зарегистрирована, а если 00, то нет. Так то оно так, но если пропатчить прогу
так, чтоб там всё время была единица,начинаются приколы разного рода: прога, видя что она пропатчена,
выдаёт сообщения об ошибке и пытается...Внимание! Перезагрузить Windows! Сильный ход для такой
проги, но мы ведь тоже не идиоты. Сделаем лоадер! Опять тот же результат. Конечно, винду
прога не перезагрузила, но сеанс завершила, нехорошо.
Всё дело в том, что прога не проверяет себя на целостность, а просто запускает таймер с
небольшим интервалом, на который повешены инструкции о проверке состояния зарегености проги,
т.е. если в вышеупомянутом адресе 01, а файла регистрации нет, или его содержимое не такое,
как надо, прога перезагружает винду, т.к. думает(кстати, правильно думает:), что её ломают.
Остаётся кейген, но что-то не хочется возиться с процедурой регистрации, когда прога сама,
как на блюдечке, выдаёт правильный ключ, хоть и разный для разных систем.
А что, если его как-то подсмотреть непосредственно после генерации и сохранить на диск?:)

В преддверии кодинга

Как вы уже поняли, по моему мнению в проге не хватает некоторых инструкций. Нет, не только
инструкций, которые бы "упрощали" нам регистрацию. Я говорю за функции, которые бы не помешали
проге. Например, после успешной регистрации мы всё равно можем вводить регистрационный ключ,
зачем? Почему бы не добавить сообщение о том, что прога уже зарегена, если это так? Конечно,
надо подправить процедуру регистрации, и ещё одно - когда мы процедуру регистрации подправим,
рядовой пользователь об этом ничего знать не будет, и не будет регистрироваться, даже если
ему в регистрационное поле надо будет лишь бы что ввести. Поэтому надо юзверю как-то
намекнуть, что, так сказать, можешь туда хоть плюнуть, а прога зарегится.
Так я и определился, что нужно добавить в прогу три функции:

1. Функция-сообщение пользователю о возможности и необходимости зарегиться.
2. Функция сохранения правильного ключа на диске в файле reginfo.txt.
3. Функция-сообщение об использовании зарегистрированной копии и блокировка дальнейшего ввода ключа.

Да, забыл упомянуть, что прога правильный серийник сама записывает в reginfo.txt, а при
запуске сравнивает, есть ли он там, и есть ли вообще такой файл.
Теперь поговорим о реализации наших функций. Во многих тьюторах для пропатчивания кода
предлагается простой метод - нужно осуществить прыжок на нули, которых обычно много в конце
файла, там вбить код, который мы хотим выполнить, после чего сделать прыжок обратно на код
программы. Метод хорош, но нам нужно так поступить с тремя процедурами, ох и много же нулей
нам нужно будет.(Почему с процедурами? Ну, они же ничего не должны возвращать - значит
процедуры, хотя если говорить асмовскими терминами, то и процедуры, и функции - все функции,
так что как вам больше нравиться). Во-вторых, нам будет очень неудобно вбивать столько
инструкций на асме, более того, признаюсь чесно, я смутно представляю, как асмовскими методами
сохранить строку в файле. Зато я всё это умею делать на Delphi:). Так кто же мне (и вам:)
мешает написать этот код на Delphi, а потом просто вызвать его из проги на выполнение?
Не знаю как вам, а лично мне не мешал никто, поэтому я так и сделал. И сейчас я про это
нелёгкое дело расскажу подробнее.

Кодим Dll или конкуренция асм-кодерам

Долгое время только асм-кодеры могли позволить себе написать библу, которая бы взаимодействовала
с приложением, написанным кем-то, меняла бы в нём что-то, как-то обрабатывала инфу из этого
приложения и т.д. Больше всего меня умиляло в тьюторах с асмовскими исходниками той или иной
библы фраза её автора:"Ну, тут и так всё ясно, поэтому комментарии я не привожу". Ясно? В
библе, листинг которой занял 3 и более страницы текста? Люди - вам скажу, как никому: ВЫ
РЕАЛЬНО ГОНИТЕ.
Нет, вам, конечно, всё ясно, а люди теряются в догадгах, с чего начать. Я сейчас умолчу о
всяким асмовских директивах типа .model flat,stdcall, а то асм-кодеры все скинуться и закажут
меня, кто же тогда вас в тайны кодинга библиотек посвятит?:)
Ладно, для себя мы определились, что Delphi лучше асма, теперь попытаемся создать библиотеку
средствами нашего любимого компилятора. Запускаем Delphi, дальше идём по такому маршруту:
File->New->Other->Dll Wizard->OK
Теперь перед вами шаблон dll, пока просто заготовка. Верхняя строка содержит имя библиотеки,
а под ней куча коментариев.

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

Удаляйте их нафиг. Также удаляйте строчку {$R *.res}, т.к. ресурсов в нашей библе не будет,
будет только код. Теперь кратко пробежимся по директивам\операторам\ситаксису (называйте,
как хотите:) которые вы сейчас видите.

library LIBNAME; // имя библы
uses Classes,Windows; //компоненты(если можно так сказать), используемые в библе
end. //конец библы
begin //какой begin? - нафиг его, к коментариям:)

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

1. Написать процедуру или функцию в библе.
2. В разделе экспорта в библе обьявить эту процедуру или функцию.
3. В разделе импорта в проге обьявить эту процедуру или функцию.
4. Выбрать место в программе для внедрения кода из библы.
5. Добавить в библу код, сглаживающий в программе вызов процедуры или функции из библы.

Вначале придумаем библе и процедуре название - у меня CrackReg.dll и Scan соответственно.
Теперь продумаем алгоритм работы процедуры. Процедура ищет файл reginfo.txt в каталоге с
игрой, если не находит, то выдаёт сообщение, что надо бы посетить регистрацию и что-то туда
вбить, а если находит, то работает как ни в чём не бывало. Теперь внимание на альфа-версию
нашей процедуры, почему на альфа, потому что её ещё придётся править


procedure Scan(i:boolean);
begin
i:=FileExists('reginfo.txt'); //проверка, существует ли регистрационный файл
if i=false then // если нет, то будет показано сообщение
begin
messageboxa(0,'Игра не зарегистрирована, введите что-то в регистрационное поле','NOT REGISTERED',MB_ICONERROR);

end;

end;

Тут мы используем MessageBoxA, поэтому если хотим, чтоб всё это дело компилилось, надо к
стандартам uses добавить Windows.

uses
SysUtils, Windows,
Classes;

Теперь начнём формарование таблицы экспорта, а затем и импорта. Для формирования экспорта
в Delphi используется директива exports. С её помощью можно даже указать порядок экспортируемых
функций в таблице экспорта. Но нам это не нужно, зато я бы порекомендовал явно указывать имя
функций при экспорте. Директива экспорта должна быть добавлена после кода процедуры перед
концом библиотеки end., а выглядит это так:
exports Scan name 'Scan';
Попробуйте компилировать библу, должно отлично компилиться и выдавать сообщение, что не
указано главное приложение. А скомпилированная библа теперь будет в директории с файлами
проекта. Найдите её и скопируйте в директорию с игрой.
Теперь импорт. Открываем игру в Pe Idetor'e из LordPe, далее идём в Directories, теперь
обращаем взгляд на надпись Import Table, чуть правее на её уровне должна красоваться кнопка
с заголовком "..." без кавычек, кликаем по ней, и перед нами таблица импорта. Клик по правой
кнопке мыши, далее add Import, ставим флажок напротив check imports for existence чтоб не
допустить опечатки, в поле Dll вводим CrackReg.dll, в поле API - Scan. Теперь ОК и всё.
Следующий этап - отладка. Он будет являться самым трудным, т.к. надо состыковать два
чужеродных модуля, но я почему-то верю, что мы справимся:). Грузим в отладчик нашу игру,
сейчас мы на ЕР, а давайте возьмём и в ЕР встроим нашу процедуру. Для этого в отладчике
узнаем адрес нашей процедуры:
Search for->Name (label) in current module
Ищем в списке справа Scan, а левее будет адрес, на который нужно сделать call. У меня этот
адрес равен 004E4035. Теперь в отладчике, стоя на ЕР, нажмём пробел и введем:
call dword ptr [004E4035]
Вследствие этого мы затрём такие инструкции:

push ebp
mov ebp,esp
add esp,-10h

Запомним их, а нашей игре сделаем Copy to Executable->All modifications. Попасть в библу мы
попали, теперь из неё нужно ещё благополучно выйти. Грузим пропатченную прогу в отладчик,
далее давим F7 и попадаем в библу. Теперь, т.к. reginfo.txt я удалил, то мы увидим сообщение,
а дальше будет retn, а после - сбой. Это совсем не то, что нам нужно, но в наших силах всё
поправить. Дело в том, что когда мы стёрли упомянутые выше инструкции, прога не подготовилась
к нормальной работе, поэтому в библу надо добавить эти инструкции, а после сделать переход
на адрес 004BB826 в игре. После исправлений наша процедура будет выглядеть так:

procedure Scan(i:boolean);
label exit_to_program;  //Особенность №2
begin
        i:=FileExists('reginfo.txt');
        if i=false then
                begin
                        messageboxa(0,'Игра не зарегистрирована, введите что-то в регистрационное поле','NOT REGISTERED',MB_ICONERROR);
                        asm
                        exit_to_program:
                                push ebp
                                mov ebp,esp
                                add esp,-10h
                                push 004BB826h //Особенность №1
                                retn
                        end;
                end;
        asm
                jmp exit_to_program;
        end;
end;

Как видите, коррекция реализована ассемблерными вставками. Я же не говорил, что асм - это
плохо, я говорил, что писать библу от и до на асме - это нехорошо. А вставки - совсем другое
дело. В этой процедуре, в принципе, ничего нового нет, есть две небольшие особенности. Во-
первых, следует заметить, что напрямую осуществить прыг из библы в прогу не удасться -
Delphi такое просто не скомпилит, зато можно позаимствовать метод у Aspack, т.е. сделать
push желаемого адреса возврата, а потом с помощью retn туда переместиться. Во-вторых, этот
код я специально так завертел, чтоб продемонстрировать, как нужно пользоваться метками, если
хотите прыгнуть из одной вставки в другую. Здесь фичи типа @метка не катят, зато если
обьявить идентификатор как метку, то всё тип-топ.
Теперь скомпилим новую библу, заменим старую на исправленную новую и просто запустим игру.
Сейчас видно, что она работает, тока добавилась новая фича.
Надеюсь, вы внимательно следили за моими рассуждениями, т.к. далее я не буду всё так жевать
и за вас глотать:).
Наверное, дальше я просто приведу листинг всей библы (с коментариями, разумеется:) и ещё
чуток расскажу. Листинг:

library CrackReg;
uses
  SysUtils, Windows,
  Classes;
procedure ARCH(save:string); //процедура сохранения ключа
var regfile:textfile;       //обьявляем переменную как идентификатор файла
begin
        asm
                push edx    //запихнём в стек правильный ключ
                pop save    //извлечём ключ из стека в переменную
        end;
        assignfile(regfile,'reginfo.txt'); //сопоставим дескриптор с файлом
        Rewrite(regfile);                  //создадим пустой файл с именем, сопоставленным дескриптору
        Write(regfile,save);               //запишем в файл ключ
        closefile(regfile);                //разорвём связь между дескриптором и файлом
        messageboxa(0,'Теперь игра зарегистрирована и требует перезапуска','REGISTERED',MB_ICONINFORMATION); //no comments:)
        exitprocess(0);                    //закроем игру 

end;
procedure Scan(i:boolean); //Эту процедуру мы рассматривали выше
label exit_to_program;
begin
        i:=FileExists('reginfo.txt');
        if i=false then
                begin
                        messageboxa(0,'Игра не зарегистрирована, введите что-то в регистрационное поле','NOT REGISTERED',MB_ICONERROR);
                        asm
                        exit_to_program:
                                push ebp
                                mov ebp,esp
                                add esp,-10h
                                push 004BB826h
                                retn
                        end;
                end;
        asm
                jmp exit_to_program;
        end;
end;
procedure block(a:boolean); //процедура блокировки повторной регистрации
var regfile:textfile;
begin
        a:=FileExists('reginfo.txt'); //уже известная вам конструкция
        if a=true then
                begin
                        messageboxa(0,'Игра уже зарегистрирована!','Куда полез?',MB_ICONQUESTION);
                        asm
                                add esp,4h //восстановление стека перед возвратом в игру
                                retn
                        end;
                end;
                asm
                        mov eax, dword ptr [$004BEF30] //восстановление программы, если нужно провести процедуру регистрации
                        mov eax, [eax]
                        push 004BADD7h
                        retn
                end;
end;
exports ARCH name 'Dump',Scan name 'Scan',block name 'Block';
end.

Как видите из этой таблицы экспорта, в таблице имя может отличаться от того, что
используется внутри библиотеки. Я имею ввиду строчку exports ARCH name 'Dump'. Ещё одно,
пока не забыл - Delphi, в отличие от OllyDebug, все числа воспринимает как десятичные, поэтому
если хотите использовать шестнадцатеричную систему, вам придётся после каждого числа ставить
знак h.
Вернёмся же к нашей проге, вы уже скомпилили полную библу, добавили импорт к игре и готовы
патчить ехе. (Кстати, импорт лучше добавлять не по одной функции, а сразу по несколько -
ввели имя функции, надавили +, опять имя, опять + и т.д.) Так как я за вас уже всё в библиотеке
подправил (можете проверить:), то после патча ехе игра будет полностью работоспособна.
Для начала определимся, куда всунуть сохранение правильного ключа. А помните участок кода,
который мы рассматривали в самом начале? Когда ещё ключ искали, а он взял и записался в EDX,
так вот после этого мы и вызовем нашу процедуру Dump.
Ищем адрес вызова нашей процедуры - у меня он равен 004E4019, и по адресу 00487C1B запишем:
call dword ptr [004E4019]
И наша процедура отработает, сохранит нам наш правильный ключ, а потом закроет прогу, потому
как если продолжить работу, то это дело чревато перезагрузкой, да и думать надо, как из библы
корректно выйти. А так - ввели ключ, получили сообщение, что, типа, зарегистрировались и надо
прогу перезапустить, а потом закрылись. Получается некий аналог FlashGet. (Там, вроде, тоже так:)
С последней процедурой всё нужно сделать так, как и с предыдущими. Скажу только пару слов о
том, куда её нужно встроить. Идея процедуры заключается в том, что если reginfo.txt существует,
то вместо формы регистрации мы должны увидеть сообщение о том, что мы уже зарегились когда-то,
и опять вернуться в прогу как-будто и не было ничего.
Для этого опять воспользуемся DeDe и по вышеописанному методу найдём процедуру вызова формы
регистрации. Эта процедура будет иметь название N4Click. А первая инструкция будет по адресу
004BADD0. Инструкцию по этому адресу мы и затрём по методу, уже описанному в этом тьюторе.
На этом можно поставить ЖИРНУЮ точку, т.к. прога злостно взломана:) Кстати, хотите прикол
напоследок? Натравите на пропатченый файл PeID, и он вам выдаст кадр под названием:
Nothing found *
Многие специально напрягаются, чтоб обойти PeID, а тут и напрягаться нечего, просто меняем пару
байтов на ЕР, и он уже не узнаёт родную Delphi:)

Послесловие

Некоторые скажут, что прога, регистрация которой стоит 1$, не стоит таких мучений. Но это
вовсе не мучения, скорее тренировка. Теперь после такого курса молодого бойца вы можете
кодить библы на уровне асм-кодеров и даже лучше (лишь бы фантазия была:). Более того,
использование библиотек позволет найти золотую середину между низкоуровневым кодингом и
лёгкими в использовании и понимании средствами высокоуровневого программирования. И ещё,
как вы заметили, используя библиотеки, мы перестаём зависеть от свободного пространства в
проге, так как можем встраивать свой код прямо в середину функций программы. Вы только
подумайте, какие теперь перед нами открываются горизонты. Можно встраивать свои функции
покруче описанных здесь (например, всеми любимый Brute-Force), можно вести с пользователем
общение типа интеракивного ввода-вывода, можно даже такой изврат сделать, чтоб пользователь
вводил с клавы, какое значение в памяти проги на какое пропатчить!!! Теперь для человека,
освоившего такой метод модификации кода банальные бит-хаки кажутся пережитками давно
забытого каменного века.
Поверьте мне, в мире крэка есть более важные проблемы, чем поиск места для своих инструкций:

1. StarForce
2. Armadillo
3. Борьба с однонаправленными hash-алгоритмами

Вот это - проблемы. Ещё, конечно, проблемой является нехватка деревянных палочек в Китае,
но это мы как-нибудь переживём:)

Благодарности

Как всегда, начинаем с того, что говорим большое спасибо cracklab, потому что если б не они,
вы бы сейчас это не читали (и много чего ещё бы не читали). Далее мне хотелось бы поблагодарить
своих друзей и читателей. Большое спасибо Pe_Kill (в том, что он будет это читать, я уже не
сомневаюсь:) за отличную статью про распаковку Pe Compact без ImpRec'a, вот бы здорово было,
если б он и StarForce распаковал. Pe_Kill, распакуешь StarForce - с меня ящик водки:)
В общем, всем спасибо за внимание и удачи в дальнейшем исследовании защит!



Обсуждение статьи: Кодим Dll во сне и на яву или таинство встраивания кода >>>


Комментарии к статье: Кодим Dll во сне и на яву или таинство встраивания кода


Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS