Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Исследование компонентов Delphi
Хакер в церкви молится:
- Bо имя Отца и Сына и Святого Духа, Enter!

Я работаю кем-то наподобие системного программиста, и вот увидел в Сети некий Компонент для Delphi, грозящийся сильно облегчить мне жизнь. Чтобы быть "канкретным", Компонент этот зовётся ODAC и означает сиё Oracle Data Access Components, версия 1.20. Компонент этот выделяется среди прочих тем, что позволяет подключаться к Oracle- базам минуя BDE. Очень удобно, ибо не нужно на каждого клиента ставить BDE и теоретически должно работать раза в два быстрее.

Скачал я его, инсталлировал в палитру компонентов, скомпилировал примеры, которые с ним поставляются (настоятельно рекомендую всегда это делать). Казалось бы всё совсем уже работает, но вот на исходе рабочего дня выяснилось, что оно не хочет работать без Delphi IDE в данной версии, а чтобы такого не было, предлагается купить нормальную версию всего за каких-то 69$ (и даже просто за 00 cents, что совсем уже удивительно). Я, конечно, не то чтобы уж какой-нибудь патологический жмот, но это сумма сейчас составляет половину моего monthly salary, так что эту мысль я отверг сразу. И стал я думать - как бы мне обойти сию неприятность. Было два подхода:

  • поправить непосредственно рабочий код
  • написать некий эмулятор "Delphi IDE"
  1. Обнаружились сразу две неприятности:
    1. IDA Pro 3.76 ни за что на свете не хотела признавать в .dcu файлах что-либо малознакомое и норовила подсунуть мне его как "binary file". Поискав с пол-часика в Сети и так ничего и не найдя, я отказался от идеи править Delphi Compiled Units (кстати, если кто-либо из читающих победил данную проблему, pls, свяжитесь с автором)
    2. В комплект поставки входил ещё и .dpl файл - динамически загружаемый модуль. С ним тоже ничего не вышло, ибо сначала Delphi не могла найти файл .dpk, а когда я его сваял вручную, благополучно не смогла найти файл .dcp (кстати, тоже может быть кто-нибудь объяснит мне тёмному и дремучему, что это такое и как его можно сделать, если это возможно ?). Вобщем, вследствие моего плохого знания прикладного инструмента решить задачу красиво не получилось
  2. Тогда стал я думать, а как бы это всё могло быть так устроено, что при живой Delphi всё работает, а иначе - пишет "ODAC trial version requires Delphi IDE" и не работает. Простейшее решение - дизассемблировать бесполезный .dpl. Довольно скоро я нашёл выдаваемую строку и отловил обращение к ней по адресу 410FC0:

    ...
    410FC0: push 0
    410FC2: push offset loc_4110E8
    410FC7: call j_FindWindowA
    410FCC: test eax, eax
    410FCE: jnz short loc_410FE6
    410FD0: mov ecx, offset aOdacTrialVersi	; грузим указатель на искомую строку
    410FD5: mov dl,1
    410FD7: mov eax, ds:SysUtils__Exception
    ...
    

    Понятно, что после выдачи Exception ничего хорошего случится не может, поэтому нужно смотреть, отчего так происходит. Вызывается функция FindWindow с двумя аргументами:
    • первый (второй в C - помните, что параметры передаются через стек в обратном порядке) - указатель на строку с названием окна (или с Caption)
    • второй (первый в C)- указатель на строку с именем класса окна.
    В данном случае передаётся вторым параметром указатель на строку "TAppBuilder", и если такого окна не найдено, программа свято уверена, что IDE не запущена.

    И вот - лампочка в голове засияла - а что если написать маленькую программу, которая будет делать лишь одно полезное действие - при старте создаст окно с искомым классом (его при этом даже не обязательно показывать - нужен лишь вызов CreateWindow) и будет висеть себе тихонько, эмулируя таким образом замечательную и большую (я бы даже добавил, чересчур большую :-) Delphi. Что и было исполнено в течение 20 минут. Исходный текст и саму программу можно взять здесь. Чтобы программу можно было таки принудить закончить без насилия, я добавил tray icon для индикации и выхода - достаточно щёлкнуть по нему два раза правой кнопкой мыши. Для полноты ощущения счастья можно поместить shortcut на сей шедевр в папку Startup системного меню.

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

Я встречался с подобным Дельфи-компонентом (DynamicSkinForm - для поддержки скинов в своих программах). Выходишь из Дельфи - при запуске своего скомпилированного проекта выдаёт окошко: "Тыры пыры, платите денежки", нажимаешь OK и программа закрывается (чесно говоря я на это наткнулся, когда ещё не занимался крэком и пришёл просто в бешенство, поняв что час работы пошёл на смарку). А почему бы не попатчить свою программу ? Конечно попатчить !!! Ставлю брейкпойнт на MessageBoxA или что-то такое и так далее... и дело сделано, а потом пишем патчер и забываем навсегда про недостатки незарегистрированной версии. (а вроде те же самые байты можно и в bpl или в dcu патчить, но у меня пропатчелось, а механизм продолжал работать - короче не стал я разбираться...)

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay