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

Оформил: DeeCo
Автор: http://www.cracklab.narod.ru

Инструменты: 1) SoftIce
2) HView
3) Spy
4) Немного знаний RE и сообразительности.

Вот попался мне этот дистрибутивчик, который, якобы, уже был кракнут, т.е. в нём был ключевой файл, зарегенный на некоего "Ledy-2000", но, как позже выяснилось, этот билт - бетта и там проверка на ключевой файл есть и в меню О программе он пишет - зарегенно, но вот баннер не исчезает! И занимает половину рабочего окна и тянет картинки с завидным упорством. Как оказалось, в этой бете баннер будет всегда, на то она и бета :)

Прийдётся "Устранять это недоразумение" (c) Др. Голова

Первым делом я вспомнил, что где-то видел тутор el-f'a по поводу исследования похожей программы NetAnts v1.23 с похожим баннером и похожей advert.dll :)
Ну я достал его и внимательно изучил.

При помощи утилиты Spy я узнал размеры баннерного окна: 468 / 62

Первым делом я пытался отследить создание окон и узнать их размеры:
bpx CreateWindowExA do "? *(ebp-18)" при этом высвечивается высота окна.
Но! "моей" высоты там не было, а может и была :) вобщем, я решил делать как el-f, я открыл прогу в HVIEW, нажал 2 раза F7 - это поиск по ассемблерной комманде, ввёл "push 3E" (3E = 62)! Т.е. я искал место создания окна и такое вхождение было единственным:
:0044BEB5 90                      nop
:0044BEB6 90                      nop
:0044BEB7 90                      nop
:0044BEB8 90                      nop
:0044BEB9 90                      nop
:0044BEBA 90                      nop
:0044BEBB 90                      nop
:0044BEBC 90                      nop
:0044BEBD 90                      nop
:0044BEBE 90                      nop
:0044BEBF 90                      nop
:0044BEC0 8B442408                mov eax, dword ptr [esp+08]
:0044BEC4 56                      push esi
:0044BEC5 052CFEFFFF              add eax, FFFFFE2C
:0044BECA 6A40                    push 00000040
:0044BECC 99                      cdq
:0044BECD 2BC2                    sub eax, edx
:0044BECF 6A3E                    push 0000003E	<--вот оно!!!
:0044BED1 8BF1                    mov esi, ecx
:0044BED3 68D4010000              push 000001D4
:0044BED8 D1F8                    sar eax, 1
:0044BEDA 6A00                    push 00000000
:0044BEDC 50                      push eax
:0044BEDD 68E8644C00              push 004C64E8
:0044BEE2 8D8E88000000            lea ecx, dword ptr [esi+00000088]
:0044BEE8 E8E1470200              call 004706CE
:0044BEED 8BCE                    mov ecx, esi
:0044BEEF E8C3160200              call 0046D5B7
:0044BEF4 5E                      pop esi
:0044BEF5 C20C00                  ret 000C
как видите, вначале куча нопов, неспроста это, ох неспроста :)
Я, как и el-f заменил push 3E на push 00 и окно исчезло, значит это нужное место, но программа продолжала качать из интернета всякие картинки, хоть их и не видно! Я посмотрел чуть ниже и увидел подозрительный код:
:0044BEF8 90                      nop
:0044BEF9 90                      nop
:0044BEFA 90                      nop
:0044BEFB 90                      nop
:0044BEFC 90                      nop
:0044BEFD 90                      nop
:0044BEFE 90                      nop
:0044BEFF 90                      nop
:0044BF00 8B442404                mov eax, dword ptr [esp+04]
:0044BF04 83EC10                  sub esp, 00000010
:0044BF07 56                      push esi
:0044BF08 8BF1                    mov esi, ecx
:0044BF0A 50                      push eax
:0044BF0B E8991E0300              call 0047DDA9
:0044BF10 83F8FF                  cmp eax, FFFFFFFF <--чего-то сравниваем
:0044BF13 7509                    jne 0044BF1E	<--прыжок на процедуру, больно похожую на загрузку картинки
:0044BF15 0BC0                    or eax, eax
:0044BF17 5E                      pop esi
:0044BF18 83C410                  add esp, 00000010
:0044BF1B C20400                  ret 0004
Опять куча нопов (может пытаются запутать адрес вызова???)
По адресу 0044BF13 я заменил jne 0044BF1E на jne 0044BF15, чтобы прыгать не на процедуру загрузки окна, а на следующую строку и запуситл прогу:
Никакого окна не осталось! Но осталось родительское окно баннера (сам баннер состоял из 2ух окон: одно родительское, а во втором сам баннер). Нужно теперь убрать родительское окно, а все окна снизу подтянуть до упора под тулбар!

