Всем привет! Т.к. привязка v1 была сделана не совсем правильно (особенно хранение hwid) я решил сделать новую версию, на этот раз подменить ответ будет невозможно. Только надо изменять инструкции программы для "кряка". В этой привязке мы сможем задавать время, до которого будет действительна лицензия.
Что нам понадобится
1. Класс для получения HWID (HardWare ID) - скачать
2. Класс для работы с RSA на C# - скачать
3. PHP скрипты - скачать
4. Хостинг с поддержкой PHP - на данном примере я буду использовать хостинг от koding.com (не реклама)
5. MySQL - на данном примере я буду использовать [Ссылки могут видеть только зарегистрированные пользователи. ] (не реклама)
6. Microsoft Visual Studio 2008+ с редистрибутивом C# - гугл : )
7. Базовые знания (например как добавить класс в проект)
Начнём
1. Для начала необходимо создать MySQL базу. Для этого зарегистрируемся на [Ссылки могут видеть только зарегистрированные пользователи. ] и создадим MySQL базу (не MSSQL).
У вас должно получится что-то типо такого:скрин
[Ссылки могут видеть только зарегистрированные пользователи. ]
2. Теперь создадим таблицу в MySQL базе данных, где будет храниться информация для лицензии. Для этого зайдём в phpMyAdmin, введём туда данные (пароль после регистрации бд приходит на почту) и нажмём "Создать таблицу", количество полей 2 - с именами "Hardware ID" и "End Time", тип - TEXT, и далее обязательно выставтить сравнение на "utf8_general_ci". и нажать "Сохранить". скрин
[Ссылки могут видеть только зарегистрированные пользователи. ]
3. Теперь надо сгенерировать паблик и приват ключи RSA. Для этого создадим проект с шаблоном "Приложение Windows Forms" и назовём его RSAKeysGenerator, далее на основную Form кинем 2 textBox-a, 2 label-a и 1 кнопку. Так же добавим в проект DigitalSign.cs. скрин
[Ссылки могут видеть только зарегистрированные пользователи. ]
Мы заменяем на адрес сервера где расположена MySQL БД.
В моём случае:
Код:
$MySQL_hostname = "sql3.freesqldatabase.com";
Далее
Код:
$MySQL_username = "user";
Мы за меняем на имя пользователя для MySQL бд.
В моём случае:
Код:
$MySQL_username = "sql313795";
Далее
Код:
$MySQL_password = "password";
Мы заменяем на пароль для пользователя для MySQL бд.
Далее
Код:
$MySQL_databasename = "database name";
Мы заменяем на имя базы данной для MySQL.
В моём случае:
Код:
$MySQL_databasename = "sql313795";
Далее
Мы заменяем имя таблицы MySQL бд
Код:
$MySQL_table = "table name";
В моём случае:
Код:
$MySQL_table = "licensetable";
Всё, сохраняем настройки, загружаем все php файлы на сервер.
7. Теперь создадим новый проект тот же шаблон "Приложение Windows Forms". На него кинем 1 richTextBox, 1 кнопку. Добавим в проект DigitalSign.cs и HWIDGrabber.cs
Теперь объявим пару функций (можно прямо в коде формы)
Код:
public string getDays(TimeSpan time)
{
return ((time < TimeSpan.Zero) ? String.Format("Лицензия истекла {0} дней {1} часов {2} минут назад", Math.Abs(time.Days).ToString(), Math.Abs(time.Hours).ToString(), Math.Abs(time.Minutes).ToString()) : String.Format("Лицензия активна. Осталось {0} дней {1} часов {2} минут", time.Days, time.Hours, time.Minutes));
}
public static string getSignedText(string[] response)
{
string returned = String.Empty;
for (int i = 0; i < response.Length - 1; i++)
{
returned += response.GetValue(i) + "\r\n";
}
return returned;
}
public static string info(Random rn, Int32 token1,string preKey)
{
string tokenString = String.Format("token={0}&hwid={1}", DigitalSign.EncryptString(token1.ToString(), preKey), HWIDGrabber.GetUHI);
return tokenString;
}
public static string GetRequest(string url, string post)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
byte[] buffer = Encoding.UTF8.GetBytes(post);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = buffer.Length;
request.Method = "POST";
Stream newStream = request.GetRequestStream();
newStream.Write(buffer, 0, post.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader strReader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1251));
string WorkingPage = strReader.ReadToEnd();
response.Close();
return WorkingPage;
}
public static string randomStringWithNumbers(int maxlength, Random rn)
{
StringBuilder sb = new StringBuilder();
char[] allowedChars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
for (int i = 0; i < maxlength; i++)
{
int n = rn.Next(0, allowedChars.Length);
if (char.IsLetter(allowedChars[n]))
{
if (rn.Next(0, 2) == 0)
{
sb.Append(allowedChars[n].ToString().ToUpper());
}
else
{
sb.Append(allowedChars[n]);
}
}
else
{
sb.Append(allowedChars[n]);
}
}
return sb.ToString();
}
Теперь на эвент OnLoad на нашей форме запишем код:
Код:
richTextBox1.Text = HWIDGrabber.GetUHI;
p.s. если у вас ругается на ссылки, то вы должны подключить следующие:
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
А если ругается на Managment, то добавьте в ссылки System.Managment в .net ветке
Далее на эвент кнопки Click:
Код:
//////////////////////////////////////////////////////////////////////////////////////////
string pubKeyNotXORed = "<RSAKeyValue><Modulus></Modulus><Exponent></Exponent></RSAKeyValue>"; //Сюда в кавычки копируем ПАБЛИК rsa ключ.
//////////////////////////////////////////////////////////////////////////////////////////
Random curRandom = new Random();
string preKey = randomStringWithNumbers(curRandom.Next(15, 21), curRandom);
Int32 XORkey = curRandom.Next(1, int.MaxValue);
///////////////////////////////////////////////////////////////////////////////////////////
string urlToScript = DigitalSign.XOR("http://site.com/base.php", XORkey); //Вместо site.com/base.php полный путь до скрипта на вашем хостинге
///////////////////////////////////////////////////////////////////////////////////////////
string pubKey = DigitalSign.XOR(pubKeyNotXORed, XORkey);
Int32 token = curRandom.Next(1000000, int.MaxValue);
string infoXORed = DigitalSign.XOR(info(curRandom, token, preKey), XORkey);
string responseXORed = DigitalSign.XOR(GetRequest(DigitalSign.XOR(urlToScript, XORkey), DigitalSign.XOR(infoXORed, XORkey)), XORkey);
string[] responseSplitted = DigitalSign.XOR(responseXORed, XORkey).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
try
{
if (responseSplitted[0].Split('=')[1] == "1")
{
if (Int32.Parse(DigitalSign.DecryptString(responseSplitted[4], preKey)) == token)
{
if (HWIDGrabber.GetUHI == Encoding.UTF8.GetString(Convert.FromBase64String(responseSplitted[1].Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries)[0])))
{
if (DigitalSign.CompareRSAMethod(getSignedText(responseSplitted), responseSplitted[responseSplitted.Length - 1].Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries)[0], DigitalSign.XOR(pubKey, XORkey)))
{
DateTime CurrentTime = DateTime.Parse(responseSplitted[2].Split('=')[1]);
DateTime EndTime = DateTime.Parse(responseSplitted[3].Split('=')[1]);
TimeSpan ActivatedTime = EndTime.Subtract(CurrentTime);
if (ActivatedTime < TimeSpan.Zero)
{
MessageBox.Show(getDays(ActivatedTime));
//Тут мы что-то делаем, если лицензия истекла
}
else
{
MessageBox.Show(getDays(ActivatedTime));
//Тут мы что-то делаем, если лицензия активна.
}
}
}
}
}
else
{
MessageBox.Show("Лицензии не обнаружено!");
}
}
catch (Exception ex)
{
MessageBox.Show("Ошибка!\nКатастрофа!\nАхтунг!");
//AnyErrors
}
8. Запускаем, видим что в richTextBox появился наш HWID.
Жмём на кнопку, получаем
[Ссылки могут видеть только зарегистрированные пользователи. ]
9. Идём в phpMyAdmin, открывает нашу таблицу выбираем "Вставить", в Hardware ID пишем то, что выдал richTextBox, в EndTime время окончания, строго в таком формате: 14.07.2013 20:00:00
[Ссылки могут видеть только зарегистрированные пользователи. ]
10. Опять нажимаем на кнопку, и получаем:
[Ссылки могут видеть только зарегистрированные пользователи. ]
11. Пробуем поставить время окончания лицензии раньше нашего текущего времени, получем:
[Ссылки могут видеть только зарегистрированные пользователи. ]
Заключение
Я сделал лишь основу, дальше вы можете модернизировать, как вам захочется, сделать автоматическое добавление в базу и т.д.
Самое главное - это обезопасить себя от декомпиляции кода, полностью обезопасить - невозможно, но от обычных юзеров можно.
Для этого делаем скрытые проверки, делаем условия из нескольких переменных типа int на основе математики и так далее... Ну и конечно использовать обсуфикаторы.
За основу для работы с RSA на php были взяты скрипты от Jim Wigginton
Гайд подготовил Nickitee специально для zhyk.ru
Автор не несёт ответственности за пользование информацией
При копировании на другие сайты/блоги/форумы и т.п. - указывать автора
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
Последний раз редактировалось Nickitee; 23.12.2013 в 02:31.
Мне очень нравятся книги Криса Касперски. В одной он дал совет, никогда! не используйте привязку через интернет. Все это ловиться снифером, пишется hook ws2_32 и...собственно все.
Как вариант, использование собственных упаковок, которые без какой либо проверки прогоняют код, юзер платит за ключ, и получает декодер. Если ключ не верный, юзер получает мусор. Ну или, самомодификация кода.
Все эти messagebox, label вообще любое сообщение о неверном/верном, выдают вас! Считайте, что вашу защиту уже поломали
Простейший пример моей идеи, что мешает продавать юзеру STEP1/STEP2 ?
А в str можно засунуть, секцию .code и прогнать Можно вообще все, включая заголовки.
Последний раз редактировалось pqsl; 14.07.2013 в 21:16.
Причина: Добавлено сообщение
Мне очень нравятся книги Криса Касперски. В одной он дал совет, никогда! не используйте привязку через интернет. Все это ловиться снифером, пишется hook ws2_32 и...собственно все.
Как вариант, использование собственных упаковок, которые без какой либо проверки прогоняют код, юзер платит за ключ, и получает декодер. Если ключ не верный, юзер получает мусор. Ну или, самомодификация кода.
Все эти messagebox, label вообще любое сообщение о неверном/верном, выдают вас! Считайте, что вашу защиту уже поломали
Ты думаешь?
Я разве не писал что тут нельзя подменить ответ?
И если накрыть приличным пакером типо Themida, то врядле рядовой юзер что-то сделает...
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
В коде мы в первую очередь проверяем license=1, далее мы проверяем HWID, чтобы нельзя было зная чужой HWID работать с программой, далее идут CT - текущее время, которое выводит сервер и ET - время окончания взятое с БД, дальше идёт закриптованный токен, он декриптуеся по случайно сгенерированому ключу и сверяется так же с токеном в программе, и в конце всё подписывается RSA-2048 и через паблик ключ проверяется подпись.
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
В коде мы в первую очередь проверяем license=1, далее мы проверяем HWID, чтобы нельзя было зная чужой HWID работать с программой, далее идут CT - текущее время, которое выводит сервер и ET - время окончания взятое с БД, дальше идёт закриптованный токен, он декриптуеся по случайно сгенерированому ключу и сверяется так же с токеном в программе, и в конце всё подписывается RSA-2048 и через паблик ключ проверяется подпись.
В дебагере будет видно, что делают с пакетом Никуда не денешься от этого
В дебагере будет видно, что делают с пакетом Никуда не денешься от этого
А зачем тогда пакеры? Тем более на сравнивай натив и .net.
----
Да и вообще, скомпиль, накрой каким-нибудь пакером, а потом попробуй снять и подменить ответ.
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
А зачем тогда пакеры? Тем более на сравнивайй натив и .net.
----
Да и вообще, скомпиль, накрой каким-нибудь пакером, а потом попробуй снять и подменить ответ.
Я не сравниваю. Я выдвигаю абстрактные теории/способы
У меня нет Windows. Да если и был бы, что тогда ? Запакую я паблик пакером и т.д Транслирую шифр из машинного на Си и т.д На паблик пакер можно найти распаковку, если конечно Вы не дадите мне ключ
Да и та же темида, распакует программу в память. Делаем дамп, восстанавливаем oep, import list и т.д
Последний раз редактировалось pqsl; 14.07.2013 в 22:15.
Ну вот, теории никому не нужны. Только работающие способы.
Ахахах, попробуй это сказать гуглу или любой другой серьезной исследовательской конторе.
Если сделать всё правильно, привязка действительно будет действовать до модификации самой программы или полного, я повторяю, ПОЛНОГО копирования скриптов которые работают на сервере и подмены этого самого сервера.
Ахахах, попробуй это сказать гуглу или любой другой серьезной исследовательской конторе.
Если сделать всё правильно, привязка действительно будет действовать до модификации самой программы или полного, я повторяю, ПОЛНОГО копирования скриптов которые работают на сервере и подмены этого самого сервера.
Угу, только до самого полнейшего копирования всех скриптов на сервере.
Включая приват RSA ключ. Но это довольно таки сложно, даже не рядовому юзеру.
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
У меня нет Windows. Да если и был бы, что тогда ? Запакую я паблик пакером и т.д Транслирую шифр из машинного на Си и т.д На паблик пакер можно найти распаковку, если конечно Вы не дадите мне ключ
Да и та же темида, распакует программу в память. Делаем дамп, восстанавливаем oep, import list и т.д
На паблик пакер можно найти распаковку? Да ладно... Вы хотябы раз что-нибудь на виндовсе распаковывли? Ну и сделаешь ты дамп, а там будет не читабельный код, что дальше?
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
На паблик пакер можно найти распаковку? Да ладно... Вы хотябы раз что-нибудь на виндовсе распаковывли? Ну и сделаешь ты дамп, а там будет не читабельный код, что дальше?
Да бывало дело.
Прогоняя программу по пакеру/криптору на выходе мы получаем набор байт с высокой энтропией. Нам нужен загрузчик, который бы распаковывал программу и запускал. Так вот, что мешает дебажить загрузчик и поймать pe вашей программы ?