PDA

Просмотр полной версии : [Руководство] Oнлaйн вepификaция + yлyчшeннaя пpивязкa к жeлeзy


Тигрь
30.04.2011, 23:39
Oнлaйн вepификaция и yлyчшeннaя привязка к жeлeзy.

B пpeдыдyщeй cтaтьe ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) я paccкaзaл o тoм кaк cдeлaть пpивязкy к жeлeзy. Ceгoдня я paccкaжy кaк yлyчшить этy зaщитy и cдeлaть oнлaйн вepификaцию. Улyчшaть зaщитy бyдeм ввeдeниeм дoпoлнитeльныx пapaмeтpoв жeлeзa к кoтopым можно пpивязывaтьcя. B кaчecтвe eщe oднoгo пapaмeтpa бyдeм иcпoльзoвaть системную информаwию. Для пoлyчeния вocпoльзyeмcя API-фyнкциeй GetSystemInfo. Эта функция в качестве параметра принимает структуру в поля которой помещается различная системная информация. Структура SYSTEM_INFO:

_SYSTEM_INFO = record
case Integer of
0: (
dwOemId: DWORD);
1: (
wProcessorArchitecture: Word;
wReserved: Word;
dwPageSize: DWORD;
lpMinimumApplicationAddress: Pointer;
lpMaximumApplicationAddress: Pointer;
dwActiveProcessorMask: DWORD;
dwNumberOfProcessors: DWORD;
dwProcessorType: DWORD;
dwAllocationGranularity: DWORD;
wProcessorLevel: Word;
wProcessorRevision: Word);
end;

Дaнныe этoй фyнкции нeльзя пoдмeнить кaк cepийный нoмep жecткoгo диcкa или мaк aдpec, чтo yвeличивaeт нaдeжнocть зaщиты. Я пpивeдy фyнкцию кoтopaя бyдeт гeнepиpoвaть yникaльнyю cтpoкy c пapaмeтpaми системы кoтopyю мoжнo бyдeт иcпoльзoвaть для пpивязки. Назовем ее GetSystemInfoAll.

function GetSystemInfoAll: String;
var
siSysInfo: TSystemInfo;
begin
GetSystemInfo(siSysInfo);
with siSysInfo do begin
Result := IntToStr(dwActiveProcessorMask) +
IntToStr(dwPageSize) +
IntToStr(dwNumberOfProcessors) +
IntToStr(dwProcessorType) +
IntToStr(dwAllocationGranularity) +
IntToStr(wProcessorArchitecture) +
IntToStr(wProcessorLevel) +
IntToStr(wProcessorRevision);
end;
end;

Опишу что обозначают исползованные нами поля структуры:

dwActiveProcessorMask - возвращает маску, представляющую набор процессоров, сконфигурированных в системе. Бит 0 представляет первый процессор, а бит 31 – 32-й
dwPageSize - содержит размер страницы в килобайтах и определяет степень разбиения при защите и фиксации страниц
dwNumberOfProcessors - число процессоров в компьютере
dwProcessorType - тип процессора
dwAllocationGranularity - минимальный размер резервируемой области памяти
wProcessorArchitecture - описывает тип архитектуры используемого процессора
wProcessorLevel - определяет уровень процессора, зависящий от архитектуры системы
wProcessorRevision - определяет модификацию процессора, зависящую от архитектуры системы

Teпepь мoдифициpyeм фyнкцию пoлyчeния ид (из предыдущей статьи) для пpивязки c иcпoльзoвaниeм фyнкции GetSystemInfoAll.

//Генерируем серийник
function getSerial:string;
begin
Result := StringToHex((GetComputerNetName + GetUserFromWindows + GetSerialNum + GetSystemInfoAll),'');
end;

Teпepь пepeйдeм к oнлaйн вepификaции.

Пpиeмyщecтвo oнлaйн вepификaции пepeд oбычным ввoдoм cepийнoгo нoмepa в тoм чтo вы в любoй мoмeнт мoжeтe зaпpeтить дocтyп любoмy пoльзoвaтeлю, нaпpимep ecли oн нapyшил ycлoвия пoльзoвaния пpoгpaммoй. Итак ключ в данном случае у нас будет хранится на сервере а не вводиться в программу. Теперь определимся с тем как наша защищаемая программа будет его получать, а затем уже перейдем к самой проверке полученного ключа в нашей защищаемой программе.

