Задача: сделать защиту программы (dll) путем шифрования участков кода. Экспериментируем в visual studio 2008.
Метод решения:
1. После компиляции участки кода из исполняемого файла (шифруемых процедур, которые прописаны как static) копируются в отдельные файлики, а их место затирается дребеденью.
2. После поставки программы заказчику ему пересылаются ключи (зашифрованные файлики), которые при исполнении программа берет с диска, расшифровывает, добавляет сама в себя и исполняется дальше.
Проблема. Все описанное прекрасно работает на x64, но при попытке переноса методы в x32 возникает проблема с тем, что содержимое static процедур в памяти при загрузке dll отличается от того, как они выглядят в самом файле dll на диске. Причем при каждой новой загрузке содержимое в памяти отличается от содержимого на диске в некоторых байтах .
Байты одни и те же. Т.е. содержимое основной массы байтов сохраняется, а небольшой массы байтов при загрузке меняется.
Варианты решения проблемы:
1. Для каждой шифруемой процедуры делать маску с байтами, содержимое которых при шифровке-расшифровке менять не нужно. — Это основной рабочий вариант, который я сейчас пытаюсь реализовать.
2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память?
B>Задача: сделать защиту программы (dll) путем шифрования участков кода. Экспериментируем в visual studio 2008. B>Метод решения: B>1. После компиляции участки кода из исполняемого файла (шифруемых процедур, которые прописаны как static) копируются в отдельные файлики, а их место затирается дребеденью. B>2. После поставки программы заказчику ему пересылаются ключи (зашифрованные файлики), которые при исполнении программа берет с диска, расшифровывает, добавляет сама в себя и исполняется дальше. B>Проблема. Все описанное прекрасно работает на x64, но при попытке переноса методы в x32 возникает проблема с тем, что содержимое static процедур в памяти при загрузке dll отличается от того, как они выглядят в самом файле dll на диске. Причем при каждой новой загрузке содержимое в памяти отличается от содержимого на диске в некоторых байтах . B>Байты одни и те же. Т.е. содержимое основной массы байтов сохраняется, а небольшой массы байтов при загрузке меняется.
Дык это наверное указатели на функции в других длл и/или rebase фиксапы, которые лоадером резолвятся. Это просто можно и нужно учесть при шифровании — вся инфа про эту "небольшую массу байтов" имеется в PE заголовках.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Barm, Вы писали:
B>2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память?
Здравствуйте, ononim, Вы писали:
B>>Задача: сделать защиту программы (dll) путем шифрования участков кода. Экспериментируем в visual studio 2008. B>>Метод решения: B>>1. После компиляции участки кода из исполняемого файла (шифруемых процедур, которые прописаны как static) копируются в отдельные файлики, а их место затирается дребеденью. B>>2. После поставки программы заказчику ему пересылаются ключи (зашифрованные файлики), которые при исполнении программа берет с диска, расшифровывает, добавляет сама в себя и исполняется дальше. B>>Проблема. Все описанное прекрасно работает на x64, но при попытке переноса методы в x32 возникает проблема с тем, что содержимое static процедур в памяти при загрузке dll отличается от того, как они выглядят в самом файле dll на диске. Причем при каждой новой загрузке содержимое в памяти отличается от содержимого на диске в некоторых байтах . B>>Байты одни и те же. Т.е. содержимое основной массы байтов сохраняется, а небольшой массы байтов при загрузке меняется. O>Дык это наверное указатели на функции в других длл и/или rebase фиксапы, которые лоадером резолвятся. Это просто можно и нужно учесть при шифровании — вся инфа про эту "небольшую массу байтов" имеется в PE заголовках.
Интересно, что при компиляции под winx64 код процедуры в dll файле полностью соответствует тому, что в памяти (изменяемых байтов нет).
Причину наличия изменяемых байтов в win32 и неналичия оных в win64 искать не хочется. Пытаюсь тупо учесть их наличие и критические участки кода не трогать. Неделя мучений уже прошла. Если получиться — отпишусь.
B>Интересно, что при компиляции под winx64 код процедуры в dll файле полностью соответствует тому, что в памяти (изменяемых байтов нет).
Потому что в win64 нету инструкции call ptr_64, а есть только call [rip + delta_32], так что в x64 компилятор вынужден ложить указатели на external функции куданить в данные. А 32хбитный компилятор может и так и прямым адресом из инструкции.
B>Причину наличия изменяемых байтов в win32 и неналичия оных в win64 искать не хочется. Пытаюсь тупо учесть их наличие и критические участки кода не трогать. Неделя мучений уже прошла. Если получиться — отпишусь.
Советую как следует изучить матчасть прежде чем делать такие проекты. Там еще много подводных граблей.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, bnk, Вы писали:
bnk>Здравствуйте, Barm, Вы писали:
B>>2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память?
bnk>Попробуй выключить ASLR в настройках проекта.
Уже пробовал. Не помогает.
bnk>Но вообще, в тращициях данного форума, попинаю bnk>IMHO, ерундой занимаетесь, если уж так нужно, просто возьмите готовый протектор.
Угу. Готовые протекторы имеют готовые методики взлома.
Мне нужен протектор:
1. Закачивающий ключи на клиента при оплате.
2. Привязка ключей к железу клиента.
3. Возможность простой перепривязки программы с одного рабочего места на другое (включая win64 и win32).
Программа планируется дешевой, трата ручного времени на привязку каждого клиента исключена.
Максимум, что делается вручную — забивается e-mail клиента в базу данных "оплачено".
Денег априори на службу поддержки-установки нет. .
Здравствуйте, ononim, Вы писали:
B>>Интересно, что при компиляции под winx64 код процедуры в dll файле полностью соответствует тому, что в памяти (изменяемых байтов нет). O>Потому что в win64 нету инструкции call ptr_64, а есть только call [rip + delta_32], так что в x64 компилятор вынужден ложить указатели на external функции куданить в данные. А 32хбитный компилятор может и так и прямым адресом из инструкции.
B>>Причину наличия изменяемых байтов в win32 и неналичия оных в win64 искать не хочется. Пытаюсь тупо учесть их наличие и критические участки кода не трогать. Неделя мучений уже прошла. Если получиться — отпишусь. O>Советую как следует изучить матчасть прежде чем делать такие проекты. Там еще много подводных граблей.
Писал прогу около полутора лет. Писал сразу под win64. Рабочий экземпляр уже есть для x64. Граблей уже было море.
Осталось перенести на win32. И тут произошел этот затык. Можно делать защиту, шифруя при исполнении данные, но:
1. Мне опять все переделывать.
2. Шифровка данных приводит к торможению проги. Код один раз расшифровал и он быстры данные перелопачивает.
Хотя можно бонусом небольшую шифровку данных делать (шифруя ключом от сервера (имея данные по клиенту), а расшифровываешь ключом с данными об оборудовании, собранном на клиенте).
Здравствуйте, Barm, Вы писали:
bnk>>Но вообще, в тращициях данного форума, попинаю bnk>>IMHO, ерундой занимаетесь, если уж так нужно, просто возьмите готовый протектор.
B>Угу. Готовые протекторы имеют готовые методики взлома.
Ты сможешь лучше, чем сделано в VmProtect?
B>Мне нужен протектор: B>1. Закачивающий ключи на клиента при оплате.
VmProtect (+vmpKit )
B>2. Привязка ключей к железу клиента.
VmProtect
B>3. Возможность простой перепривязки программы с одного рабочего места на другое (включая win64 и win32).
VmProtect
B>Программа планируется дешевой, трата ручного времени на привязку каждого клиента исключена. B>Максимум, что делается вручную — забивается e-mail клиента в базу данных "оплачено".
VmProtect
B>Денег априори на службу поддержки-установки нет. .
B>Задача: сделать защиту программы (dll) путем шифрования участков кода.
Ух. Это привет из… 1999 года?
B>Метод решения: B>1. После компиляции участки кода из исполняемого файла (шифруемых процедур, которые прописаны как static) копируются в отдельные файлики, а их место затирается дребеденью.
Почему не просто зашифровать на месте, зачем файлы? Или зашифровать dll, если уж хочется совсем не давать код для demo?
B>Байты одни и те же. Т.е. содержимое основной массы байтов сохраняется, а небольшой массы байтов при загрузке меняется.
За полтора года "проекта" про релоки не слышали?
B>2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память?
В gcc есть -fPIC.
X>да, отднажды, лет через 200 — возможно. но меня интересует сейчас.
На unpack.cn и прочих подобных ресурсах постоянно выкладывают анпакеры для всех популярных протекторов, включая VMProtect и WinLicense. В паблик, разумеется, обычно попадают анпакеры для предпоследних версий данных протекторов.
Здравствуйте, niXman, Вы писали:
pva>>Это в виде шутки? Ее ж заломали недавно. Да и ценник у нее кусючий. X>а vmprotect взломали, случаем не в курсе?
По VMP 2.x бегают какие-то скрипты + есть одна серъезная работа по восстановлению ВМ кода, но требует хотя бы средней квалификации. Не для скрипткиддис точно.
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, Barm, Вы писали:
bnk>>>Но вообще, в тращициях данного форума, попинаю bnk>>>IMHO, ерундой занимаетесь, если уж так нужно, просто возьмите готовый протектор.
B>>Угу. Готовые протекторы имеют готовые методики взлома.
M>Ты сможешь лучше, чем сделано в VmProtect?
B>>Мне нужен протектор: B>>1. Закачивающий ключи на клиента при оплате.
M>VmProtect (+vmpKit )
B>>2. Привязка ключей к железу клиента.
M>VmProtect
B>>3. Возможность простой перепривязки программы с одного рабочего места на другое (включая win64 и win32).
M>VmProtect
B>>Программа планируется дешевой, трата ручного времени на привязку каждого клиента исключена. B>>Максимум, что делается вручную — забивается e-mail клиента в базу данных "оплачено".
M>VmProtect
B>>Денег априори на службу поддержки-установки нет. .
M>VmProtect
Все заработало. Кажется я таки справился.
В win32 маска участка исполняемой команды имеет вид:
110000000000000000000011000000000000000000000001100000000000000000011000000000000000000000000000000 и т.д.
где единичками показаны изменяемые байты при загрузке dll в память. Т.е. изменяемые байты располагаются по два друг за другом.
Как показали эксперименты при шифровке их трогать нельзя, а шифровать можно только данные на некотором расстоянии между изменяемыми байтами (в маске это нули).
Тогда dll корректно грузиться в память и данные можно расшифровывать.
Я не верю в стандартные методики защиты, применяемые массово. Для них есть стандартные методики взлома.
На мой взгляд как раз оптимальный вариант — шифрование участков кода своей программы. Тем более, это относительно простая задача.
Если в программе зашифровать сотню процедур — задача слома программы становиться бессмысленной в случае, если цена программы не заоблачна.
Мне показалось, что иметь собственный протектор — более удобный подход, чем пользоваться сторонним.
Да, он более тупой, чем VMProtect, но чтобы его сломать, придется потратить время. А кому это нужно, если программа дешевая, а алгоритм шифровки неизвестен?
Всем спасибо за советы.
B>Все заработало. Кажется я таки справился. B>В win32 маска участка исполняемой команды имеет вид: B>110000000000000000000011000000000000000000000001100000000000000000011000000000000000000000000000000 и т.д. B>где единичками показаны изменяемые байты при загрузке dll в память. Т.е. изменяемые байты располагаются по два друг за другом.
Значит, это релоки.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, flаt, Вы писали:
F>Здравствуйте, Barm, Вы писали:
B>>Задача: сделать защиту программы (dll) путем шифрования участков кода. F>Ух. Это привет из… 1999 года?
Угу. Когда то давно я пописывал на делфи и этот привет тоже юзал.
B>>Метод решения: B>>1. После компиляции участки кода из исполняемого файла (шифруемых процедур, которые прописаны как static) копируются в отдельные файлики, а их место затирается дребеденью. F>Почему не просто зашифровать на месте, зачем файлы? Или зашифровать dll, если уж хочется совсем не давать код для demo?
Да, программу (demo) вообще нельзя сломать, если в ней вообще нет кода.
B>>Байты одни и те же. Т.е. содержимое основной массы байтов сохраняется, а небольшой массы байтов при загрузке меняется. F>За полтора года "проекта" про релоки не слышали?
Полтора года я делал основной код. С шифровкой разбирался около месяца. Это не трудная задача и не требует знания ассемблера вообще (и структуры pe-таблиц тоже). Достаточно сделать дамп памяти проги в файл, потом сравнить его с исходником и затереть данные в исходнике.
B>>2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память? F>В gcc есть -fPIC.
Здравствуйте, Mr.Delphist, Вы писали:
MD>Здравствуйте, Barm, Вы писали:
B>>Задача: сделать защиту программы (dll) путем шифрования участков кода. Экспериментируем в visual studio 2008.
MD>Это видели? MD>http://rsdn.ru/article/baseserv/peloader.xml
Спасибо за инфу. Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты.
Собственно сложность защиты можно наращивать до бесконечности, используя несколько алгоритмов шифрования и формирования ключей. Так как процесс шифровки можно автоматизировать, то
наличие в программе хотя бы 5 вариантов шифра, применяемых по определенному правилу к 500 разбросанным участкам кода — приведет к тому, что задача слома становиться бессмысленной для проги минимальной стоимости.
Здравствуйте, Barm, Вы писали:
B>Я не верю в стандартные методики защиты, применяемые массово. Для них есть стандартные методики взлома.
Не стоит основываться на вере, лучше ориентироваться на факты. Есть факты, что VMProtect хорошо ломается?
B>На мой взгляд как раз оптимальный вариант — шифрование участков кода своей программы. Тем более, это относительно простая задача.
Нужно будет — сломают на раз. У тебя перестановка инструкций есть? Есть виртуализация со случайно генерируемым набором инструкций VM?
B>Если в программе зашифровать сотню процедур — задача слома программы становиться бессмысленной в случае, если цена программы не заоблачна.
А если их зашифровать VMProtect'ом?
B>Мне показалось, что иметь собственный протектор — более удобный подход, чем пользоваться сторонним.
Если есть очень много времени, то подход неплох.
B>Да, он более тупой, чем VMProtect, но чтобы его сломать, придется потратить время. А кому это нужно, если программа дешевая, а алгоритм шифровки неизвестен?
VMProtect легко ломается?
B>Всем спасибо за советы.
Не за что. Я, кстати, думаю, что ты нашел какой-то частный случай, который работает на твоей системе. На другой машине с другой виндой не факт, что заработает.
Удачи
Здравствуйте, Barm, Вы писали:
B>Здравствуйте, Mr.Delphist, Вы писали:
MD>>Здравствуйте, Barm, Вы писали:
B>>>Задача: сделать защиту программы (dll) путем шифрования участков кода. Экспериментируем в visual studio 2008.
MD>>Это видели? MD>>http://rsdn.ru/article/baseserv/peloader.xml
B>Спасибо за инфу. Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты.
Ну, суть работы с секциями PE там показана хорошо. Равно как и проблемы типа релоков, защиты страниц exec-памяти от записи (функции семейства VirtualProtect) и т.п.
Причём заметьте, это ещё не вступили в игру корпоративные policy и антивирусы
B>Спасибо за инфу. Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты. B>Собственно сложность защиты можно наращивать до бесконечности, используя несколько алгоритмов шифрования и формирования ключей. Так как процесс шифровки можно автоматизировать, то B>наличие в программе хотя бы 5 вариантов шифра, применяемых по определенному правилу к 500 разбросанным участкам кода — приведет к тому, что задача слома становиться бессмысленной для проги минимальной стоимости.
Никто не будет ломать голову над вашими шифрами. Понаставят бракпоинтов и сдампят все в расшифрованном виде
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Barm, Вы писали:
B>Полтора года я делал основной код. С шифровкой разбирался около месяца. Это не трудная задача и не требует знания ассемблера вообще (и структуры pe-таблиц тоже). Достаточно сделать дамп памяти проги в файл, потом сравнить его с исходником и затереть данные в исходнике.
Ахаха, а drVano-то дурень не в курсе, годами сидит пилит свой VmProtect. А тут оказывается всё просто, месяц работы — и никто не взломает.
ЗЫ Твою защиту, думаю, за полдня любой школьник заломает. Тебя от взлома спасет только принцип неуловимого Джо.
Здравствуйте, ononim, Вы писали:
B>>Спасибо за инфу. Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты. B>>Собственно сложность защиты можно наращивать до бесконечности, используя несколько алгоритмов шифрования и формирования ключей. Так как процесс шифровки можно автоматизировать, то B>>наличие в программе хотя бы 5 вариантов шифра, применяемых по определенному правилу к 500 разбросанным участкам кода — приведет к тому, что задача слома становиться бессмысленной для проги минимальной стоимости. O>Никто не будет ломать голову над вашими шифрами. Понаставят бракпоинтов и сдампят все в расшифрованном виде
Да. Вы правы. Надо дополнительно шифровать данные, чтобы в них при сломе результат менялся. Тогда дампить память тоже смысла не будет.
Здравствуйте, ononim, Вы писали:
B>>Спасибо за инфу. Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты. B>>Собственно сложность защиты можно наращивать до бесконечности, используя несколько алгоритмов шифрования и формирования ключей. Так как процесс шифровки можно автоматизировать, то B>>наличие в программе хотя бы 5 вариантов шифра, применяемых по определенному правилу к 500 разбросанным участкам кода — приведет к тому, что задача слома становиться бессмысленной для проги минимальной стоимости. O>Никто не будет ломать голову над вашими шифрами. Понаставят бракпоинтов и сдампят все в расшифрованном виде
Хорошего состояния памяти нет. Есть состояние отдельных участков кода. Дампить память 500 раз и сравнивать где хороший участок, где плохой — это только если сервер сбербанка надо сломать.
B>>>Собственно сложность защиты можно наращивать до бесконечности, используя несколько алгоритмов шифрования и формирования ключей. Так как процесс шифровки можно автоматизировать, то B>>>наличие в программе хотя бы 5 вариантов шифра, применяемых по определенному правилу к 500 разбросанным участкам кода — приведет к тому, что задача слома становиться бессмысленной для проги минимальной стоимости. O>>Никто не будет ломать голову над вашими шифрами. Понаставят бракпоинтов и сдампят все в расшифрованном виде B>Хорошего состояния памяти нет. Есть состояние отдельных участков кода. Дампить память 500 раз и сравнивать где хороший участок, где плохой — это только если сервер сбербанка надо сломать.
Дампить память 500 раз (каждые 10мсек например) — пишется за 15 минут. Сравнивать потом дампы и выявлять изменившиеся регионы — тоже ни разу не рокетсайнс.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Barm, Вы писали:
B>Я не верю в стандартные методики защиты, применяемые массово. Для них есть стандартные методики взлома.
Кустарный самопал тем более не остановит.
B>На мой взгляд как раз оптимальный вариант — шифрование участков кода своей программы. Тем более, это относительно простая задача.
Фиговый вариант. Шифрованные куски прекрасно вычисляются по стат.распределению. Дальше находится и вызывается их дешифровщик. Всех. Еще раз: ты сам всё расшифруешь взломщику. Он просто вежливо попросит твой самопал это сделать.
B>Всем спасибо за советы.
Здравствуйте, Barm, Вы писали:
B> Я не прячу dll. Я использую немного иной подход. Я поставляю dll без кусков кода, а куски кода поставляются как ключи после оплаты.
Поставляй их внутри аппаратного USB свистка. Причём наружу не отдавай. Только обмен данными. В свисток входные, из свистка только обсчитанный результат. Это единственный более-менее надёжный способ. И то сломают.
Здравствуйте, Barm, Вы писали:
B>Здравствуйте, bnk, Вы писали:
bnk>>Здравствуйте, Barm, Вы писали:
B>>>2. Может быть в настройках visual studio есть какие-то параметры, которые делают код процедур dll-ки неизменяющимся при загрузке в память?
bnk>>Попробуй выключить ASLR в настройках проекта. B>Уже пробовал. Не помогает.
bnk>>Но вообще, в тращициях данного форума, попинаю bnk>>IMHO, ерундой занимаетесь, если уж так нужно, просто возьмите готовый протектор.
B>Угу. Готовые протекторы имеют готовые методики взлома. B>Мне нужен протектор: B>1. Закачивающий ключи на клиента при оплате. B>2. Привязка ключей к железу клиента. B>3. Возможность простой перепривязки программы с одного рабочего места на другое (включая win64 и win32).
B>Программа планируется дешевой, трата ручного времени на привязку каждого клиента исключена. B>Максимум, что делается вручную — забивается e-mail клиента в базу данных "оплачено".
B>Денег априори на службу поддержки-установки нет. .
Это прекрасная идея, но сразу как только код будет расшифрован его можно просто сохранить из памяти в файл,
а после этого с ним работать.
Здравствуйте, Barm, Вы писали:
B>Как показали эксперименты при шифровке их трогать нельзя, а шифровать можно только данные на некотором расстоянии между изменяемыми байтами (в маске это нули).
Если всё так печально, то у тебя вероятно довольно слабая защита...
B>Я не верю в стандартные методики защиты, применяемые массово. Для них есть стандартные методики взлома.
Ломается всё, вопрос только трудозатрат. Можно поверить в то, что изучив всё что есть ты придумал что-то лучше. Но ИМХО, складывается впечатление, что ты не вникал в то что есть и наколхозил велосипед, который ломается ещё проще "стандартных методик". B>На мой взгляд как раз оптимальный вариант — шифрование участков кода своей программы. Тем более, это относительно простая задача. B>Если в программе зашифровать сотню процедур — задача слома программы становиться бессмысленной в случае, если цена программы не заоблачна.
Ключ шифрования, IDA и скрипт на питоне — работа на день. А если ещё и не "стандартный шифр", то вероятно даже ключ шифрования не нужен. B>Мне показалось, что иметь собственный протектор — более удобный подход, чем пользоваться сторонним.
Если твой протектор сопоставим со сторонним по качеству, то да. Нужно будет тратить время на его изучение и обход защит. Если это простое шифрование отдельных участков, то толку от такой защиты сильно меньше. B>Да, он более тупой, чем VMProtect, но чтобы его сломать, придется потратить время. А кому это нужно, если программа дешевая, а алгоритм шифровки неизвестен?
Твоя программа ведь расшифровывает же эти блоки кода? А значит алгоритм "шфировки" известен.
Короче есть мысль, что ты сильно заморачиваешся и тратишь много усилий на относительно простую защиту дешевой программы, когда можно за маленькие деньги с меньшими усилиями сделать более серьезную защиту навесным протектором. Они не панацея, но как раз для простых и дешевых программ тот же VMProtect даёт защиту со слишком большими трудозатратами на взлом.