Blog. Just Blog

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

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

Программа MD5 Tool предназначена для подсчета и проверки контрольной суммы MD5 файлов. Есть множество бесплатных и гораздо более мощных аналогов, поэтому мне очень странно, что за эту софтину аффтар пытается подрезать с пользователей по червонцу баксов. "И его посчитаем".

На сайте есть два дистрибутива, нас интересует полная версия. Скачиваем, устанавливаем, запускаем. Без ввода правильного серийника эта версия отказывается даже запускаться.

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

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

Текст сообщения
Текст сообщения

Файл небольшой, дизассемблер закончил работу за несколько секунд, теперь мы можем посмотреть условия срабатывания защиты и код, где используется строка сообщения о неправильной регистрации.
  1. .text:0040AB43                 lea     ecx, [esp+850h+var_838]
  2. .text:0040AB47                 lea     edx, [esp+850h+Str1]
  3. .text:0040AB4B                 push    ecx             ; int
  4. .text:0040AB4C                 push    edx             ; Str1
  5. .text:0040AB4D                 mov     byte ptr [esp+858h+var_4], 1
  6. ; Вызвать функцию проверки
  7. .text:0040AB55                 call    sub_40AD20
  8. .text:0040AB5A                 add     esp, 8
  9. .text:0040AB5D                 lea     ecx, [esp+850h+Str1]
  10. ; Сохранить ее результат из регистра EAX в регистр EDI
  11. .text:0040AB61                 mov     edi, eax
  12. .text:0040AB63                 mov     byte ptr [esp+850h+var_4], 0
  13. .text:0040AB6B                 call    sub_45AB88
  14. .text:0040AB70                 or      ebp, 0FFFFFFFFh
  15. .text:0040AB73                 lea     ecx, [esp+850h+var_838]
  16. .text:0040AB77                 mov     [esp+850h+var_4], ebp
  17. .text:0040AB7E                 call    sub_45AB88
  18. ; Результат проверки = 0?
  19. .text:0040AB83                 test    edi, edi
  20. .text:0040AB85                 pop     edi
  21. ; Да, значит введенный серийник неправильный
  22. .text:0040AB86                 jz      short loc_40AC07
  23. .text:0040AB88                 lea     eax, [esp+84Ch+Src]
  24. .text:0040AB8C                 lea     ecx, [esp+84Ch+var_83C]
  25. .text:0040AB90                 push    eax             ; Src
  26. .text:0040AB91                 mov     dword_475A98, 1
  27. .text:0040AB9B                 call    sub_45ABFC
  28. .text:0040ABA0                 lea     ecx, [esp+84Ch+String]
  29. .text:0040ABA4                 mov     [esp+84Ch+var_4], 2
  30. .text:0040ABAF                 push    ecx             ; Src
  31. .text:0040ABB0                 lea     ecx, [esp+850h+var_840]
  32. .text:0040ABB4                 call    sub_45ABFC
  33. ; Сохранить регистрацию в реестре и закрыть окно ввода серийника
  34. .text:0040ABB9                 lea     edx, [esp+84Ch+var_83C]
  35. .text:0040ABBD                 lea     eax, [esp+84Ch+var_840]
  36. .text:0040ABC1                 push    edx             ; int
  37. .text:0040ABC2                 push    eax             ; int
  38. .text:0040ABC3                 push    offset dword_475A90 ; lpSubKey
  39. .text:0040ABC8                 mov     byte ptr [esp+858h+var_4], 3
  40. .text:0040ABD0                 call    sub_40B780
  41. .text:0040ABD5                 add     esp, 0Ch
  42. .text:0040ABD8                 lea     ecx, [esp+84Ch+var_840]
  43. .text:0040ABDC                 mov     byte ptr [esp+84Ch+var_4], 2
  44. .text:0040ABE4                 call    sub_45AB88
  45. .text:0040ABE9                 lea     ecx, [esp+84Ch+var_83C]
  46. .text:0040ABED                 mov     [esp+84Ch+var_4], ebp
  47. .text:0040ABF4                 call    sub_45AB88
  48. .text:0040ABF9                 push    0               ; nResult
  49. .text:0040ABFB                 push    esi             ; hDlg
  50. .text:0040ABFC                 call    ds:EndDialog
  51. .text:0040AC02                 jmp     loc_40AC99
  52. .text:0040AC07 ; ---------------------------------------------------
  53. .text:0040AC07 loc_40AC07:
  54. ; Сообщение о неправильной регистрации
  55. .text:0040AC07                 mov     ecx, off_46F018
  56. .text:0040AC0D                 mov     [esp+84Ch+lpText], ecx
  57. .text:0040AC11                 mov     edx, lpFile
  58. .text:0040AC17                 lea     eax, [esp+84Ch+lpText]
  59. .text:0040AC1B                 push    edx             ; int
  60. .text:0040AC1C                 push    offset aTheUnlockCodeY
  61. ; "The Unlock Code you have provided is no"...
  62. .text:0040AC21                 push    eax             ; int
  63. .text:0040AC22                 mov     [esp+858h+var_4], 4
  64. .text:0040AC2D                 call    sub_455E06
  65. .text:0040AC32                 mov     ecx, [esp+858h+lpText]
  66. .text:0040AC36                 add     esp, 0Ch
  67. .text:0040AC39                 push    14h             ; uType
  68. .text:0040AC3B                 push    offset Caption  ; "Code not valid"
  69. .text:0040AC40                 push    ecx             ; lpText
  70. .text:0040AC41                 push    0               ; hWnd
  71. .text:0040AC43                 call    ds:MessageBoxW
  72. .text:0040AC49                 cmp     eax, 6
