Программная защита и авторизация приложений магазина.

Автор Тема: Программная защита и авторизация приложений магазина.  (Прочитано 46421 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2457
  • Карма: 692
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Цитировать
Речь идёт о оптимальном варианте простейшей защиты.
Берите номер тома системного раздела HDD. В качестве простейшей защиты вполне нормально.

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 33
как бы так проще выразиться. какой бы простой не была защита, стоимость взлома должна превышать стоимость покупки )))
по поводу того, к чему еще дополнительно привязаться. если функция "vk_GetMacAddress" рабочая, то могу посоветовать глянуть в сторону "Win32_Processor" (Win32_NetworkAdapter поменять на Win32_Processor) и запустить. Будет интересовать значение поля "ProcessorId". Если в поисковике написать WMI Win32_Processor то в первой десятке будет ссылка майкрософтовская на все ключевые слова (хотя, если честно, выбирать там особо не из чего ))) )
дальше, не стоит хранить файл лицензии в открытом виде (ну мало ли, взруг он таки хранится без шифрования), лучше превратить его в набор кракозябликов ))), самый простой вариант без использования навороченных библиотек, но с сохранением логики шифрования будет выглядеть так:
Код - C++ [Выбрать]
  1. // строка в кракозяблики по ключевому слову
  2. void _encode(ACHAR * key, ACHAR * str, int strlen)
  3. {
  4.         int j = 0;
  5.         for (long i = 0; i < strlen; i++)
  6.         {
  7.                 str[i] -= key[j++];
  8.                 if (j >= _tcslen(key)) j = 0;
  9.         }
  10. }
  11.  
  12. // кракозяблики в строку по ключевому слову
  13. void _decode(ACHAR * key, ACHAR * str, int strlen)
  14. {
  15.         long j = 0;
  16.         for (long i = 0; i < strlen; i++)
  17.         {
  18.                 str[i] += key[j++];
  19.                 if (j >= _tcslen(key)) j = 0;
  20.         }
  21. }
  22.  
  23. // и так. key - ключ шифрования, str - строка данных (грубо говоря, лицензия), strlen - длина строки str
  24.  
  25. ну и примерчик создания файла лицензии на жестком диске
  26. FILE * f;
  27. _wfopen_s(&f,licFilePath.GetString(),_T("wb"));
  28. if (f == NULL)return false;
  29. ACHAR str[1024]; _tcscpy(str, licData.GetString());
  30. _encode(_T("Это мой ключик шифрования. чем он длинней, тем сложней ломать"),str,_tcslen(str));
  31. fwrite(str,sizeof(ACHAR),_tcslen(str),f);
  32. fclose(f);
  33.  
PS: думаю перевести при необходимости код на lisp труда не составит

Оффлайн BearDyugin

  • ADN Club
  • ****
  • Сообщений: 259
  • Карма: 22
  • Геодезист
