Исследование защиты программы LogViewer
Скриншот программы LogViewer
Программа LogViewer предназначена для просмотра файлов логов. Работает очень шустро, поддерживает огромные файлы даже от 4 гигов, отслеживает последние изменения в реальном времени, подсвечивает строки по сигнатурам, портативная, да и вообще полезный инструмент для системных администраторов. Без регистрации при запуске выводит напоминание о необходимости покупки и ограничивает количество активных вкладок.
Забираем с офсайта дистрибутив, распаковываем куда-нибудь. Программа, как я уже говорил, портативная и не требует установки. А вот и триальное окно.
Триальное окно
Кроме этого в заголовке обнаруживается приметная надпись "Unregistered", тоже хорошая зацепка. Исполняемый файл ничем не упакован, отправляем его в дизассемблер.
Строка в файле
Строка легко обнаруживается поиском по файлу. Переходим в дизассемблер и смотрим, при каких условиях она появляется.
Code (Assembler) : Убрать нумерацию
- CODE:252C8C41 lea edx, [ebp+var_5]
- CODE:252C8C44 lea eax, [ebp+var_4]
- ; Вызвать функцию проверки
- CODE:252C8C47 call sub_252C8AF0
- ; Сохранить ее результат
- CODE:252C8C4C mov ds:byte_252E0BA8, al
- ; Проверить результат
- CODE:252C8C51 cmp ds:byte_252E0BA8, 0
- ; Программа работает в триальном режиме
- CODE:252C8C58 jz short loc_252C8C6E
- CODE:252C8C5A mov eax, offset unk_252E3094
- CODE:252C8C5F mov ecx, [ebp+var_4]
- CODE:252C8C62 mov edx, offset dword_252C8CA8
- CODE:252C8C67 call sub_25204968
- CODE:252C8C6C jmp short loc_252C8C7D
- CODE:252C8C6E ; ----------------------------------------------------------------
- CODE:252C8C6E loc_252C8C6E:
- ; Дописать в заголовок строку " - Unregistered"
- CODE:252C8C6E mov eax, offset unk_252E3094
- CODE:252C8C73 mov edx, offset aUnregistered
- ; " - Unregistered"
- CODE:252C8C78 call sub_252046A0
- CODE:252C8C7D
Code (Assembler) : Убрать нумерацию
- CODE:252C8AF0 sub_252C8AF0 proc near
- CODE:252C8AF0 push ebp
- CODE:252C8AF1 mov ebp, esp
- CODE:252C8AF3 xor ecx, ecx
- CODE:252C8AF5 push ecx
- CODE:252C8AF6 push ecx
- CODE:252C8AF7 push ecx
- CODE:252C8AF8 push ecx
- CODE:252C8AF9 push ecx
- CODE:252C8AFA push ecx
- CODE:252C8AFB push ebx
- CODE:252C8AFC push esi
- CODE:252C8AFD push edi
- CODE:252C8AFE mov [ebp+var_4], edx
- CODE:252C8B01 mov esi, eax
- CODE:252C8B03 xor eax, eax
- CODE:252C8B05 push ebp
- CODE:252C8B06 push offset loc_252C8BDC
- CODE:252C8B0B push dword ptr fs:[eax]
- CODE:252C8B0E mov fs:[eax], esp
- CODE:252C8B11 xor ebx, ebx
- CODE:252C8B13 mov eax, esi
- CODE:252C8B15 call sub_2520464C
- CODE:252C8B1A mov eax, [ebp+var_4]
- CODE:252C8B1D mov byte ptr [eax], 0
- CODE:252C8B20 lea edx, [ebp+var_18]
- CODE:252C8B23 mov eax, ds:off_252E0F50
- CODE:252C8B28 mov eax, [eax]
- CODE:252C8B2A call sub_2526D39C
- CODE:252C8B2F mov eax, [ebp+var_18]
- CODE:252C8B32 lea edx, [ebp+var_14]
- CODE:252C8B35 call sub_25209C88
- CODE:252C8B3A mov edx, [ebp+var_14]
- CODE:252C8B3D lea eax, [ebp+var_8]
- ; Проверить наличие файла
- CODE:252C8B40 mov ecx, offset aKey_txt ; "\\Key.txt"
- CODE:252C8B45 call sub_25204968
- CODE:252C8B4A mov eax, [ebp+var_8]
- CODE:252C8B4D call sub_25209B28
- CODE:252C8B52 test al, al
- CODE:252C8B54 jz short loc_252C8BC1
- CODE:252C8B56 mov ecx, [ebp+var_8]
- CODE:252C8B59 mov dl, 1
- CODE:252C8B5B mov eax, off_25286B64
- CODE:252C8B60 call sub_25286C14
- CODE:252C8B65 mov ebx, eax
- CODE:252C8B67 push 0
- CODE:252C8B69 lea eax, [ebp+var_C]
- CODE:252C8B6C push eax
- CODE:252C8B6D mov ecx, offset aName ; "Name"
- CODE:252C8B72 mov edx, offset aKey ; "Key"
- CODE:252C8B77 mov eax, ebx
- CODE:252C8B79 mov edi, [eax]
- ; Неявный вызов GetPrivateProfileStringA
- CODE:252C8B7B call dword ptr [edi]
- CODE:252C8B7D push 0
- CODE:252C8B7F lea eax, [ebp+var_10]
- CODE:252C8B82 push eax
- CODE:252C8B83 mov ecx, offset aStr ; "Str"
- CODE:252C8B88 mov edx, offset aKey ; "Key"
- CODE:252C8B8D mov eax, ebx
- CODE:252C8B8F mov edi, [eax]
- ; Неявный вызов GetPrivateProfileStringA
- CODE:252C8B91 call dword ptr [edi]
- CODE:252C8B93 mov eax, ebx
- CODE:252C8B95 call sub_252037C0
- CODE:252C8B9A mov edx, [ebp+var_10]
- CODE:252C8B9D mov eax, [ebp+var_C]
- ; Вызов функции проверки регистрации
- CODE:252C8BA0 call sub_252C88A4
- CODE:252C8BA5 mov ebx, eax
- CODE:252C8BA7 test bl, bl
- CODE:252C8BA9 jz short loc_252C8BC1
- CODE:252C8BAB mov eax, esi
- CODE:252C8BAD mov edx, [ebp+var_C]
- CODE:252C8BB0 call sub_252046A0
- CODE:252C8BB5 mov eax, esi
- CODE:252C8BB7 call sub_252C8AA8
- CODE:252C8BBC mov edx, [ebp+var_4]
- CODE:252C8BBF mov [edx], al
- CODE:252C8BC1 loc_252C8BC1:
- CODE:252C8BC1 xor eax, eax
- CODE:252C8BC3 pop edx
- CODE:252C8BC4 pop ecx
- CODE:252C8BC5 pop ecx
- CODE:252C8BC6 mov fs:[eax], edx
- CODE:252C8BC9 push offset loc_252C8BE3
- CODE:252C8BCE loc_252C8BCE:
- CODE:252C8BCE lea eax, [ebp+var_18]
- CODE:252C8BD1 mov edx, 5
- CODE:252C8BD6 call sub_25204670
- CODE:252C8BDB retn
- CODE:252C8BDC ; --------------------------------------
- CODE:252C8BDC loc_252C8BDC:
- CODE:252C8BDC jmp loc_25203F68
- CODE:252C8BE1 ; --------------------------------------
- CODE:252C8BE1 jmp short loc_252C8BCE
- CODE:252C8BE3 ; --------------------------------------
- CODE:252C8BE3 loc_252C8BE3:
- CODE:252C8BE3 mov eax, ebx
- CODE:252C8BE5 pop edi
- CODE:252C8BE6 pop esi
- CODE:252C8BE7 pop ebx
- CODE:252C8BE8 mov esp, ebp
- CODE:252C8BEA pop ebp
- CODE:252C8BEB retn
- CODE:252C8BEB sub_252C8AF0 endp
Программа успешно "зарегистрирована"
Триальное окно пропало, в заголовке окна больше не показывается "Unregistered", в окне "О программе" отображается бизнес-лицензия, а главное, больше нет ограничений по функционалу. В принципе, цель достигнута. Но можно сделать все красиво, то есть добиться корректной регистрации. Если посмотреть функцию проверки, то там, во-первых, проверяется наличие файла "Key.txt", а во-вторых, из него читаются данные регистрации. Функции чтения данных вызываются неявно, но если посмотреть под отладчикам, то все сводится к обычному вызову GetPrivateProfileStringA. Это значит, что файл "Key.txt" имеет структуру ini-файла с секцией [Key] и параметрами Name и Str. Открываем блокнотик и создаем в нем этот файл, после чего возвращаемся к логу дизассемблера. После чтения из файла регистрационных данных по адресу 252C8BA0 вызывается следующая функция проверки, результат которой влияет на возвращаемое значение. Она тоже не такая большая, приведу ее полностью.
Code (Assembler) : Убрать нумерацию
- CODE:252C88A4 sub_252C88A4 proc near
- CODE:252C88A4 push ebp
- CODE:252C88A5 mov ebp, esp
- CODE:252C88A7 xor ecx, ecx
- CODE:252C88A9 push ecx
- CODE:252C88AA push ecx
- CODE:252C88AB push ecx
- CODE:252C88AC push ecx
- CODE:252C88AD push ecx
- CODE:252C88AE push ebx
- CODE:252C88AF mov [ebp+var_8], edx
- CODE:252C88B2 mov [ebp+var_4], eax
- CODE:252C88B5 mov eax, [ebp+var_4]
- CODE:252C88B8 call sub_25204B0C
- CODE:252C88BD mov eax, [ebp+var_8]
- CODE:252C88C0 call sub_25204B0C
- CODE:252C88C5 xor eax, eax
- CODE:252C88C7 push ebp
- CODE:252C88C8 push offset loc_252C89A4
- CODE:252C88CD push dword ptr fs:[eax]
- CODE:252C88D0 mov fs:[eax], esp
- CODE:252C88D3 lea eax, [ebp+var_4]
- CODE:252C88D6 call sub_252C87F4
- CODE:252C88DB mov eax, [ebp+var_8]
- ; Получить длину серийника
- CODE:252C88DE call sub_2520491C
- CODE:252C88E3 cmp eax, 0Eh
- CODE:252C88E6 jnz short loc_252C88FA
- ; Проверить наличие символов "-" на указанных позициях
- CODE:252C88E8 mov eax, [ebp+var_8]
- CODE:252C88EB cmp byte ptr [eax+4], 2Dh
- CODE:252C88EF jnz short loc_252C88FA
- CODE:252C88F1 mov eax, [ebp+var_8]
- CODE:252C88F4 cmp byte ptr [eax+9], 2Dh
- CODE:252C88F8 jz short loc_252C88FE
- CODE:252C88FA loc_252C88FA:
- CODE:252C88FA xor ebx, ebx
- CODE:252C88FC jmp short loc_252C8900
- CODE:252C88FE ; --------------------------------------
- CODE:252C88FE loc_252C88FE:
- CODE:252C88FE mov bl, 1
- CODE:252C8900 loc_252C8900:
- CODE:252C8900 test bl, bl
- CODE:252C8902 jz loc_252C8989
- CODE:252C8908 push ebp
- CODE:252C8909 lea eax, [ebp+var_C]
- CODE:252C890C push eax
- CODE:252C890D mov ecx, 4
- CODE:252C8912 mov edx, 1
- CODE:252C8917 mov eax, [ebp+var_8]
- CODE:252C891A call sub_25204B7C
- CODE:252C891F mov eax, [ebp+var_C]
- ; Контрольное значение для первой части серийника
- CODE:252C8922 mov edx, 1
- ; Проверить первую часть серийника
- CODE:252C8927 call sub_252C8864
- CODE:252C892C pop ecx
- CODE:252C892D test al, al
- CODE:252C892F jz short loc_252C8983
- CODE:252C8931 push ebp
- CODE:252C8932 lea eax, [ebp+var_10]
- CODE:252C8935 push eax
- CODE:252C8936 mov ecx, 4
- CODE:252C893B mov edx, 6
- CODE:252C8940 mov eax, [ebp+var_8]
- CODE:252C8943 call sub_25204B7C
- CODE:252C8948 mov eax, [ebp+var_10]
- ; Контрольное значение для второй части серийника
- CODE:252C894B mov edx, 2
- ; Проверить вторую часть серийника
- CODE:252C8950 call sub_252C8864
- CODE:252C8955 pop ecx
- CODE:252C8956 test al, al
- CODE:252C8958 jz short loc_252C8983
- CODE:252C895A push ebp
- CODE:252C895B lea eax, [ebp+var_14]
- CODE:252C895E push eax
- CODE:252C895F mov ecx, 4
- CODE:252C8964 mov edx, 0Bh
- CODE:252C8969 mov eax, [ebp+var_8]
- CODE:252C896C call sub_25204B7C
- CODE:252C8971 mov eax, [ebp+var_14]
- ; Контрольное значение для третьей части серийника
- CODE:252C8974 mov edx, 3
- ; Проверить третью часть серийника
- CODE:252C8979 call sub_252C8864
- CODE:252C897E pop ecx
- CODE:252C897F test al, al
- CODE:252C8981 jnz short loc_252C8987
- CODE:252C8983 loc_252C8983:
- CODE:252C8983 xor ebx, ebx
- CODE:252C8985 jmp short loc_252C8989
- CODE:252C8987 ; --------------------------------------
- CODE:252C8987 loc_252C8987:
- CODE:252C8987 mov bl, 1
- CODE:252C8989 loc_252C8989:
- CODE:252C8989 xor eax, eax
- CODE:252C898B pop edx
- CODE:252C898C pop ecx
- CODE:252C898D pop ecx
- CODE:252C898E mov fs:[eax], edx
- CODE:252C8991 push offset loc_252C89AB
- CODE:252C8996 loc_252C8996:
- CODE:252C8996 lea eax, [ebp+var_14]
- CODE:252C8999 mov edx, 5
- CODE:252C899E call sub_25204670
- CODE:252C89A3 retn
- CODE:252C89A4 ; --------------------------------------
- CODE:252C89A4 loc_252C89A4:
- CODE:252C89A4 jmp loc_25203F68
- CODE:252C89A9 ; --------------------------------------
- CODE:252C89A9 jmp short loc_252C8996
- CODE:252C89AB ; --------------------------------------
- CODE:252C89AB loc_252C89AB:
- CODE:252C89AB mov eax, ebx
- CODE:252C89AD pop ebx
- CODE:252C89AE mov esp, ebp
- CODE:252C89B0 pop ebp
- CODE:252C89B1 retn
- CODE:252C89B1 sub_252C88A4 endp
Code (Assembler) : Убрать нумерацию
- CODE:252C8864 sub_252C8864 proc near
- CODE:252C8864 push ebp
- CODE:252C8865 mov ebp, esp
- CODE:252C8867 push ebx
- CODE:252C8868 push esi
- CODE:252C8869 mov esi, edx
- CODE:252C886B mov ebx, eax
- CODE:252C886D mov eax, [ebp+arg_0]
- CODE:252C8870 mov eax, [eax-4]
- CODE:252C8873 mov edx, esi
- ; Манипуляции с регистрационным именем
- CODE:252C8875 call sub_252C8768
- CODE:252C887A push eax
- CODE:252C887B xor eax, eax
- ; Просуммировать символы фрагмента серийника
- CODE:252C887D mov al, [ebx]
- CODE:252C887F xor edx, edx
- CODE:252C8881 mov dl, [ebx+1]
- CODE:252C8884 add eax, edx
- CODE:252C8886 xor edx, edx
- CODE:252C8888 mov dl, [ebx+2]
- CODE:252C888B add eax, edx
- CODE:252C888D xor edx, edx
- CODE:252C888F mov dl, [ebx+3]
- CODE:252C8892 add eax, edx
- CODE:252C8894 pop edx
- ; Разделить на число из регистрационного имени
- CODE:252C8895 mov ecx, edx
- CODE:252C8897 cdq
- CODE:252C8898 idiv ecx
- CODE:252C889A inc esi
- ; Сравнить полученный результат с контрольным значением
- CODE:252C889B cmp edx, esi
- CODE:252C889D setz al
- CODE:252C88A0 pop esi
- CODE:252C88A1 pop ebx
- CODE:252C88A2 pop ebp
- CODE:252C88A3 retn
- CODE:252C88A3 sub_252C8864 endp
Аналогичным образом подбираем нужные значения для второго и третьего фрагмента серийника. После этого приводим содержимое файла Key.txt к виду
[Key]
Name=ManHunter / PCL
Str=1112-1116-1111
Запускаем программу и смотрим, что получилось. Тут приведен серийник для моего регистрационного имени, у вас он, естественно, будет другой.
Программа успешно зарегистрирована
Вот теперь цель достигнута окончательно. Программа зарегистрирована валидным ключом, никаких ограничений нет, в заголовке и в окне "О программе" красуется регистрационное имя. Только тип лицензии снизился до персональной, но это я как-нибудь переживу.
Просмотров: 1032 | Комментариев: 4
Метки: исследование защиты
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(25.01.2023 в 10:45):
Тут релоков нет, поставил флаг в заголовке и все работает.
pawel97
(25.01.2023 в 07:55):
И поломается файл, ибо релоки применяются, если система грузит его не по своему адресу. Но вопрос же не в этом, просто факт интересный и для чего-то сделано.
А бизнес или сайтовую лицензию можно получить, просто добавив в имя [B] или [S]
А бизнес или сайтовую лицензию можно получить, просто добавив в имя [B] или [S]
ManHunter
(24.01.2023 в 23:22):
В заголовке перебить на 400000h и все
pawel97
(24.01.2023 в 22:56):
Вот сколько файлов перековырял под 32 и 64 бита, ImageBase 25200000h ещё не встречал.
Добавить комментарий
Заполните форму для добавления комментария