
Скриншот программы Grungetastic
Программа Grungetastic предназначена для добавления к вашим фотографиям эффектов в стиле Grunge. В результате получается нечто мрачное, похожее на кадры из Silent Hill, и даже от самой доброй фотографии начинают бегать мурашки по коже. Цена, к счастью, невысока, но на сайте разработчиков еще целая груда аналогичных программ, и если покупать каждую, то итоговая сумма набегает более чем приличная. Попробуем обойтись вообще без покупки.
Скачиваем дистрибутив, устанавливаем, смотрим что получилось. Приложение представляет из себя один исполняемый файл размером более 70 мегабайт. Файл ничем не упакован, поэтому сразу отправляем его в дизассемблер, а параллельно посмотрим как проявляется триальность. Основное ограничение в том, что без регистрации сохранить отредактированный файл нельзя.
Окно регистрации вызывается через меню Help. Регистрационного имени нет, только серийный номер. Причем программа сама подсказывает правильную длину серийника - 16 символов.

Окно регистрации
На неправильный ввод программа реагирует сообщением "Invalid Serial Number".

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

Строка сообщения найдена
В листинге дизассемблера находим место, где есть указатель на эту строчку. Тоже никаких проблем:
...
.text:0044CBF2 call sub_58BD4D
.text:0044CBF7 mov esi, eax
.text:0044CBF9 add esp, 4
.text:0044CBFC mov [ebp+var_1C], esi
.text:0044CBFF mov bl, 4
.text:0044CC01 mov byte ptr [ebp+var_4], bl
.text:0044CC04 test esi, esi
.text:0044CC06 jz loc_44CCD5
.text:0044CC0C push 0
.text:0044CC0E push ecx
.text:0044CC0F mov eax, esp
.text:0044CC11 lea edx, [ebp+var_10]
.text:0044CC14 mov [ebp+var_18], esp
.text:0044CC17 push edx
.text:0044CC18 push eax
.text:0044CC19 mov [ebp+var_10], offset aInvalidSerialN
; "Invalid Serial Number."
.text:0044CC20 call sub_46BD00
.text:0044CC25 add esp, 4
.text:0044CC28 mov byte ptr [ebp+var_4], 5
.text:0044CC2C mov eax, esp
.text:0044CC2E lea ecx, [ebp+var_10]
.text:0044CC31 mov [ebp+var_14], esp
.text:0044CC34 push ecx
.text:0044CC35 push eax
.text:0044CC36 mov [ebp+var_10], offset aInvalidSerial
; "Invalid Serial"
.text:0044CC3D call sub_46BD00
.text:0044CC42 add esp, 4
.text:0044CC45 mov byte ptr [ebp+var_4], 6
.text:0044CC49 mov [ebp+var_10], esp
.text:0044CC4C lea edx, [ebp+var_10]
.text:0044CC4F mov eax, esp
...
Чуть выше несколько условных переходов, один из которых ведет на сообщение о неправильной регистрации, а другой - на сообщение о правильной.
.text:0044CB47 mov edx, [eax+0B8h]
.text:0044CB4D add esp, 8
.text:0044CB50 mov ecx, esi
; Неявно вызвать какую-то функцию
.text:0044CB52 call edx
; Проверить ее результат
.text:0044CB54 test al, al
; Если AL!=0, то переход на сообщение о правильной регистрации
.text:0044CB56 jnz loc_44CC5B
.text:0044CB5C lea eax, [ebp+arg_0]
; Проверить длину введенного серийника
.text:0044CB5F call sub_45BB00
.text:0044CB64 push 0D0h
; Если длина 16 символов, то серийник просто неправильный
.text:0044CB69 cmp eax, 10h
.text:0044CB6C jz loc_44CBF2
; Иначе сообщение о неправильной длине введенного серийника
А вот тут возникает небольшая проблемка. Как вы уже увидели в листинге дизассемблера, функция проверки вызывается неявным образом, через содержимое регистра EDX. Статичный анализ тут не поможет, так как искомый адрес в этом случае остается неизвестным. Но ведь отладчики придумали как раз для подобных случаев! Запускаем программу под отладчиком, ставим точку останова по адресу 0044CB52, пробуем зарегистрировать любым серийником. В момент срабатывания точки останова узнаем адрес вызываемой функции. Вот она:
.text:00401560 push ebp
.text:00401561 mov ebp, esp
.text:00401563 push ecx
.text:00401564 push esi
.text:00401565 push ecx
.text:00401566 mov esi, ecx
.text:00401568 mov eax, [esi]
.text:0040156A mov edx, [eax+0BCh]
.text:00401570 mov ecx, esp
.text:00401572 mov [ebp+var_4], esp
.text:00401575 push ecx
.text:00401576 mov ecx, esi
.text:00401578 call edx
.text:0040157A push 47525431h
.text:0040157F call sub_425120
.text:00401584 add esp, 8
.text:00401587 test al, al
.text:00401589 jz short loc_401592
.text:0040158B mov al, 1
.text:0040158D pop esi
.text:0040158E mov esp, ebp
.text:00401590 pop ebp
.text:00401591 retn
.text:00401592 ; -----------------------------------------
.text:00401592 loc_401592:
.text:00401592 mov eax, [esi]
.text:00401594 mov edx, [eax+0BCh]
.text:0040159A push ecx
.text:0040159B mov ecx, esp
.text:0040159D mov [ebp+var_4], esp
.text:004015A0 push ecx
.text:004015A1 mov ecx, esi
.text:004015A3 call edx
.text:004015A5 push 424E4431h
.text:004015AA call sub_425120
.text:004015AF add esp, 8
.text:004015B2 test al, al
.text:004015B4 setnz al
.text:004015B7 pop esi
.text:004015B8 mov esp, ebp
.text:004015BA pop ebp
.text:004015BB retn
Первый вариант патча: записать в самое начало команды MOV AL,1 и RET. Второй вариант патча: заNOPить условный переход по адресу 00401589. В обоих случаях функция проверки всегда будет возвращать нужное нам значение AL=1.

Программа успешно "зарегистрирована"
Пункт регистрации в меню пропал, вместе с ним пропало ограничение при попытке сохранения отредактированного файла. Цель достигнута. Сигнатура для патча очень приметная, так что можно сделать универсальный патч. Кроме того, аналогичным образом исцеляются от жадности и другие программы этого разработчика.