Исследование защиты программы FinalRecovery


Скриншот программы FinalRecovery

FinalRecovery от MeetSoft - хорошая программа для восстановления удаленных файлов. Авторы старательно борются со всеми появляющимися варезными решениями, изменяя алгоритмы генерации серийных номеров. Новые кейгены быстро перестают работать, поэтому я расскажу как подбирать серийники к программе фишингом. Кроме того, в FinalRecovery используется интересная система проверки регистрации, на которой могут срезаться начинающие крякеры. Для исследования потребуется дистрибутив FinalRecovery и отладчик. Устанавливаем программу, смотрим. Исполняемый файл упакован UPX, он распаковывается самим же UPX с ключом "-d", тут никаких сюрпризов нет.

Запускаем распакованную программу под отладчиком, пробуем зарегистрировать какими-нибудь левыми данными. Получаем сообщение "Invalid license code", поищем эту строчку в файле.


Строка найдена

Теперь посмотрим в пошаговом режиме под отладчиком код, который ссылается на "нехорошую" строчку. Он небольшой и достаточно понятный.
CODE:004A6274                 push    ebp
CODE:004A6275                 mov     ebp, esp
CODE:004A6277                 mov     ecx, 6
CODE:004A627C loc_4A627C:
CODE:004A627C                 push    0
CODE:004A627E                 push    0
CODE:004A6280                 dec     ecx
CODE:004A6281                 jnz     short loc_4A627C
CODE:004A6283                 push    ebx
CODE:004A6284                 push    esi
CODE:004A6285                 mov     ebx, eax
CODE:004A6287                 xor     eax, eax
CODE:004A6289                 push    ebp
CODE:004A628A                 push    offset unk_4A64A7
CODE:004A628F                 push    dword ptr fs:[eax]
CODE:004A6292                 mov     fs:[eax], esp
CODE:004A6295                 lea     edx, [ebp+var_C]
CODE:004A6298                 mov     eax, [ebx+2D8h]
CODE:004A629E                 call    sub_42FCA8
CODE:004A62A3                 mov     eax, [ebp+var_C]
CODE:004A62A6                 lea     edx, [ebp+var_4]
CODE:004A62A9                 call    sub_4085A8
; Непонятная пауза. С понтом имитация напряженых вычислений :)
CODE:004A62AE                 push    32h             ; dwMilliseconds
CODE:004A62B0                 call    Sleep
CODE:004A62B5                 mov     eax, [ebp+var_4]
CODE:004A62B8                 call    sub_403DB8
CODE:004A62BD                 cmp     eax, 6
; Проверка длины регистрационного имени, должно быть не менее 6 символов,
; иначе вывести сообщение об ошибке
CODE:004A62C0                 jge     short loc_4A62DC
CODE:004A62C2                 push    0
CODE:004A62C4                 mov     cx, word_4A64B4
CODE:004A62CB                 mov     dl, 1
                                      ; "Invalid license code."
CODE:004A62CD                 mov     eax, offset aInvalidLicense
CODE:004A62D2                 call    sub_4569F8
CODE:004A62D7                 jmp     loc_4A644A
CODE:004A62DC ; -----------------------------------------------------
CODE:004A62DC loc_4A62DC:
CODE:004A62DC                 lea     eax, [ebp+var_4]
CODE:004A62DF                 push    eax
CODE:004A62E0                 mov     eax, [ebp+var_4]
CODE:004A62E3                 call    sub_403DB8
CODE:004A62E8                 mov     ecx, eax
CODE:004A62EA                 sar     ecx, 1
CODE:004A62EC                 jns     short loc_4A62F1
CODE:004A62EE                 adc     ecx, 0
CODE:004A62F1 loc_4A62F1:
CODE:004A62F1                 mov     edx, 1
CODE:004A62F6                 mov     eax, [ebp+var_4]
CODE:004A62F9                 call    sub_403FC0
; Опять какая-то непонятная пауза. Хороший понт дороже денег :)
CODE:004A62FE                 push    32h             ; dwMilliseconds
CODE:004A6300                 call    Sleep
CODE:004A6305                 lea     ecx, [ebp+var_8]
CODE:004A6308                 mov     edx, offset unk_4A64E0
CODE:004A630D                 mov     eax, [ebp+var_4]
CODE:004A6310                 call    sub_4753D8
CODE:004A6315                 lea     ecx, [ebp+var_10]
CODE:004A6318                 mov     edx, [ebp+var_8]
CODE:004A631B                 mov     eax, [ebp+var_4]
CODE:004A631E                 call    sub_4753D8
CODE:004A6323                 mov     edx, [ebp+var_10]
CODE:004A6326                 lea     eax, [ebp+var_8]
CODE:004A6329                 call    sub_403BD0
; И еще немного имитируем напряженные вычисления...
CODE:004A632E                 push    32h             ; dwMilliseconds
CODE:004A6330                 call    Sleep
CODE:004A6335                 lea     edx, [ebp+var_18]
CODE:004A6338                 mov     eax, [ebx+2E0h]
CODE:004A633E                 call    sub_42FCA8
CODE:004A6343                 mov     eax, [ebp+var_18]
CODE:004A6346                 lea     edx, [ebp+var_14]
CODE:004A6349                 call    sub_4085A8
; В регистре EAX указатель на вычисленный серийник, в регистре EDX
; наши введенные "левые" данные. Далее выполняется проверка их совпадения
CODE:004A634E                 mov     edx, [ebp+var_14]
CODE:004A6351                 mov     eax, [ebp+var_8]
CODE:004A6354                 call    sub_4040A4
CODE:004A6359                 dec     eax
CODE:004A635A                 jnz     loc_4A6435
; Проверка успешно пройдена, записать в реестр регистрационные данные
CODE:004A6360                 mov     dl, 1
CODE:004A6362                 mov     eax, off_44FFC0
CODE:004A6367                 call    sub_4500C0
CODE:004A636C                 mov     esi, eax
CODE:004A636E                 mov     edx, 80000002h
CODE:004A6373                 mov     eax, esi
CODE:004A6375                 call    sub_450160
CODE:004A637A                 mov     cl, 1
                              .......