Тут проверка немного размазана по коду, похоже на старания оптимизатора при компиляции исходника. Я прокомментировал все строки кода, которые имеют отношение к защите. Посмотрим функцию проверки серийника:
  1. .text:0040AD20 sub_40AD20      proc near
  2. .text:0040AD20                 mov     eax, dword_475A94
  3. .text:0040AD25                 mov     ecx, [esp+Str1]
  4. .text:0040AD29                 push    esi
  5. .text:0040AD2A                 push    eax
  6. .text:0040AD2B                 lea     edx, [esp+8+Str1]
  7. .text:0040AD2F                 push    ecx
  8. .text:0040AD30                 push    edx
  9. .text:0040AD31                 call    sub_40AE20
  10. .text:0040AD36                 mov     eax, [esp+10h+arg_4]
  11. .text:0040AD3A                 mov     ecx, [esp+10h+Str1]
  12. .text:0040AD3E                 mov     eax, [eax]
  13. ; Сравнить две строчки
  14. .text:0040AD40                 push    eax             ; Str2
  15. .text:0040AD41                 push    ecx             ; Str1
  16. .text:0040AD42                 call    _wcscmp
  17. .text:0040AD47                 add     esp, 14h
  18. .text:0040AD4A                 lea     ecx, [esp+4+Str1]
  19. ; Если они равны, то EAX=0
  20. .text:0040AD4E                 test    eax, eax
  21. ; Соответственно, DL станет = 1
  22. .text:0040AD50                 setz    dl
  23. .text:0040AD53                 and     edx, 0FFh
  24. .text:0040AD59                 mov     esi, edx
  25. .text:0040AD5B                 call    sub_45AB88
  26. ; И при успешном сравнении на выходе EAX=1
  27. .text:0040AD60                 mov     eax, esi
  28. .text:0040AD62                 pop     esi
  29. .text:0040AD63                 retn
  30. .text:0040AD63 sub_40AD20      endp
При таком раскладе применять патч даже не поднимается рука, но все-таки. Если записать пару команд MOV EAX,1 и RET по адресу 0040AD20, то программа для регистрации будет принимать любой серийник и считать его правильным. На этом с хирургическими методами закончили, переходим в отладчик. Как вы поняли по коду, в нем сравниваются две строки и на основании результатов сравнения выносится вердикт о правильности серийника. Отлично, ставим в отладчике точку останова по адресу 0040AD42 и попробуем зарегистрировать программу с любым левым серийником.

Правильный серийный номер в стеке
Правильный серийный номер в стеке

Что мы видим в отладчике при срабатывании точки останова? На вершине стека перед вызовом функции сравнения лежит наш левый серийник и еще какая-то строка, с которой он сравнивается. В моем случае для введенного имени "ManHunter / PCL" эта строка будет "8CF1C5A4BBB3108F". Не надо быть семи пядей во лбу, чтобы догадаться, что это и есть правильный серийный номер. Перезапускаем программу и пробуем зарегистрироваться с найденной парой имя-серийник. На этот раз сообщение о неправильной регистрации не появляется, окно регистрации закрывается и запускается основное рабочее окно MD5 Tool. При последующем запуске регистрация не слетает, значит мы все сделали правильно.

