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

Автор: Hex

Еще одна прога которая подвисает если ей BBS нормальную не сделать. Но тут апи нам жизнь портят. Зарегить конечно без ключа не выйдет, но поисследовать стоит.

Дамп и импорт тут берется как в Actual Startup.


OEP: 0013F624
IATRVA: 001481C8
IATSize: 0000085C

Но запустив такой дамп мы увидим синий экран смерти :( Глюк... И происходит он вот тут:


code:00636C3E mov eax, ds:dword_0_643E18 - тут 5
code:00636C43 push eax
code:00636C44 mov eax, ds:dword_0_643E14 - тут FFFFFFFF
code:00636C49 push eax
code:00636C4A call GetProcAddress_0
code:00636C4F call eax

Естественно GetProcAddress офигевает от такого имени функции и возвращает 0 в EAX, ну а потом CALL EAX завершает концертную программу :) Так не бывает :) Смотрим в упакованый вариант и видим что вместо call GetProcAddress в этом месте идет перенаправление в аспротект на вот такую процедуру:


0167:00460EE8 PUSH EBP
0167:00460EE9 MOV EBP,ESP
0167:00460EEB MOV EDX,[EBP+0C] - берет первый параметр GetProcAddress (т.е. 5)
0167:00460EEE MOV EAX,[EBP+08] - берет второй параметр GetProcAddress (т.е. FFFFFFFF)
0167:00460EF1 MOV ECX,[0046543C]
0167:00460EF7 MOV ECX,[ECX] - а тут в ECX тоже записывается FFFFFFFF
0167:00460EF9 CMP ECX,EAX
0167:00460EFB JNZ 00460F06 - прыжок не происходит
0167:00460EFD MOV EAX,[EDX*4+00465350] - в EAX записывается значение в соответствии с первым параметром
0167:00460F04 JMP 00460F0D
0167:00460F06 PUSH EDX
0167:00460F07 PUSH EAX
0167:00460F08 CALL KERNEL32!GetProcAddress
0167:00460F0D POP EBP
0167:00460F0E RET 0008

Ну естественно Imprec решил что это GetProcAddress, и нельзя сказать что он не прав. Во всех случаях когда имя функции не лежит по адресу FFFFFFFF, оно работает как GetProcAddress. Ну и ладно. Просто посмотрим что теперь сделает CALL EAX. Ничего интересно оно не сделает, а просто в EAX вернет ноль поэтому такой вызов (call eax) можно смело менять на xor eax,eax. Дальше будет еще один такой же вызов(636D6F) Getprocaddress но теперь уже нужно будет заменить call eax на mov al,1a. Синие экраны пропали. Теперь прога запускается, выводит окно триала, потом щелкает и закрывается. Это у нас апи аспротекта пакости делают. Находим в аспротекте табличку этих самых апи. Как это делать уже рассказывал, не забывайте что тут у нас ImageBase = 500000 а не 400000. Вот они по возрастанию:


62CA28
62CA4C
62CA5C
62CA6C
62CA98
62CAB4
62CAD8
63F01C
63F078
63F0AC

Теперь запускаем запакованную прогу доходим до места где мы сделали дамп и ставим брейкпоинты на адреса этих апи. Теперь берем бумажку и ручку, будем записывать записывать чо там происходит. Я вот типа в табличку оформил. В столбике "Чо делает" я записываю общий смысл апи.


№ Срабатывания Адрес Чо делает

1 62CA98 mov ds:dword_0_643DCC, 0 
mov ds:dword_0_643DD0, Адрес_Подписи

2 62CA4C mov ds:dword_0_643DDC, Адрес_Заглушки

3 62CA5C mov ds:dword_0_643DE0, Адрес_Заглушки

4 62CA28 mov ds:dword_0_643DD8, 4612E0

5 62CA5C mov ds:dword_0_643DE0, 4612B0

6 62CA4C mov ds:dword_0_643DDC, 46127C

7 62CA6C mov ds:byte_0_643DD4, 0
mov ds:dword_0_643DC8, 453861 

8 62CAB4 mov ds:dword_0_643DE4, FFFFFFFE
mov ds:dword_0_643DE8, 1E
mov ds:dword_0_643DEC, 18

9 62CAD8 mov ds:dword_0_643DF0, FFFFFFFD
mov ds:dword_0_643DF4, 0
mov ds:dword_0_643DF8, 0

10 63F0CA mov ds:off_0_643E20, 63F01C

11* 63F01C Выводит месагу о триале.