Из алгоритма видно, что берется половина регистрационного имени, над ним выполняются какие-то действия и в результате получается 16-символьный код, который и сравнивается с введенным серийным номером.


Проверка серийного номера

Сохраним его и попробуем зарегистрировать программу с тем же именем, но с уже пойманным серийником. Ура! Программа сообщает, что успешно зарегистрирована, триальная надпись в заголовке пропадает, окно About показывает ваше имя. Вроде бы все хорошо и можно выкладывать релиз, но вот тут и начинается самое интересное. Попробуем восстановить какой-нибудь удаленный файл нашей свежезарегистрированной программой, например в режиме "Standard Recovery". Что мы видим в логе?


Программа не зарегистрирована и работает с ограничениями

Значит где-то выполняется дополнительная проверка регистрационных данных. Попробуем найти вторую "нехорошую" строчку.


Строка найдена

Смотрим ссылающийся код и условия появления сообщения об ограничении функционала незарегистрированной версии.
                              .......
CODE:00479517                 mov     eax, [ebp+var_8]
CODE:0047951A                 mov     [ebp+var_14], eax
; Проверка, если вообще никаких регистрационных данных не вводилось
CODE:0047951D                 cmp     ds:byte_4B49E0, 0
CODE:00479524                 jz      short loc_479533
; Вот она, вторая проверка. Сраваниваются две строки. В регистре EAX строка
; из серийного номера, в регистре EDX - вычисленное значение
CODE:00479526                 mov     eax, [ebp+var_74]
CODE:00479529                 mov     edx, [ebp+var_78]
CODE:0047952C                 call    sub_403EC8
; В случае совпадения файл восстанавливается в обычном режиме
CODE:00479531                 jz      short loc_47956F
CODE:00479533 loc_479533:
CODE:00479533                 mov     eax, [ebp+var_14]
; Размер файла меньше 64 килобайт? Если да, то восстановить в любом случае
CODE:00479536                 cmp     dword ptr [eax+1Ch], 0FA00h
CODE:0047953D                 jle     short loc_47956F
CODE:0047953F                 lea     eax, [ebp+var_EC]
; Иначе вывести "нехорошую" надпись
; ": Unregistered version can recover file"...
CODE:00479545                 mov     ecx, offset aUnregisteredVe
CODE:0047954A                 mov     edx, [ebp+var_C]
CODE:0047954D                 call    sub_403E04
CODE:00479552                 mov     edx, [ebp+var_EC]
CODE:00479558                 mov     cl, 2
CODE:0047955A                 mov     eax, [ebp+arg_0]
                              .......

Таких участков кода в программе всего три, расставим под отладчиком точки останова на все три вызова функции сравнения. Пробуем снова восстановить файл, отладчик остановится на втором вхождении:


Дополнительная проверка серийника

Кажется странно, потому что фактически вторая строка серийника сравнивается с первой, а такого быть не может. Значит это только часть серийного номера. Попробуем дописать вторую строчку к уже найденному серийному номеру и повторить все проверки. Первая проверка при вводе регистрационного имени и уже 32-символьного серийника проходится успешно. Во второй проверке при восстановлении файла в регистре EAX уже будет правильное значение, значит все сделано правильно. Пойманный серийный номер "2FA02A1773CC30C097AD622D9893F5FA".


Программа успешно зарегистрирована

Вот и очередная рыбалка закончилась успешно, больше не придется ждать посторонних кряков в случае выхода новой версии с новой регистрацией.
Теги:
защита, взлом
Добавлено: 21 Сентября 2013 05:40:36 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...