Search code examples
vb.netlicense-key

How do I check to see if the license expired on my app?


I am creating an application in VB.NET (for windows) in which the license expires after a year. What date can I use that the user can not manipulate to see if a year has gone by?

I don't want the user to have to be online to use the software, so an online check is not a valid option.

Thanks.


Solution

  • A date based expiry without NIST (network time servers) is precarious because the only alternative is the local clock, which the user can fiddle with. Checking once in a while, such as every week or two, presents a very large vulnerability: This requires the app write down the date of the last check somewhere and it is simply impossible to keep that a secret on the user's machine.

    One way to get the approximate date is to calculate it from the last boot datetime:

    Public Class WMI
    
        Friend Shared Function GetWMISetting(wmiClass As String, value As String) As String
            Dim retVal As String = ""
            Dim query = String.Format("SELECT {0} FROM {1}", value, wmiClass)
    
            Using searcher As New System.Management.ManagementObjectSearcher(query)
                For Each item As System.Management.ManagementObject In searcher.Get
                    For Each p As System.Management.PropertyData In item.Properties
                        If String.Compare(value, p.Name,
                                          StringComparison.InvariantCultureIgnoreCase) = 0 Then
                            If p.Value IsNot Nothing Then
                                retVal = p.Value.ToString
                            End If
                            Exit For
                        End If
                    Next
                Next
            End Using
            Return retVal
    
        End Function
    
        Friend Shared Function GetMinSystemDateTime() As DateTime
    
            Dim lastBoot = WMI.GetWMISetting("Win32_OperatingSystem", "LastBootUpTime")
            Dim uptime = WMI.GetWMISetting("Win32_PerfFormattedData_PerfOS_System", 
                       "SystemUpTime")
    
            Dim ts As New TimeSpan(0, 0, Convert.ToInt32(uptime))
            Dim MinimumDate = ManagementDateTimeConverter.ToDateTime(lastBoot).Add(ts)
    
            Return MinimumDate  
        End Function
    End Class
    

    The calculates the approximate date from the LastBootUp date, and the SystemUpTime values. The latter can be seen on the Performance tab of TaskManager. The date format is peculiar, so the System.Management namespace provides a converter.

    The Date returned is approximate because the "UpTime" does not include time sleeping. Otherwise, it gives you an idea of the approximate minimum date.

    They could probably spoof this using a VM, and it could be totally wrong if the battery is dead, they wont let Windows set the time so the PC is permanently off date. If your license includes an install/issue date (set by you at the Home Office, not the client PC), you could test if the Date returned is less than the install and treat that as expired.

    Then the trick becomes protecting those values. When you issue the license, serialize the user name, serial, install date and expiry date to a MemoryStream. Then run a RSA hash on the data to create an asymmetric signature.

    Create a class to hold the license data as a base64 string and the signature hash and serialize it to a file. At runtime, open it and validate the signature using the license data and the Private Key. If it validates, the data in the "license" portion is valid.1

    Ultimately, they really just need to patch your code:

    ' from:
    IsRegistered = ValidateLicense()
    ' to:
    IsRegistered = (True = True)
    

    Obfuscate your app to slow them down on that.

    Now, if you think something like that will thwart say, 80% of your likely user base, then go for it.

    The the user can not manipulate part is not do-able, but you can concoct a solution that will work to a fair degree. WHO you are trying to keep out (crackers vs super users vs AOL-LoLs) determines how extensive or sophisticated you need to be.

    1 Such a file is read only on the client. You cant write to it without invalidating the signature. And you cannot update/change it without including the Private Key in the app which is suicide.