* - Сработает не в протекторе. Адрес_Подписи - это я так называю адрес строки 12 байтной вот такого вида "3xEhLwAAImw=". Чувствую что она юзается для расшифровки кусков кода... а может я и не прав. В общем кто знает скажите что это? :) Адрес_Заглушки - тут оно просто записывает адрес процедуры из 1 команды = RET. Т.е. типа заглушка. Срабатывания 1,2,3,8,9 никакой информационной нагрузки не несут, просто какие-то данные пишет в секцию DATA. C 10 и 11 все просто: 10 - это GetApplicationRunFunction, 11 - это Executetrial. Как мы видим адрес 63F078 у нас тут не участвует. Если запихнуть этот адрес вместо 63F01C в GetApplicationRunFunction то мы увидим месагу "Expired". Так что это у нас типа RunExpired. А вот 4,5,6 интересные какие-то адреса записывают... Берем IDA дизасмим наш дамп и смотрим чо у нас там по адресам 643DD8, 643DDC, 643DE0. Видим вот такое:


data:00643DD8 dword_0_643DD8 dd 62CA0Ch ; DATA XREF: code:0062CA2E w
data:00643DDC dword_0_643DDC dd 62CA38h ; DATA XREF: code:0062CA52 w
data:00643DDC ; sub_0_62CB28+5 r
data:00643DE0 dword_0_643DE0 dd 62CA38h ; DATA XREF: code:0062CA62 w
data:00643DE0 ; sub_0_62CB50+5 r

Данные читаются с этих мест по адресам sub_0_62CB28+5 и sub_0_62CB50+5. А там:


code:0062CB28 mov eax, offset sub_0_62CA38
code:0062CB2D cmp eax, ds:dword_0_643DDC
code:0062CB33 jnz short loc_0_62CB3A
code:0062CB35 call sub_0_62CA38 - Тут данные для ошибки и RaiseException

Ух ты! В Eax записывается 62CA38 а дальше EAX сравнивается с данными по адресу ds:dword_0_643DDC а там у нас тоже 62CA38. А что у нас апи записывало в ds:dword_0_643DDC? - 46127C. Это проверка на наличие Аспротекта! Дальше еще одна проверка:


code:0062CB3A 
code:0062CB3A loc_0_62CB3A: ; CODE XREF: sub_0_62CB28+Bj
code:0062CB3A cmp ds:byte_0_643DD4, 0 - эту нас делает вызов №7
code:0062CB41 jz short locret_0_62CB4D
code:0062CB43 push 643DE1h
code:0062CB48 call sub_0_62CAFC - Тут RaiseException
code:0062CB4D 
code:0062CB4D locret_0_62CB4D: ; CODE XREF: sub_0_62CB28+19j
code:0062CB4D retn

Итого 2 джампа должны состояться чтобы все работало. Если глянуть что происходит в sub_0_62CB50+5 - то там тоже самое. Патчим и антивирус запускается! :)

Теперь он у нас работает в триальном режиме... А хотелось бы в зарегеном... Смотрим подозрительные строчки в IDA. И видим:


code:00636F63 mov edx, eax
code:00636F65 mov ecx, offset aTrialVersion ; "Trial version"
code:00636F6A mov eax, ds:dword_0_644224
code:00636F6F mov eax, [eax]
code:00636F71 call sub_0_57B3E8

Смотрим выше...


code:00636D41 loc_0_636D41: ; CODE XREF: code:00636C7Bj
code:00636D41 mov eax, ds:dword_0_644464

Еще выше..


code:00636C77 loc_0_636C77: ; CODE XREF: code:00636C63j
code:00636C77 cmp dword ptr [ebp-8], 0
code:00636C7B jz loc_0_636D41

И вот наконец интересное место:


code:00636C3E mov eax, ds:dword_0_643E18
code:00636C43 push eax
code:00636C44 mov eax, ds:dword_0_643E14
code:00636C49 push eax
code:00636C4A call GetProcAddress_0
code:00636C4F call eax
code:00636C51 mov edx, eax
code:00636C53 lea eax, [ebp-8]
code:00636C56 call unknown_libname_248

Хе-хе :) А я тут был... Значит это была не просто функция возвращающая 0... Зайдем в call unknown_libname_248. Там у нас:


code:00504E94 @@LStrFromPChar:

Это функция делающая String из Pchar. Видимо call eax должен был все-таки вернуть в EAX какую-то Pchar строку... Я даже могу предположить что это имя на кого зарегено... Запихиваем куда-нить в конце файла свое имя, я записал по адресу 740700. Теперь bpx 636C51 как сработает запихиваем 740700 в eax. ВАУ! Появилась картинка зарегеной версии! И в About тоже горит наше имя! А что же тогда делал еще один такой Call Getprocaddress? Он брал число дней до конца триала! У меня там было 1a = 26 дней. Радостно? А теперь о грустном... Дальше фиг чего сделать без ключа можно. Т.к. все Disabled пункты открываются когда код раскриптуется :( Если кто вдруг не знает чо это такое - гляньте по адресу 632B54 или 6324C3.

P.S. Если порассматривать код дальше то станет видно что на самом деле проверка наличия аспротекта(62CB28) ведется неспроста, там проверяется наличие функции раскриптовки. Перед каждым закриптованным куском кода идет вызов этой самой "проверки". Дайте чтоли ключик - поисследовать :)

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