Осталось забить последний гвоздь в гроб буржуазии и попробовать разобрать алгоритм генерации и, соответственно, проверки серийного номера. Функция генерации проверочной строки не очень большая, приведу прокомментированный листинг целиком. Чтобы было понятнее, эту функцию надо исследовать параллельно в отладчике и дизассемблере.
  1. .text:0040AE20                 push    0FFFFFFFFh
  2. .text:0040AE22                 push    offset SEH_40AE20
  3. .text:0040AE27                 mov     eax, large fs:0
  4. .text:0040AE2D                 push    eax
  5. .text:0040AE2E                 mov     large fs:0, esp
  6. .text:0040AE35                 sub     esp, 8Ch
  7. .text:0040AE3B                 xor     eax, eax
  8. .text:0040AE3D                 push    esi
  9. .text:0040AE3E                 mov     [esp+9Ch+var_84], 0
  10. .text:0040AE46                 push    edi
  11. .text:0040AE47                 mov     edi, [esp+0A0h+arg_4]
  12. .text:0040AE4E                 mov     [esp+0A0h+var_97], eax
  13. .text:0040AE52                 mov     [esp+0A0h+var_93], eax
  14. .text:0040AE56                 mov     [esp+0A0h+var_98], 0
  15. .text:0040AE5B                 mov     ecx, [edi]
  16. .text:0040AE5D                 mov     [esp+0A0h+var_8F], eax
  17. .text:0040AE61                 mov     [esp+0A0h+var_8B], eax
  18. .text:0040AE65                 mov     eax, [ecx-8]
  19. .text:0040AE68                 add     eax, 2
  20. .text:0040AE6B                 push    eax             ; Size
  21. .text:0040AE6C                 call    sub_45A8C1
  22. .text:0040AE71                 mov     esi, eax
  23. .text:0040AE73                 mov     eax, [edi]
  24. .text:0040AE75                 mov     ecx, [eax-8]
  25. .text:0040AE78                 add     ecx, 2
  26. .text:0040AE7B                 push    ecx             ; MaxCount
  27. .text:0040AE7C                 push    eax             ; Source
  28. .text:0040AE7D                 push    esi             ; Dest
  29. .text:0040AE7E                 call    _wcstombs
  30. .text:0040AE83                 add     esp, 10h
  31. .text:0040AE86                 lea     ecx, [esp+0A0h+var_7C]
  32. .text:0040AE8A                 push    40h
  33. .text:0040AE8C                 push    4
  34. .text:0040AE8E                 call    sub_40D210
  35. .text:0040AE93                 lea     ecx, [esp+0A0h+var_7C]
  36. .text:0040AE97                 mov     [esp+0A0h+var_4], 0
  37. .text:0040AEA2                 mov     [esp+0A0h+var_7C], offset off_462D08
  38. .text:0040AEAA                 call    sub_40C390
  39. .text:0040AEAF                 mov     edi, esi
  40. .text:0040AEB1                 or      ecx, 0FFFFFFFFh
  41. .text:0040AEB4                 xor     eax, eax
  42. .text:0040AEB6                 mov     [esp+0A0h+var_4], 1
  43. .text:0040AEC1                 repne scasb
  44. .text:0040AEC3                 not     ecx
  45. .text:0040AEC5                 dec     ecx
  46. .text:0040AEC6                 push    ecx
  47. .text:0040AEC7                 push    esi
  48. .text:0040AEC8                 lea     ecx, [esp+0A8h+var_7C]
  49. ; Посчитать MD5 от введенного регистрационного имени
  50. .text:0040AECC                 call    sub_40C3C0
  51. .text:0040AED1                 lea     edx, [esp+0A0h+var_98]
  52. .text:0040AED5                 lea     ecx, [esp+0A0h+var_7C]
  53. .text:0040AED9                 push    edx
  54. .text:0040AEDA                 call    sub_40D320
  55. .text:0040AEDF                 push    esi
  56. .text:0040AEE0                 call    sub_45A8EA
  57. .text:0040AEE5                 mov     eax, [esp+0A4h+arg_8]
  58. .text:0040AEEC                 push    10h
  59. .text:0040AEEE                 lea     ecx, [esp+0A8h+var_84]
  60. .text:0040AEF2                 push    eax
  61. .text:0040AEF3                 push    ecx
  62. ; Загрузить текстовую строку "4F5AE4CCE89903B8" и преобразовать ее
  63. ; в четверное слово (QWORD)
  64. .text:0040AEF4                 call    sub_40BE20
  65. .text:0040AEF9                 add     esp, 10h
  66. ; Побайтовый XOR первой половины значения MD5 (байты с 0 по 7)
  67. ; на вторую половину значения MD5 (байты с 8 до 15)
  68. .text:0040AEFC                 xor     eax, eax
  69. .text:0040AEFE loc_40AEFE:
  70. .text:0040AEFE                 mov     dl, byte ptr [esp+eax+0A0h+var_93+3]
  71. .text:0040AF02                 mov     cl, [esp+eax+0A0h+var_98]
  72. .text:0040AF06                 xor     cl, dl
  73. .text:0040AF08                 mov     [esp+eax+0A0h+var_98], cl
  74. .text:0040AF0C                 inc     eax
  75. .text:0040AF0D                 cmp     eax, 10h
  76. .text:0040AF10                 jl      short loc_40AEFE
  77. ; Дополнительный побайтовый XOR первой половины MD5 на преобразованную
  78. ; бинарную строку "4F5AE4CCE89903B8", то есть с цепочкой байт
  79. ; 0CCh,0E4h,5Ah,4Fh,  0B8h,03h,99h,0E8h
  80. .text:0040AF12                 xor     eax, eax
  81. .text:0040AF14 loc_40AF14:
  82. .text:0040AF14                 mov     cl, byte ptr [esp+eax+0A0h+var_84]
  83. .text:0040AF18                 mov     dl, [esp+eax+0A0h+var_98]
  84. .text:0040AF1C                 xor     dl, cl
  85. .text:0040AF1E                 mov     [esp+eax+0A0h+var_98], dl
  86. .text:0040AF22                 inc     eax
  87. .text:0040AF23                 cmp     eax, 8
  88. .text:0040AF26                 jl      short loc_40AF14
  89. ; Дальше первые 8 байт после двух XOR'ов преобразуются в строку, это и
  90. ; будет правильный серийный номер
  91. .text:0040AF28                 push    11h             ; Size
  92. .text:0040AF2A                 call    sub_45A8C1
  93. .text:0040AF2F                 xor     edx, edx
  94. .text:0040AF31                 mov     esi, eax
  95. .text:0040AF33                 mov     [eax], edx
  96. .text:0040AF35                 push    8
  97. .text:0040AF37                 lea     ecx, [esp+0A8h+var_98]
  98. .text:0040AF3B                 push    esi
  99. .text:0040AF3C                 mov     [eax+4], edx
  100. .text:0040AF3F                 push    ecx
  101. .text:0040AF40                 mov     [eax+8], edx
  102. .text:0040AF43                 mov     [eax+0Ch], edx
  103. .text:0040AF46                 mov     [eax+10h], dl
  104. .text:0040AF49                 call    sub_40BE70
  105. .text:0040AF4E                 add     esp, 10h
  106. .text:0040AF51                 push    esi             ; lpMultiByteStr
  107. .text:0040AF52                 mov     esi, [esp+0A4h+arg_0]
  108. .text:0040AF59                 mov     ecx, esi
  109. .text:0040AF5B                 call    sub_45AC51
  110. .text:0040AF60                 mov     ecx, [esp+0A0h+var_C]
  111. .text:0040AF67                 mov     eax, esi
  112. .text:0040AF69                 pop     edi
  113. .text:0040AF6A                 pop     esi
  114. .text:0040AF6B                 mov     large fs:0, ecx
  115. .text:0040AF72                 add     esp, 98h
  116. .text:0040AF78                 retn
