Исследование защиты программы ID3 Editor
Скриншот программы ID3 Editor
ID3 Editor - неудобный, некрасивый и абсолютно бесполезный редактор тегов MP3-файлов. Может быть его единственный плюс заключается в поддержке различных операционных систем. А еще это поделие требует пятнашку зелени за регистрацию, иначе оно будет работать только несколько дней. С удобством и полезностью я помочь не могу, а вот отучить софтину от вредных привычек - это завсегда пожалуйста.
Забираем с офсайта дистрибутив (анкету заполнять не обязательно, над формой есть кнопка для скачивания), устанавливаем, запускаем. Регистрация выполняется через меню "Help".
Сообщение о неправильной регистрации
При вводе в поле серийного номера 24 символов активируется кнопка "OK", но при попытке зафиксировать это выводится сообщение о неправильной регистрации. Исходные данные для поиска у нас теперь есть, исполняемый файл ничем не накрыт, значит можно сразу отправить его в дизассемблер. Когда листинг будет получен, надо будет поискать текст сообщения, а также код, где он используется.
Code (Assembler) : Убрать нумерацию
- .text:0042F4B2 push eax
- .text:0042F4B3 push ecx
- ; Вызвать функцию проверки серийника
- .text:0042F4B4 call sub_4245E0
- .text:0042F4B9 add esp, 0Ch
- .text:0042F4BC test al, al
- ; Если AL не нулевой, значит серийник правильный
- .text:0042F4BE jnz short loc_42F4FE
- .text:0042F4C0 mov eax, [esi+9Ch]
- .text:0042F4C6 lea edx, [esp+4Ch+MultiByteStr]
- .text:0042F4CA push edx
- .text:0042F4CB push offset a240e7cee1c2945
- ; "240E7CEE1C29454C9A16DF1C323D0C34"
- .text:0042F4D0 push eax
- .text:0042F4D1 call sub_424600
- .text:0042F4D6 add esp, 0Ch
- .text:0042F4D9 test al, al
- .text:0042F4DB jnz short loc_42F514
- ; Сообщение о неправильной регистрации
- .text:0042F4DD push 0 ; unsigned int
- .text:0042F4DF push 24h ; uType
- .text:0042F4E1 push offset aTheSerialNumbe
- ; "The serial number supplied is incorrect"...
- .text:0042F4E6 call ?AfxMessageBox@@YGHPB_WII@Z
- .text:0042F4EB cmp eax, 6
- .text:0042F4EE jz short loc_42F51B
- .text:0042F4F0 push offset Class ; Src
- .text:0042F4F5 mov ecx, edi
- .text:0042F4F7 call sub_401E60
- .text:0042F4FC jmp short loc_42F514
- .text:0042F4FE ; ---------------------------------------------
- .text:0042F4FE loc_42F4FE:
- .text:0042F4FE mov eax, [esi+0A8h]
- .text:0042F504 cmp dword ptr [eax-0Ch], 0
- .text:0042F508 jle short loc_42F514
- .text:0042F50A push 0 ; unsigned int
- .text:0042F50C push 40h ; uType
- .text:0042F50E push eax ; wchar_t *
- .text:0042F50F call ?AfxMessageBox@@YGHPB_WII@Z
Code (Assembler) : Убрать нумерацию
- .text:004245E0 sub_4245E0 proc near
- .text:004245E0 mov eax, [esp+arg_8]
- .text:004245E4 mov ecx, [esp+arg_4]
- .text:004245E8 mov edx, [esp+arg_0]
- .text:004245EC push eax
- .text:004245ED push ecx
- .text:004245EE push edx
- .text:004245EF call sub_424450
- .text:004245F4 add esp, 0Ch
- .text:004245F7 neg eax
- .text:004245F9 sbb eax, eax
- .text:004245FB neg eax
- .text:004245FD retn
- .text:004245FD sub_4245E0 endp
Ошибка проверки триального состояния
Одного патча проверки серийника недостаточно, где-то проверяется еще какое-то значение. Возвращаемся в дизассемблер, чтобы выяснить где и что.
Code (Assembler) : Убрать нумерацию
- ; Ссылка на строку
- .data:005CC0C4 off_5CC0C4 dd offset aFailedToCheckT
- ; "Failed to check the trial status. Abort"...
Code (Assembler) : Убрать нумерацию
- ; Указатель на ссылку на строку
- .text:0040CF68 mov ecx, off_5CC0C4
- .text:0040CF6E jmp loc_40D35C
- ...
- ...
- ; Вывести сообщение
- .text:0040D35C loc_40D35C:
- .text:0040D35C push 0 ; unsigned int
- .text:0040D35E push 10h ; uType
- .text:0040D360 push ecx ; wchar_t *
- .text:0040D361 call ?AfxMessageBox@@YGHPB_WII@Z
Code (Assembler) : Убрать нумерацию
- .text:0040CE8A push edx ; lpSubKey
- .text:0040CE8B call sub_424740
- .text:0040CE90 add esp, 0Ch
- .text:0040CE93 test al, al
- .text:0040CE95 jnz loc_40D0FA
- .text:0040CE9B push 0
Триальное окно
В принципе, если его просто закрывать, то ничего страшного не произойдет, программа будет работать и дальше. Но давайте сделаем красиво. Вот процедура, которая выводит это сообщение, найти ее в коде по ссылке на строку сообщения не составит труда.
Code (Assembler) : Убрать нумерацию
- .text:0042F530 sub_42F530 proc near
- .text:0042F530 push 0FFFFFFFFh
- .text:0042F532 push offset loc_55FD48
- .text:0042F537 mov eax, large fs:0
- .text:0042F53D push eax
- .text:0042F53E sub esp, 14h
- .text:0042F541 push esi
- .text:0042F542 push edi
- .text:0042F543 mov eax, dword_5D166C
- .text:0042F548 xor eax, esp
- .text:0042F54A push eax
- .text:0042F54B lea eax, [esp+2Ch+var_C]
- .text:0042F54F mov large fs:0, eax
- .text:0042F555 mov esi, ecx
- .text:0042F557 mov [esp+2Ch+var_20], esi
- .text:0042F55B push 3Fh
- .text:0042F55D push 0F2h
- .text:0042F562 push 4
- .text:0042F564 call sub_42ED70
- .text:0042F569 mov [esp+2Ch+var_4], 0
- .text:0042F571 push 0Ah ; int
- .text:0042F573 lea ecx, [esi+90h]
- .text:0042F579 push offset off_58025C ; Src
- .text:0042F57E mov dword ptr [esi], offset off_580904
- .text:0042F584 call sub_401B70
- .text:0042F589 mov ecx, [esi+8Ch]
- .text:0042F58F push 0 ; int
- .text:0042F591 push 0 ; int
- .text:0042F593 push offset aThisTrialVersi
- ; "This trial version of ID3 Editor has ex"...
- .text:0042F598 lea eax, [esp+38h+rc]
- .text:0042F59C push eax ; int
- .text:0042F59D push 0FFFFFFFFh ; __int16
Code (Assembler) : Убрать нумерацию
- .text:0040D05B add esp, 8
- .text:0040D05E test eax, eax
- .text:0040D060 jz short loc_40D073
- .text:0040D062 push 0 ; int
- .text:0040D064 push 10h ; uType
- ; Вывести сообщение о несовпадении версий
- .text:0040D066 mov eax, off_5CC0BC
- .text:0040D06B push eax ; int
- .text:0040D06C call ?AfxMessageBox@@YGHPB_WII@Z
- .text:0040D071 jmp short loc_40D0B2
- .text:0040D073 ; ----------------------------------------
- .text:0040D073 loc_40D073:
- .text:0040D073 lea ecx, [ebp+240h+var_310]
- ; Вывести сообщение об окончании триала
- .text:0040D079 call sub_42F530
- .text:0040D07E mov [ebp+240h+var_244], 1
- .text:0040D085 push 0
Code (Assembler) : Убрать нумерацию
- .text:0040CE8B call sub_424740
- .text:0040CE90 add esp, 0Ch
- .text:0040CE93 test al, al
- .text:0040CE95 jnz loc_40D0FA
- .text:0040CE9B push 0
- .text:0040CE9D lea eax, [ebp+240h+var_27C]
- .text:0040CEA0 push eax
Предупреждение при изменении пути установки
По аналогии с предыдущими находим строчку в листинге и по единственной перекрестной ссылке переходим на код, где она используется.
Code (Assembler) : Убрать нумерацию
- .text:0040D356 loc_40D356:
- ; Указатель на строку сообщения
- .text:0040D356 mov ecx, off_5CC0B8
- .text:0040D35C loc_40D35C:
- .text:0040D35C push 0 ; unsigned int
- .text:0040D35E push 10h ; uType
- .text:0040D360 push ecx ; wchar_t *
- .text:0040D361 call ?AfxMessageBox@@YGHPB_WII@Z
- .text:0040D366 loc_40D366:
- .text:0040D366 mov ecx, esi
- .text:0040D368 call sub_404D00
Code (Assembler) : Убрать нумерацию
- .text:0040CD88 cmp [ebp+240h+var_21F], 90h
- .text:0040CD8C jnz loc_40D356
- .text:0040CD92 cmp [ebp+240h+var_21E], 1Ah
- .text:0040CD96 jnz loc_40D356
- .text:0040CD9C cmp [ebp+240h+var_21D], 1Bh
- .text:0040CDA0 jnz loc_40D356
- .text:0040CDA6 cmp [ebp+240h+var_21C], 0E7h
- .text:0040CDAA jnz loc_40D356
- .text:0040CDB0 cmp [ebp+240h+var_21B], 0E3h
- .text:0040CDB4 jnz loc_40D356
- .text:0040CDBA cmp [ebp+240h+var_21A], 6Dh
- .text:0040CDBE jnz loc_40D356
- .text:0040CDC4 cmp [ebp+240h+var_219], 0Ch
- .text:0040CDC8 jnz loc_40D356
- .text:0040CDCE cmp [ebp+240h+var_218], 0C0h
- .text:0040CDD2 jnz loc_40D356
- .text:0040CDD8 cmp [ebp+240h+var_217], 54h
- .text:0040CDDC jnz loc_40D356
- .text:0040CDE2 cmp [ebp+240h+var_216], 0DEh
- .text:0040CDE6 jnz loc_40D356
- .text:0040CDEC cmp [ebp+240h+var_215], 38h
- .text:0040CDF0 jnz loc_40D356
- .text:0040CDF6 cmp [ebp+240h+var_214], 58h
- .text:0040CDFA jnz loc_40D356
- .text:0040CE00 cmp [ebp+240h+var_213], 2Ch
- .text:0040CE04 jnz loc_40D356
- .text:0040CE0A cmp [ebp+240h+var_212], 0D8h
- .text:0040CE0E jnz loc_40D356
- .text:0040CE14 cmp [ebp+240h+var_211], 0F4h
- .text:0040CE18 jnz loc_40D356
- .text:0040CE1E cmp [ebp+240h+var_210], 2Fh
- .text:0040CE22 jnz loc_40D356
Программа успешно "зарегистрирована"
Цель достигнута. Программой пользоваться вовсе необязательно, она реально ущербная, а вот потренироваться в нейтрализации ее защиты очень даже ничего.
Просмотров: 1660 | Комментариев: 10
Метки: исследование защиты, мультимедиа
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Alex
(26.11.2019 в 11:42):
Ну такое, так ломать)))
Прежде всего, если программа при запуске определяет что она триальная, значит не нашли узловую проверку. Править последствия (окошки, строки) сомнительный вариант.
Скачал прогу. У меня Мак, поэтому и версия под macOS.
Сразу открываем в Hopper Disassembler, смотрим через Tag Scope список классов. Хм, есть только один интересный - LicenseDlg. В нем куча методов: saveLicense:, getLicense, saveRegistration: и самый интересный okButtonPressed. В последнем проеряется серийный номер - 24 символа (0x18), каждый 5-й символ "-" (0x2d), разблокируется кнопка OK.
И все... Объектно-ориентированное программирование. Как дальше проверяется серийный номер неясно.
Надо либо дебажить, либо снова рыться в коде.
Дебажить еще успеем. Поищем license(d) ->
Есть интерсный-[DocumentController isLicensed]: Ну что сказать в 90% случаев этого достаточно - mov eax, 0x1 и мы в шоколаде. Но хочется выяснить, как мы определяем себя зарегистрированными, увидеть свое имя и компанию в окне About. Видим, что в этом инстасном методе используется переменная m_bLicenseValid. Это уже ближе к телу. Исследуем ее перекрестные ссылки - 2 интересных:
- "-[DocumentController init]:" можно сразу прописать 1 в переменную, но чаще всего программы могут обнулить проверкой это значение, поэтому просто пока берем на заметку;
- "-[DocumentController loadLicense]:" а вот здесь после кучи проверок в нее лишь в одном случае заносится единица. Проверка перед этой операцией и есть искомая, узловая функция. В ней все: проверка серийного номера, константы, хеши (причем их две, одна на валидность серийного номера, другая - на триальный срок), по итогу возвращаем в eax результат, если 1 - серийный номер верный. Ну что ж вот тут и ставим бряк №1.
На всякий случай заглядываем в saveRegistration: - там есть функция записи в файл настроек значений для "Registered company" & "Registered user". Здесь тоже поставим бряк №2 чтобы проверить что эта информация записывается.
Прежде всего, если программа при запуске определяет что она триальная, значит не нашли узловую проверку. Править последствия (окошки, строки) сомнительный вариант.
Скачал прогу. У меня Мак, поэтому и версия под macOS.
Сразу открываем в Hopper Disassembler, смотрим через Tag Scope список классов. Хм, есть только один интересный - LicenseDlg. В нем куча методов: saveLicense:, getLicense, saveRegistration: и самый интересный okButtonPressed. В последнем проеряется серийный номер - 24 символа (0x18), каждый 5-й символ "-" (0x2d), разблокируется кнопка OK.
И все... Объектно-ориентированное программирование. Как дальше проверяется серийный номер неясно.
Надо либо дебажить, либо снова рыться в коде.
Дебажить еще успеем. Поищем license(d) ->
Есть интерсный-[DocumentController isLicensed]: Ну что сказать в 90% случаев этого достаточно - mov eax, 0x1 и мы в шоколаде. Но хочется выяснить, как мы определяем себя зарегистрированными, увидеть свое имя и компанию в окне About. Видим, что в этом инстасном методе используется переменная m_bLicenseValid. Это уже ближе к телу. Исследуем ее перекрестные ссылки - 2 интересных:
- "-[DocumentController init]:" можно сразу прописать 1 в переменную, но чаще всего программы могут обнулить проверкой это значение, поэтому просто пока берем на заметку;
- "-[DocumentController loadLicense]:" а вот здесь после кучи проверок в нее лишь в одном случае заносится единица. Проверка перед этой операцией и есть искомая, узловая функция. В ней все: проверка серийного номера, константы, хеши (причем их две, одна на валидность серийного номера, другая - на триальный срок), по итогу возвращаем в eax результат, если 1 - серийный номер верный. Ну что ж вот тут и ставим бряк №1.
На всякий случай заглядываем в saveRegistration: - там есть функция записи в файл настроек значений для "Registered company" & "Registered user". Здесь тоже поставим бряк №2 чтобы проверить что эта информация записывается.
user
(14.05.2019 в 09:04):
)) Пару "философских" замечаний.
Программа стоит 15 баксов, но в "магазинном виде" не вполне юзабельна.
Пяток потраченных блин часов стоят значительно дороже, но есть и результат.
Программа стоит 15 баксов, но в "магазинном виде" не вполне юзабельна.
Пяток потраченных блин часов стоят значительно дороже, но есть и результат.
user
(14.05.2019 в 08:50):
Что получилось у меня, по итогу:
Вынутый из инсталляшки без инсталляции комплект программ
работает в "триальном" режиме, портабле, вроде без ограничений.
GUI, если вводить отфонарный код, делается "регистрированной", но только в текущем сеансе. Там ещё пришлось несколько мест поправить.
В общем, заскладировал, при случае поюзаю.
Сенкс за программку.
Вынутый из инсталляшки без инсталляции комплект программ
работает в "триальном" режиме, портабле, вроде без ограничений.
GUI, если вводить отфонарный код, делается "регистрированной", но только в текущем сеансе. Там ещё пришлось несколько мест поправить.
В общем, заскладировал, при случае поюзаю.
Сенкс за программку.
ManHunter
(13.05.2019 в 17:28):
Вот, блин, сколько ж там говна понатыкано. Дополнил статью.
user
(13.05.2019 в 17:11):
Ещё неплохо поправить ругань при запуске не из того места, куда инсталлировалась.
Как в консольной версии. Типа портабле.
Как в консольной версии. Типа портабле.
ManHunter
(13.05.2019 в 11:57):
Добавил немного про гуишный вариант.
user
(13.05.2019 в 07:10):
Что-то там GUI-версия не вполне добита.
Гляну ещё, по свободе.
А вот консольную версию, похоже, удалось уговорить.
Ну, и запротоколировал правки в таком виде:
Файл id3ed.CRK:
;----------------------------------------------->8
ID3 Editor 1.26.43
1) id3ed.exe - by ManHunter
id3ed.exe
.0040CE95: 0F E9 ;0000C295:
.0040CE96: 85 60 ;0000C296:
.0040CE97: 5F 02 ;0000C297:
.0040CE98: 02 00 ;0000C298:
.0040CE9A: 00 90 ;0000C29A:
2) id3ed.exe - by ManHunter
id3ed.exe
.004245E0: 8B 31 ;000239E0:
.004245E1: 44 C0 ;000239E1:
.004245E2: 24 40 ;000239E2:
.004245E3: 0C C3 ;000239E3:
;----------------------------------------------
1) id3edcmd.exe - Skip trial limit
id3edcmd.exe
.0043B1F5: 76 EB ;0003A5F5:
.0043B1FE: 76 EB ;0003A5FE:
.0043B377: 76 EB ;0003A777:
.0043B4DF: 76 EB ;0003A8DF:
.0043B4E8: 76 EB ;0003A8E8:
id3edcmd.exe
.0043B170: 28 00 ;0003A570:
id3edcmd.exe
.0043B1E2: 14 00 ;0003A5E2:
.0043B1ED: 09 00 ;0003A5ED:
.0043B33B: 65 00 ;0003A73B:
.0043B36F: 09 00 ;0003A76F:
.0043B45A: 28 00 ;0003A85A:
.0043B468: 1A 00 ;0003A868:
.0043B476: 0C 00 ;0003A876:
id3edcmd.exe
.0043B3DF: 0F E9 ;0003A7DF:
.0043B3E0: 85 39 ;0003A7E0:
.0043B3E1: 38 01 ;0003A7E1:
.0043B3E2: 01 00 ;0003A7E2:
.0043B3E4: 00 90 ;0003A7E4:
.0043B4D7: 09 00 ;0003A8D7:
2) id3edcmd.exe - Skip "Modified..Reinstall" message.
id3edcmd.exe
.0043E273: 0F E9 ;0003D673:
.0043E274: 85 D8 ;0003D674:
.0043E275: D9 00 ;0003D675:
.0043E278: 00 90 ;0003D678:
;----------------------------------------------->8
Гляну ещё, по свободе.
А вот консольную версию, похоже, удалось уговорить.
Ну, и запротоколировал правки в таком виде:
Файл id3ed.CRK:
;----------------------------------------------->8
ID3 Editor 1.26.43
1) id3ed.exe - by ManHunter
id3ed.exe
.0040CE95: 0F E9 ;0000C295:
.0040CE96: 85 60 ;0000C296:
.0040CE97: 5F 02 ;0000C297:
.0040CE98: 02 00 ;0000C298:
.0040CE9A: 00 90 ;0000C29A:
2) id3ed.exe - by ManHunter
id3ed.exe
.004245E0: 8B 31 ;000239E0:
.004245E1: 44 C0 ;000239E1:
.004245E2: 24 40 ;000239E2:
.004245E3: 0C C3 ;000239E3:
;----------------------------------------------
1) id3edcmd.exe - Skip trial limit
id3edcmd.exe
.0043B1F5: 76 EB ;0003A5F5:
.0043B1FE: 76 EB ;0003A5FE:
.0043B377: 76 EB ;0003A777:
.0043B4DF: 76 EB ;0003A8DF:
.0043B4E8: 76 EB ;0003A8E8:
id3edcmd.exe
.0043B170: 28 00 ;0003A570:
id3edcmd.exe
.0043B1E2: 14 00 ;0003A5E2:
.0043B1ED: 09 00 ;0003A5ED:
.0043B33B: 65 00 ;0003A73B:
.0043B36F: 09 00 ;0003A76F:
.0043B45A: 28 00 ;0003A85A:
.0043B468: 1A 00 ;0003A868:
.0043B476: 0C 00 ;0003A876:
id3edcmd.exe
.0043B3DF: 0F E9 ;0003A7DF:
.0043B3E0: 85 39 ;0003A7E0:
.0043B3E1: 38 01 ;0003A7E1:
.0043B3E2: 01 00 ;0003A7E2:
.0043B3E4: 00 90 ;0003A7E4:
.0043B4D7: 09 00 ;0003A8D7:
2) id3edcmd.exe - Skip "Modified..Reinstall" message.
id3edcmd.exe
.0043E273: 0F E9 ;0003D673:
.0043E274: 85 D8 ;0003D674:
.0043E275: D9 00 ;0003D675:
.0043E278: 00 90 ;0003D678:
;----------------------------------------------->8
user
(11.05.2019 в 10:36):
.. Не, реально полезная штука - там есть и отдельная утиль командной строки.
Сенкс. Заскладировал.
Сенкс. Заскладировал.
user
(11.05.2019 в 10:19):
) Когда-то, в начале 2000-х, начал было ваять свою такую же.
Замышлялось, что упор будет на пакетную обработку сразу многих файлов.
Даже уже диалог запилил, выдранный из WinAMP'а,
да только появились какие-то дела и забросил тогда эту игрушку.
Замышлялось, что упор будет на пакетную обработку сразу многих файлов.
Даже уже диалог запилил, выдранный из WinAMP'а,
да только появились какие-то дела и забросил тогда эту игрушку.
Добавить комментарий
Заполните форму для добавления комментария
Запускаем программу для отладки. Пытаемся зарегистрироваться: любые имя и компания и любой серийный номер в формате xxxx-xxxx-xxxx-xxxx-xxxx.
Так вываливаемся на брейкпоинте №1. Видим что eax 0, ну нет так не пойдет - 0x1. Получаем окно об успешной регистрации, а затем вываливаемся в брейкпоинте №2, проверяем пишет ли программа наши данные в файл настроек или что-то еще хочет проверить - нет, не проверяет и пишет наши данные, значит все верно.
Осталось проверить есть ли в программе защита на целостность и подпись. Заходим в Hopper в списк импортируемых функций - есть ли что-то из стандартного API (security.framework_ - нет, что в 90% случаев говорит об отсутствии таковых проверок.
В таком случае правим возврат eax по первому брейкпоинту - есть только 3 байта и для обнуления eax, и для записи в младший байт 1. Маловато. Вариантов 2: либо в предыдущей операции обнулить регистр, а потом в этой во младший записать 1 (как вариант or eax, 0x1), либо сразу push 0x1; pop rax (6A 01 58) - как раз 3 байта. Выбираем последний, правим бинарник и вуаля, программа зарегистрирована, в окне About наши данные.
Осталось только определиться - либо просто снять подпись и выложить взломанный бинарник с readme.txt, где разжевать какой формат серийного номера использовать, либо сразу сделать инжект с данными регистрации и правкой проверки по первому бряку. Это уже на ваше усмотрение. Мне второй вариант больше нравится.