
Скриншот программы uTorrent
Для пополнения своей видеотеки я уже давно пользуюсь бесплатным торрент-клиентом
uTorrent, но вот уже два обновления подряд начали показывать рекламный баннер. Я, конечно, понимаю, что при такой популярности программы было бы странным не попытаться поиметь с нее бабла, но... Мне категорически не нравится реклама в программах в любом виде. Сейчас будем возвращать uTorrent его былое великолепие.
Скачиваем
дистрибутив, устанавливаем, запускаем. Рекламный баннер в главном окне программы появляется не сразу же, а через некоторое время после запуска. Но его мерзость от этого ничуть не уменьшается. Посмотрим на исполняемый файл. Судя по названиям секций, он упакован UPX, однако сам UPX с распаковкой не справляется:

Файл не распаковывается UPX
Видимо дело в том, что к файлу после упаковки еще прикреплены сертификаты. Но с распаковкой прекрасно справляется универсальный распаковщик UPX от китайских товарищей.
UpxUnpacker 0.2
Для борьбы с баннером надо узнать хоть что-нибудь о нем. Для этого воспользуемся моей программой
WinDowzer, и с ее помощью узнаем, что название класса окна баннера "AdBar". Теперь надо поискать в исполняемом файле что-нибудь, связанное с этой строкой. В ресурсах ничего похожего нет, зато где-то в середине файла находится единственное вхождение искомой строки в юникоде:

Строка с названием класса окна
Следующий шаг - надо найти код, который ссылается на эту строку. Это, естественно, делается в дизассемблере, в который вы уже отправили распакованный файл. Еще не отправили? Тогда сделайте это незамедлительно. Нашему взору открывается длиннющая процедура:
.text:0047402F sub esp, 74h
.text:00474032 push ebx
.text:00474033 push esi
.text:00474034 mov esi, ecx
.text:00474036 xor ebx, ebx
.text:00474038 cmp [esi+104h], ebx
.text:0047403E jnz loc_4743D9
.text:00474044 cmp [esi+10Ch], ebx
.text:0047404A jnz loc_4743D9
.text:00474050 cmp [esi+110h], ebx
.text:00474056 jnz loc_4743D9
.text:0047405C cmp [esi+114h], ebx
.text:00474062 jnz loc_4743D9
.text:00474068 push ebp
.text:00474069 push edi
; Указатель на строку AdBar
.text:0047406A push offset aAdbar ; lParam
.text:0047406F push ebx ; wParam
.text:00474070 push 0Ch ; Msg
.text:00474072 push dword ptr [esi+4] ; hWnd
.text:00474075 call ds:SendMessageW
.text:0047407B mov ebp, 236h
...
Куча кода, который, судя по вызываемым функциям WinApi, отрисовывает окно баннера и добавляет его к основному окну программы. И, что самое интересное, сама эта функция вызывается вот из такого кода:
.text:0047549D loc_47549D:
.text:0047549D cmp eax, 808Ah
.text:004754A2 jnz short loc_4754AB
.text:004754A4 push edx
.text:004754A5 call sub_47402F
.text:004754AA retn
До и после этого блока точно такие же вызовы, которые отличаются только числом в операторе сравнения и вызываемой функцией в случае его совпадения. Если вы немного разбираетесь в программировании, то без труда опознаете оператор "case" или несколько последовательных конструкций "if-then-else". Попробуем пропатчить uTorrent, чтобы условие инициализации баннера никогда не сработало. Для этого меняем условный переход по адресу 004754A2. Сохраняем изменения, запускаем. На первый взгляд все нормально, но в момент, когда баннер должен появляться, программа падает с ошибкой:

Окно ошибки
Было бы логично предположить, что после инициализации баннера с ним должны выполняться какие-то действия. А раз окно баннера не было создано, то попытки программы взаимодействовать с ним приводят к падению. Снова предположим, что раз код инициализации баннера равняется 808Ah, то код взаимодействия с баннером должен быть похожим. Как я говорил выше, прямо под блоком вызова инициализации есть похожий блок, в котором проверяется код, отличающийся от кода инициализации только на единицу:
.text:004754AB loc_4754AB:
.text:004754AB cmp eax, 8089h
.text:004754B0 jnz short loc_4754B9
.text:004754B2 push edx
.text:004754B3 call sub_474FBC
.text:004754B8 retn
Тут вызывается не менее громоздкая процедура, которая, в принципе, может быть чем угодно. Если бы не кусочек кода в середине, который выдает ее с потрохами:
...
.text:00475279 call dword ptr [eax+4]
.text:0047527C push eax
.text:0047527D push [ebp+arg_0]
.text:00475280 push offset aLadwindowRefre
; "\n--LAdWindow refreshing ad group %d for"...
.text:00475285 call nullsub_2
.text:0047528A mov ecx, [ebp+xLeft]
.text:0047528D add esp, 14h
.text:00475290 call sub_403145
...
Значит вся эта процедура так же как-то связана с обновлением баннера. По аналогии с первым патчем меняем условный переход по адресу 004754B0 на безусловный. Сохраняем изменения, запускаем. На этот раз рекламный баннер пропал навсегда, а uTorrent прекрасно работает без всяких вылетов.

Рекламного баннера больше нет
Сигнатура для патча уникальная и очень удобная для поиска, поэтому можно сделать что-то типа универсального лоадера или даже универсальный inline-патч. Главное, чтобы аффтары софта поняли, что так будет с каждым, кто захочет запомоить правильную программу своей поганой рекламой.