Исследование защиты программы Batch Watermark Creator
Скриншот программы Batch Watermark Creator
Как легко догадаться из названия, программа Batch Watermark Creator предназначена для нанесения водяных знаков на изображения. Действительно, это инструмент для пакетного нанесения графических и текстовых маркеров на изображения. Если вы публикуете фотографии на открытых ресурсах и не хотите, чтобы ими воспользовался кто-то еще без вашего ведома, то такая маркировка в большинстве случаев может вам помочь. О других возможностях программы вы можете прочитать на ее офсайте. О том, как сделать ее бесплатной, вы можете прочитать здесь.
Как обычно начинаем со скачивания дистрибутива, устанавливаем, смотрим, что у нас получается. У нас получается ничем не упакованный основной файл BWC.exe, два каких-то редактора и вспомогательная утилита для регистрации RegNow.exe. Начнем с главного файла, отправляем его в дизассемблер и параллельно посмотрим на проявления триальности.
Ограничения триальной версии программы
Их два. Надпись о том, что программа не зарегистрирована в окне "О программе" и водяной знак в виде пунктирной линии на всех сохраненных фотографиях.
Окно регистрации программы
Модуль ввода и проверки серийного номера вынесен в отдельную утилиту, которая вызывается при попытке регистрации. Обратите внимание, что в программе используется привязка к компьютеру, на скриншоте она обозначена как "Machine Code". Это не есть хорошо. Поищем какую-нибудь из строчек, которые относятся к незарегистрированной программе.
Строчки в ресурсах
В ресурсах обнаруживаются строчки из окна "О программе" для зарегистрированной и незарегистрированной версий программы. Нас интересует та, которая "UNREGISTERED". Она имеет индекс 64871 или 0FD67h в шестнадцатеричной системе счисления. Ищем что-то подобное в дизассемблере. Как и положено для программ на Дельфи, сперва находится указатель на ресурс:
Code (Assembler) : Убрать нумерацию
- CODE:0059A8E4 off_59A8E4 dd offset hModule
- CODE:0059A8E8 dd 0FD67h
Code (Assembler) : Убрать нумерацию
- DATA:005DDA58 off_5DDA58 dd offset off_59A8E4
- ; DATA XREF: _TfrmAbout_FormCreate+EE
Code (Assembler) : Убрать нумерацию
- ; Проверить байт по адресу off_5DDD90
- CODE:0059B87B mov eax, ds:off_5DDD90
- CODE:0059B880 cmp byte ptr [eax], 0
- ; Если он равен нулю, то вывести сообщение "UNREGISTERED"
- CODE:0059B883 jz short loc_59B8D3
- CODE:0059B885 lea edx, [ebp+var_10]
- CODE:0059B888 mov eax, ds:off_5DDD7C
- ; Загрузить сообщение "REGISTERED"
- CODE:0059B88D call @System@LoadResString
- CODE:0059B892 mov edx, [ebp+var_10]
- CODE:0059B895 mov eax, [ebp+var_4]
- CODE:0059B898 mov eax, [eax+324h]
- CODE:0059B89E call @Controls@TControl@SetText
- ; Controls::TControl::SetText(System::AnsiString)
- CODE:0059B8A3 lea edx, [ebp+var_14]
- CODE:0059B8A6 mov eax, ds:off_5DD564
- CODE:0059B8AB call @System@LoadResString
- ; System::LoadResString(System::TResStringRec *)
- CODE:0059B8B0 lea eax, [ebp+var_14]
- CODE:0059B8B3 mov edx, ds:off_5DD638
- CODE:0059B8B9 mov edx, [edx]
- CODE:0059B8BB call @System@@LStrCat$qqrv
- ; System::__linkproc__ LStrCat(void)
- CODE:0059B8C0 mov edx, [ebp+var_14]
- CODE:0059B8C3 mov eax, [ebp+var_4]
- CODE:0059B8C6 mov eax, [eax+328h]
- CODE:0059B8CC call @Controls@TControl@SetText
- ; Controls::TControl::SetText(System::AnsiString)
- CODE:0059B8D1 jmp short loc_59B901
- CODE:0059B8D3 ; ---------------------------------------------
- CODE:0059B8D3 loc_59B8D3:
- CODE:0059B8D3 lea edx, [ebp+var_18]
- CODE:0059B8D6 mov eax, ds:off_5DDA58
- ; Загрузить сообщение "UNREGISTERED"
- CODE:0059B8DB call @System@LoadResString
- ; System::LoadResString(System::TResStringRec *)
- CODE:0059B8E0 mov edx, [ebp+var_18]
- CODE:0059B8E3 mov eax, [ebp+var_4]
- CODE:0059B8E6 mov eax, [eax+324h]
- CODE:0059B8EC call @Controls@TControl@SetText
- ; Controls::TControl::SetText(System::AnsiString)
- CODE:0059B8F1 mov eax, [ebp+var_4]
- CODE:0059B8F4 mov eax, [eax+328h]
- CODE:0059B8FA xor edx, edx
- CODE:0059B8FC call @Controls@TControl@SetText
- ; Controls::TControl::SetText(System::AnsiString)
Перекрестные ссылки на проверочный байт
Глянем на перекрестные ссылки, касающиеся этого байта. Их не так много. По трем из них выполняются проверки, типа:
Code (Assembler) : Убрать нумерацию
- CODE:005C6EA4 mov eax, ds:off_5DDD90
- CODE:005C6EA9 cmp byte ptr [eax], 0
- CODE:005C6EAC jnz short loc_5C6EBC
Code (Assembler) : Убрать нумерацию
- CODE:005C8629 mov eax, ds:off_5DDD90
- CODE:005C862E mov byte ptr [eax], 0
- ...
- ...
- ...
- CODE:005C8686 mov eax, ds:off_5DDD90
- CODE:005C868B mov byte ptr [eax], 1
Программа успешно "зарегистрирована"
Сохраняем изменения и запускаем пропатченную программу. В окне "О программе" теперь надпись, что программа зарегистрирована (нет регистрационного имени, но это и не так важно), при сохранении файлов никаких предупреждений не выводится и никаких искажений на фотографии не накладывается. Значит цель достигнута. Все эти привязки к железу, вспомогательные утилиты для регистрации и прочие навороты удалось обойти изменением не то что одного байта, а даже одного единственного бита.
Просмотров: 6688 | Комментариев: 9
Метки: исследование защиты, графика
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(05.07.2014 в 00:00):
Там и без кейгена все патчится на раз-два. Я его релизил уже лет 7 назад. А вот строки всех сообщений пошифрованы. brute же этого хотел.
DimitarSerg
(04.07.2014 в 23:54):
> поразбирай BWMeter
Не знаю какая там сложность по патчинку, патч-кейген делается за час, находим стандартные функции проверки подпсии Crypt*, заменяем rsa-1024 на свой, ваяем кейген. (конечно там есть один интересный момент, который я увидел впервые в защитах программа с проверкой сигны на МСКриптоАпи).
Не знаю какая там сложность по патчинку, патч-кейген делается за час, находим стандартные функции проверки подпсии Crypt*, заменяем rsa-1024 на свой, ваяем кейген. (конечно там есть один интересный момент, который я увидел впервые в защитах программа с проверкой сигны на МСКриптоАпи).
DagalProject
(04.07.2014 в 09:05):
2655847 еще раз Спасибо. Прочитал эту статью, и больше таких глупых вопросов не задам.
Способы представления чисел
Двоичные (binary) числа – каждая цифра означает значение одного бита (0 или 1), старший бит всегда пишется слева, после числа ставится буква «b». Для удобства восприятия тетрады могут быть разделены пробелами. Например, 1010 0101b.
Шестнадцатеричные (hexadecimal) числа – каждая тетрада представляется одним символом 0...9, А, В, ..., F. Обозначаться такое представление может по-разному, здесь используется только символ «h» после последней шестнадцатеричной цифры. Например, A5h. В текстах программ это же число может обозначаться и как 0хА5, и как 0A5h, в зависимости от синтаксиса языка программирования. Незначащий ноль (0) добавляется слева от старшей шестнадцатеричной цифры, изображаемой буквой, чтобы различать числа и символические имена.
Десятичные (decimal) числа – каждый байт (слово, двойное слово) представляется обычным числом, а признак десятичного представления (букву «d») обычно опускают. Байт из предыдущих примеров имеет десятичное значение 165. В отличие от двоичной и шестнадцатеричной формы записи, по десятичной трудно в уме определить значение каждого бита, что иногда приходится делать.
Восьмеричные (octal) числа – каждая тройка бит (разделение начинается с младшего) записывается в виде цифры 0–7, в конце ставится признак «о». То же самое число будет записано как 245о. Восьмеричная система неудобна тем, что байт невозможно разделить поровну.
Способы представления чисел
Двоичные (binary) числа – каждая цифра означает значение одного бита (0 или 1), старший бит всегда пишется слева, после числа ставится буква «b». Для удобства восприятия тетрады могут быть разделены пробелами. Например, 1010 0101b.
Шестнадцатеричные (hexadecimal) числа – каждая тетрада представляется одним символом 0...9, А, В, ..., F. Обозначаться такое представление может по-разному, здесь используется только символ «h» после последней шестнадцатеричной цифры. Например, A5h. В текстах программ это же число может обозначаться и как 0хА5, и как 0A5h, в зависимости от синтаксиса языка программирования. Незначащий ноль (0) добавляется слева от старшей шестнадцатеричной цифры, изображаемой буквой, чтобы различать числа и символические имена.
Десятичные (decimal) числа – каждый байт (слово, двойное слово) представляется обычным числом, а признак десятичного представления (букву «d») обычно опускают. Байт из предыдущих примеров имеет десятичное значение 165. В отличие от двоичной и шестнадцатеричной формы записи, по десятичной трудно в уме определить значение каждого бита, что иногда приходится делать.
Восьмеричные (octal) числа – каждая тройка бит (разделение начинается с младшего) записывается в виде цифры 0–7, в конце ставится признак «о». То же самое число будет записано как 245о. Восьмеричная система неудобна тем, что байт невозможно разделить поровну.
DagalProject
(02.07.2014 в 23:21):
2655847
Спасибо.
Спасибо.
2655847
(02.07.2014 в 22:59):
DagalProject
Преобразование 64871 = 0FD67h [h - шестнадцатеричное] для поиска в дизассемблере, IDA например.
Преобразование 64871 = 0FD67h [h - шестнадцатеричное] для поиска в дизассемблере, IDA например.
DagalProject
(02.07.2014 в 18:29):
Извините меня за глупый вопрос, но 64871 это FD67 в шестнадцатеричной системе счисления. Откуда взялось 0FD67h. Спасибо.
ManHunter
(01.07.2014 в 09:13):
Точка останова на участок памяти. Сработает при фактическом обращении.
Если хочется чем-нибудь заняться, то посиди поразбирай BWMeter, там таких шифрованных строчек дофига и больше.
brute
(01.07.2014 в 09:08):
хочется увидеть более сложные примеры, когда ресурсы пошифрованы и строки в секции data пошифрованы (самой программой, без пакера). Когда на одну строку "UNREGISTERED" приходится несколько сотен левых (или нет) ссылок. Может, есть какие-нибудь "легкие" решения в этих случаях?
kaktustv
(01.07.2014 в 00:59):
Для красоты можно создать в папке с программой файл User.dat с содержимым типа
[Setup]
RegCode=F751EE14C728
UserEmail=mail@mail.ru
UserName=Registered Userr
и окно "О программе" будет выглядеть наряднее!
[Setup]
RegCode=F751EE14C728
UserEmail=mail@mail.ru
UserName=Registered Userr
и окно "О программе" будет выглядеть наряднее!
Добавить комментарий
Заполните форму для добавления комментария