Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот программы NTFS Streams Info
Скриншот программы NTFS Streams Info

Программа NTFS Streams Info предназначена для просмотра и редактирования альтернативных потоков NTFS. Не самый удобный инструмент, тот же NTFS Stream Explorer гораздо лучше и по возможностям, и по интерфейсу, да к тому же и бесплатный. Как бы то ни было, проект давно прекратил свое существование, на офсайте уже совсем другая информация. Хороший повод, чтобы потренироваться в некромантии и обратной инженерии.

В связи с закрытием разработки, ссылок на закачу на бывшем офсайте больше нет, но глобальный интернет-архив еще хранит данные о самой последней версии. Забираем оттуда дистрибутив, устанавливаем.

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

На ввод левого серийника программа реагирует характерным сообщением. Исполняемый файл ничем не упакован, поэтому отправим его в дизассемблер, а пока поищем строку сообщения.

Строка в файле
Строка в файле

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

Но запустить программу под отладчиком обычным способом не получается. На каждый чих она сыплет необрабатываемые исключения и при попытке запуска под отладчиком валится с ошибкой памяти, не доходя до проверки регистрации. Это срабатывает защита от взлома. Но на каждую хитрую жопу есть хуй с винтом, в нашем случае это возможность приаттачить отладчик к работающему процессу. Запускаем программу в обычном режиме, ждем появления окна регистрации. Аттачим отладчик к процессу и ставим точку останова на начало функции проверки. Отпускаем программу на выполнение. Теперь никаких исключений нет (пока что), после ввода серийника срабатывает точка останова и мы можем пройти все проверки в пошаговом режиме. Поехали.
  1. CODE:0049553D                 mov     eax, [ebp+var_8]
  2. CODE:00495540                 call    sub_404B44
  3. CODE:00495545                 cmp     eax, 13h
  4. CODE:00495548                 jz      short loc_495560
  5. CODE:0049554A                 mov     ecx, offset _str_Invalid_registr.Text
  6. CODE:0049554F                 mov     dl, 1
  7. CODE:00495551                 mov     eax, off_4953F0
Первая проверка. Длина серийного номера должна быть 13h (19 в десятичной системе) символов. И тут же первый сюрприз от разработчика: в каждое поле для ввода частей серийника помещается 5 символов, а согласно этой проверке должно быть 4 (4 группы по 4 символа + 3 разделителя = 19).
  1. CODE:0049559F                 mov     [ebp+var_1C], 1
  2. CODE:004955A6 loc_4955A6:
  3. CODE:004955A6                 lea     eax, [ebp+var_28]
  4. CODE:004955A9                 push    eax
  5. CODE:004955AA                 mov     ecx, 1
  6. CODE:004955AF                 mov     edx, [ebp+var_1C]
  7. CODE:004955B2                 mov     eax, [ebp+var_14]
  8. CODE:004955B5                 call    unknown_libname_592
  9. CODE:004955BA                 mov     eax, [ebp+var_28]
  10. CODE:004955BD                 movzx   eax, byte ptr [eax]
  11. CODE:004955C0                 add     [ebp+var_18], eax
  12. CODE:004955C3                 inc     [ebp+var_1C]
  13. CODE:004955C6                 cmp     [ebp+var_1C], 5
  14. CODE:004955CA                 jnz     short loc_4955A6
Суммируются 4 символа первого блока. В дальнейшем к этой сумме будут добавляться и другие части серийника, но всему свое время. Для удобства назовем эту сумму накопителем.
  1. CODE:004955E5                 mov     al, [eax]
  2. CODE:004955E7                 sub     al, 47h
  3. CODE:004955E9                 jz      short loc_49560D
  4. CODE:004955EB                 sub     al, 5
  5. CODE:004955ED                 jz      short loc_49560D
  6. CODE:004955EF                 sub     al, 6
  7. CODE:004955F1                 jz      short loc_49560D
  8. CODE:004955F3                 sub     al, 4
  9. CODE:004955F5                 jz      short loc_49560D
  10. CODE:004955F7                 mov     ecx, offset _str_Invalid_registr.Text
  11. CODE:004955FC                 mov     dl, 1
  12. CODE:004955FE                 mov     eax, off_407CF4
