
Скриншот программы CC Get MAC Address
Программа CC Get MAC Address предназначена для сканирования сети с целью получения списка MAC-адресов, получения имени компьютера по IP-адресу, "пробуждения" по сети компьютеров с поддержкой опции "Wake On LAN". В общем небольшая полезная программа для системного администратора. Только почему-то за все это программа просит денег, и немало.
Качаем дистрибутив, устанавливаем, запускаем. В заголовке программы сразу бросается в глаза строка с сообщением об триальности и оставшемся количестве дней. Основной файл ничем не упакован, "нехорошая" строка находится легко.

"Нехорошая строка" найдена
Теперь в дизассемблере посмотрим код, который ссылается на нее, а также проверки и условия, которые приводят к срабатыванию этой ветки алгоритма:
...
.text:00401FD6 mov [esp+1928h+ReturnedString], cl
.text:00401FDD mov ecx, 0FFh
.text:00401FE2 lea edi, [esp+1928h+var_100B]
.text:00401FE9 push offset FileName ; lpFileName
.text:00401FEE rep stosd
.text:00401FF0 lea edx, [esp+192Ch+ReturnedString]
.text:00401FF7 push 400h ; nSize
.text:00401FFC stosw
; Прочитать из ini-файла из секции "System" значение параметра "RegCode"
.text:00401FFE push edx ; lpReturnedString
.text:00401FFF push offset byte_438740 ; lpDefault
.text:00402004 push offset aRegcode ; "RegCode"
.text:00402009 push offset MultiByteStr ; "System"
.text:0040200E stosb
.text:0040200F call ebx ; GetPrivateProfileStringA
.text:00402011 lea eax, [esp+1928h+ReturnedString]
; Указатель на полученную строку
.text:00402018 push eax
; Вызвать функцию проверки регистрационного кода
.text:00402019 call sub_404E00
.text:0040201E add esp, 4
.text:00402021 test eax, eax
.text:00402023 pop ebx
; Если функция проверки вернула EAX=0, то серийник неправильный
.text:00402024 jz short loc_402055
; Программа работает в зарегистрированном режиме
.text:00402026 push 0 ; nCmdShow
.text:00402028 push 409h ; nIDDlgItem
.text:0040202D mov ecx, ebp
.text:0040202F call sub_420AE4
.text:00402034 mov ecx, eax
.text:00402036 call sub_420CA4
.text:0040203B push 0 ; nCmdShow
.text:0040203D push 408h ; nIDDlgItem
.text:00402042 mov ecx, ebp
.text:00402044 call sub_420AE4
.text:00402049 mov ecx, eax
.text:0040204B call sub_420CA4
.text:00402050 jmp loc_40213F
.text:00402055 ; ---------------------------------------------------
.text:00402055 loc_402055:
; Программа работает в триальном режиме
.text:00402055 mov cl, byte_438740
.text:0040205B xor eax, eax
.text:0040205D mov [esp+1924h+String], cl
.text:00402064 mov ecx, 0FFh
.text:00402069 lea edi, [esp+1924h+var_C0B]
.text:00402070 rep stosd
.text:00402072 stosw
.text:00402074 stosb
.text:00402075 call sub_401A60
.text:0040207A push eax
.text:0040207B lea edx, [esp+1928h+String]
.text:00402082 push offset aCcGetMacAddr_1
; "CC Get MAC Address(unregistered version"...
.text:00402087 push edx ; Dest
.text:00402088 call _sprintf
...
Теперь посмотрим саму процедуру проверки серийного номера. Можно пропатчить ее, чтобы на выходе всегда было EAX=1, но попробуем лучше посмотреть на сам алгоритм проверки:
.text:00404E00 sub_404E00 proc near
.text:00404E00 arg_0 = dword ptr 4
; EAX -> указатель на строку серийного номера
.text:00404E00 mov eax, [esp+arg_0]
; ECX = первый символ серийника
.text:00404E04 movsx ecx, byte ptr [eax]
; EDX = пятый символ серийника
.text:00404E07 movsx edx, byte ptr [eax+4]
.text:00404E0B inc ecx
; Проверка EDX = (ECX + 1)
.text:00404E0C cmp ecx, edx
; Не равны - номер неправильный
.text:00404E0E jnz short loc_404E43
; ECX = второй символ серийника
.text:00404E10 movsx ecx, byte ptr [eax+1]
; EDX = шестой символ серийника
.text:00404E14 movsx edx, byte ptr [eax+5]
.text:00404E18 add ecx, 9
; Проверка EDX = (ECX + 9)
.text:00404E1B cmp ecx, edx
; Не равны - номер неправильный
.text:00404E1D jnz short loc_404E43
; ECX = третий символ серийника
.text:00404E1F movsx ecx, byte ptr [eax+2]
; EDX = седьмой символ серийника
.text:00404E23 movsx edx, byte ptr [eax+6]
.text:00404E27 add ecx, 7
; Проверка EDX = (ECX + 7)
.text:00404E2A cmp ecx, edx
; Не равны - номер неправильный
.text:00404E2C jnz short loc_404E43
; ECX = четвертый символ серийника
.text:00404E2E movsx ecx, byte ptr [eax+3]
; EDX = восьмой символ серийника
.text:00404E32 movsx edx, byte ptr [eax+7]
.text:00404E36 add ecx, 7
; Проверка EDX = (ECX + 7)
.text:00404E39 cmp ecx, edx
; Не равны - номер неправильный
.text:00404E3B jnz short loc_404E43
; Серийный номер правильный, EAX=1
.text:00404E3D mov eax, 1
.text:00404E42 retn
.text:00404E43 ; -------------------------------------------------
.text:00404E43 loc_404E43:
; Серийный номер неправильный, EAX=0
.text:00404E43 xor eax, eax
.text:00404E45 retn
.text:00404E45 sub_404E00 endp
Теперь то же самое, но словами. Длина проверяемой части серийного номера - 8 символов. Пятый символ равен первому + 1, шестой равен второму + 9, седьмой равен третьему + 7, восьмой равен четвертому + 7. Например, под эту схему подходит номер "00001977". Вводим его в программу, она радостно благодарит за регистрацию. После перезапуска программы пропадают все признаки триальности, значит все сделано правильно.

Программа успешно зарегистрирована
Положительным моментом является то, что серийник записывается в файл конфигурации, а не в реестр, так что после регистрации CC Get MAC Address становится полностью портативной и может работать, например, с флешки.