>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
Это на самом деле несложно организовать. Достаточно иметь бесплатный хост с установленным php, даже базы не нужны, можно организовать хранение в файлах на крайний случай. Синтаксис php очень похож на синтаксис autoit, поэтому любой кто знаком хорошо с аутоит легко разберется с php. У меня был обратный путь, я пришел с php на autoit, CreatoR заинтересовал своими наработками с оперой, которыми я пользовался несколько лет и даже не задумывался как все сделано, поэтому я и пришел сюда. Нагрузка на хост достаточно незначительна при такой привязке при условии что не миллионы обращений в секунду, поэтому подойдет практически любой хостинг, лишь бы доступность сайта по времени была близка к 100%.Клиент при старте связывается с сервером который представляет из себя PHP скрипт принимающий сигнатуру компа на котором стоит клиент. Сигнатуре может генериться различными способами, в любом случае пересылка туда и обратно должна делаться с динамичной шифровкой. Далее сервер смотрит ini файлик в котором указано до какого времени работает программа. Время истекло - плати снова абонентку. Сменил железку - изъявляй об этом разработчика и тебе перезапишут старую сигнатуру на новую. Не хочешь - покупай программу заново.
Проверка при старте и далее каждые несколько минут
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
If SN = pDisk.Model & pDisk.SerialNumber Then
Да не сморю я знаком со взломами и пожно просто подменить функцию - сделать ее возвращающую всегда True и этого будет достаточно. НО!Whited сказал(а):ivanius [?]
If SN = pDisk.Model & pDisk.SerialNumber Then
Вот такие проверки ломаются опытными на OllyDbg.
Мое мнение, нужно держать данные для клиента на серваке и отдавать их только если получил допустим тот же серийник жесткого.
#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
$UID= ;получить UID
_Crypt_EncryptData('ПО для UID ПК '&$UID&' не активировано', 'Огроменный ключ шифрования', $CALG_AES_256)
_Crypt_EncryptData('ПО для UID ПК '&$UID&' активировано', 'Огроменный ключ шифрования', $CALG_AES_256)
inververs сказал(а):mef-t вы изобрели серийный ключ. Вам присылается строка в виде XXXX-XXXX-XX-XXX-XXXXX, а ваша программа проверяет его на валидность.
Vovsla сказал(а):Если цель - простая привязка ПО к железу, то мне кажется лишним ID программы, логин, пароль.
...
А как отличить апгрейд от передачи логина и пароля другому лицу?А что делать, если произошел апгрейд?
Пользователь отправляет код на нужный почтовый ящик со своего ящика.Ваш вариант более приятен, если все абсолютно автоматизировано.