если функция "vk_GetMacAddress" рабочая, то могу посоветовать глянуть в сторону "Win32_Processor" (Win32_NetworkAdapter поменять на Win32_Processor) и запустить. Будет интересовать значение поля "ProcessorId"
Спасибо
По аналогии с "vk_GetMacAddress" получилось вот так
Код - Auto/Visual Lisp [Выбрать]
  1. (defun Get_ProcessorId (/               LocatorObj      SecurityObj
  2.                         SecurityObj     ObjectSetObj    Processor_Id
  3.                        )
  4.   (setq LocatorObj
  5.          (vlax-create-object "WbemScripting.SWbemLocator")
  6.   )
  7.   (setq ServiceObj
  8.          (vlax-invoke
  9.            LocatorObj 'ConnectServer nil nil nil nil nil nil nil nil)
  10.   )
  11.   (setq ObjectSetObj
  12.          (vlax-invoke
  13.            ServiceObj
  14.            'ExecQuery
  15.            "Select * from Win32_Processor"
  16.          )
  17.   )
  18.   (vlax-for Obj ObjectSetObj
  19.     (setq Processor_Id
  20.            (vlax-get Obj 'ProcessorId)
  21.     )
  22.   )
  23.   (foreach Obj
  24.                (list LocatorObj ServiceObj SecurityObj ObjectSetObj)
  25.     (and Obj (vlax-release-object Obj))
  26.   )
  27.   Processor_Id
  28. )
Работает, но всё равно половина не понятно.
1) переменная SecurityObj есть, но в коде (исходном) ни где не определяется, но зато в конце успешно release-ится, или это просто ошибка, притянулось от куда-то из прошлого?
2) Для чего в конце делают release объектов?
3) ID процессора, который мы вроде как получили, ни кто направо и налево не меняет, как тот же MAC-адрес?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2457
  • Карма: 692
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
3) ID процессора, который мы вроде как получили, ни кто направо и налево не меняет, как тот же MAC-адрес?
Нет. Но, насколько я помню, он не является уникальным. То есть, на одинаковых процессорах он один и тот же.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2457
  • Карма: 692
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
На основе предыдущего кода. Получаем серийный номер материнской платы:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun Get_BaseBoardSerialNumber (/ LocatorObj ServiceObj ObjectSetObj SerialNumber)
  2.   (setq LocatorObj
  3.          (vlax-create-object "WbemScripting.SWbemLocator")
  4.   )
  5.   (setq ServiceObj
  6.          (vlax-invoke
  7.            LocatorObj 'ConnectServer nil nil nil nil nil nil nil nil)
  8.   )
  9.   (setq ObjectSetObj
  10.          (vlax-invoke
  11.            ServiceObj
  12.            'ExecQuery
  13.            "Select * from Win32_BaseBoard"
  14.          )
  15.   )
  16.   (vlax-for Obj ObjectSetObj
  17.     (setq SerialNumber
  18.            (vlax-get Obj 'SerialNumber)
  19.     )
  20.   )
  21.   (foreach Obj
  22.                (list LocatorObj ServiceObj ObjectSetObj)
  23.     (and Obj (vlax-release-object Obj))
  24.   )
  25.   SerialNumber
  26. )
То же самое, только из BIOS:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun Get_BIOSSerialNumber (/ LocatorObj ServiceObj ObjectSetObj SerialNumber)
  2.   (setq LocatorObj
  3.          (vlax-create-object "WbemScripting.SWbemLocator")
  4.   )
  5.   (setq ServiceObj
  6.          (vlax-invoke
  7.            LocatorObj 'ConnectServer nil nil nil nil nil nil nil nil)
  8.   )
  9.   (setq ObjectSetObj
  10.          (vlax-invoke
  11.            ServiceObj
  12.            'ExecQuery
  13.            "SELECT * FROM Win32_BIOS"
  14.          )
  15.   )
  16.   (vlax-for Obj ObjectSetObj
  17.     (setq SerialNumber
  18.            (vlax-get Obj 'SerialNumber)
  19.     )
  20.   )
  21.   (foreach Obj
  22.                (list LocatorObj ServiceObj ObjectSetObj)
  23.     (and Obj (vlax-release-object Obj))
  24.   )
  25.   SerialNumber
  26. )

Ну и на закуску - уникальный идентификатор компьютера (UUID):
Код - Auto/Visual Lisp [Выбрать]
  1. (defun Get_UUID (/ LocatorObj ServiceObj ObjectSetObj UUID)
  2.   (setq LocatorObj
  3.          (vlax-create-object "WbemScripting.SWbemLocator")
  4.   )
  5.   (setq ServiceObj
  6.          (vlax-invoke
  7.            LocatorObj 'ConnectServer nil nil nil nil nil nil nil nil)
  8.   )
  9.   (setq ObjectSetObj
  10.          (vlax-invoke
  11.            ServiceObj
  12.            'ExecQuery
  13.            "SELECT UUID FROM Win32_ComputerSystemProduct"
  14.          )
  15.   )
  16.   (vlax-for Obj ObjectSetObj
  17.     (setq UUID
  18.            (vlax-get Obj 'UUID)
  19.     )
  20.   )
  21.   (foreach Obj
  22.                (list LocatorObj ServiceObj ObjectSetObj)
  23.     (and Obj (vlax-release-object Obj))
  24.   )
  25.   UUID
  26. )

И на основе вот этого: http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine
Код - Auto/Visual Lisp [Выбрать]
  1. (defun get-machine-guid ()
  2.   (vl-registry-read
  3.     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography"
  4.     "MachineGuid"
  5.   )
  6. )

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 12976
  • Карма: 1669
  • Рыцарь ObjectARX
  • Skype: rivilis
Не уверен, что WbemScripting будет всегда работать. Скорее всего админ запретит его для обычных пользователей.
Возможны и другие проблемы. Обсуждение их здесь: Проблемы использования WMI
« Последнее редактирование: 17-12-2015, 12:07:18 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 33
На основе предыдущего кода. Получаем серийный номер материнской платы:
То же самое, только из BIOS:
Ну и на закуску - уникальный идентификатор компьютера (UUID):
в картинке результат работы этих функций на компьютере, собранном вручную (возможно, если б это был ноут или запаяный деловский или HP-шный корпус, было бы более информативно ))) )
ID процессора, который мы вроде как получили, ни кто направо и налево не меняет
увы, это не серийный номер, а набор циферок-буковок, которые набираются из характеристик процессора. скажу одно, поменять его руками практически никак, он не меняется после повторного включения компьютера ))). пользоваться можно, но не ТОЛЬКО ЭТИМ полем, а совместно с другими. UUID работает (правда возможен вариант, когда первых три набора идут с нулями, если верить документации).