Начинается проверка первой группы. Второй символ должен иметь код 47h, (47h+5), (47h+5+6) или (47h+5+6+4), то есть "G", "L", "R", или "V".
  1. CODE:00495631                 mov     eax, [ebp+var_30]
  2. CODE:00495634                 mov     al, [eax]
  3. CODE:00495636                 cmp     al, 44h
  4. CODE:00495638                 jbe     short loc_4956A5
  5. CODE:0049563A                 lea     eax, [ebp+var_38]
  6. CODE:0049563D                 push    eax
  7. CODE:0049563E                 mov     ecx, 1
  8. CODE:00495643                 mov     edx, 4
  9. CODE:00495648                 mov     eax, [ebp+var_14]
  10. CODE:0049564B                 call    unknown_libname_592
  11. CODE:00495650                 mov     eax, [ebp+var_38]
  12. CODE:00495653                 mov     al, [eax]
  13. CODE:00495655                 cmp     al, 4Fh
  14. CODE:00495657                 jnb     short loc_4956A5
  15. CODE:00495659                 lea     eax, [ebp+var_3C]
  16. CODE:0049565C                 push    eax
  17. CODE:0049565D                 lea     eax, [ebp+var_40]
  18. CODE:00495660                 mov     edx, [ebp+var_14]
4-й символ первой группы должен находиться в интервале 45h..4Eh, то есть от "E" до "N".
  1. CODE:0049567D                 mov     eax, [ebp+var_3C]
  2. CODE:00495680                 mov     al, [eax]
  3. CODE:00495682                 cmp     al, 50h
  4. CODE:00495684                 jb      short loc_4956A5
  5. CODE:00495686                 lea     eax, [ebp+var_44]
  6. CODE:00495689                 push    eax
  7. CODE:0049568A                 mov     ecx, 1
  8. CODE:0049568F                 mov     edx, 3
  9. CODE:00495694                 mov     eax, [ebp+var_14]
  10. CODE:00495697                 call    unknown_libname_592
  11. CODE:0049569C                 mov     eax, [ebp+var_44]
  12. CODE:0049569F                 mov     al, [eax]
  13. CODE:004956A1                 cmp     al, 59h
  14. CODE:004956A3                 jbe     short loc_4956BD
3-й символ первой группы должен находиться в интервале 50h..59h, то есть от "P" до "Y".
  1. CODE:004956EC                 push    offset loc_495929
  2. CODE:004956F1                 push    dword ptr fs:[eax]
  3. CODE:004956F4                 mov     fs:[eax], esp
  4. CODE:004956F7                 lea     ecx, [ebp+var_14]
  5. CODE:004956FA                 mov     edx, [ebp+var_C]
  6. CODE:004956FD                 sub     edx, 42h
  7. CODE:00495700                 mov     eax, [ebp+var_10]
  8. CODE:00495703                 mov     ebx, [eax]
  9. CODE:00495705                 call    dword ptr [ebx+0Ch]
  10. CODE:00495708                 mov     [ebp+var_1C], 1
1-й символ серийника проверяется очень замысловато: из его кода вычитается 42h, затем выполняется какая-то операция типа чтения из памяти, которая при попытке трассировки под отладчиком выбрасывает исключение, если значение получилось отрицательным. То есть код первого символа должен быть 43h и больше, например, символ "С".
  1. CODE:00495750                 mov     bl, [eax]
  2. CODE:00495752                 lea     eax, [ebp+var_58]
  3. CODE:00495755                 push    eax
  4. CODE:00495756                 mov     ecx, 1
  5. CODE:0049575B                 mov     edx, 1
  6. CODE:00495760                 mov     eax, [ebp+var_14]
  7. CODE:00495763                 call    unknown_libname_592
  8. CODE:00495768                 mov     eax, [ebp+var_58]
  9. CODE:0049576B                 movzx   eax, byte ptr [eax]
  10. CODE:0049576E                 add     eax, 6
  11. CODE:00495771                 cmp     ebx, eax
  12. CODE:00495773                 jnz     short loc_4957C3
  13. CODE:00495775                 lea     eax, [ebp+var_5C]
  14. CODE:00495778                 push    eax