Тут тоже море вариантов. Мы рассмотрим самый простой.
Создадим текстовый файл с названием серийного номера который прислал нам пользователь, а в этом файле первой строкой запишем наш ключ. Вот и все. Защищаемая программа будет генирировать серийник, затем с назнанием серийника скачивать файл с нашего сервера и читать оттуда ключ. Дальше она проверит ключ и если он подходит для этого железа то программа скажет нам что все ОК, иначе она скажет обратное.

Алгоритм:
Защищаемая программа будет генерировать серийник (например: 6XXXV46546), затем с названием серийника скачивать файл с нашего сервера (6XXXV46546.txt) и читать оттуда ключ. Дальше она сгенерирует ключ и сравнит его с тем что указан в скачанном файле, если эти ключи равны то программа скажет нам что все ОК, иначе она скажет обратное.

Исходный код я приводить не стану и оставлю его разработку на вас, так как нужно всего лишь немного модифицировать код из первой статьи.

Если вдруг возникнут какие то проблемы с написанием кода, то помогу в написании.

© Тигрь.

АзЕсмьЦарь
01.05.2011, 11:47
Вряд ли антивирусам понравится, что какая-то прога сканирует систему для своих нужд, да ещё потом отправляет собранные данные через интернет.

Тигрь
01.05.2011, 17:39
Если тебе нужна к примеру такая программа и ты будешь ей пользоваться то добавишь ее в исключения, если не нужна то и ставить не будешь.

Kyroki
01.05.2011, 18:32
он имел ввиду,когда другому скидываешь,антивирус может тупо не пустить ее

Тигрь
01.05.2011, 19:51
Пустит. Вообще проактивная защита будет орать на любые читы.

lcd1232
29.02.2012, 19:36
Тигрь, а процедуры уже встроены в делфи или в инете искать?

Тигрь
29.02.2012, 19:57
Смотря какие, StringToHex самописная, но я вроде ее в предыдущей статье приводил

lcd1232
29.02.2012, 20:07
wProcessorArchitecture: Word;
wReserved: Word;
dwPageSize: DWORD;
lpMinimumApplicationAddress: Pointer;
lpMaximumApplicationAddress: Pointer;
dwActiveProcessorMask: DWORD;
dwNumberOfProcessors: DWORD;
dwProcessorType: DWORD;
dwAllocationGranularity: DWORD;
wProcessorLevel: Word;
wProcessorRevision: Word);
Вот эти. Как я понял их в интернете искать?

VeTaL_UA
29.02.2012, 21:00
Вот эти. Как я понял их в интернете искать?
_SYSTEM_INFO = record
Ни о чём не говорит? msdn ([Ссылки могут видеть только зарегистрированные и активированные пользователи](v=vs.85).aspx)

Zo_Om4eG
17.03.2012, 07:30
Хм, а не посоветуете ли где взять такой хостинг? Юкоз к примеру подойдет? Желательно с сорцами для подключения к серверу и скачке нужной информации.

VeTaL_UA
17.03.2012, 10:26
Юкоз к примеру подойдет?
Подойдёт, но всё же лучше использовать платные хостинги.

FarmHitman1
18.03.2012, 19:14
Пример на ucoz, если кому интересно :)

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Clear;
Edit1.Text := (GetSerial);
Button2.click;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Response:TFileStream;
s:string;
Version:TStringList;
begin
[Ссылки могут видеть только зарегистрированные и активированные пользователи](nil);
Version:=TStringList.Create;
try
s:=[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]Ваш сайт.ucoz.ru/Name.txt');
if Pos(s,Edit1.Text)<>0 then //Проверка ключа полученный в Edit1 и написанный в Name.txt
begin
ShowMessage('Все ок')
end
else
begin
ShowMessage('Не верный ключ.');
end;
finally
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Version.Free;
end;
end;

