Разные серийные номера для разных частей приложения

Issues related to VMProtect
Post Reply
ivan_3
Posts: 10
Joined: Mon Jun 29, 2020 10:35 pm

Разные серийные номера для разных частей приложения

Post by ivan_3 »

Привет всем.

У нас в приложении есть несколько разделов приложения которые продаются как фичи и мы планируем сохранять информацию о том какие части приложения доступы в секции UserData. Т.е. при генерации серийника у нас будет записываться типа "Part_1, Part_2", типа можно пользовать часть 1 и 2 только.
Преположим, у нас есть 3 защищенные части.
Первый ключ разблочивает части 1 и 2, второй часть 3.
Когда пользователь использует часть 1 или 2 мы загружаем через VMProtectSetSerialNumber первый, когда ему нужна часть 3, мы вызываем VMProtectSetSerialNumber для части 3, а когда опять часть 1, то снова активируем первый ключ.

В связи с этим вопросы:
1. Правильно ли я понял идею с использованием UserData для разделения какой ключ для чего?
2. Не будет ли проблем с тем что так меняются ключи?
3. Как должна быть защищена секция, которая читает данные из UserData и принимает решения какие части приложения доступны, а какие нет?
Admin
Site Admin
Posts: 2566
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: Разные серийные номера для разных частей приложения

Post by Admin »

Я не понял зачем вам несколько серийников. Пользователь купил фичи 1 и 2 - записали в серийник "1,2". Докупил фичу "3" - выдали ему новый серийник с "1,2,3".
ivan_3
Posts: 10
Joined: Mon Jun 29, 2020 10:35 pm

Re: Разные серийные номера для разных частей приложения

Post by ivan_3 »

У разных серийников будет разное время жизни. Некоторые серийники вообще бессрочные, а некоторые для триалов с ограничением работы в пару недель.
YouBestClient
Posts: 14
Joined: Tue Mar 17, 2020 8:47 am

Re: Разные серийные номера для разных частей приложения

Post by YouBestClient »

ivan_3 wrote:У разных серийников будет разное время жизни. Некоторые серийники вообще бессрочные, а некоторые для триалов с ограничением работы в пару недель.
как сказано выше, используй "пользовательские данные" в серийном ключе. А в свою очередь этот серийник может быть триалом, бессрочным и т.д.
Admin
Site Admin
Posts: 2566
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: Разные серийные номера для разных частей приложения

Post by Admin »

У разных серийников будет разное время жизни. Некоторые серийники вообще бессрочные, а некоторые для триалов с ограничением работы в пару недель.
Обычно в программе используется только один серийник (так гораздо удобнее для конечного пользователя), а все остальные опции зашиваются в UserData. При вашей схеме мне например совершенно непонятно как серийники вообще попадают в программу (они у вас там где-то списком лежат?). Вот у вас запускается программа. Нужно проверить доступ к пунктам меню "1", "2" и "3". Вы начинаете перебирать все доступные серийники и анализировать UserData? Прикол начнется когда у вас к существующему списку начнут добавляться серийники, имеющие "более высокий приоритет" - это когда например у вас в списке серийников есть триал на "3", а пользователь потом купил фичу "3" и этот серийник попал в общий список - как при этом будет вести себя программа, если триальный серийник попадет в "конец списка"?

Ну и самое плохое у данной схемы - вы не сможете "безопасно" определить (без повторного перебора всех доступных серийников) внутри выполнения фичи "3" - действительно ли она доступна пользователю или это просто хакер руками сделал доступен соответствующий пункт меню. При использовании одного серийника это можно было бы достаточно "просто" проанализировать с помощью VMProtect и накрыть этот код виртуализацией:

Code: Select all

void feature3()
{
  if (VMProtectGetSerialNumberSate() != SERIAL_STATE_SUCCESS)
    throw std::runtime_error("This feature isn't available");
    
  VMProtectSerialNumberData vmp_data;
  if (!VMProtectGetSerialNumberData(vmp_data, sizeof(vmp_data))
    throw std::runtime_error("This feature isn't available");
    
  if (! (vmp_data.UserData contains "feature_3"))  
    throw std::runtime_error("This feature isn't available");

  // your code here
}
ivan_3
Posts: 10
Joined: Mon Jun 29, 2020 10:35 pm

Re: Разные серийные номера для разных частей приложения

Post by ivan_3 »

Полностью с вами согласен что очень, так сказать, неправильное решение с переключением серийников, но у нас на разные фичи у серийников разный срок действия.
Одним серийником мы ведь такое сделать не сможем?
При вашей схеме мне например совершенно непонятно как серийники вообще попадают в программу (они у вас там где-то списком лежат?).
Серийники генерит наш самописный сервер и приложение само их скачивает и активирует в автоматическом режиме. Для пользователя все махинации с серийником выглядят прозрачно. От пользователя максимум что нужно это авторизоваться и далее он просто пользуется приложением. Если нужен триал на какую-то фичу, то просто сервер сгенерит триальный серийник, а приложение его скачает и активирует в нужный момент.
Прикол начнется когда у вас к существующему списку начнут добавляться серийники, имеющие "более высокий приоритет" - это когда например у вас в списке серийников есть триал на "3", а пользователь потом купил фичу "3" и этот серийник попал в общий список - как при этом будет вести себя программа, если триальный серийник попадет в "конец списка"?
Да, есть список серийников и у серийнков есть флаги (которые отдает сервер) для чего подходит данный серийник. Т.е. мы можем выбрать нужный серийник без необходимости вызова для каждого VMProtectSetSerialNumber.

У нас есть 3 вида фичей:
1. платные с подпиской - у них серийники будут по 3 месяца и потом продляться если пользователь дальше платит
2. триальные - ну это пару недель чтобы пользователь мог "поиграться" с фичей
3. бесплатные - у них нет ограничения по времени
Ну и самое плохое у данной схемы - вы не сможете "безопасно" определить (без повторного перебора всех доступных серийников) внутри выполнения фичи "3" - действительно ли она доступна пользователю или это просто хакер руками сделал доступен соответствующий пункт меню
Я думал так сделать:

Code: Select all

struct Serial {
  bool to_feature_1;
  bool to_feature_2;
  std::vector<char> data;
};

std::vector<Serial> serials;

void Feature1() {
  for (const auto& next : serials) {
    if (next.to_feature_1) {
      if (VMProtectSetSerialNumber(next.data().c_str()) == SERIAL_STATE_SUCCESS) {
        VMProtectSerialNumberData vmp_data;
        if (VMProtectGetSerialNumberData(vmp_data, sizeof(vmp_data))) {
          if (vmp_data.UserData contains "feature_1")) {
            // correct serial found
            return;
          }
        }
      }
    }
  }
  // correct serial not found
}
YouBestClient
Posts: 14
Joined: Tue Mar 17, 2020 8:47 am

Re: Разные серийные номера для разных частей приложения

Post by YouBestClient »

Самый простой способ
в UserData указать Номер_Функции=Когда_закончится;
Пример: 1=2020-10-10;2=2020-08-10
либо выдавай ключа до ближайшей даты окончания любой платной функции (1, 2, 3), а там уже будет запрос к серверу за новым ключём, а сервер уже сам решит какой ключ отдавать с каким функционалом, либо триалку. Собственно зачем логику работы с разными серийниками переносить в код программы, когда за это может отвечать сервер. И выдавать суточную лицензию с разрешённым функционалом
Post Reply