Инструменты: W32Dasm v 8.93, SoftIce v 4.x (или) Spy++.

Всем нравится трепаться по Асе и другим IM-системам, и никто не хочет за это удовольствие деньги авторам того же клиента отстегивать. Чтобы спасти свой бюджет производители вставляют в софт баннеры, которые приносят деньги первым и раздражают своим миганием пользователей. Однако, если клиент вдруг захочет избавиться от баннера, сможет ли он это сделать?

Коль скоро, защиту ICQ исследуют все кому только не лень, посмотрим как организована реклама в IM-клиенте Odigo. Скачиваем русскую версию, инсталим ее, регимся (сомневаюсь, что у кого-то уже есть аккаунт в Odigo) и вот он внизу окошка противный такой желтый — баннер.

Исследуем

Сначала выясним куда этот баннер рисуется и какой
программный модуль им рулит. Достаем MS Spy++ (у всех есть Visual C++?), в нем «Search->Find Window», тянем прицел и отпускаем его над баннером. Окно нашли, теперь клик по «OK» в диалоге «Find Window». Смотрим в открывшемся диалоге caption окна-баннера: «NwAnimatedGif» и на вкладку «процессы», щелкаем по ThreadID — высветилось имя модуля, создавшего окно (и имя это — ODIGO). 

HWND 0B24                                              
; сегодня оно так называется

Window  Handle hQueue SZ QOwner Class Name Window Procedure
0B24  (2) 3457 32 ODIGO Afx:400000:8:8926 3EEF:00000610

