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


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

ExtraCHM - неплохая замена стандартному просмотрщику CHM-файлов, который используется в Windows. Программа обладает удобным многовкладочным интерфейсом, возможностью поиска по файлу справки, даже если в нем отсутствует поисковый индекс, с помощью ExtraCHM можно декомпилировать CHM-файл и даже подключить его к голосовому движку для чтения содержимого. Такая куча ништяков просто обязана быть бесплатной, но аффтар почему-то имеет на этот счет другое мнение. Я же, в свою очередь, это мнение не поддерживаю.

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


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

Юникодная строка сообщения в исполняемом файле находится легко.

https://pp.vk.me/c9463/v9463982/3486/aunzz6_DhYY.jpg
Строка сообщения найдена

К этому времени дизассемблер закончил свою работу, и мы можем посмотреть участок кода, который ссылается на эту строку. Ну и конечно же посмотреть условия срабатывания этой ветки алгоритма.
; Вызывать функцию проверки регистрации
.text:0040C809                 call    sub_421F20
.text:0040C80E                 push    0               ; int
.text:0040C810                 push    0               ; uType
; Если она вернула AL=0, то регистрация неправильная
.text:0040C812                 test    al, al
.text:0040C814                 jnz     short loc_40C822
.text:0040C816                 push    offset aThisDoesNotApp
; "This does not appear to be a valid regi"...
.text:0040C81B                 call    ?AfxMessageBox@@YGHPB_WII@Z
; AfxMessageBox(wchar_t const *,uint,uint)
.text:0040C820                 jmp     short loc_40C85A
.text:0040C822 ; -----------------------------------------
.text:0040C822 loc_40C822:
; Сообщение об успешной регистрации
.text:0040C822                 push    offset aThankYouForReg
; "Thank you for registering your copy of "...
.text:0040C827                 call    ?AfxMessageBox@@YGHPB_WII@Z
; AfxMessageBox(wchar_t const *,uint,uint)
.text:0040C82C                 mov     edi, dword_5E1DC0

Вся проверка уместилась в несколько строчек. Простой и максимально эффективный способ решения нашей проблемы - пропатчить функцию проверки по адресу 00421F20, записав в ее начало две любимые команды - MOV AL,1 и RET. После этого программа будет с радостью принимать любые регистрационные данные. Быстро, надежно, но некрасиво. Чтобы стало красиво, посмотрим функцию проверки введенных регистрационных данных. Желательно под отладчиком, так будет гораздо интереснее и понятнее.
.text:00421F20                 push    0FFFFFFFFh
.text:00421F22                 push    offset loc_572C18
.text:00421F27                 mov     eax, large fs:0
.text:00421F2D                 push    eax
.text:00421F2E                 sub     esp, 78h
.text:00421F31                 mov     eax, dword_5D8760
.text:00421F36                 xor     eax, esp
.text:00421F38                 mov     [esp+84h+var_10], eax
.text:00421F3C                 push    ebx
.text:00421F3D                 push    esi
.text:00421F3E                 mov     eax, dword_5D8760
.text:00421F43                 xor     eax, esp
.text:00421F45                 push    eax
.text:00421F46                 lea     eax, [esp+90h+var_C]
.text:00421F4D                 mov     large fs:0, eax
.text:00421F53                 xor     ebx, ebx
.text:00421F55                 mov     esi, ecx
.text:00421F57                 cmp     [edi], bx
; Серийный номер вообще введен?
.text:00421F5A                 jz      short loc_421FD2
; Вызвать функцию проверки серийного номера
.text:00421F5C                 push    edi
.text:00421F5D                 call    sub_421EB0
.text:00421F62                 add     esp, 4
.text:00421F65                 test    al, al
; Если он неправильный, то переход на возврат AL=0
.text:00421F67                 jz      short loc_421FD2
.text:00421F69                 push    8               ; size_t
.text:00421F6B                 lea     eax, [esp+94h+Buffer]
...