короче говоря, вот так выглядит файл лицензии у меня:
Цитировать
Application:название приложения| <- думаю тут всё понятно
360UserID:XXXXXXXXX| <-идентификатор Autodesk360
MAC:XX:XX:XX:XX| <- мак адрес. не надежно, но не страшно ))) Win32_NetworkAdapter.MACAddress
UUID:XXXXXXXXXXXXXXXXXXXXXXXX| <- Win32_ComputerSystemProduct.UUID
ProcessorId:XXXXXXXXXXX| <- Win32_Processor.ProcessorId
Status:request| <-(ну или ключевое слово, позволяющее перейти в оффлайн режим работы)
KEY:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| <- рандомно генерируется ключ
и так, если пользователь прошел онлайн проверку (хотя б один раз), генерируется такой файл. сам файл естественно шифруется. функции шифрования написал выше.
получение оффлайн лицензии возможно ТОЛЬКО в случае наличия этого файла. т.е. если установил купленную прогу на 10 компов, то файл запроса лицензии появится только на тех компиках, где входил под своим аккаунтом в Autodesk360 и ЗАПУСКАЛ программу.
дальше, если хочет офлайн, нужно на мыло отправить ключик, состоящий из значений полей: Application|360UserID|KEY
В ответ он получает ключ для того, чтоб файл запроса офлайн лицензии поменялся на полный файл лицензии. Естественно, перед тем, как выдать ключик можно зайти в магазин и глянуть, сколько версий проги купил человечек с этим UID-ом ))).
в открытом виде никакая информация не передается. есть три набора алфавита
1. ABCDE...
2. VGDHA...
3. GRDSL...
инфа внутри файла лицензии лежит в первом варианте алфавита.
мне передается код запроса во втором варианте алфавита
я отправляю код активации в третьем варианте алфавита.
ну и естественно, вся работа происходит в первом варианте алфавита, значит есть функции для превращения набора буковок-циферок ИЗ-В

Не уверен, что WbemScripting будет всегда работать. Скорее всего админ запретит его для обычных пользователей.
если у пользователя такие вольготные условия, что даже интернет есть ))), то вряд-ли закрыт WMI ). ну а если и закрыт, то работа будет только с онлайн лицензией, что тоже лично для меня не сильно страшно.
И на основе вот этого: http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine
очень интересно. нужно потестировать. как проверю, отпишусь по этому поводу.

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 33
почитал про MachineGuid. Это ключ, который использует криптография виндузов. без проблем его можно поменять на тот, который хочется. если просто удалить и перегрузиться, виндуза сгенерят новый.
http://forum.screenconnect.com/yaf_postst1694_MachineGuid-reset.aspx#post6966

PS: перестают работать программы, которые создают свой ключ на основе HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid. Простая переустановка переставших работать программ решает проблему )))
http://blogs.msdn.com/b/vivekkum/archive/2009/02/14/machinekey-in-iis.aspx (много букв ни о чем. всё важное в последнем абзаце статьи))) )

так что уж если и привязываться к чему-то, то только к тому, что сложно поменять и уж точно таких привязок должно быть больше, чем одна (например, работать можно если совпало минимум 2/3 или 3/5 привязок). пусть в результате получится не уникальный набор данных в целом, но вероятность того, что одна и та же лицензия будет работать на нескольких компьютерах даже одного отдела уменьшается с увеличением количества привязок.
ну, еще пару слов о процессоре. хоть ProcessorId и не является серийным номером, но для четырех одинаковых процессоров купленных из одного ящика (серийные номера на коробках сверить не получится, чтоб узнать идут ли они подряд))), коробки уже давно сгнили на свалке) я получил четыре разных набора буковок-циферок.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 12976
  • Карма: 1669
  • Рыцарь ObjectARX
  • Skype: rivilis
