Что нового

Привязка скрипта к одному компьютеру (железу)

shift72

Новичок
Сообщения
86
Репутация
2
Я конечно извиняюсь. Но кто нибудь может помочь с этим?
Могу скромно вознаградить.
 

shift72

Новичок
Сообщения
86
Репутация
2
Балин народ что помочь никто не хочет?
 

Gzzk

Новичок
Сообщения
104
Репутация
1
Т.е. нужно просто впихнуть обе функции в код и последовательно их вызвать перед выполнением основной части кода?


Добавлено:
Сообщение автоматически объединено:

Код:
>D:\Program Files\AI3\install\SciTe\..\au3check.exe "D:\MyProg.au3"
AutoIt3 Syntax Checker v1.54.8  Copyright (c) Tylo 2007

D:\MyProg.au3(68,57) : WARNING: $UHID_MB: possibly used before declaration.
    Local $sID = _WinAPI_UniqueHardwareID(BitOR($UHID_MB,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
D:\MyProg.au3(68,69) : WARNING: $UHID_BIOS: possibly used before declaration.
    Local $sID = _WinAPI_UniqueHardwareID(BitOR($UHID_MB, $UHID_BIOS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
D:\MyProg.au3(68,57) : ERROR: $UHID_MB: undeclared global variable.
    Local $sID = _WinAPI_UniqueHardwareID(BitOR($UHID_MB,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
D:\MyProg.au3 - 1 error(s), 2 warning(s)
>Exit code: 2    Time: 0.318
Вот такие вот чудесные ошибочки,подскажите,что я не так сделал?
 

LyU6I

Новичок
Сообщения
2
Репутация
1
Клиент при старте связывается с сервером который представляет из себя PHP скрипт принимающий сигнатуру компа на котором стоит клиент. Сигнатуре может генериться различными способами, в любом случае пересылка туда и обратно должна делаться с динамичной шифровкой. Далее сервер смотрит ini файлик в котором указано до какого времени работает программа. Время истекло - плати снова абонентку. Сменил железку - изъявляй об этом разработчика и тебе перезапишут старую сигнатуру на новую. Не хочешь - покупай программу заново.
Проверка при старте и далее каждые несколько минут
Это на самом деле несложно организовать. Достаточно иметь бесплатный хост с установленным php, даже базы не нужны, можно организовать хранение в файлах на крайний случай. Синтаксис php очень похож на синтаксис autoit, поэтому любой кто знаком хорошо с аутоит легко разберется с php. У меня был обратный путь, я пришел с php на autoit, CreatoR заинтересовал своими наработками с оперой, которыми я пользовался несколько лет и даже не задумывался как все сделано, поэтому я и пришел сюда. Нагрузка на хост достаточно незначительна при такой привязке при условии что не миллионы обращений в секунду, поэтому подойдет практически любой хостинг, лишь бы доступность сайта по времени была близка к 100%.
Если кому нужна помощь для организации подобной проверки на стороне сервера то могу помочь. php + mysql знал раньше на достаточно высоком уровне. Сейчас просто этим не занимаюсь для себя.
 

shift72

Новичок
Сообщения
86
Репутация
2
Было бы неплохо наблюдать статейку от тебя на этом сайте. Думаю очень много народу будут тебе благодарны.
 

ivanius

Знающий
Сообщения
74
Репутация
5
Хочу поделится со своим способом защиты, он конечно на VBA и очень кривой - но работает и достаточно хорошо, программы свои я продаю, а некоторые продаю не я, а дистрибьюторы, а я выполняю роль тех поддержки - получаю и исправляю багрепорты.
Код:
Private Function Encode(ByVal strString As String) As String
  Dim tempstr2 As String
  Dim PArray() As String
  Dim VArray() As String

  KolS = Len(strString)
  If KolS Mod 2 = 1 Then
    ReDim PArray((KolS - 1) / 2)
    ReDim VArray((KolS - 1) / 2)
    PSim = Mid(strString, ((KolS - 1) / 2) + 1, 1)
    For I = 1 To (KolS - 1) / 2
      PArray(I) = Mid(strString, I, 1)
      VArray(I) = Mid(strString, I + ((KolS - 1) / 2) + 1, 1)
      tempstr2 = tempstr2 & PArray(I) & VArray(I)
    Next
    tempstr2 = tempstr2 & PSim
  Else
    ReDim PArray(KolS / 2)
    ReDim VArray(KolS / 2)
    For I = 1 To KolS / 2
      PArray(I) = Mid(strString, I, 1)
      VArray(I) = Mid(strString, I + KolS / 2, 1)
      tempstr2 = tempstr2 & PArray(I) & VArray(I)
    Next
  End If
  Encode = tempstr2
End Function

Private Function Decode(ByVal strString As String) As String
  Dim strHexDecode As String, tempstr1 As String

  Dim PArray() As String
  Dim VArray() As String
  Dim n As Integer
  Dim Mst As String

  KolS = Len(strString)
  ReDim PArray(KolS)
  ReDim VArray(KolS)

  If KolS Mod 2 = 1 Then
    Mst = Left(strString, KolS - 1)
  Else
    Mst = strString
  End If
  n = 1
  For I = 1 To Len(Mst) / 2
    PArray(I) = Mid(Mst, n, 1)
    VArray(I) = Mid(Mst, n + 1, 1)
    n = n + 2
    tempstr1 = tempstr1 & PArray(I)
  Next
  If KolS Mod 2 = 1 Then
    tempstr1 = tempstr1 & Right(strString, 1)
  End If
  For q = 1 To Len(Mst) / 2
    tempstr1 = tempstr1 & VArray(q)
  Next

  Decode = tempstr1

End Function

Private Function EncodeHX(ByVal strString As String) As String

  For index = 1 To Len(strString)
    EncodeHX = EncodeHX & Hex(Asc(Mid(strString, index, 1)))
  Next

End Function

Private Function DecodeHX(ByVal strString As String) As String
  
   On Error GoTo DecodeHX_Error

  For index = 1 To Len(strString) Step 2
    DecodeHX = DecodeHX & Chr(CLng("&H" & Mid(strString, index, 2)))
  Next

   On Error GoTo 0
   Exit Function

DecodeHX_Error:

  DecodeHX = ""

End Function

Public Function GetClientSerial() As String
    Dim pWMI As Object, pDisks As Object, pDisk As Object
     
    Set pWMI = GetObject("winmgmts:\\")
    Set pDisks = pWMI.ExecQuery("Select * from Win32_DiskDrive Where BytesPerSector Is Not Null", , 48)
    
    For Each pDisk In pDisks
        Dim SN As String: SN = pDisk.Model & pDisk.SerialNumber
    Next
    Dim clientsn As String, generetedSN As String
    GetClientSerial = Encode(Encode(SN))

End Function
 
Public Function CheckSerial(ByVal SN As String) As Boolean
    Dim pWMI As Object, pDisks As Object, pDisk As Object
    Set pWMI = GetObject("winmgmts:\\")
    SN = Decode(Decode(DecodeHX(Decode(Decode(SN)))))
    Set pDisks = pWMI.ExecQuery("Select * from Win32_DiskDrive Where BytesPerSector Is Not Null", , 48)
    CheckSerial = False
    For Each pDisk In pDisks
        If SN = pDisk.Model & pDisk.SerialNumber Then
          CheckSerial = True: Exit For
        End If
    Next
End Function
Код почти полностью пригоден к AutoIt - смысл его -
1)берем серийник винта -
2)пвседорандомом мешаем,
3)потом каждый символ по ASCII в цифру
4)и потом в HEX
5)и еще раз мешаем чтобы не догадались что там именно HEX значения,.
Мне присылают данные из пункта 3, я им отправляю из пункта 5, в программе расшифровую, для защиты функций 4 и 5 в программе клиента - нету.
 

Whited

Знающий
Сообщения
79
Репутация
10
ivanius [?]
If SN = pDisk.Model & pDisk.SerialNumber Then

Вот такие проверки ломаются опытными на OllyDbg.
Мое мнение, нужно держать данные для клиента на серваке и отдавать их только если получил допустим тот же серийник жесткого.
 

ivanius

Знающий
Сообщения
74
Репутация
5
Whited сказал(а):
ivanius [?]
If SN = pDisk.Model & pDisk.SerialNumber Then

Вот такие проверки ломаются опытными на OllyDbg.
Мое мнение, нужно держать данные для клиента на серваке и отдавать их только если получил допустим тот же серийник жесткого.
Да не сморю я знаком со взломами и пожно просто подменить функцию - сделать ее возвращающую всегда True и этого будет достаточно. НО!
Ты учитывай что это не Exe а VBA там может проще может сложнее - не знаю, но вот тебе пример на чем я зарабатываю последние 2 месяца (пример один из многих)
https://vk.com/topic-33511649_31194084 - то что продается за 1000-2000 рублей пользователей программы достаточно, обновляю ее не часто. А защита там из цитируемого кода. И буду продалжать ее использовать только менять ключ от программы к программе и сейчас в боте для WOWP сделаю тоже самое.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Немного изменил, в данном варианте можно дать кому то программу, и впредь она будет работать только там, где её запустили впервые.
Смысла нет, но так просто, ради интереса:

Код:
#include <WinAPIEx.au3>

Global $iUH_IDs = BitOR($UHID_MB, $UHID_BIOS)

If Not @Compiled Then
	MsgBox(16, ':-(', 'Please compile this program first.')
	Exit
EndIf

If Not _UniqueID_Inject(@ScriptFullPath, _WinAPI_UniqueHardwareID($iUH_IDs)) Then
	Switch @error
		Case 2
			;MsgBox(16, 'Error', 'MyProg.exe already patched.')
		Case Else
			MsgBox(16, 'Error', 'Unable to patch file.')
	EndSwitch
EndIf

If Not _UniqueID_Validate(@ScriptFullPath) Then
	MsgBox(16, ':-(', 'The program has not been installed on this computer.')
	Exit
EndIf

MsgBox(0, ':-)', 'OK')

Func _UniqueID_Validate($sFile)
	Local $sID = _WinAPI_UniqueHardwareID($iUH_IDs)
	
	If Not $sID Then
		Return 0
	EndIf
	
	Local $hFile = _WinAPI_CreateFile($sFile, 2, 2)
	
	If Not $hFile Then
		Return 0
	EndIf
	
	Local $tData = DllStructCreate($tagGUID), $pData = DllStructGetPtr($tData)
	Local $sData, $iByte, $Result = 0
	
	Do
		If Not _WinAPI_SetFilePointer($hFile, -16, 2) Then
			ExitLoop
		EndIf
		
		If (Not _WinAPI_ReadFile($hFile, $pData, 16, $iByte)) Or ($iByte <> 16) Then
			ExitLoop
		EndIf
		
		$sData = _WinAPI_StringFromGUID($pData)
		
		If (Not $sData) Or ($sData <> $sID) Then
			ExitLoop
		EndIf
		
		$Result = 1
	Until 1
	
	_WinAPI_CloseHandle($hFile)
	
	Return $Result
EndFunc

Func _UniqueID_Inject($sFile, $sID)
	Local $tData = _WinAPI_GUIDFromString($sID)
	
	If Not IsDllStruct($tData) Then
		Return 0
	EndIf
	
	Local $sTmp_File = @TempDir & '\InjectUID.exe'
	FileCopy($sFile, $sTmp_File, 1)
	
	Local $hFile = _WinAPI_CreateFile($sTmp_File, 2, 6)
	
	If Not $hFile Then
		Return 0
	EndIf
	
	Local $tSign = DllStructCreate('dword'), $pSign = DllStructGetPtr($tSign)
	Local $iByte, $Error = 1
	
	Do
		If Not _WinAPI_SetFilePointer($hFile, -20, 2) Then
			ExitLoop
		EndIf
		
		If (Not _WinAPI_ReadFile($hFile, $pSign, 4, $iByte)) Or ($iByte <> 4) Then
			ExitLoop
		EndIf
		
		If DllStructGetData($tSign, 1) = 0x0144ADDA Then
			$Error = 2
			ExitLoop
		EndIf
		
		If Not _WinAPI_SetFilePointer($hFile, 0, 2) Then
			ExitLoop
		EndIf
		
		DllStructSetData($tSign, 1, 0x0144ADDA)
		
		If (Not _WinAPI_WriteFile($hFile, $pSign, 4, $iByte)) Or ($iByte <> 4) Then
			ExitLoop
		EndIf
		
		If (Not _WinAPI_WriteFile($hFile, DllStructGetPtr($tData), 16, $iByte)) Or ($iByte <> 16) Then
			ExitLoop
		EndIf
		
		$Error = 0
	Until 1
	
	_WinAPI_CloseHandle($hFile)
	
	If $Error = 0 Then
		Run(@ComSpec & ' /C ping -n 2 localhost && move /y "' & $sTmp_File & '" "' & $sFile & '" && start "" "' & $sFile & '"', '', @SW_HIDE)
		Exit
	EndIf
	
	Return SetError($Error, 0, Number($Error = 0))
EndFunc
 

mef-t

Осваивающий
Сообщения
306
Репутация
30
Как я понимаю, в данной теме уже опробовали сервер, связку, пришли к некоторому выводу, и на этом закончили.

Так же хотел попробовать, но при данном варианте есть проблема:
Необходимость держать сервер при условии, что он обеспечивает только проверку. А значит перенаправление данных на ложный сервер позволит легко обойти проверку. Если конечно не придумать более сложные ответы с шифрованием.
Если же на сервер перенести часть логики, то это становится дорогим удовольствием для простых приложений.

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

Как на счет такой логики.
1. Каждый экземпляр программы имеет свой ID
2. Для входа требуется логин (почта) и пароль.
3. Пароль проверяется по логину, ID программы, UID оборудования
Таким образом один и тот же пароль нельзя использовать на разных машинах.

Первый экран, или отдельная форма с полями логина и пароля.
В качестве логина используется почта.
Если пароль еще не известен, то рядом с логином можно нажать кнопку "Запросить пароль".
Далее программа формирует письмо и отправляет на вашу почту логин, ID программы, UID оборудования. (можно нарисовать формат письма, зашифровать и прочее)

Вы раз в день/час проверяете почту. В свой программе указываете полученные данные.
Программа проверяет, оплачен ли данный экземпляр (по ID программы в каком нибудь файле).
Если оплачен, то формирует пароль по полученным данным и отправляет обратно на почту.
У Вас в файле дописывается привязка экземпляра (id программы) к почте.

Алгоритм формирования пароля и проверки в программе одинаковый.

Просьба высказать о недостатках такого метода и трудностях реализации
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
mef-t вы изобрели серийный ключ. Вам присылается строка в виде XXXX-XXXX-XX-XXX-XXXXX, а ваша программа проверяет его на валидность.
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Если цель - простая привязка ПО к железу, то мне кажется лишним ID программы, логин, пароль.
Можно же просто брать UID оборудования, шифровать его вместе с каким-нибудь контрольным словом, например.
Код:
$UID= ;получить UID
_Crypt_EncryptData('ПО для UID ПК '&$UID&' не активировано', 'Огроменный ключ шифрования', $CALG_AES_256)


Шифрованные данные отправляются на сервер, сервер расшифровывает данные, проверяет наличие слов которые должны быть постоянно, например "ПО для UID ПК". Если слова есть, то пришел корректный код и сервер просто меняет "не активировано" на "активировано" и отправляет шифрованный ключ.
Код:
_Crypt_EncryptData('ПО для UID ПК '&$UID&' активировано', 'Огроменный ключ шифрования', $CALG_AES_256)


Клиент получает код, дает его программе, программа расшифровывает код, ищет контрольные слова "ПО для UID ПК" для проверки корректности ключа, потом проверяет соответствует ли UID в коде UIDу текущего ПК, смотрит в коде какой статус должен быть у программы "не активировано" / "активировано".
 

mef-t

Осваивающий
Сообщения
306
Репутация
30
inververs сказал(а):
mef-t вы изобрели серийный ключ. Вам присылается строка в виде XXXX-XXXX-XX-XXX-XXXXX, а ваша программа проверяет его на валидность.

Все верно. Я отталкивался от истории существующих защит.
Это простой вариант в реализации. Не требует настройки серверной части. Можно просто проверять почту.
Этот вариант защищает программу от неразрешенной установки.
Этот вариант защищает программу от копирования. Но при этом позволяет выслать новый ключ, если переустановлена система, произведен апргрейд компа, или вообще новый комп.
Я допускаю простоту обхода защиты, но и затраченные средства на защиту достаточно малы.

Vovsla сказал(а):
Если цель - простая привязка ПО к железу, то мне кажется лишним ID программы, логин, пароль.
...

А что делать, если произошел апгрейд?
В остальном все тоже самое, только вместо того, чтобы отправлять на сервер, как реализовать который я не знаю, данные отправляются на почту.
Вместо одной составляющей их будет три, т.е. общий шифрованный код будет сформирован из трех составляющих.
В остальном все почти так.
Разве что почта появляется. Но ее вводить так же можно всего один раз в начале.
Ваш вариант более приятен, если все абсолютно автоматизировано. Т.е. данные отправились, программа ждет. Сервер получил, обработал, вернул данные. Программа получила данные и активировалась.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
mef-t

Предупреждение За нарушение общих правил (пункт В.2):
Старайтесь избегать “Over quoting” (преувеличенное цитирование) - цитируйте только необходимую часть сообщения, которая наилучшим образом подчеркнёт суть цитируемого.


С уважением, ваш Глобальный модератор.
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
А что делать, если произошел апгрейд?
А как отличить апгрейд от передачи логина и пароля другому лицу?
Как вариант, можно брать не UID, а например, серийный номер системного диска.

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