Дальше смотреть нет смысла, там только работа с файлом ключа и все такое прочее. Это неинтересно, так как непосредственно к проверке регистрации никак не относится. Зато нас интересует следующий уровень проверки - функция по адресу 00421EB0.
.text:00421EB0                 push    ecx
.text:00421EB1                 mov     eax, esi
; Подсчитать длину строки серийного номера
.text:00421EB3                 lea     edx, [eax+2]
.text:00421EB6 loc_421EB6:
.text:00421EB6                 mov     cx, [eax]
.text:00421EB9                 add     eax, 2
.text:00421EBC                 test    cx, cx
.text:00421EBF                 jnz     short loc_421EB6
.text:00421EC1                 sub     eax, edx
; Длина пополам, так как строка в юникоде
.text:00421EC3                 sar     eax, 1
; Первая проверка - длина серийного номера должна быть 8 символов
.text:00421EC5                 cmp     eax, 8
.text:00421EC8                 jz      short loc_421ECE
; Иначе выход с ошибкой
.text:00421ECA                 xor     al, al
.text:00421ECC                 pop     ecx
.text:00421ECD                 retn
.text:00421ECE ; -------------------------------------------------
.text:00421ECE loc_421ECE:
.text:00421ECE                 mov     ecx, [esp+4+arg_0]
; Сгенерировать из регистрационного имени проверочную строку
.text:00421ED2                 call    sub_421E20
.text:00421ED7                 mov     [esp+4+var_4], eax
.text:00421EDA                 xor     ecx, ecx
.text:00421EDC                 push    edi
.text:00421EDD                 lea     ecx, [ecx+0]
.text:00421EE0 loc_421EE0:
; Сравнить по два символа из серийного номера с проверочной строкой
.text:00421EE0                 movzx   eax, byte ptr [esp+ecx+8+var_4]
.text:00421EE5                 movzx   edx, word ptr [esi+ecx*4]
.text:00421EE9                 mov     edi, eax
.text:00421EEB                 and     edi, 0Fh
.text:00421EEE                 add     edi, 41h
; EDX = правильный символ серийного номера
.text:00421EF1                 cmp     edx, edi
; Не совпало, возврат с ошибкой
.text:00421EF3                 jnz     short loc_421F0F
.text:00421EF5                 movzx   edx, word ptr [esi+ecx*4+2]
.text:00421EFA                 shr     eax, 4
.text:00421EFD                 add     eax, 41h
; EDX = правильный символ серийного номера
.text:00421F00                 cmp     edx, eax
; Не совпало, возврат с ошибкой
.text:00421F02                 jnz     short loc_421F0F
.text:00421F04                 inc     ecx
; Проверить 4 пары (8 символов серийного номера)
.text:00421F05                 cmp     ecx, 4
.text:00421F08                 jl      short loc_421EE0
.text:00421F0A                 mov     al, 1
.text:00421F0C                 pop     edi
.text:00421F0D                 pop     ecx
.text:00421F0E                 retn
.text:00421F0F ; ----------------------------------------------------
.text:00421F0F loc_421F0F:
.text:00421F0F                 xor     al, al
.text:00421F11                 pop     edi
.text:00421F12                 pop     ecx
.text:00421F13                 retn

Честно скажу, мне лениво разбирать процедуру получения проверочной строки из регистрационного имени. Поэтому ограничусь сниффингом правильного серийника под отладчиком. Для этого достаточно поставить точки останова по адресам 00421EF1 и 00421F00, ввести нужное имя и произвольный восьмизначный серийный номер, а затем за четыре прохода узнать все правильные символы. Так, для регистрационного имени "manhunter@pcl" регистрационный код будет "BCOFAFOK". Можно получить все символы и за один проход, достаточно в отладчике заменить условные переходы после сравнения символов на команды NOP. Проверим найденный серийный номер:


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

Все прекрасно работает. Точно так же вы можете подобрать серийный номер для любого другого имени. Но вариант с патчем тоже нельзя списывать со счетов, ведь в этом случае программа становится портативной.
Добавлено: 13 Сентября 2013 04:14:25 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...