Можно тоже самое проделать при помощи SoftIce, но тут сложнее будет: пишем сначала «HWND Odigo» — вылетает длинный список, в нем куча окон первого уровня (в первом столбце такая цифра в скобках 😉 — их класс_нейм Tooltips_class32 — это, ясное дело, к
рекламе отношения не имеет. Дальше следует окно класса #32770 (Dialog), в нем несколько дочерних окон. Стало быть, окно вида #32770 — главное, а баннер надо искать внутри, среди его детей. Так вот, если присмотреться к столбцу «QOwner», сразу становится понятно, что все эти окна наделал Odigo.exe. Если у кого-то остались подозрения, что модуль ODIGO и файл «odigo.exe» не связаны, можно дать Айсу команду «MOD Odigo».

Словом, где искать вызов рекламы, мы узнали. Посмотрим дизассемблером, что делает exe-шник (W32Dasm как раз пригодится). В секции «Imports» есть такое: 

Import Module 001: WINMM.dll
Import Module 002: IMM32.dll
Import Module 003: OdigoMsg.dll
Import Module 004: OdigoShared.dll
Import Module 005: OdigoUI.dll
Import Module 006: OdigoUtil.dll
Import Module 007: OdigoCppApi.dll
Import Module 008: OdigoNet.dll
Import Module 009: MFC42.DLL
Import Module 010: MSVCRT.dll
Import Module 011: KERNEL32.dll
Import Module 012: USER32.dll
Import Module 013: GDI32.dll
Import Module 014: SHELL32.dll
Import Module 015: ole32.dll
Import Module 016: OLEAUT32.dll
Import Module 017: WSOCK32.dll

Здесь кроме стандартных библиотек используются и свои собственные. Совместными усилиями они и создают рекламу. Заглянем в список импортируемых функций (меню Functions->Imports 😉 — пропустим GDI32, KERNEL32, MFC42, MSVCRT. Это все ядро Windows и библиотеки от С++. Остановились на OdigoApi… Удивительно: у всех функций сохранены имена, среди них обработчики всяких событий, а дальше есть такие строки:

OdigoCppApi._OdigoApiCall_FreeIMIPBrandData@4
OdigoCppApi._OdigoApiCall_GetActiveBrowser@16
OdigoCppApi._OdigoApiCall_GetAd@20
OdigoCppApi._OdigoApiCall_GetAdsData@4
OdigoCppApi._OdigoApiCall_GetBrandAllowesAdultContent@4
OdigoCppApi._OdigoApiCall_GetBrandBooleanValue@8

Вот и оно! Ad = Advertisement — оно же реклама. Попробуем найти, где вызывается функция GetAd (дабл-клик по имени функции, при необходимости повторть нужное число раз), два вызова. Первый раз:

:00463376 8D86D4000000 lea eax, dword ptr [esi+000000D4]
:0046337C 6A00                
push 00000000
:0046337E 50                      
push eax
:0046337F 8D86D0000000 lea eax, dword ptr [esi+000000D0]
:00463385 50                      
push eax
:00463386 FFB6B8000000 push dword ptr [esi+000000B8]
:0046338C 55                     
push ebp

* Reference To: OdigoCppApi._OdigoApiCall_GetAd@20, Ord:00BBh

:0046338D E814350400    Call 004A68A6
:00463392 8BF8               
mov edi, eax

Это что-то вроде GetAd( EBP, *(ESI + 0xB8), ESI + 0xD0, 0, ESI + 4), — смысла параметров сразу не понять, да оно и не так важно. И второй:

:00462FF9 6A01              
push 00000001
:00462FFB 6A00             
push 00000000
:00462FFD 8DBEC4000000 lea edi, dword ptr [esi+000000C4]
:00463003 6A00              
push 00000000
:00463005 53                   
push ebx
:00463006 57                   
push edi

* Reference To: OdigoCppApi._OdigoApiCall_GetAd@20, Ord:00BBh

:00463007 E89A380400  Call 004A68A6
:0046300C 83F801          cmp eax, 00000001
:0046300F 7508              
jne 00463019
:00463011 8B0F             
mov ecx, dword ptr [edi]

* Reference To: OdigoShared.?AddReference@CAd@@QAEXXZ, Ord:00C9h

:00463013 FF15E8F54B00 Call dword ptr [004BF5E8]
:00463019 8BCE            
mov ecx, esi ; сюда ведет jne из 46300F

Это похоже на if ( GetAd( ESI + 0xC4, EBX, 0, 0, 1) == 1) AddReference(…).
Это уже очень даже интересно. Стало быть, если GetAd не вернет единичку, то скачанный баннер не появится в программе (если GetAd действительно его скачивает). Здесь даже неважно, что передается в AddReference (а передается туда, скорее всего, инфа о баннере и, похоже, через регистры). Кстати, после первого вызова тоже есть такая проверка и неизменное AddReference(…).

Запрещаем программе загружать рекламу (метод 1)

Итак, естественным желанием будет обойти GetAd() — очистить стек от параметров, и установить EAX != 1, дескать закачать не удалось. Для первого вызова оффсеты в odigo.EXE с 0x6337С по 0x6338F включительно забиты NOP’ами (зачем загонять в стек параметры, когда их никто не прочитает), в 0x63390 пишем 33С0 — оно же EAX = 0. На втором вызове 0x62ff9-0x62ffc, 0x63003-0x63009 заполним байтом 0x90, в 0x6300A записали ’33С0′.

Запускаем… Все ок, никаких баннеров, только логотип odigo на их месте, и его по-прежнему можно кликать ;).

Удаление баннера хирургическим путем (метод 2)

Есть и другое слабое место в Odigo. Это само создание окошка с баннером: 

:00462F56 59                 
pop ecx
:00462F57 894510          mov dword ptr [ebp+10], eax
:00462F5A 68C7040000 push 000004C7
:00462F5F 57                
push edi
:00462F60 FF750C        push [ebp+0C]
:00462F63 8BCE           
mov ecx, esi
:00462F65 6800000050 push 50000000

* Reference To: OdigoUI.?Create@CAnimatedGif@@UAEHKABUtagRECT@@PAVCWnd@@I@Z, Ord:0198h

:00462F6A FF1580FE4B00 Call dword ptr [004BFE80]
:00462F70 85C0           
test eax, eax

Почему бы не попробовать отменить вызов Create(0x50000000, *(EBP+12), EDI, 0x4C7)?
Ровно по оффсету 0x62F6A вводим код ’83 C4 10 90 90 90′ — оно же очистить стек от параметров. Обычно результат выполнения функции хранится в EAX, но здесь мы ничего не меняем. В EAX уже что-то записано, а проверка идет по принципу «ноль — не_ноль».
Недостатком такого метода станет потеря внешнего вида программы. Так что
придется подрисовать скин — закрасить зеленое пятно, на котором некогда «красовался» баннер.

Выводы

Защита рекламы оставляет желать лучшего. Даже такой примитивный способ как подавление создания окна работает и программа не выдает при этом никаких ошибок. Да и кому интересно их читать? Программа создавалась для развлечения, а не изучения или отладки. Так что общайтесь на здоровье, и да не напряжет Вас реклама!

Ваши отзывы всегда велком!

P.S. Здесь можно было бы привести достаточно подробный экскурс в Reverse-Engineering по odigo — для многих методов можно узнать названия и получить представление, что они делают. Однако, Reversing программы явно выходит за рамки статьи об удалении баннеров.

Оставить мнение

Check Also

Из-за проблемы «посмотреть как» пострадали 30 000 000 пользователей Facebook

Представители Facebook обнародовали подробности атаки, произошедшей в конце сентября. Стал…