Я долго промучался с этим и обнаружил такую вещь: если в Spy сделать окно с баннером Visible=false, то при изменении размеров главного окна окно с баннером исчезает, а все нижние окна САМИ поддтягиваются под самый тулбар! Это значит, что программа сначала узнает размеры окна с баннером, а затем на основе этого "строит" остальные окна, а у el-f'a просто прибавлялось смещение окна и все!
Тут можно было бы написать простую консольную программу, которая бы при старте CuteFTP находила бы окно с баннером и делала бы его невидимым и сама бы изменяла размер главного окна, чтобы изменения вступили в силу.

Но, я решил встроить в cutftp32.exe небольшую функцию, которая бы делала окно с баннером невидимым:
я ставлю брекпоинт
bpx GetWindowRect do "p ret" 
это функция, получающая инфу об окне! вываливаюсь тут:
:0046F280 8D45F0                  lea eax, dword ptr [ebp-10]
:0046F283 50                      push eax			<--адрес, куда сохранять инфу об окне
:0046F284 53                      push ebx			<--передаём Handle окна
:0046F285 FF15C8D64900            Call USER32.GetWindowRect	<--получаем о нём инфу
:0046F28B 8B35F8D54900            mov esi, dword ptr [0049D5F8]
Это место вызывается много раз, так как окон много, теперь нам нужно отследить окно с баннером и сделать его невидимым.

Почитав немного "Windows API Reference" я узнал, что высота окна при вызове GetWindowRect будет сохраняться по адресу (esp+48). Теперь нужно найти в программе свободное место (обычно это где-то в районе ресурсов), и вписать туда код, который будет проверять, чтобы в (esp+48) было 3F (размер окна с баннером) и если размер окна равен 3F, то делаем его невидимым.

Я нашёл много пустого места по адресу 00506876 делаем так:
по адресу 0046F28B делаем безусловный переход на пустое место (00506876)
по адресу 00506876 пишем нужный нам код, где предпоследней коммандой должна быть затёртая mov esi, dword ptr [0049D5F8] а последней командой должна быть jmp 0046F290
Итак, по адресу 0046F285 делаем так:
:0046F285             Call USER32.GetWindowRect
:0046F28B             jmp 00506876
:0046F290             nop
ноп появился потому что на команду jmp ушло на 1 байт меньше, чем было.

а по адресу пустого места (00506876) пишем такой код:
00506881: 8B442448                     mov         eax,[esp+00048]	<--записываем в eax длинну окна
00506885: 83F83F                       cmp         eax,03F		<--если это не окно с баннером
00506888: 7509                         jne         000506893		<--то прыгаем на выход
0050688A: 6A00                         push        000			<--если это окно с баннером, то сохраняем параметр Visible = False
0050688C: 53                           push        ebx			<--и Handle окна
0050688D: FF157CD44900                 call        User32!ShowWindow	<--и вызваем функцию ShowWindow
00506893: 8B35F8D54900                 mov         esi,ScreenToClient	<--восстанавливаем затёртую строку
00506899: E9F289F6FF                   jmp         00046F290		<--возвращаемся
теперь пробуем запустить программу и видим, что больше окна с баннером нет, а все остальные окна подтянуты до тулбара!!! УрА!

ВсЁ!

Исследовал и наваял туториал:
vallkor //PTDS
e-mail: vallkor@chat.ru
Page : http://vallkor.chat.ru

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