Проверяем вторую группу серийника. 3-й символ второй группы должен равняться первому + 6.
  1. CODE:0049579C                 mov     dl, [edx+1]
  2. CODE:0049579F                 call    unknown_libname_77
  3. CODE:004957A4                 mov     eax, [ebp+var_64]
  4. CODE:004957A7                 mov     ecx, 1
  5. CODE:004957AC                 mov     edx, 1
  6. CODE:004957B1                 call    unknown_libname_592
  7. CODE:004957B6                 mov     eax, [ebp+var_60]
  8. CODE:004957B9                 movzx   eax, byte ptr [eax]
  9. CODE:004957BC                 add     eax, 2
  10. CODE:004957BF                 cmp     ebx, eax
  11. CODE:004957C1                 jz      short loc_4957DB
4-й символ второй группы должен равняться второму + 2.
  1. CODE:00495708                 mov     [ebp+var_1C], 1
  2. CODE:0049570F loc_49570F:
  3. CODE:0049570F                 lea     eax, [ebp+var_50]
  4. CODE:00495712                 push    eax
  5. CODE:00495713                 mov     ecx, 1
  6. CODE:00495718                 mov     edx, [ebp+var_1C]
  7. CODE:0049571B                 mov     eax, [ebp+var_14]
  8. CODE:0049571E                 call    unknown_libname_592
  9. CODE:00495723                 mov     eax, [ebp+var_50]
  10. CODE:00495726                 movzx   eax, byte ptr [eax]
  11. CODE:00495729                 add     [ebp+var_18], eax
  12. CODE:0049572C                 inc     [ebp+var_1C]
  13. CODE:0049572F                 cmp     [ebp+var_1C], 5
  14. CODE:00495733                 jnz     short loc_49570F
К накопителю поочередно прибавляется вторая группа символов серийника.
  1. CODE:004957F0                 mov     [ebp+var_1C], 1
  2. CODE:004957F7 loc_4957F7:
  3. CODE:004957F7                 lea     eax, [ebp+var_68]
  4. CODE:004957FA                 push    eax
  5. CODE:004957FB                 lea     eax, [ebp+var_6C]
  6. CODE:004957FE                 mov     edx, [ebp+var_14]
  7. CODE:00495801                 mov     ecx, [ebp+var_1C]
  8. CODE:00495804                 mov     dl, [edx+ecx-1]
  9. CODE:00495808                 call    unknown_libname_77
  10. CODE:0049580D                 mov     eax, [ebp+var_6C]
  11. CODE:00495810                 mov     ecx, 1
  12. CODE:00495815                 mov     edx, 1
  13. CODE:0049581A                 call    unknown_libname_592
  14. CODE:0049581F                 mov     eax, [ebp+var_68]
  15. CODE:00495822                 movzx   eax, byte ptr [eax]
  16. CODE:00495825                 add     [ebp+var_18], eax
  17. CODE:00495828                 inc     [ebp+var_1C]
  18. CODE:0049582B                 cmp     [ebp+var_1C], 5
  19. CODE:0049582F                 jnz     short loc_4957F7
Третья группа вообще никак не проверяется, просто прибавляется к накопителю. Тут могут быть любые символы.
  1. CODE:0049584A                 mov     edx, 3
  2. CODE:0049584F                 mov     eax, [ebp+var_14]
  3. CODE:00495852                 call    unknown_libname_592
  4. CODE:00495857                 mov     eax, [ebp+var_70]
  5. CODE:0049585A                 movzx   eax, byte ptr [eax]
  6. CODE:0049585D                 add     [ebp+var_18], eax
  7. CODE:00495860                 lea     eax, [ebp+var_74]
  8. CODE:00495863                 push    eax
  9. CODE:00495864                 mov     ecx, 1
  10. CODE:00495869                 mov     edx, 1
  11. CODE:0049586E                 mov     eax, [ebp+var_14]
  12. CODE:00495871                 call    unknown_libname_592
  13. CODE:00495876                 mov     eax, [ebp+var_74]
  14. CODE:00495879                 movzx   eax, byte ptr [eax]
  15. CODE:0049587C                 add     [ebp+var_18], eax
