Get Demo
  • Windows
  • MacOS
  • Linux

Windows-version


Description

The Windows key generators are DLL files for x86 and x64 platforms, along with a C header file and an MSVC-compatible .lib file. Therefore, the library can be linked either statically or loaded dynamically.

All generator files are located in the %Examples%\Keygen\DLL folder. A test application that generates serial numbers is also included there.

Generator API

The generator exports only two functions: the first generates a serial number, and the second frees the memory allocated by the first. Let’s start with the main function:

VMProtectErrors __stdcall VMProtectGenerateSerialNumber(
                                VMProtectProductInfo * pProductInfo, 
                                VMProtectSerialNumberInfo * pSerialInfo, 
                                char ** pSerialNumber
                        );

The first parameter is a pointer to the VMProtectProductInfo structure, which contains data exported from VMProtect (see Exporting product parameters). This structure includes the product private key, the encryption algorithm, and the product identifier. More details on how to fill this structure are provided below.

The second parameter is a pointer to the VMProtectSerialNumberInfo structure, which contains the data to be written into the serial number. This structure includes all serial number fields and a bitmask that defines which fields should be included in the serial number.

struct VMProtectSerialNumberInfo
{
        INT              flags;
        wchar_t *        pUserName;
        wchar_t *        pEMail;
        DWORD            dwExpDate;
        DWORD            dwMaxBuildDate;
        BYTE             nRunningTimeLimit;
        char *           pHardwareID;
        size_t           nUserDataLength;
        BYTE *           pUserData;
};

The flags field contains bit flags from the VMProtectSerialNumberFlags set described before the structure:

  • HAS_USER_NAME – includes the user name from pUserName in the serial number.
  • HAS_EMAIL – includes the e-mail from pEMail in the serial number.
  • HAS_EXP_DATE – the serial number expires after the date specified in dwExpDate.
  • HAS_MAX_BUILD_DATE – the serial number works only with versions of the product built up to the date specified in dwMaxBuildDate.
  • HAS_TIME_LIMIT – the program stops working after the time specified in nRunningTimeLimit expires (in minutes, maximum 255).
  • HAS_HARDWARE_ID – the program works only on hardware with the ID specified in pHardwareID.
  • HAS_USER_DATA – includes custom user data of length nUserDataLength from pUserData into the serial number.

The third parameter is a pointer to a pointer. The address of the generated serial number is written there. After generation, the serial number should be copied, and the pointer must be passed to the second API function to free the allocated memory.

void __stdcall VMProtectFreeSerialNumberMemory(char * pSerialNumber);

The VMProtectGenerateSerialNumber function returns a VMProtectErrors value. It returns 0 if the serial number is generated successfully, or an error code otherwise. Possible error codes are:

  • ALL_RIGHT – no errors, the serial number was generated successfully.
  • UNSUPPORTED_ALGORITHM – an unsupported encryption algorithm was passed in the first parameter.
  • UNSUPPORTED_NUMBER_OF_BITS – an invalid number of bits was passed in the first parameter.
  • USER_NAME_IS_TOO_LONG – the UTF-8 encoded user name exceeds 255 bytes.
  • EMAIL_IS_TOO_LONG – the UTF-8 encoded e-mail exceeds 255 bytes.
  • USER_DATA_IS_TOO_LONG – the user data exceeds 255 bytes.
  • HWID_HAS_BAD_SIZE – the hardware identifier has an invalid size.
  • PRODUCT_CODE_HAS_BAD_SIZE – the product identifier has an invalid size.
  • SERIAL_NUMBER_TOO_LONG – the serial number is too long for the key size defined by the algorithm.
  • BAD_PRODUCT_INFO – the first parameter is invalid or NULL.
  • BAD_SERIAL_NUMBER_INFO – the second parameter is invalid or NULL.
  • BAD_SERIAL_NUMBER_CONTAINER – the third parameter does not point to valid memory for the serial number.
  • NOT_EMPTY_SERIAL_NUMBER_CONTAINER – the third parameter must point to a NULL value.
  • BAD_PRIVATE_EXPONENT – the private exponent in the first parameter is invalid.
  • BAD_MODULUS – the modulus in the first parameter is invalid.

Errors fall into two categories: those caused by incorrect parameters (or incorrect product configuration), and all others. The first category is rare and indicates incorrect structure initialization. In such cases, you should re-export the product data and verify that the structure is filled correctly.

The second category occurs when too much data is provided for the key size. In this case, we recommend sending a message to the e-commerce provider such as “The key will be sent within 24 hours” instead of the serial number, and notifying the developer by e-mail. The key can then be generated manually in VMProtect, with some data truncated to fit the maximum key size.

Example usage

Below is an example demonstrating how to use the functions above to generate a serial number. Note the block at the beginning of the code. It will not work until it is replaced with data exported from VMProtect for your product:

//////////////////////////////////////////////////////////////////////////
// !!! this block should be generated by VMProtect !!!                 ///
//////////////////////////////////////////////////////////////////////////
VMProtectAlgorithms g_Algorithm = ALGORITHM_RSA;
size_t g_nBits = 0;
byte g_vModulus[1];
byte g_vPrivate[1];
byte g_vProductCode[1];
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
        VMProtectProductInfo pi;
        pi.algorithm = g_Algorithm;
        pi.nBits = g_nBits;
        pi.nModulusSize = sizeof(g_vModulus);
        pi.pModulus = g_vModulus;
        pi.nPrivateSize = sizeof(g_vPrivate);
        pi.pPrivate = g_vPrivate;
        pi.nProductCodeSize = sizeof(g_vProductCode);
        pi.pProductCode = g_vProductCode;
        VMProtectSerialNumberInfo si = {0};
        si.flags = HAS_USER_NAME | HAS_EMAIL;
        si.pUserName = L"John Doe";
        si.pEMail = L"john@doe.com";
        char * pBuf = NULL;
        VMProtectErrors res = VMProtectGenerateSerialNumber(&pi, &si, &pBuf);
        if (res == ALL_RIGHT)
        {
                printf("Serial number:\n%s\n", pBuf);
                VMProtectFreeSerialNumberMemory(pBuf);
        }
        else
        {
                printf("Error: %d\n", res);
        }
        return 0;
}

This is a sample project for Microsoft Visual Studio located in %Examples%\Keygen\DLL\Example. Below are the most important parts of the code with explanations.

The first part of the main function fills the VMProtectProductInfo structure with data exported from VMProtect. This code is standard and should not be modified to avoid errors. Next, we create the VMProtectSerialNumberInfo structure and set flags indicating that the user name and e-mail should be included in the serial number. Then we assign values to the corresponding fields. Note that values are provided in Unicode; the generator will convert them to UTF-8.

After that, we initialize a pointer to store the generated serial number and call VMProtectGenerateSerialNumber, then check the return code. If there are no errors, the serial number is printed to the console and the allocated memory is freed.

VMProtectSerialNumberInfo structure

Some fields require additional explanation. For example, the dwExpDate and dwMaxBuildDate fields store dates in the format 0xYYYYMMDD, where the year is stored in the high word, and the month and day are stored in the low word. To generate such a value, the macro MAKEDATE(y, m, d) is used. For example: MAKEDATE(2010, 05, 12).

The pHardwareID field must contain a pointer to a string returned by the VMProtectGetCurrentHWID function from the licensing SDK.

Last updated 11 days ago