mirror of
				https://github.com/Obfuscator-Collections/VMProtect.git
				synced 2025-10-30 04:01:32 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			285 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!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>
 |