Переходим к четветой, последней группе серийного номера. К накопителю прибавляется первый и третий символ группы.
  1. CODE:0049587F                 mov     eax, [ebp+var_18]
  2. CODE:00495882                 mov     ecx, 0Ah
  3. CODE:00495887                 cdq
  4. CODE:00495888                 idiv    ecx
  5. CODE:0049588A                 mov     [ebp+var_20], edx
  6. ...
  7. ...
  8. CODE:004958BB                 mov     eax, [ebp+var_78]
  9. CODE:004958BE                 movzx   eax, byte ptr [eax]
  10. CODE:004958C1                 mov     edx, [ebp+var_20]
  11. CODE:004958C4                 add     edx, 41h
  12. CODE:004958C7                 cmp     eax, edx
  13. CODE:004958C9                 jnz     short loc_4958F1
Накопитель делится на 10, к остатку прибавляется 41h. Четвертый символ последней группы должен равняться этому результату.
  1. CODE:0049588D                 mov     eax, [ebp+var_18]
  2. CODE:00495890                 mov     ecx, 64h
  3. CODE:00495895                 cdq
  4. CODE:00495896                 idiv    ecx
  5. CODE:00495898                 mov     eax, edx
  6. CODE:0049589A                 mov     ecx, 0Ah
  7. CODE:0049589F                 cdq
  8. CODE:004958A0                 idiv    ecx
  9. CODE:004958A2                 mov     [ebp+var_24], eax
  10. ...
  11. ...
  12. CODE:004958E1                 mov     eax, [ebp+var_7C]
  13. CODE:004958E4                 movzx   eax, byte ptr [eax]
  14. CODE:004958E7                 mov     edx, [ebp+var_24]
  15. CODE:004958EA                 add     edx, 41h
  16. CODE:004958ED                 cmp     eax, edx
  17. CODE:004958EF                 jz      short loc_495909
Накопитель делится на 100, остаток делится на 10, к финальному частному прибавляется 41h. Второй символ последней группы должен равняться этому результату.

После каждой проваленной проверки под отладчиком программа кидает исключение и фатально падает с ошибкой чтения памяти. Так что приходится опять ее запускать, аттачить отладчик, переходить на точку останова в функции проверки... То еще удовольствие. Автор хорошо потрудился, действительно творчески подойдя к системе проверики регистрации.

Вооружившися калькулятором, можно подсчитать правильный серийник по описанному алгоритму. Например, валидным серийником должен быть "CGQE-0062-PCLX-MEHI". Проверим. Вводим серийник на запрос программы, никаких сообщений о неправильной регистрации не появляется, сразу открывается главное окно программы. Выходим. Снова запускаем. На этот раз о регистрации ни слова, программа сразу работает как надо. Цель достигнута. Кейген вы можете написать самостоятельно.

Поделиться ссылкой ВКонтакте
Просмотров: 2451 | Комментариев: 5

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
user (27.02.2024 в 11:06):
;-----------------------------NTFFSI.CRK file
NTFS Streams info 2.1

Set licensed
NTFSInfo.exe
.0049550C: 55 B8 ;0009490C:
.0049550D: 8B 02 ;0009490D:
.0049550E: EC 00 ;0009490E:
.0049550F: B9 00 ;0009490F:
.00495510: 0F 00 ;00094910:
.00495511: 00 C3 ;00094911:
;-----------------------------NTFFSI.CRK file END
ManHunter (22.02.2017 в 12:56):
По ссылке страница архива, там снапшот за 24 ноября. Или так можно попробовать: http://web.archive.org/web/200...nfoSetup.exe
Хз, напрямую даст скачать или нет.
user1 (22.02.2017 в 12:43):
Дистрибутив не качается.
ManHunter (21.02.2017 в 14:49):
Конечно можно, например, во всех проверках поменять условные переходы на безусловные, хотя при броске эксепшена на проверке 1-го символа серийника это все равно не поможет. Всегда приятно видеть творческий подход к программированию, а не тупое нагромождение готовых компонентов.
wet (21.02.2017 в 14:42):
ЦитатаАвтор хорошо потрудился, действительно творчески подойдя к системе проверики регистрации.

А смысл? Неспортивные методы тоже ни кто не отменял! Наверняка, если прога не защищена протектором, можно где то поменять переход или прыгнуть куда надо, что бы любой серийник считался валидным?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0044 сек.) / Память: 4.5 Mb
Наверх