
Скриншот программы 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, а затем попытаться зарегистрировать с его помощью программу, то вместо ошибки вы получите вот такое забавное сообщение:

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