В принципе все, мб у кого то еще на что то фантазии хватит.
PS: Проверку ключа переделал с помощью этой темы [Ссылки могут видеть только зарегистрированные и активированные пользователи]

victor20011
24.05.2012, 00:45
а как сделать что бы он не 1 HWID сравнивал а много??

например весь список с 1 до 100 и HWID это тот тогда пропускает дальше

Тигрь
24.05.2012, 04:30
Есть такая штука, называется цыклы.

victor20011
24.05.2012, 10:37
for i :=0 to -1 do?
а дальше что ?))))
если не трудно обьясните тогда что нужно сделать.
Скачать в мемо и там уже проверять?

st:=id[Ссылки могут видеть только зарегистрированные и активированные пользователи]('url')
memo1.lines.text:=st;
for i := 0 to memo1.Lines.Count -1 do
if memo1.Lines[i]=edit1.Text
then label1.caption:='Ключ верный, Вы вошли в аккаунт'
else label1.Caption:=('Неверный ключ!');

вот так правильно да?)

Skrillex3
24.05.2012, 11:14
for i :=0 to -1 do?
а дальше что ?))))
если не трудно обьясните тогда что нужно сделать.
Скачать в мемо и там уже проверять?

st:=id[Ссылки могут видеть только зарегистрированные и активированные пользователи]('url')
memo1.lines.text:=st;
for i := 0 to memo1.Lines.Count -1 do
if memo1.Lines[i]=edit1.Text
then label1.caption:='Ключ верный, Вы вошли в аккаунт'
else label1.Caption:=('Неверный ключ!');

вот так правильно да?)

с кодом скачивания не помогу ,а с проверкой могу , гдето там ты как бы скачиваешь файлик с ключами ну и дальше загрузаешь в стринглист и обрабатываешь , всё просто
Var Data:tstringlist;
begin
Data:=tstringlist.create;
Data.loadFromFile('blabla.txt');
For i := 0 to Data.count -1 do
begin
if Edit1.text= Data[i] then
begin
Showmessage('Ключ найден!');
Break;
end;
end;

victor20011
24.05.2012, 11:44
да но так нужно скачивать фаил
а потом прийдеться удалять

st:=id[Ссылки могут видеть только зарегистрированные и активированные пользователи]('url')
memo1.lines.text:=st;
for i := 0 to memo1.Lines.Count -1 do
if memo1.Lines[i]=edit1.Text
then label1.caption:='Ключ верный, Вы вошли в аккаунт'
else label1.Caption:=('Неверный ключ!');

вот этот код мне тоже помго но
он только сверяеться с последним)))

