<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="Stylesheet" type="text/css" href= "../../default.css" /> <meta http-equiv="Content-Type" content= "text/html; charset=utf-8" /> <title>Генератор ключей: Windows-версия</title> </head> <body> <h1>Генераторы ключей: Windows-версия</h1> <h3>Описание</h3> <p>Генератор для Windows представляет собой DLL-файлы для платформ x86 и x64, заголовочный файл языка C и lib-файл, совместимый с MSVC. Таким образом, библиотека может быть как слинкована статически, так и загружаться динамически.</p> <p>Все файлы генератора находятся в каталоге <strong>Keygen\DLL</strong>, там же находится тестовое приложение, которое генерирует серийные номера.</p> <h3>API генератора</h3> <p>Генератор экспортирует всего две функции: одна непосредственно генерирует серийный номер, вторая - освобождает память, выделенную первой. Начнем с первой и основной функции:</p> <pre class="code"><strong>VMProtectErrors</strong> __stdcall <strong>VMProtectGenerateSerialNumber</strong>( <strong>VMProtectProductInfo *</strong> pProductInfo, <strong>VMProtectSerialNumberInfo *</strong> pSerialInfo, <strong>char **</strong> pSerialNumber ); </pre> <p>Первый параметр - указатель на структуру <strong>VMProtectProductInfo</strong>, содержимое которой выгружается в VMProtect (см. <a href= "../licenses.htm#export">Экспорт параметров продукта</a>). Структура содержит приватный ключ продукта, используемый алгоритм и количество бит, а также идентификатор продукта. Подробнее о заполнении этой структуры написано ниже.</p> <p>Второй параметр - указатель на структуру <strong>VMProtectSerialNumberInfo</strong>, содержимое которой переносится в генерируемый серийный номер. Структура содержит все поля серийного номера, а также битовую маску, определяющую какие именно поля должны быть записаны в серийный номер.</p> <pre class="code">struct <strong>VMProtectSerialNumberInfo</strong> { <strong>INT</strong> flags; <strong>wchar_t *</strong> pUserName; <strong>wchar_t *</strong> pEMail; <strong>DWORD</strong> dwExpDate; <strong>DWORD</strong> dwMaxBuildDate; <strong>BYTE</strong> nRunningTimeLimit; <strong>char *</strong> pHardwareID; <strong>size_t</strong> nUserDataLength; <strong>BYTE *</strong> pUserData; }; </pre> <p>Поле <strong>flags</strong> содержит битовые флаги из набора <strong>VMProtectSerialNumberFlags</strong>, описанного перед структурой:</p> <ul> <li><strong>HAS_USER_NAME</strong> - поместить в серийный номер имя пользователя, находящееся в переменной <strong>pUserName</strong>.</li> <li><strong>HAS_EMAIL</strong> - поместить в серийный номер e-mail пользователя, находящийся в переменной <strong>pEMail</strong>.</li> <li><strong>HAS_EXP_DATE</strong> - серийный номер перестанет действовать поле окончания дня, указанного в переменной <strong>dwExpDate</strong>.</li> <li><strong>HAS_MAX_BUILD_DATE</strong> - серийный номер будет подходить только к версиям продукта, созданным до даты, указанной в переменной <strong>dwMaxBuildDate</strong>.</li> <li><strong>HAS_TIME_LIMIT</strong> - программа перестанет работать по истечении времени, указанного в переменной <strong>nRunningTimeLimit</strong> (время указывается в минутах и не может превышать 255).</li> <li><strong>HAS_HARDWARE_ID</strong> - программа будет работать только на оборудовании с идентификатором, указанным в переменной <strong>pHardwareID</strong>.</li> <li><strong>HAS_USER_DATA</strong> - поместить в серийный номер пользовательские данные длинной <strong>nUserDataLength</strong>, расположенные по адресу, указанному в переменной <strong>pUserData</strong>.</li> </ul> <p>Третий параметр - указатель на указатель. Туда будет записан адрес сгенерированного серийного номера. После генерации номер необходимо скопировать, а адрес передать во вторую функцию API генератора, которая освободит занимаемую серийным номером память.</p> <pre class="code"><strong>void</strong> __stdcall <strong>VMProtectFreeSerialNumberMemory</strong>(<strong>char *</strong> pSerialNumber); </pre> <p>Функция <strong>VMProtectGenerateSerialNumber</strong> возвращает значение типа <strong>VMProtectErrors</strong>, содержащее 0 в случае успешной генерации номера или код ошибки в противном случае. Возможны следующие коды ошибок:</p> <ul> <li><strong>ALL_RIGHT</strong> - ошибок нет, номер сгенерирован успешно.</li> <li><strong>UNSUPPORTED_ALGORITHM</strong> - в первом параметре функции передан некорректный алгоритм шифрования ключа.</li> <li><strong>UNSUPPORTED_NUMBER_OF_BITS</strong> - в первом параметре функции передано некорректное количество бит в ключе.</li> <li><strong>USER_NAME_IS_TOO_LONG</strong> - длина имени пользователя в кодировке UTF-8 превысила 255 байт.</li> <li><strong>EMAIL_IS_TOO_LONG</strong> - длина e-mail пользователя в кодировке UTF-8 превысила 255 байт.</li> <li><strong>USER_DATA_IS_TOO_LONG</strong> - длина пользовательских данных превышает 255 байт.</li> <li><strong>HWID_HAS_BAD_SIZE</strong> - идентификатор оборудования имеет некорректный размер.</li> <li><strong>PRODUCT_CODE_HAS_BAD_SIZE</strong> - идентификатор продукта, переданный в первом параметре функции, имеет неверный размер.</li> <li><strong>SERIAL_NUMBER_TOO_LONG</strong> - серийный номер слишком длинный и не помещается в указанное в алгоритме количество бит.</li> <li><strong>BAD_PRODUCT_INFO</strong> - первый параметр функции некорректен или NULL.</li> <li><strong>BAD_SERIAL_NUMBER_INFO</strong> - второй параметр функции некорректен или NULL.</li> <li><strong>BAD_SERIAL_NUMBER_CONTAINER</strong> - третий параметр функции не указывает на ячейку памяти для записи адреса серийного номера.</li> <li><strong>NOT_EMPTY_SERIAL_NUMBER_CONTAINER</strong> - третий параметр функции не указывает на пустую ячейку, в ячейке должно быть значение NULL.</li> <li><strong>BAD_PRIVATE_EXPONENT</strong> - значение приватной экспоненты в первом параметре функции некорректно.</li> <li><strong>BAD_MODULUS</strong> - значение модуля в первом параметре функции некорректно.</li> </ul> <p>Ошибки делятся на две категории: те, что связаны с некорректными параметрами или с содержимым первого параметра функции, и все остальные. Ошибки первой категории редки и являются признаком некорректной настройки структуры. Имеет смысл выгрузить информацию о продукте повторно и убедиться, что структура заполняется правильно. Пример правильного заполнения приведен ниже.</p> <p>Ошибки второй категории связаны с попыткой вместить в ключ больше данных, чем это возможно ввиду его размера. В таком случае разумно будет отправить регистратору вместо ключа текст "Ключ будет выслан в течение суток", а всю необходимую информацию отправить себе по почте. Ключ в таком случае генерируется в VMProtect в ручном режиме, какие-то данные обрезаются, чтобы уместить все необходимое в максимальный размер ключа.</p> <h3>Пример использования</h3> <p>Ниже приведен пример кода, который вызывает две вышеописанные функции и генерирует серийный номер. Обратите внимание на блок кода, расположенный в самом начале. Пример не будет работать пока вы не замените его на блок, выгруженный для продукта из VMProtect:</p> <pre class="code">////////////////////////////////////////////////////////////////////////// // !!! this block should be generated by VMProtect !!! /// ////////////////////////////////////////////////////////////////////////// <strong>VMProtectAlgorithms</strong> g_Algorithm = ALGORITHM_RSA; <strong>size_t</strong> g_nBits = 0; <strong>byte</strong> g_vModulus[1]; <strong>byte</strong> g_vPrivate[1]; <strong>byte</strong> g_vProductCode[1]; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// <strong>int</strong> _tmain(<strong>int</strong> argc, <strong>_TCHAR*</strong> argv[]) { <strong>VMProtectProductInfo</strong> 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; <strong>VMProtectSerialNumberInfo</strong> si = {0}; si.flags = HAS_USER_NAME | HAS_EMAIL; si.pUserName = L"John Doe"; si.pEMail = L"john@doe.com"; <strong>char *</strong> pBuf = NULL; <strong>VMProtectErrors</strong> res = <strong>VMProtectGenerateSerialNumber</strong>(&pi, &si, &pBuf); <strong>if</strong> (res == ALL_RIGHT) { <strong>printf</strong>("Serial number:\n%s\n", pBuf); <strong>VMProtectFreeSerialNumberMemory</strong>(pBuf); } else { <strong>printf</strong>("Error: %d\n", res); } <strong>return</strong> 0; } </pre> <p>Этот пример с проектом для Microsoft Visual Studio находится в каталоге <strong>Keygen\DLL\Example</strong>, ниже будут описаны наиболее интересные места кода.</p> <p>Первые строчки функции <strong>main</strong> заполняют структуру <strong>VMProtectProductInfo</strong> данными, выгруженными из VMProtect. Этот код стандартен, его не следует менять во избежание появления ошибок. Далее создается структура <strong>VMProtectSerialNumberInfo</strong>, в поле флагов выставляется комбинация из битов имени пользователя и e-mail. Строчкой ниже в соответствующие поля структуры заносятся значения имени пользователя и пароля. Обратите внимание, что значения принимаются в кодировке UNICODE. Генератор ключей внутри преобразует их в кодировку UTF-8.</p> <p>Далее описывается переменная-указатель, куда будет записан адрес сгенерированного ключа, и вызывается функция <strong>VMProtectGenerateSerialNumber</strong>, после чего анализируется код возврата. Если ошибок нет, то сгенерированный номер печатается на консоль и вызывается функция осовобождения памяти.</p> <h3>Остальные поля структуры VMprotectSerialNumberInfo</h3> <p>Некоторые поля структуры требуют дополнительных поясненений. К примеру, поля <strong>dwExpDate</strong> и <strong>dwMaxBuildDate</strong> содержат даты в определенном формате: <strong>0xYYYYMMDD</strong>, т.е. год хранится в старшем слове, а месяц и день в старшем и младшем байтах младшего слова. Для формирования такого числа описан макрос <strong>MAKEDATE(y, m, d)</strong>, который можно вызвать так: <strong>MAKEDATE(2010, 05, 12)</strong>.</p> <p>В поле <strong>pHardwareID</strong> должен быть записан указатель на строку, которую вернул метод <strong>VMProtectGetCurrentHWID</strong> из SDK лицензирования.</p><br /> <br /> <br /> <br /> <br /> <hr noshade="noshade" size="1" /> <div align="center"> © 2006-2015 Copyright VMProtect Software </div> </body> </html>