mirror of
https://github.com/Obfuscator-Collections/VMProtect.git
synced 2024-12-27 08:49:27 +03:00
261 lines
11 KiB
HTML
261 lines
11 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>Формат серийного номера</title>
|
|||
|
<style type="text/css">
|
|||
|
/*<![CDATA[*/
|
|||
|
th {text-align:left;}
|
|||
|
table {border-collapse:collapse; margin-top: 4px;}
|
|||
|
td,th {border: 1px solid #B0B0B0; padding-left:10;padding-right:10;}
|
|||
|
/*]]>*/
|
|||
|
</style>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
<h1>Формат серийного номера</h1>
|
|||
|
|
|||
|
<h3>Структура серийного номера</h3>
|
|||
|
|
|||
|
<p>Серийный номер состоит из блоков. Каждый блок
|
|||
|
начинается с байта идентификатора, который определяет его
|
|||
|
содержимое и, возможно, длину. Последним всегда идет блок с
|
|||
|
идентификатором 255, содержащий контрольную сумму всего серийного
|
|||
|
номера, за исключением последнего блока.</p>
|
|||
|
|
|||
|
<p>В зависимости от типа блока, он может иметь фиксированную или
|
|||
|
переменную длину. Во втором случае обычно длина идет в следующем
|
|||
|
за идентификатором блока байте. Подробно формат каждого блока
|
|||
|
описан ниже.</p>
|
|||
|
|
|||
|
<h3>Формат блоков</h3>
|
|||
|
|
|||
|
<table border="1" cellspacing="0" cellpadding="2">
|
|||
|
<tr>
|
|||
|
<th>ID</th>
|
|||
|
|
|||
|
<th>Название</th>
|
|||
|
|
|||
|
<th>Размер (байт)</th>
|
|||
|
|
|||
|
<th>Описание</th>
|
|||
|
|
|||
|
<th>Пример</th>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x01</td>
|
|||
|
|
|||
|
<td>Версия</td>
|
|||
|
|
|||
|
<td>1</td>
|
|||
|
|
|||
|
<td>Блок содержит версию серийного номера размером в 1 байт.
|
|||
|
Версия должна быть равна 1.</td>
|
|||
|
|
|||
|
<td>01 01</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x02</td>
|
|||
|
|
|||
|
<td>Имя пользователя</td>
|
|||
|
|
|||
|
<td>1 + N</td>
|
|||
|
|
|||
|
<td>Блок содержит имя пользователя в кодировке UTF-8. Перед
|
|||
|
именем пользователя располагается 1 байт длины имени. Таким
|
|||
|
образом, длина имени пользователя не может превышать 255
|
|||
|
байт. Завершающий 0 не требуется.</td>
|
|||
|
|
|||
|
<td>02 04 4A 5F 48 4E</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x03</td>
|
|||
|
|
|||
|
<td>E-Mail</td>
|
|||
|
|
|||
|
<td>1 + N</td>
|
|||
|
|
|||
|
<td>Блок содержит e-mail пользователя в кодировке UTF-8.
|
|||
|
Перед e-mail'ом располагается 1 байт длины. Таким образом,
|
|||
|
длина e-mail не может превышать 255 байт. Завершающий 0 не
|
|||
|
требуется.</td>
|
|||
|
|
|||
|
<td>03 07 61 40 62 2E 63 6F 6D</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x04</td>
|
|||
|
|
|||
|
<td>Идентификатор оборудования</td>
|
|||
|
|
|||
|
<td>1 + N</td>
|
|||
|
|
|||
|
<td>Блок содержит идентификатор оборудования, возвращенный
|
|||
|
функцией <strong>VMProtectGetCurrentHWID()</strong>. Функция
|
|||
|
возвращает строку в кодировке base-64, в серийный номер
|
|||
|
помещается раскодированный вариант строки. Длина блока данных
|
|||
|
должна быть кратна 4. Перед блоком данных располагается байт
|
|||
|
длины. Максимальная длина блока - 32 байта.</td>
|
|||
|
|
|||
|
<td>04 08 E1 E2 E3 E4 A1 A2 A3 A4</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x05</td>
|
|||
|
|
|||
|
<td>Дата окончания лицензии</td>
|
|||
|
|
|||
|
<td>4</td>
|
|||
|
|
|||
|
<td>Блок содержит дату окончания действия серийного номера.
|
|||
|
Формат хранения даты описан ниже.</td>
|
|||
|
|
|||
|
<td>05 01 0A 07 DA</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x06</td>
|
|||
|
|
|||
|
<td>Максимальное время работы</td>
|
|||
|
|
|||
|
<td>1</td>
|
|||
|
|
|||
|
<td>Блок содержит 1 байт с временем работы программы в
|
|||
|
минутах. Максимальное время работы, таким образом, может
|
|||
|
составлять 255 минут.</td>
|
|||
|
|
|||
|
<td>06 05</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x07</td>
|
|||
|
|
|||
|
<td>Код продукта</td>
|
|||
|
|
|||
|
<td>8</td>
|
|||
|
|
|||
|
<td>Блок содержит код продукта - 8 байт, которые создаются
|
|||
|
VMProtect и выгружаются при экспорте параметров продукта.
|
|||
|
Выгружаются они в кодировке base-64, перед помещением в
|
|||
|
серийный номер строку необходимо преобразовать в массив байт.
|
|||
|
Размер массива должен быть строго равен 8 байтам.
|
|||
|
<strong>Этот блок является обязательным, без него защищенная
|
|||
|
программа будет работать некорректно!</strong></td>
|
|||
|
|
|||
|
<td>07 01 02 03 04 05 06 07 08</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x08</td>
|
|||
|
|
|||
|
<td>Данные пользователя</td>
|
|||
|
|
|||
|
<td>1 + N</td>
|
|||
|
|
|||
|
<td>Блок содержит до 255 байт пользовательских данных.
|
|||
|
Система лицензирования не анализирует эти данные и возвращает
|
|||
|
их при вызове функции
|
|||
|
<strong>VMProtectGetSerialNumberData()</strong>. Перед блоком
|
|||
|
данных располагается байт, содержащий размер пользовательских
|
|||
|
данных.</td>
|
|||
|
|
|||
|
<td>08 05 01 02 03 04 05</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0x09</td>
|
|||
|
|
|||
|
<td>Максимальная дата сборки</td>
|
|||
|
|
|||
|
<td>4</td>
|
|||
|
|
|||
|
<td>Блок содержит максимальную дату сборки приложения, с
|
|||
|
которым будет работать этот серийный номер. Формат хранения
|
|||
|
даты описан ниже.</td>
|
|||
|
|
|||
|
<td>09 01 0A 07 DA</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>0xFF</td>
|
|||
|
|
|||
|
<td>Контрольная сумма</td>
|
|||
|
|
|||
|
<td>4</td>
|
|||
|
|
|||
|
<td>Блок содержит контрольную сумму серийного номера. Блок
|
|||
|
располагается последним и контрольная сумма считается для
|
|||
|
всех блоков, идущих перед этим. Подробнее о расчете
|
|||
|
контрольной суммы написано ниже.</td>
|
|||
|
|
|||
|
<td>FF 01 02 03 04</td>
|
|||
|
</tr>
|
|||
|
</table>
|
|||
|
|
|||
|
<h3>Формат хранения даты</h3>
|
|||
|
|
|||
|
<p>Даты в серийном номере хранятся в виде двойного слова -
|
|||
|
0xYYYYMMDD. Старшее слово содержит год, а младшее - день и месяц.
|
|||
|
Байты расположены в порядке Little Endian - от младшего к
|
|||
|
старшему. В случае, если имеется указатель на первый байт записи,
|
|||
|
то дата может быть считана и записана следующим кодом:</p>
|
|||
|
<pre class="code"><strong>byte *</strong>pDate = 0xNNNNNN; // адрес даты
|
|||
|
<strong>*</strong>(<strong>DWORD *</strong>)pDate = (2010 << 16) | (10 << 8) | 1; // October 1, 2010
|
|||
|
<strong>DWORD</strong> dwExp = *(<strong>DWORD *</strong>)pDate;
|
|||
|
</pre>
|
|||
|
|
|||
|
<h3>Подсчет контрольной суммы</h3>
|
|||
|
|
|||
|
<p>Контрольная сумма серийного номера вычисляется при помощи
|
|||
|
алгоритма хеширования SHA-1. Результатом работы алгоритма
|
|||
|
являются пять 32-битных слов. Первое слово используется в
|
|||
|
качестве контрольной суммы серийного номера. <strong>Обратите
|
|||
|
внимание:</strong> слово записывается в формате Little Endian (от
|
|||
|
младшего байта к старшему). В строковом представлении хеша SHA-1
|
|||
|
используется формат Big Endian - числа записываются от старшего
|
|||
|
байта к младшему, поэтому если SHA-1 генерируется функцией,
|
|||
|
которая возвращает строку (как в PHP), то первые четыре байта
|
|||
|
хеша необходимо предварительно
|
|||
|
развернуть.</p>
|
|||
|
|
|||
|
<h3>Дополнительная информация</h3>
|
|||
|
|
|||
|
<p>Блоки с номерами, отличными от описанных выше, игнорируются
|
|||
|
системой лицензирования. Возможно появление новых блоков в
|
|||
|
будущих версиях. <strong>Не рекомендуется создавать свои блоки,
|
|||
|
используя свободные идентификаторы!</strong> Во-первых, это может
|
|||
|
привести к неработоспособности ключа с новыми версиями системы
|
|||
|
лицензирования. А во-вторых, защищаемая программа все равно не
|
|||
|
сможет прочитать значения этих блоков. Для хранения какой-либо
|
|||
|
информации в ключе нужно использовать поле <strong>User
|
|||
|
Data</strong>, которое предназначено именно для этого.</p>
|
|||
|
|
|||
|
<p>Серийный номер не содержит "соли" (SALT) - случайной
|
|||
|
информации, предназначенной для того, чтобы ключи для одних и тех
|
|||
|
же данных получались разными. Эта задача возлагается на алгоритм
|
|||
|
шифрования. Если необходимы отличия на уровне серийных номеров,
|
|||
|
скажем для серии ключей, проданных в организацию, можно записать
|
|||
|
номер ключа строкой в поле имени пользователя (ООО "Компания",
|
|||
|
ключ 1 из 10) или занести эту информацию в поле <strong>User
|
|||
|
Data</strong> в любом удобном для разработчика формате.</p><br />
|
|||
|
<br />
|
|||
|
<br />
|
|||
|
<br />
|
|||
|
<br />
|
|||
|
<hr noshade="noshade" size="1" />
|
|||
|
|
|||
|
<div align="center">
|
|||
|
© 2006-2015 Copyright VMProtect Software
|
|||
|
</div>
|
|||
|
</body>
|
|||
|
</html>
|