Relli
24.05.2012, 13:41
var
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Response:TFileStream;
s,a:string;
Version:TStringList;
begin
a := getSerial; //ключик
[Ссылки могут видеть только зарегистрированные и активированные пользователи](nil);
Version:=TStringList.Create;
try
s:=[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]******.ucoz.ru/****.txt');
if a = s then //если текст в файле совпадает,то нас пускает
begin
ShowMessage('Ключ действителен.');
Form1.Show;
Form2.Hide;
end
else
begin
ShowMessage('Ключ не действителен.');
Form1.Hide;
end;
finally
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Version.Free;
end;
Это пример получения текстового файла и чтение его.Но он читается полностью.Н-р если у тебя пароли фиксированного значения,то читай каждые N-ые символы.Т.е. если у тебя пас по 5 символов,а в текстовом файле их 5(пасов).То читаешь в переменную какуюнить по циклу с s[1] по s[5],это например первый пас и тд.

victor20011
24.05.2012, 14:11
var
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Response:TFileStream;
s,a:string;
Version:TStringList;
begin
a := getSerial; //ключик
[Ссылки могут видеть только зарегистрированные и активированные пользователи](nil);
Version:=TStringList.Create;
try
s:=[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]******.ucoz.ru/****.txt');
if a = s then //если текст в файле совпадает,то нас пускает
begin
ShowMessage('Ключ действителен.');
Form1.Show;
Form2.Hide;
end
else
begin
ShowMessage('Ключ не действителен.');
Form1.Hide;
end;
finally
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Version.Free;
end;
Это пример получения текстового файла и чтение его.Но он читается полностью.Н-р если у тебя пароли фиксированного значения,то читай каждые N-ые символы.Т.е. если у тебя пас по 5 символов,а в текстовом файле их 5(пасов).То читаешь в переменную какуюнить по циклу с s[1] по s[5],это например первый пас и тд.

Он читает все строчки?
У меня устроено так пользователь скидывает ключь который я прописываю в свой тхт фаил и мне нужно к примеру
1 пользователь
2 ид
3 ид
4 ид

Этот код поможет?
Не могу проверить не дома сори за флуд

Relli
24.05.2012, 14:43
victor20011, да,он считывает вообще все строчки в 1 строку и без пробелов ^^
потому просто запомни кол-во знаков в иде и по циклу сравнивай.

by_Ghoster
28.05.2012, 09:48
Хм.. А вы не забыли про реверсеров? легко же узнать где файл находиться.

victor20011
28.05.2012, 12:05
Var Data:tstringlist;
begin
Data:=tstringlist.create;
Data.loadFromFile('blabla.txt');
For i := 0 to Data.count -1 do
begin
if Edit1.text= Data[i] then
begin
Showmessage('Ключ найден!');
Break;
end;
end;

я сдела по примеру скрилекса
он скачивает после проверки удаляет фаил

D.E.Z.E.R.T.I.R
20.06.2012, 23:16
procedure TForm1.FormCreate(Sender: TObject);
var b,s:string;
begin
b:=getserial;
[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]',Memo3.Lines);
s:=Memo3.Text;
if Pos(b,s) =0 then
begin Showmessage('Зарегестрируйте программу'); Application.Terminate; end;
end;

Собственно все ключи загоняю в 1 файл, как он выглядит можете посмотреть и все

[Na`Vi]DendI
22.06.2012, 11:29
Пример на ucoz, если кому интересно :)

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Clear;
Edit1.Text := (GetSerial);
Button2.click;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Response:TFileStream;
s:string;
Version:TStringList;
begin
[Ссылки могут видеть только зарегистрированные и активированные пользователи](nil);
Version:=TStringList.Create;
try
s:=[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]Ваш сайт.ucoz.ru/Name.txt');
if Pos(s,Edit1.Text)<>0 then //Проверка ключа полученный в Edit1 и написанный в Name.txt
begin
ShowMessage('Все ок')
end
else
begin
ShowMessage('Не верный ключ.');
end;
finally
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Version.Free;
end;
end;

В принципе все, мб у кого то еще на что то фантазии хватит.
PS: Проверку ключа переделал с помощью этой темы [Ссылки могут видеть только зарегистрированные и активированные пользователи]
о спасибо большое)
переделал чучуть и вышло прям айс)

procedure TForm1.FormCreate(Sender: TObject);

begin
GetSystemInfo(siSysInfo);
with siSysInfo do begin
Result := IntToStr(dwActiveProcessorMask) +
IntToStr(dwPageSize) +
IntToStr(dwNumberOfProcessors) +
IntToStr(dwProcessorType) +
IntToStr(dwAllocationGranularity) +
IntToStr(wProcessorArchitecture) +
IntToStr(wProcessorLevel) +
IntToStr(wProcessorRevision);
k:=(result);
edit1.Text:=(k);


end;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
[Ссылки могут видеть только зарегистрированные и активированные пользователи](nil);
Version:=TStringList.Create;
try
s:=[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]ваш сайт)/'+k+'.txt');
if Pos(s,k)<>0 then
begin
form2.show;
form1.Hide;


end
else


finally

end;
end;


После просто нам дают свой серийник,мы создаем файлик к примеру 43243r654634563456(ваш серийник ) должно выйти примерно так 43243r654634563456.txt и в самом файле пропишем опять серийник,и заливаем наш файлик на ucoz)

DKENT
06.07.2012, 15:54
Данный метод не есть хорошо!
Так как софт можно обмануть с помошью подмены адресов в файле хост!
И уже прописать свой серийник в него!
Лучше стандартная привязка!

TeedI
06.07.2012, 16:14
Данный метод не есть хорошо!
Так как софт можно обмануть с помошью подмены адресов в файле хост!
И уже прописать свой серийник в него!
Лучше стандартная привязка!

Это хранение ключа проверки и ключа регистрации ?.Совершенно не надежно , ибо их можно вытащит с помощью ce :)

Роспотребнадзор
16.07.2012, 16:15
Спасибо за статью, но полученная программа активируется либо любым ключом, либо вообще без ключа :)
Вот код:

function GetSystemInfoAll: String;
var
siSysInfo: TSystemInfo;
begin
GetSystemInfo(siSysInfo);
with siSysInfo do begin
Result := IntToStr(dwActiveProcessorMask) +
IntToStr(dwPageSize) +
IntToStr(dwNumberOfProcessors) +
IntToStr(dwProcessorType) +
IntToStr(dwAllocationGranularity) +
IntToStr(wProcessorArchitecture) +
IntToStr(wProcessorLevel) +
IntToStr(wProcessorRevision);
end;
end;

function StringToHex(str1,Separator:String):String;
var
buf:String;
i:Integer;
begin
buf:='';
for i:=1 to Length(str1) do begin
buf:=buf+IntToHex(Byte(str1[i]),2)+Separator;
end;
Result:=buf;
end;

//Генерируем серийник
function getSerial:string;
begin
Result := StringToHex(( GetSystemInfoAll),'');
end;
//Генерируем ключ
function getKey(Serial: string):string;
begin
Result := MD5DigestToStr(MD5String(Serial));
Result := MD5DigestToStr(MD5String(Result));
end;

procedure TForm2.FormCreate(Sender: TObject);
var
s : TStringList;
begin
sedit1.Text:= (getSerial);
s := TStringList.Create;
s.LoadFromFile('license.txt');
sedit2.text := s.Text;
end;

procedure TForm2.sButton1Click(Sender: TObject);
begin
if sEdit2.Text = getKey(getSerial) then
ShowMessage('Программа успешно активирована');
form2.close;
form1.slabelfx12.Caption:= ('Активация прошла успешно!');
form1.sButton3.enabled:=false;
form1.sButton5.enabled:=true;

end;


Укажите где именно ошибка :)

[Na`Vi]DendI
18.07.2012, 15:10
procedure TForm2.sButton1Click(Sender: TObject);
begin
if sEdit2.Text = getKey(getSerial) then
ShowMessage('Программа успешно активирована');
form2.close;
form1.slabelfx12.Caption:= ('Активация прошла успешно!');
form1.sButton3.enabled:=false;
form1.sButton5.enabled:=true;

end;
Прочитай что ты написал: если в эдит2 твой серийник то прогу пропускаем, то есть тут нет проверки) Напиши к примеру проверку на сайте,если на таком-то сайте есть серийник то пропускаем или же нет.:)

Doverito
09.10.2012, 07:42
Не увидел сохранение ключа вообще.
Так вот подскажите как сохранять ключ в какой нить файл(я сохраняю в ини) и как потом сделать если программа уже активирована то не проходить регу проги...

Роспотребнадзор
12.10.2012, 14:42
Не увидел сохранение ключа вообще.
Сохраняем ключ в файл:
procedure TForm1.Button1Click(Sender: TObject);
var s: TStringList;
begin
s := TStringList.Create;
s.Add(edit1.Text);
s.SaveToFile('key.ini');
s.Free;
end;

потом сделать если программа уже активирована то не проходить регу проги
В событии On Show у формы:
if FileExist('Key.ini')// если нашли этот файл, то делаем то, что между begin и end
then begin ... end

MastaDan
28.10.2012, 14:43
//Генерируем ключ
function getKey(Serial: string):string;
begin
Result := MD5DigestToStr(MD5String(Serial));
Result := MD5DigestToStr(MD5String(Result));
end;
Ругается на строчки MD5DigestToStr
С Md5 не работал, я так понимаю бибилиотека нужна ?

UPD
Разобрался сам.