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

Скриншот программы Chaos Intellect
Chaos Intellect - почтовая программа, менеджер контактов, календарь и планировщик в одном флаконе. Что-то наподобие Outlook'а, только без лишних и никому не нужных наворотов. Зато от мелкомягкого прототипа у Chaos Intellect осталась патологическая тяга к кошельку пользователя. Сейчас мы будем устранять этот досадный недостаток, тем более что цена почти в 60 баксов для подобной программы явно завышена.
Скачиваем последний дистрибутив (на момент написания статьи это версия 4.0.4.7), устанавливаем, смотрим. В папке с программой целая куча исполняемых файлов, но нас интересует только один - Intellect.exe. Предварительным осмотром узнаем, что он упакован бесплатным пакером UPX. Никаких модификаций в код распаковщика не внесено, поэтому он легко распаковывается самим же UPX с ключом "-d". Отправляем бедолагу в дизассемблер, а пока посмотрим как он регистрируется и как реагирует на неправильную регистрацию.

Окно регистрации программы
Строка легко находится поиском. Рядышком находится строка сообщения-благодарности за правильную регистрацию. Это нам пока не надо.

Строка сообщения найдена
Теперь посмотрим условия появления сообщения о неправильной регистрации (часть малозначительного кода я опустил):
Code (Assembler) : Убрать нумерацию
- .text:009E89DA mov eax, [ebp-1Ch]
- .text:009E89DD pop edx
- .text:009E89DE pop ecx
- ; Вызвать функцию проверки
- .text:009E89DF call sub_78BF54
- .text:009E89E4 cmp al, 1
- ; Если она вернула AL не равный 1, то регистрационный номер неправильный
- .text:009E89E6 jnz loc_9E8B1E
- .text:009E89EC xor eax, eax
- .text:009E89EE push ebp
- .text:009E89EF push offset loc_9E8B12
- .text:009E89F4 push dword ptr fs:[eax]
- ; ...
- ; Часть кода пропущена
- ; ...
- .text:009E8AF3 push 0
- .text:009E8AF5 movzx ecx, ds:word_9E8C28
- .text:009E8AFC mov dl, 2
- .text:009E8AFE mov eax, offset _str_Thank_you_for_r
- ; Указатель на строку "Thank you for registering..."
- .text:009E8B03 call @Dialogs@MessageDlg
- .text:009E8B08 loc_9E8B08:
- .text:009E8B08 xor eax, eax
- .text:009E8B0A pop edx
- .text:009E8B0B pop ecx
- .text:009E8B0C pop ecx
- .text:009E8B0D mov fs:[eax], edx
- .text:009E8B10 jmp short loc_9E8B58
- .text:009E8B12 ; -------------------------------------------
- ; Часть кода пропущена
- .text:009E8B1E loc_9E8B1E:
- .text:009E8B1E push 0
- .text:009E8B20 movzx ecx, ds:word_9E8C28
- .text:009E8B27 mov dl, 1
- .text:009E8B29 mov eax, offset _str_Please_try_agai
- ; Указатель на строку "Please try again"
- .text:009E8B2E call @Dialogs@MessageDlg
- .text:009E8B33 mov eax, [ebp-0Ch]
- .text:009E8B36 mov eax, [eax+37Ch]
- .text:009E8B3C xor edx, edx
- ...

