Getting unique machine id for software copy protection

Posted on 2010-01-01
Last Modified: 2013-11-27
I am deploying a microsoft access application, and I would like, as best as I can to keep people from just copying it and giving it to someone else.

I'm thinking of using (and storing) the host id of the machine on which it was first installed.  Is this possible?  Is this the best way to do this?

Question by:tpigielski
    LVL 89

    Expert Comment

    by:John Hurst
    Yes, you can do that. Ad-Aware does that.

    I set it up on a Virtual Machine to test because of reports of major problems and they told me: "Too bad for you, you have used up your license". I no longer am a customer of Ad-Aware (although I used to be), and now instead of having some money, they have none. I use a different product.

    Yes, you can do that.

    ... Thinkpads_User
    LVL 84
    There is no such thing as a Machine ID value, at least for what you're looking to do.

    In terms of copy protection, a "MachineID" is nothing more than some value you contrive, based on various hardware item information you get from a machine. For example, you can get the MAC address, cpu version and such, and then generate some value based on that.

    If you really want to employ copy protection, use a 3rd party utility to do this. I've tested this one, and it works very well:
    LVL 81

    Accepted Solution

    The copy protection schemes I have used grab a NIC MAC address. A NIC (Network Interface Controller or the network card) is installed on every machine and every NIC is unique amongst all NICs manufactured to date and in the future. Another trick is to generate a GUID which is a Windows generated "key" that is unique in the universe and based on various items such as the active NIC MAC, date and time, etc.

    This code gets the active NIC MAC:

    Public Function GetNetworkConnectionMACAddress() As String

    ' Return the currently used network adapter's MAC address

    ' Syntax
    ' GetNetworkConnectionMACAddress()

        Dim oWMIService As Object
        Dim vAdapters As Variant
        Dim oAdapter As Object
        Dim lIndex As Long
        Dim lMatchIndex As Long
        Dim vResult As Variant
        ' Adapters are pulled from the Windows Management Instrumentation database
        ' The currently used adapter has a MAC address and an IP address that is not
        Set oWMIService = GetObject("winmgmts:\\" & "." & "\root\cimv2")
        Set vAdapters = oWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
        For Each oAdapter In vAdapters
            If Not IsNull(oAdapter.MACAddress) And IsArray(oAdapter.IPAddress) Then
                lMatchIndex = -1
                For lIndex = 0 To UBound(oAdapter.IPAddress)
                    If Not oAdapter.IPAddress(lIndex) = "" Then
                        lMatchIndex = lIndex
                        Exit For
                    End If
                Next lIndex
                If Not lMatchIndex < 0 Then
                    GetNetworkConnectionMACAddress = oAdapter.MACAddress
                End If
            End If

    End Function

    This code generates a GUID:

    Private Type tGUID
       l1 As Long
       l2 As Long
       l3 As Long
       l4 As Long
    End Type

    Private Declare Function CoCreateGuid Lib "ole32.dll" ( _
          lpGuid As tGUID _
       ) As Long

    Private Declare Function StringFromGUID2 Lib "ole32.dll" ( _
          lpGuid As tGUID, _
          ByVal lpString As String, _
          ByVal cbBytes As Integer _
       ) As Integer

    Public Function CreateGUID() As String

    ' Create and return a unique GUID string.

       Dim GUID As tGUID
       Dim Temp As String
       Dim Result As Long
       Dim Length As Long
       Result = CoCreateGuid(GUID)
       If (Result = 0) Then
          Temp = StrConv(String(38, Chr(0)), vbUnicode)
          Length = StringFromGUID2(GUID, Temp, Len(Temp))
          Temp = StrConv(Temp, vbFromUnicode)
          If (Length > 0) Then
             If (Left(Temp, 1) = "{") Then Temp = Right(Temp, Len(Temp) - 1)
             If (Right(Temp, 1) = "}") Then Temp = Left(Temp, Len(Temp) - 1)
             Length = InStr(Temp, "-")
             Do While (Length <> 0)
                Temp = Left(Temp, Length - 1) & Right(Temp, Len(Temp) - Length)
                Length = InStr(Temp, "-")
             Temp = ""
          End If
       End If
       CreateGUID = Temp

    End Function

    LVL 56

    Assisted Solution

    by:Jim Dettman (Microsoft MVP/ EE MVE)
    I would go with the NIC as well. Just watch out for the dial-up adapters and VPN interfaces, which may or may not exist at the time the code runs.
    I have VBA code that does not rely on the winmgmts object if you want it, but I'm what Kevin has posted will work fine.
    One other note: believe it or not, a GUID is not guaranteed to unique. I didn't believe it myself either when someone told me (after all they call it a "globally unique ID"), but I reasearched and found out that it is true. However the odds of getting a duplicate are so infinitesimally small that you can consider it to be one, so the other routine that Kevin posted would work as well.
    I forget what the odds were, but there were a LOT of zeros after it....
    LVL 3

    Expert Comment

    by:Paul Thompson
    This method is very simple but effective.

    Use the Hard Drive volume serial number created when the drive was formatted.

    The code below extracts this serial number.

    The user provides you with this serial number...
    You provide a key code that only works with that serial number...
    The application has a simple algorithm that allows the app to run when a valid key is entered...
    The app should be able to run in a reduced functionality mode without a key...
    The key will not work on other unregistered machines.

    You will of course need to write a small key-code generator app.

    This protects you from people who just give away the key to their friends.

    If the user reformats or replaces the drive, they will need another key code.

    '-- Put this in a module
    Public Declare Function GetVolumeInformation& Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal pVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long)
    Public Const MAX_FILENAME_LEN = 256
    Public Function DriveSerial(ByVal sDrv As String) As Long
    Dim RetVal As Long
    Dim str As String * MAX_FILENAME_LEN
    Dim str2 As String * MAX_FILENAME_LEN
    Dim a As Long
    Dim b As Long
    Call GetVolumeInformation(sDrv & ":\", str, MAX_FILENAME_LEN, RetVal, a, b, str2, MAX_FILENAME_LEN)
    DriveSerial = Abs(RetVal)
    End Function
    '-- Put this on a form
    Private Sub Command1_Click()
        Text1.Text = DriveSerial("C") ' where "C" is the drive volume.
    End Sub

    Open in new window

    LVL 69

    Expert Comment

    by:Éric Moreau
    you can get ActiveLock for free:
    LVL 56

    Expert Comment

    by:Jim Dettman (Microsoft MVP/ EE MVE)

    <<you can get ActiveLock for free>>

    That site seems to be quite old and mostly non-functional. I'd also hesitate to download something that says it's "open source", yet it wants to collect info for you to download the source. That goes against open source guide lines.


    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Enabling OSINT in Activity Based Intelligence

    Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

    Suggested Solutions

    I originally created this report in Crystal Reports 2008 where there is an option to underlay sections. I initially came across the problem in Access Reports where I was unable to run my border lines down through the entire page as I was using the P…
    I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
    Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
    In Microsoft Access, when working with VBA, learn some techniques for writing readable and easily maintained code.

    779 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    16 Experts available now in Live!

    Get 1:1 Help Now