Исследование защиты программы MD5 Tool
Скриншот программы MD5 Tool
Программа MD5 Tool предназначена для подсчета и проверки контрольной суммы MD5 файлов. Есть множество бесплатных и гораздо более мощных аналогов, поэтому мне очень странно, что за эту софтину аффтар пытается подрезать с пользователей по червонцу баксов. "И его посчитаем".
На сайте есть два дистрибутива, нас интересует полная версия. Скачиваем, устанавливаем, запускаем. Без ввода правильного серийника эта версия отказывается даже запускаться.
Окно регистрации и сообщение о неправильном серийнике
Серийника у нас, естественно, нет, но зато есть текст сообщения. Исполняемый файл ничем не упакован и не защищен, отправим его дизассемблироваться, а пока поищем нужную нам строчку.
Текст сообщения
Файл небольшой, дизассемблер закончил работу за несколько секунд, теперь мы можем посмотреть условия срабатывания защиты и код, где используется строка сообщения о неправильной регистрации.
Code (Assembler) : Убрать нумерацию
- .text:0040AB43 lea ecx, [esp+850h+var_838]
- .text:0040AB47 lea edx, [esp+850h+Str1]
- .text:0040AB4B push ecx ; int
- .text:0040AB4C push edx ; Str1
- .text:0040AB4D mov byte ptr [esp+858h+var_4], 1
- ; Вызвать функцию проверки
- .text:0040AB55 call sub_40AD20
- .text:0040AB5A add esp, 8
- .text:0040AB5D lea ecx, [esp+850h+Str1]
- ; Сохранить ее результат из регистра EAX в регистр EDI
- .text:0040AB61 mov edi, eax
- .text:0040AB63 mov byte ptr [esp+850h+var_4], 0
- .text:0040AB6B call sub_45AB88
- .text:0040AB70 or ebp, 0FFFFFFFFh
- .text:0040AB73 lea ecx, [esp+850h+var_838]
- .text:0040AB77 mov [esp+850h+var_4], ebp
- .text:0040AB7E call sub_45AB88
- ; Результат проверки = 0?
- .text:0040AB83 test edi, edi
- .text:0040AB85 pop edi
- ; Да, значит введенный серийник неправильный
- .text:0040AB86 jz short loc_40AC07
- .text:0040AB88 lea eax, [esp+84Ch+Src]
- .text:0040AB8C lea ecx, [esp+84Ch+var_83C]
- .text:0040AB90 push eax ; Src
- .text:0040AB91 mov dword_475A98, 1
- .text:0040AB9B call sub_45ABFC
- .text:0040ABA0 lea ecx, [esp+84Ch+String]
- .text:0040ABA4 mov [esp+84Ch+var_4], 2
- .text:0040ABAF push ecx ; Src
- .text:0040ABB0 lea ecx, [esp+850h+var_840]
- .text:0040ABB4 call sub_45ABFC
- ; Сохранить регистрацию в реестре и закрыть окно ввода серийника
- .text:0040ABB9 lea edx, [esp+84Ch+var_83C]
- .text:0040ABBD lea eax, [esp+84Ch+var_840]
- .text:0040ABC1 push edx ; int
- .text:0040ABC2 push eax ; int
- .text:0040ABC3 push offset dword_475A90 ; lpSubKey
- .text:0040ABC8 mov byte ptr [esp+858h+var_4], 3
- .text:0040ABD0 call sub_40B780
- .text:0040ABD5 add esp, 0Ch
- .text:0040ABD8 lea ecx, [esp+84Ch+var_840]
- .text:0040ABDC mov byte ptr [esp+84Ch+var_4], 2
- .text:0040ABE4 call sub_45AB88
- .text:0040ABE9 lea ecx, [esp+84Ch+var_83C]
- .text:0040ABED mov [esp+84Ch+var_4], ebp
- .text:0040ABF4 call sub_45AB88
- .text:0040ABF9 push 0 ; nResult
- .text:0040ABFB push esi ; hDlg
- .text:0040ABFC call ds:EndDialog
- .text:0040AC02 jmp loc_40AC99
- .text:0040AC07 ; ---------------------------------------------------
- .text:0040AC07 loc_40AC07:
- ; Сообщение о неправильной регистрации
- .text:0040AC07 mov ecx, off_46F018
- .text:0040AC0D mov [esp+84Ch+lpText], ecx
- .text:0040AC11 mov edx, lpFile
- .text:0040AC17 lea eax, [esp+84Ch+lpText]
- .text:0040AC1B push edx ; int
- .text:0040AC1C push offset aTheUnlockCodeY
- ; "The Unlock Code you have provided is no"...
- .text:0040AC21 push eax ; int
- .text:0040AC22 mov [esp+858h+var_4], 4
- .text:0040AC2D call sub_455E06
- .text:0040AC32 mov ecx, [esp+858h+lpText]
- .text:0040AC36 add esp, 0Ch
- .text:0040AC39 push 14h ; uType
- .text:0040AC3B push offset Caption ; "Code not valid"
- .text:0040AC40 push ecx ; lpText
- .text:0040AC41 push 0 ; hWnd
- .text:0040AC43 call ds:MessageBoxW
- .text:0040AC49 cmp eax, 6
Code (Assembler) : Убрать нумерацию
- .text:0040AD20 sub_40AD20 proc near
- .text:0040AD20 mov eax, dword_475A94
- .text:0040AD25 mov ecx, [esp+Str1]
- .text:0040AD29 push esi
- .text:0040AD2A push eax
- .text:0040AD2B lea edx, [esp+8+Str1]
- .text:0040AD2F push ecx
- .text:0040AD30 push edx
- .text:0040AD31 call sub_40AE20
- .text:0040AD36 mov eax, [esp+10h+arg_4]
- .text:0040AD3A mov ecx, [esp+10h+Str1]
- .text:0040AD3E mov eax, [eax]
- ; Сравнить две строчки
- .text:0040AD40 push eax ; Str2
- .text:0040AD41 push ecx ; Str1
- .text:0040AD42 call _wcscmp
- .text:0040AD47 add esp, 14h
- .text:0040AD4A lea ecx, [esp+4+Str1]
- ; Если они равны, то EAX=0
- .text:0040AD4E test eax, eax
- ; Соответственно, DL станет = 1
- .text:0040AD50 setz dl
- .text:0040AD53 and edx, 0FFh
- .text:0040AD59 mov esi, edx
- .text:0040AD5B call sub_45AB88
- ; И при успешном сравнении на выходе EAX=1
- .text:0040AD60 mov eax, esi
- .text:0040AD62 pop esi
- .text:0040AD63 retn
- .text:0040AD63 sub_40AD20 endp
Правильный серийный номер в стеке
Что мы видим в отладчике при срабатывании точки останова? На вершине стека перед вызовом функции сравнения лежит наш левый серийник и еще какая-то строка, с которой он сравнивается. В моем случае для введенного имени "ManHunter / PCL" эта строка будет "8CF1C5A4BBB3108F". Не надо быть семи пядей во лбу, чтобы догадаться, что это и есть правильный серийный номер. Перезапускаем программу и пробуем зарегистрироваться с найденной парой имя-серийник. На этот раз сообщение о неправильной регистрации не появляется, окно регистрации закрывается и запускается основное рабочее окно MD5 Tool. При последующем запуске регистрация не слетает, значит мы все сделали правильно.
Осталось забить последний гвоздь в гроб буржуазии и попробовать разобрать алгоритм генерации и, соответственно, проверки серийного номера. Функция генерации проверочной строки не очень большая, приведу прокомментированный листинг целиком. Чтобы было понятнее, эту функцию надо исследовать параллельно в отладчике и дизассемблере.
Code (Assembler) : Убрать нумерацию
- .text:0040AE20 push 0FFFFFFFFh
- .text:0040AE22 push offset SEH_40AE20
- .text:0040AE27 mov eax, large fs:0
- .text:0040AE2D push eax
- .text:0040AE2E mov large fs:0, esp
- .text:0040AE35 sub esp, 8Ch
- .text:0040AE3B xor eax, eax
- .text:0040AE3D push esi
- .text:0040AE3E mov [esp+9Ch+var_84], 0
- .text:0040AE46 push edi
- .text:0040AE47 mov edi, [esp+0A0h+arg_4]
- .text:0040AE4E mov [esp+0A0h+var_97], eax
- .text:0040AE52 mov [esp+0A0h+var_93], eax
- .text:0040AE56 mov [esp+0A0h+var_98], 0
- .text:0040AE5B mov ecx, [edi]
- .text:0040AE5D mov [esp+0A0h+var_8F], eax
- .text:0040AE61 mov [esp+0A0h+var_8B], eax
- .text:0040AE65 mov eax, [ecx-8]
- .text:0040AE68 add eax, 2
- .text:0040AE6B push eax ; Size
- .text:0040AE6C call sub_45A8C1
- .text:0040AE71 mov esi, eax
- .text:0040AE73 mov eax, [edi]
- .text:0040AE75 mov ecx, [eax-8]
- .text:0040AE78 add ecx, 2
- .text:0040AE7B push ecx ; MaxCount
- .text:0040AE7C push eax ; Source
- .text:0040AE7D push esi ; Dest
- .text:0040AE7E call _wcstombs
- .text:0040AE83 add esp, 10h
- .text:0040AE86 lea ecx, [esp+0A0h+var_7C]
- .text:0040AE8A push 40h
- .text:0040AE8C push 4
- .text:0040AE8E call sub_40D210
- .text:0040AE93 lea ecx, [esp+0A0h+var_7C]
- .text:0040AE97 mov [esp+0A0h+var_4], 0
- .text:0040AEA2 mov [esp+0A0h+var_7C], offset off_462D08
- .text:0040AEAA call sub_40C390
- .text:0040AEAF mov edi, esi
- .text:0040AEB1 or ecx, 0FFFFFFFFh
- .text:0040AEB4 xor eax, eax
- .text:0040AEB6 mov [esp+0A0h+var_4], 1
- .text:0040AEC1 repne scasb
- .text:0040AEC3 not ecx
- .text:0040AEC5 dec ecx
- .text:0040AEC6 push ecx
- .text:0040AEC7 push esi
- .text:0040AEC8 lea ecx, [esp+0A8h+var_7C]
- ; Посчитать MD5 от введенного регистрационного имени
- .text:0040AECC call sub_40C3C0
- .text:0040AED1 lea edx, [esp+0A0h+var_98]
- .text:0040AED5 lea ecx, [esp+0A0h+var_7C]
- .text:0040AED9 push edx
- .text:0040AEDA call sub_40D320
- .text:0040AEDF push esi
- .text:0040AEE0 call sub_45A8EA
- .text:0040AEE5 mov eax, [esp+0A4h+arg_8]
- .text:0040AEEC push 10h
- .text:0040AEEE lea ecx, [esp+0A8h+var_84]
- .text:0040AEF2 push eax
- .text:0040AEF3 push ecx
- ; Загрузить текстовую строку "4F5AE4CCE89903B8" и преобразовать ее
- ; в четверное слово (QWORD)
- .text:0040AEF4 call sub_40BE20
- .text:0040AEF9 add esp, 10h
- ; Побайтовый XOR первой половины значения MD5 (байты с 0 по 7)
- ; на вторую половину значения MD5 (байты с 8 до 15)
- .text:0040AEFC xor eax, eax
- .text:0040AEFE loc_40AEFE:
- .text:0040AEFE mov dl, byte ptr [esp+eax+0A0h+var_93+3]
- .text:0040AF02 mov cl, [esp+eax+0A0h+var_98]
- .text:0040AF06 xor cl, dl
- .text:0040AF08 mov [esp+eax+0A0h+var_98], cl
- .text:0040AF0C inc eax
- .text:0040AF0D cmp eax, 10h
- .text:0040AF10 jl short loc_40AEFE
- ; Дополнительный побайтовый XOR первой половины MD5 на преобразованную
- ; бинарную строку "4F5AE4CCE89903B8", то есть с цепочкой байт
- ; 0CCh,0E4h,5Ah,4Fh, 0B8h,03h,99h,0E8h
- .text:0040AF12 xor eax, eax
- .text:0040AF14 loc_40AF14:
- .text:0040AF14 mov cl, byte ptr [esp+eax+0A0h+var_84]
- .text:0040AF18 mov dl, [esp+eax+0A0h+var_98]
- .text:0040AF1C xor dl, cl
- .text:0040AF1E mov [esp+eax+0A0h+var_98], dl
- .text:0040AF22 inc eax
- .text:0040AF23 cmp eax, 8
- .text:0040AF26 jl short loc_40AF14
- ; Дальше первые 8 байт после двух XOR'ов преобразуются в строку, это и
- ; будет правильный серийный номер
- .text:0040AF28 push 11h ; Size
- .text:0040AF2A call sub_45A8C1
- .text:0040AF2F xor edx, edx
- .text:0040AF31 mov esi, eax
- .text:0040AF33 mov [eax], edx
- .text:0040AF35 push 8
- .text:0040AF37 lea ecx, [esp+0A8h+var_98]
- .text:0040AF3B push esi
- .text:0040AF3C mov [eax+4], edx
- .text:0040AF3F push ecx
- .text:0040AF40 mov [eax+8], edx
- .text:0040AF43 mov [eax+0Ch], edx
- .text:0040AF46 mov [eax+10h], dl
- .text:0040AF49 call sub_40BE70
- .text:0040AF4E add esp, 10h
- .text:0040AF51 push esi ; lpMultiByteStr
- .text:0040AF52 mov esi, [esp+0A4h+arg_0]
- .text:0040AF59 mov ecx, esi
- .text:0040AF5B call sub_45AC51
- .text:0040AF60 mov ecx, [esp+0A0h+var_C]
- .text:0040AF67 mov eax, esi
- .text:0040AF69 pop edi
- .text:0040AF6A pop esi
- .text:0040AF6B mov large fs:0, ecx
- .text:0040AF72 add esp, 98h
- .text:0040AF78 retn
Просмотров: 5818 | Комментариев: 5
Метки: исследование защиты, хеши
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Segodnew
(01.05.2014 в 06:54):
Shapoklyak (31.03.2014 в 16:01):
Segodnew, Причём здесь "подвижничество" и "патриотизм"?
А притом, что всё познаётся в сравнении. Если вы способны
оценить хотя бы приблизительно объём работы для содержания
(поддержания) такого сайта "на плаву", то не зададите
таких вопросов. Тем более, что контент сайта на очень
высоком уровне, не сравнить с основной планктонной рунетовской
массой. Ы?
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 !
В который уже раз испытываю чувство гордости ... за то, что
"... когда такие люди в Стране Советской есть!".
Поражаюсь вашей трудоспособности и компетентности.
Широте интересов. Вашему патриотизму!
Даже я бы сказал - подвижничеству!
Спасибо за ваш нелёгкий, но очень нужный Труд.
You Are The Best !
Добавить комментарий
Заполните форму для добавления комментария
В общем спс автору огромное.