Программа успешно "зарегистрирована"
Регистрация прошла успешно, программа действительно принимает любое имя и серийный номер. Патч быстрый и эффективный, но, как сказали бы мои "коллеги по цеху", это слишком простое решение. Посему попробуем разобрать алгоритм проверки серийного номера. Для этого загрузим программу под отладчиком, поставим точку останова на начало функции проверки по адресу 0078BF54 и попробуем вновь зарегистрировать ее.
Code (Assembler) : Убрать нумерацию
- .text:0078BF54 push ebp
- .text:0078BF55 mov ebp, esp
- .text:0078BF57 add esp, 0FFFFFFE0h
- .text:0078BF5A push ebx
- .text:0078BF5B push esi
- .text:0078BF5C push edi
- .text:0078BF5D xor ebx, ebx
- .text:0078BF5F mov [ebp+var_20], ebx
- .text:0078BF62 mov [ebp+var_18], ebx
- .text:0078BF65 mov [ebp+var_1C], ebx
- .text:0078BF68 mov [ebp+var_14], ebx
- .text:0078BF6B mov [ebp+var_C], ecx
- .text:0078BF6E mov [ebp+var_8], edx
- .text:0078BF71 mov [ebp+var_4], eax
- .text:0078BF74 mov eax, [ebp+var_4]
- .text:0078BF77 call @System@@LStrAddRef$qqrpv
- .text:0078BF7C mov eax, [ebp+var_8]
- .text:0078BF7F call @System@@LStrAddRef$qqrpv
- .text:0078BF84 mov eax, [ebp+var_C]
- .text:0078BF87 call @System@@LStrAddRef$qqrpv
- .text:0078BF8C xor eax, eax
- .text:0078BF8E push ebp
- .text:0078BF8F push offset loc_78C0EF
- .text:0078BF94 push dword ptr fs:[eax]
- .text:0078BF97 mov fs:[eax], esp
- .text:0078BF9A mov [ebp+var_D], 0
- .text:0078BF9E lea eax, [ebp+var_14]
- .text:0078BFA1 mov ecx, [ebp+var_8]
- .text:0078BFA4 mov edx, [ebp+var_4]
- .text:0078BFA7 call @System@@LStrCat3$qqrv
- .text:0078BFAC cmp [ebp+var_14], 0
- .text:0078BFB0 jz loc_78C0C7
- .text:0078BFB6 cmp [ebp+var_C], 0
- .text:0078BFBA jz loc_78C0C7
Code (Assembler) : Убрать нумерацию
- .text:0078BFC0 lea eax, [ebp+var_1C]
- .text:0078BFC3 mov edx, [ebp+var_C]
- .text:0078BFC6 movzx edx, byte ptr [edx+5]
- .text:0078BFCA call unknown_libname_87
- .text:0078BFCF mov eax, [ebp+var_1C]
- .text:0078BFD2 lea edx, [ebp+var_18]
- .text:0078BFD5 call @Sysutils@UpperCase$qqrx17System@AnsiString
- .text:0078BFDA mov eax, [ebp+var_18]
- .text:0078BFDD mov edx, offset _str_G.Text
- .text:0078BFE2 call @System@@LStrCmp$qqrv
- .text:0078BFE7 jnz loc_78C0C7
Code (Assembler) : Убрать нумерацию
- .text:0078BFED xor eax, eax
- .text:0078BFEF push ebp
- .text:0078BFF0 push offset loc_78C025
- .text:0078BFF5 push dword ptr fs:[eax]
- .text:0078BFF8 mov fs:[eax], esp
- .text:0078BFFB lea eax, [ebp+var_20]
- .text:0078BFFE push eax
- .text:0078BFFF mov ecx, 4
- .text:0078C004 mov edx, 2
- .text:0078C009 mov eax, [ebp+var_C]
- .text:0078C00C call @System@@LStrCopy$qqrv
- .text:0078C011 mov eax, [ebp+var_20]
- .text:0078C014 call @Sysutils@StrToInt$qqrx17System@AnsiString
- .text:0078C019 mov esi, eax
Code (Assembler) : Убрать нумерацию
- .text:0078C034 xor ecx, ecx
- .text:0078C036 mov eax, [ebp+var_4]
- .text:0078C039 test eax, eax
- .text:0078C03B jz short loc_78C042
- .text:0078C03D sub eax, 4
- .text:0078C040 mov eax, [eax]
- .text:0078C042 loc_78C042:
- .text:0078C042 test eax, eax
- .text:0078C044 jle short loc_78C059
- .text:0078C046 mov edx, 1
- .text:0078C04B loc_78C04B:
- .text:0078C04B mov ebx, [ebp+var_4]
- .text:0078C04E movzx ebx, byte ptr [ebx+edx-1]
- .text:0078C053 add ecx, ebx
- .text:0078C055 inc edx
- .text:0078C056 dec eax
- .text:0078C057 jnz short loc_78C04B
- .text:0078C059 loc_78C059:
- .text:0078C059 mov eax, esi
- .text:0078C05B sub eax, 7D6h
- .text:0078C060 cmp ecx, eax
- .text:0078C062 jnz short loc_78C06A
- .text:0078C064 mov [ebp+var_D], 1
- .text:0078C068 jmp short loc_78C07B
Code (Assembler) : Убрать нумерацию
- .text:0078C06A loc_78C06A:
- .text:0078C06A mov eax, esi
- .text:0078C06C sub eax, 29Ah
- .text:0078C071 cmp ecx, eax
- .text:0078C073 jnz short loc_78C07B
- .text:0078C075 jmp short loc_78C07B
- .text:0078C077 ; ----------------------------------
- .text:0078C077 mov [ebp+var_D], 1
Дальше повтор кода проверки, но на этот раз уже считается сумма кодов символов из названия организации. То есть программу можно регистрировать как на имя + любое название организации, так и на название организации + пустое имя, разницы никакой.
Code (Assembler) : Убрать нумерацию
- .text:0078C08A sub eax, 4
- .text:0078C08D mov eax, [eax]
- .text:0078C08F loc_78C08F:
- .text:0078C08F test eax, eax
- .text:0078C091 jle short loc_78C0A6
- .text:0078C093 mov edx, 1
- .text:0078C098 loc_78C098:
- .text:0078C098 mov ebx, [ebp+var_8]
- .text:0078C09B movzx ebx, byte ptr [ebx+edx-1]
- .text:0078C0A0 add ecx, ebx
- .text:0078C0A2 inc edx
- .text:0078C0A3 dec eax
- .text:0078C0A4 jnz short loc_78C098
- .text:0078C0A6 loc_78C0A6:
- .text:0078C0A6 mov eax, esi
- .text:0078C0A8 sub eax, 7D6h
- .text:0078C0AD cmp ecx, eax
- .text:0078C0AF jnz short loc_78C0B7
- .text:0078C0B1 mov [ebp+var_D], 1
- .text:0078C0B5 jmp short loc_78C0C7
- .text:0078C0B7 ; -----------------------------------------
- .text:0078C0B7 loc_78C0B7:
- .text:0078C0B7 sub esi, 29Ah
- .text:0078C0BD cmp ecx, esi
- .text:0078C0BF jnz short loc_78C0C7
- .text:0078C0C1 jmp short loc_78C0C7

Программа успешно зарегистрирована
Как видите, регистрация прошла успешно. Теперь все ограничения сняты, на сэкономленные деньги можно идти пить пиво или купить свечку во спасение души. Ну а кейген вы можете написать самостоятельно.
Просмотров: 4553 | Комментариев: 4
Метки: исследование защиты

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Laki
(16.08.2013 в 05:47):
Интересно,но мудрёно,Затык произошол на первых шагах)))

rogue
(24.07.2012 в 15:16):
Да Вы красавец каких редко встретиш. Огромное Вам спасибо за труд.

2
(07.07.2012 в 08:16):
Все понятно, автор настолько хорошо все объясняет что вопросов не возникает.

Musika
(06.07.2012 в 21:58):
Приветствую,
ничего не понятно, но интересно.
Спасибо.
ничего не понятно, но интересно.
Спасибо.

Добавить комментарий
Заполните форму для добавления комментария