1) ProcessorId не обязательно уникален.
2) Это фишка Intel, а процессор может быть и не Intel
3) Получение CPUID может быть отключено в BIOS.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 33
1) ProcessorId не обязательно уникален.
2) Это фишка Intel, а процессор может быть и не Intel
3) Получение CPUID может быть отключено в BIOS.
увы, это жизнь ))). но другого выхода нет. чем больше брать параметров и чем меньше порог проходимости (2/3 параметров или 2/10) тем больше вероятность того, что хоть что-то будет работать (или что комп разберут на части для сбора нескольких других машинок ))) для установки одного ключа на них))) ). и в любом случае, ключ генерится только если всё срабатывает, в противном случае остается только онлайн защита.
кстати, один из самых простых способов получения уникального ключа для виндузов делается на основе времени создания папки виндузов на компьютере ))). завалить  ключ можно только переустановив windows ))). хакнуть можно написав маленький досовый экзешник, который установит дату создания папки на требуемом компьютере в нужное время ))).
так что повторюсь, взлом защиты должен превышать цену покупки. этого вполне достаточно

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 573
  • Карма: 135
    • ПГСу Бложик
Так как топик посвящен защите ПО, то хотелось бы узнать, как уважаемые форумчане пишущие на .net защищают свой од от просмотра и как выглядит защита этого кода?

Оффлайн BearDyugin

  • ADN Club
  • ****
  • Сообщений: 259
  • Карма: 22
  • Геодезист
работать можно если совпало минимум 2/3
При этом мне кажется, если из 3 параметров совпало только 2, то 3-й стоит переписать на новое значение?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2457
  • Карма: 692
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
в картинке результат работы этих функций на компьютере, собранном вручную (возможно, если б это был ноут или запаяный деловский или HP-шный корпус, было бы более информативно ))) )
Эта информация не является неизменяемой.
У меня был случай, когда я обновлял BIOS своей материнской платы. После этого, слетела регистрация всех моих автокадов и у меня не получилось никак их заново активировать. Помню, я даже обращался в ADN за помощью в этом вопросе.
Дело оказалось вот в чем: в утилите обновления есть кнопка "Clear DMI". Ну я ее и нажал, по глупости, удалив, тем самым, данные о номере матплаты из BIOS. В итоге, удалось раскопать инструмент, который позволил вбить этот номер заново и проблема пропала.
http://www.gigabyte.ru/forum/viewtopic.php?f=58&t=84520&p=398811#p398811

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 33
Цитировать
При этом мне кажется, если из 3 параметров совпало только 2, то 3-й стоит переписать на новое значение?
ага, только делать это желательно незаметно для пользователя (дата последних изменений файла лицензии меняться не должна, чтоб пользователь ничего не заподозрил ))) )

Так как топик посвящен защите ПО, то хотелось бы узнать, как уважаемые форумчане пишущие на .net защищают свой од от просмотра и как выглядит защита этого кода?
хоть я и начинающий дотнетовец ))) (жизнь заставила разбираться с ревитом))) ) но на этот вопрос ответ один - обфускаторы. по факту, на любой обфускатор есть "деобфускаторы", да и, как пишут люди, после обфускации иногда увеличивается время обработки функций. в принципе, это имеет право оказатья правдой, ведь обфускация не защищает код, а путает следы ))). так что правильный ответ будет... увы никак. из советов в интернете советуют на дотнете делать то, что не жалко, а всю логику выносить в web сервисы или писать на с++. по факту, на c# пишут полностью всё))) в надежде на порядочность и особо не заморачиваются возможностью взлома.
уж что точно не стоит писать на c#, так это защиту ))) с открытым ключом проверки.

Эта информация не является неизменяемой.
тут вот в чем дело... я и не утверждал, что это константы, выцарапанные гвоздем на заводе))). но какова будет вероятность того, что это компьютер, для которого была получена лицензия, если 4/5 характеристик не совпали с данными ключа? а так как в тех полях просто мусор, скорей всего одинаковый для всех компьютеров на моей фирмы ))), т.к. готовое в принципе не берем, а собираем под себя и свои требования, то данные поля в ключе перекинутом на разные компьютеры совпадут, что уж точно не есть хорошо. пользоваться лучше осмысленными полями, хоть вероятность нарваться на пустое всегда остается. отсюда вывод - чем больше полей возьмем, тем лучше.

Оффлайн BearDyugin

  • ADN Club
  • ****
  • Сообщений: 259
  • Карма: 22
  • Геодезист
Ну в общем так и сделал, собрал серийник из:
  • части Mac адреса,
  • части GUID-а,
  • кода приложения,
  • части  ProcessorId.
Но вот примерно каждый третий серийник стал приходить, где часть Mac адреса,и часть GUID-а, совпадают.
Тогда проверил ещё раз что возвращают эти функции, на моём ПК
Get_MacAddress -> ("FC:8B:97:0A:52:FE" "48:5B:39:97:5B:88")
Get_GUID -> "7E529360-FE8D-11D5-84C5-485B39975B88"
и оказалось они содержат общую часть...