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


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

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

Скачиваем дистрибутив последней версии, распаковываем, запускаем. В принципе, каких-то ограничений при работе незарегистрированного калькулятора нет, но вот после истечения триального срока он самоликвидируется (не проверял). Давайте исследуем его защиту на предмет обхода всех ограничений. Исполняемый файл ничем не упакован и не защищен, отправляем его в дизассемблер, а сами посмотрим на его работу. Кнопка регистрации находится в окне "About":


Окно "О программе"

Вводить серийный номер надо в том же окне, где выполняются остальные расчеты. На ввод любого неправильного серийника программа реагирует сообщением "Registration invalid. Visit www.zoesoft.com to acquire a license".


Сообщение о неправильной регистрации

Поищем эту строчку в файле и посмотрим условия ее срабатывания.
.text:00404049                 sub     eax, edx
; Проверить длину строки серийника. Она должна быть 12 символов
.text:0040404B                 cmp     eax, 0Ch
.text:0040404E                 jnz     short loc_404073
.text:00404050                 lea     edx, [esp+88h+var_80]
.text:00404054                 push    edx
.text:00404055                 lea     eax, [esp+8Ch+var_7C]
.text:00404059                 push    eax
.text:0040405A                 lea     ecx, [esp+90h+var_78]
.text:0040405E                 push    ecx
.text:0040405F                 lea     edx, [esp+94h+var_68]
; Разложить серийный номер на 3 группы по 4 шестнадцатеричные цифры
.text:00404063                 push    offset a4x4x4x  ; "%4x%4x%4x"
.text:00404068                 push    edx
.text:00404069                 call    sub_44004E
.text:0040406E                 add     esp, 14h
.text:00404071                 mov     edi, eax
.text:00404073 loc_404073:
.text:00404073                 push    ebx
.text:00404074                 push    ebp
.text:00404075                 mov     ecx, esi
.text:00404077                 call    sub_4026F0
.text:0040407C                 cmp     edi, 3
.text:0040407F                 jnz     loc_4041F8
.text:00404085                 mov     edx, [esp+90h+var_78]
.text:00404089                 mov     edi, [esp+90h+var_7C]
.text:0040408D                 mov     ebp, [esp+90h+var_80]
.text:00404091                 mov     eax, edx
.text:00404093                 or      eax, edi
.text:00404095                 or      eax, ebp
.text:00404097                 cmp     eax, 0FFFFh
.text:0040409C                 ja      loc_4041F8
.text:004040A2                 mov     ecx, edx
.text:004040A4                 shl     ecx, 10h
.text:004040A7                 or      ecx, edi
.text:004040A9                 push    ecx
.text:004040AA                 push    ebp
; Вызывать функцию проверки серийного номера
.text:004040AB                 call    sub_4024F0
.text:004040B0                 add     esp, 8
.text:004040B3                 cmp     edx, 2EF1h
; Сохранить в EBX результат проверки
.text:004040B9                 mov     ebx, eax
.text:004040BB                 jnz     loc_404193
.text:004040C1                 cmp     edi, 7B14h
.text:004040C7                 jnz     loc_404193
.text:004040CD                 cmp     ebp, 8072h
.text:004040D3                 jnz     loc_404193
...

