Licence Key to C++

Тема в разделе "Флудилка", создана пользователем HighDigital, 1 май 2013.

  1. HighDigital

    HighDigital Гик

    Всем привет! :)

    Вот задался себе вопросом - по какому принципу работает серийный/лицензионный ключ.
    А так же KeyGen этих ключей.

    Не, я не хочу ничего ломать и ничего изобретать, просто заинтересовало, возможно сделаю как "винт" и прикручу к какой-нибудь программе.

    В инете пишут, есть некие алгоритмы шифровки и дешифровки, но их я не нашел :/
    Может кто-нибудь вкраце может пояснить что да как? :)

    Заранее спасибо!
     
  2. warman

    warman Гик

    алгоритмов великое множество. Например, можно сделать привязку ключа с серийным номерам какого то оборудования. В этом случае при переносе программы на другое железо, или замена одной из компонент, на основе номеров которых строился общий серийный номер, приведет к необходимости покупки новой лицензии. А сам ключ в этом примере - просто зашифрованная структура из имени владельца и того же общего серийного номера. Программа при запуске заново вычисляет общий номер и сверяет его с указанным в лицензии. Если совпали - профит - позволит продолжить работу.
    Кейген работает на том же принципе, только в обратную сторону. Зная, как строится номер лицензии к программе, вычисляет необходимый номер, запрашивает на какого пользователя делать лицензию и создает итоговую структуру, которую подсовываем к оригинальной программе и "не платим разработчику".
    Это принцип с привязкой к оборудованию. Бывает еще просто последовательность символов, такой ломается проще менее надежен по определению.
     
  3. HighDigital

    HighDigital Гик

    а что он запрашивает у компьютера, Mac-адрес?
    или есть ещё что-то индивидуальное у компьютера?

    И как можно запросить у компьютера МАС-адрес через С++?
    Где про это можно почитать?
     
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Серийный номер процессора, жесткого диска, да практически любой железки в компе...
    А вот MAC-адрес скорей всего не используют, т.к. его можно изменить программно.
     
  5. warman

    warman Гик

    можно и МАС адрес, можно и серийные номера процессора/мат.платы/жесткого диска
    Для Arduino можно и ATSHA204 чип использовать

    http://www.cracklab.ru/pro/cpp.php?r=network&d=zdrt21
     
  6. HighDigital

    HighDigital Гик

    Гигантское спасибо! :)
     
  7. HighDigital

    HighDigital Гик

    Но я попробовал сделать по своему, конечно толку ноль от такого серийника, но зато очень хорошо защищает от пользователей "начального уровня" :)

    пример серийника: p3t5-zk65-7
    "p3t5" - часть X
    "7" - часть Y
    "zk65" - программная часть (если этого требует программа, например доступ "root" или "user", некая "активация дополнения программы" и т.п)

    Расчет идет по такому принципу: X - Y = 260
    Программная часть в проверку серийника не идёт.

    Если хотите: могу код выложить :)
     
  8. HighDigital

    HighDigital Гик

    Так же keygen для него сделал.
     
  9. pasha08

    pasha08 Нерд

    Выкладывай) Только насчет X-Y как то не понял. Как ты из букв вычитаешь цифры?
     
  10. HighDigital

    HighDigital Гик

    Обратимся к теории: весь "внутренний мир" компьютера состоит из "0" и "1".
    Следовательно все в компе "0" и "1".
    Тогда почему бы и не вычесть? :)
    Но это очень глубоко, я обратился к ACSII таблице, где у каждого символа в системе (их 255) есть свой номер.
    т.е сначало в "приёмнике" мы весь серийник ( а он у меня в массиве key[] типа char) конвертируем в численный вид (тип int), вычисляем, проверяем,
    "if(md2==260){Правильно!}", с кейгеном наоборот.
     
  11. HighDigital

    HighDigital Гик

    Проверялка:
    Код (Text):
    #include <iostream>
    #include <string.h>
    #include <conio.h>
     
    #define GEN_MD 260 //Сумма, которая получится в результате вычислений.
     
    using namespace std;
    char str[255] = {0};
    char ch;
    char* p = str;
     
    int buff[] ={0};
     
    int main()
    {
        cout << "LKE, press your licence key: " << endl;
    //***********************************************
        memset(str, 0, 255); //Ввод серийника
        p = str;
        while (cin.get(ch) && isalnum(ch)) *p++ = ch;
    //***********************************************
     
    //===============================================
        for(int q=0; q<9; q++) //конвертация из char в int
        {
            buff[q] = str[q];
        }
    //===============================================
        buff[16] = buff[0] + buff[1] + buff[2] + buff[3] - buff[8]; //Вычисляем по формуле.
     
        if(buff[16] == GEN_MD)
        {
            //Accept
            cout << endl << "Accept!" << endl;
            while(true)
            {
            //Выполнение программы...
            }
        }
        else
        {
            //ERROR, не лицензионный!
            cout << endl << "Invalid key!" << endl << "Reboot programm, and reenter your key..."
            << endl << "Press any key, to out programm...";
            getch();
            return 0;
            //cout << "MD = " << buff[16] << endl;
            //cout << endl << buff[0] << " " << buff[1] << " " << buff[2] << " " << buff[3] << " - " << buff[8] << endl;
        }
    //===============================================
     
    }
     
    КейГен:
    Код (Text):
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <time.h>
     
    #define GEN_Type 260 //Сумма, которая должна получиться
    #define PER_Type 2 //permission
     
    using namespace std;
     
    char key[] = {0};
    int buff[] = {0};
     
    int md1[2] = {0};
    int md2[2] = {0};
    int x[1] = {0};
     
    void aces(int xx) //Permission to User
    {
        switch(xx)
        {
        case 0:
            {
                cout << "root";
                break;
            }
        case 1:
            {
                cout << "admin";
                break;
            }
        case 2:
            {
                cout << "user";
                break;
            }
            default: cout << "error"; break;
        }
    }
     
    int main()
    {
        cout << "Press 'g' - to generate key, press 'q' - to exit programm, 'i' - info" << endl;
     
        while(true)
        {
            if(getch() == 'g')
            {
                //X-Y=260;
        //****************************************
                srand(time(0));
                x[1] = rand() % 9 + 48; //от 0 до 9
     
                buff[8] = x[1]; //вычитаемое Y
                md1[1]=GEN_Type+x[1]; //MD1 - сумма ключа Х, которая должна получиться
        //===
        //Генерация ключа X
                srand(time(0));
                buff[0] = rand() % 16 + 97;
     
                srand(time(0));
                buff[1] = rand() % 9 + 48;
     
                buff[10] = 97;
     
                srand(time(0));
                buff[3] = rand() % 7 + 48;
        //===
                md2[1] = md1[1] - buff[0] - buff[1] - buff[10] - buff[3]; //MD2 - Проверка, сравнение с md1
     
                buff[2] = buff[10] + md2[1]; //Сливаем остаток в 3-ий символ части Х
     
                //Конвертация из int в char.
                key[0] = buff[0];
                key[1] = buff[1];
                key[2] = buff[2];
                key[3] = buff[3];
                key[4] = 'u';
                key[5] = 'p';
                key[6] = '8';
                key[7] = '0';
                key[8] = x[1];
     
        //****************************************
                cout << "================" << endl;
                cout << "MD = " << md1[1] << "/" << md2[1] << endl; //Проверка
                cout << "permission: "; aces(PER_Type); cout << endl << endl;
                cout << "Key: ";
                for(int i=0; i<9; i++) cout << key[i];
                cout << endl;
                cout << "================" << endl << endl;
            }
            if(getch() == 'i')
            {
                cout << endl;
                cout << "---------------" << endl << "KeyGen v1.4" << endl << "---------------" << endl;
            }
            if(getch() == 'q')
            {
                break;
                break;
            }
        }
        return 0;
    }
     
    Немного о кейгене: он не совершенен, его следует доработать...
    В него я встроил три режима пользователей: root, admin, user.
    После ввода пользователя, нажимаете "g", он вам генерирует ключ.

    Если в строке MD второе число отрицательное - заново нажмите на "g", оно должно быть положительное, иначе возможна ошибка в ключе.
    Потом я автоматизирую этот процесс..

    Проверял на Win7 Ultimate x64
     
  12. pasha08

    pasha08 Нерд

    Что то не дошло до меня сначала. И она не ACSII а ASCII.
     
  13. HighDigital

    HighDigital Гик

    Я постоянно путаю :)
     
  14. Unixon

    Unixon Оракул Модератор

    Читайте как [аски] и не будете путать.

    p.s. ИМХО, не делом вы занимаетесь. За применение программной защиты в FOSS/OSHW черные метки выдают ;)
     
  15. warman

    warman Гик

    OSHW не запрещено использовать в коммерческих проектах, а комерческий код надо защищать. Нигде не написано, что если железо опенсорсное, то оно не может нести в себе проприетарный код.
    Так же можно взять плату ардуино и вытереть программатором загрузчик, залить свой - вот и всё, железо опенсорс, прошивка проприетарная :)
     
  16. HighDigital

    HighDigital Гик

    Ну да, я не мастер в этом, что то попытался сделать в этой сфере))