В исходнике комментарии есть, продублирую словами. Сперва считается MD5 от введенного регистрационного имени. Затем первые 8 байт полученной MD5 по очереди XOR'ятся на следующие 8 байт. После этого обработанные первые 8 байт побайтно XOR'ятся с последовательностью значений 0CCh, 0E4h, 5Ah, 4Fh, 0B8h, 03h, 99h, 0E8h. Полученные 8 байт переводятся в строку, это и есть серийный номер. Вот и вся защита. Готовый кейген теперь вы можете написать самостоятельно.

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

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

Комментарии

Отзывы посетителей сайта о статье
угу (05.06.2014 в 03:05):
"Подвижничество, патриотизм" - здесь есть хоть какая-то инфа, которую приятно и полезно почитать.
В общем спс автору огромное.
Segodnew (01.05.2014 в 06:54):
Shapoklyak (31.03.2014 в 16:01):
Segodnew, Причём здесь "подвижничество" и "патриотизм"?

А притом, что всё познаётся в сравнении. Если вы способны
оценить хотя бы приблизительно объём работы для содержания
(поддержания) такого сайта "на плаву", то не зададите
таких вопросов. Тем более, что контент сайта на очень
высоком уровне, не сравнить с основной планктонной рунетовской
массой. Ы?
Vladimir (03.04.2014 в 02:39):
Shapoklyak, может подвижничество в том, чтобы нести просвещение в массы?
Shapoklyak (31.03.2014 в 16:01):
Segodnew, Причём здесь "подвижничество" и "патриотизм"?
Segodnew (31.03.2014 в 07:16):
ManHunter, здравствуйте!
В который уже раз испытываю чувство гордости ... за то, что
"... когда такие люди в Стране Советской есть!".
Поражаюсь вашей трудоспособности и компетентности.
Широте интересов. Вашему патриотизму!
Даже я бы сказал - подвижничеству!
Спасибо за ваш нелёгкий, но очень нужный Труд.
You Are The Best !

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

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

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