Qualsiasi software è decompilabile, quindi non c'è protezione che tenga. Tuttavia si tratta di rendere le cose un po' difficili per gli utenti che non hanno competenze da hacker, cioè la maggior parte.
Leggendo la tua richiesta ho subito pensato che si potrebbe leggere il numero seriale della chiavetta e confrontarlo con il numero seriale annegato nel tuo software.
Il codice che ti riporto qui sotto fa uso di WMI ed estrae il numero seriale dell'unità sulla quale è in esecuzione il software. Per un harddisk si usa normalmente la proprietà "Win32_DiskDrive\SerialNumber", mentre per le chiavette USB tale proprietà risulta vuota ed è necessario leggere "Win32_DiskDrive\PNPDeviceID".
codice:
Imports System.Management
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim scope As ManagementScope
Dim query As ObjectQuery
Dim searcher As ManagementObjectSearcher
Dim queryCollection As ManagementObjectCollection
'imposta lo scope sulla macchina locale
scope = New ManagementScope("\\" & Environment.MachineName & "\root\cimv2")
'determina il volume che contiene l'eseguibile
Dim logical As String = IO.Path.GetPathRoot(Application.ExecutablePath).First
'logical = "F"
'determina l'unità fisica che contiene il volume
Dim phisical As String = ""
query = New ObjectQuery("SELECT * FROM Win32_LogicalDiskToPartition")
searcher = New ManagementObjectSearcher(scope, query)
queryCollection = searcher.Get()
For Each manObj In queryCollection
Dim matchlogical As Match = Regex.Match(manObj.GetPropertyValue("Dependent").ToString,
"^\\\\" & Environment.MachineName & "\\root\\cimv2:Win32_LogicalDisk.DeviceID=""(?<logical>[A-Z]):""")
If matchlogical.Groups("logical").Value = logical Then
Dim matchphisical As Match = Regex.Match(manObj.GetPropertyValue("Antecedent").ToString,
"^\\\\" & Environment.MachineName & "\\root\\cimv2:Win32_DiskPartition.DeviceID=""Disk #(?<phisical>\d)")
phisical = matchphisical.Groups("phisical").Value
Exit For
End If
Next
'determina il numero seriale dell'unità fisica
Dim hdserial As String = ""
query = New ObjectQuery("SELECT * FROM Win32_DiskDrive")
searcher = New ManagementObjectSearcher(scope, query)
queryCollection = searcher.Get()
For Each manObj In queryCollection
Dim matchtag As Match = Regex.Match(manObj.GetPropertyValue("DeviceID").ToString,
"^\\\\.\\PHYSICALDRIVE(?<phisical>\d)")
If matchtag.Groups("phisical").Value = phisical Then
hdserial = manObj.GetPropertyValue("PNPDeviceID").ToString
Exit For
End If
Next
'output
Dim output As String = String.Format("logical = {0}" & vbCrLf &
"phisical = {1}" & vbCrLf &
"hdserial = {2}", logical, phisical, hdserial)
MsgBox(output)
End Sub
End Class
Offuscando opportunamente il codice dovresti ottenere un buon risultato.