часть кода пропущена
...
.text:00404193 loc_404193:
; Результат проверки = 0?
.text:00404193                 test    ebx, ebx
; Да, значит введенный серийный номер неправильный
.text:00404195                 jz      short loc_4041F8
; Серийный номер правильный
.text:00404197                 mov     eax, [esi+94h]
.text:0040419D                 push    offset aRegistrationSu
; "\nRegistration successful. Thank you!\n"
.text:004041A2                 push    0               ; wParam
.text:004041A4                 push    0C2h            ; Msg
.text:004041A9                 push    eax             ; hWnd
.text:004041AA                 call    ds:SendMessageA
.text:004041B0                 fld     ds:dbl_45EAF0
.text:004041B6                 fld     ds:dbl_45EAD0
.text:004041BC                 call    __CIpow
.text:004041C1                 mov     ecx, [esp+90h+var_78]
.text:004041C5                 shl     ecx, 10h
.text:004041C8                 or      ecx, [esp+90h+var_7C]
.text:004041CC                 push    0
.text:004041CE                 mov     [esp+94h+var_74], ecx
.text:004041D2                 fild    [esp+94h+var_74]
.text:004041D6                 mov     dword_480398, 1
.text:004041E0                 fmulp   st(1), st
.text:004041E2                 fiadd   [esp+94h+var_80]
.text:004041E6                 fstp    dbl_47B518
.text:004041EC                 call    sub_403DE0
.text:004041F1                 add     esp, 4
.text:004041F4 loc_4041F4:
.text:004041F4                 test    ebx, ebx
.text:004041F6                 jnz     short loc_404211
.text:004041F8 loc_4041F8:
; Серийный номер неправильный
.text:004041F8                 mov     edx, [esi+94h]
.text:004041FE                 push    offset aRegistrationIn
; "\nRegistration invalid.\nVisit www.zoesof"...
.text:00404203                 push    0               ; wParam
.text:00404205                 push    0C2h            ; Msg
.text:0040420A                 push    edx             ; hWnd
.text:0040420B                 call    ds:SendMessageA
...

Итак, что мы имеем. Длина серийного номера должна быть 12 символов, и это три группы по 4 шестнадцатеричных цифры. Теперь посмотрим функцию проверки введенного серийного номера. Под отладчиком весь алгоритм проверки становится еще более понятным.
.text:004024F0 sub_4024F0      proc near
; В регистре EAX значение конечного WORD'а
.text:004024F0                 movzx   eax, [esp+arg_0]
.text:004024F5                 lea     ecx, [eax+7531h]
.text:004024FB                 shl     eax, 10h
.text:004024FE                 and     ecx, 0FFFFh
.text:00402504                 add     ecx, eax
.text:00402506                 rol     ecx, 6
.text:00402509                 add     ecx, 12341234h
.text:0040250F                 xor     eax, eax
; Сейчас в регистре ECX правильное значение начального DWORD'а
.text:00402511                 cmp     ecx, [esp+arg_4]
.text:00402515                 setz    al
.text:00402518                 retn
.text:00402518 sub_4024F0      endp

Функция проверки серийного номера настолько прозрачная, что даже не требует каких-то дополнительных комментариев. Можно просто скопировать и вставить в свой генератор ключей. Все манипуляции производятся с завершающим WORD'ом из введенного серийного номера, а первый DWORD является проверочным. Если принять, что в регистре EAX записан завершающий WORD, то формулу можно записать в виде:
Код = ((((EAX + 7531h) AND 0FFFFh) + (EAX SHL 10h)) ROL 6) + 12341234h

Например, для начального значения 1122h проверочный код получится 5AD5A6F8h, значит целиком серийный номер будет 5AD5A6F81122. Теперь попробуем зарегистрировать программу с найденным серийником:


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

Программа успешно зарегистрирована. Вот такой пятиминутный ребус стоимостью пять баксов. При желании можете даже купить этот калькулятор, а можно написать кейген, выбор за вами. Кстати, с чувством юмора у автора тоже все в порядке. Если внимательно посмотрите на код проверки, то обнаружите там такие строки:
.text:004040B3                 cmp     edx, 2EF1h
.text:004040B9                 mov     ebx, eax
.text:004040BB                 jnz     loc_404193
.text:004040C1                 cmp     edi, 7B14h
.text:004040C7                 jnz     loc_404193
.text:004040CD                 cmp     ebp, 8072h

Если собрать проверяемые значения в серийный номер 2EF17B148072, а затем попытаться зарегистрировать с его помощью программу, то вместо ошибки вы получите вот такое забавное сообщение:


Варезный серийный номер

Естественно, никто ничего форматировать не собирается, это просто реакция программы на ранее скарденный или сгенерированный серийный номер, утекший в сеть. Но шутка юмора удачная, лично я оценил.
Добавлено: 14 Сентября 2013 12:28:54 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...