-
Notifications
You must be signed in to change notification settings - Fork 1
/
kms.h
287 lines (248 loc) · 9.16 KB
/
kms.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#ifndef __kms_h
#define __kms_h
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
#include <sys/time.h>
#include <stdlib.h>
#include "types.h"
//
// REQUEST... types are actually fixed size
// RESPONSE... size may vary, defined here is max possible size
//
#define MAX_RESPONSE_SIZE 384
#define PID_BUFFER_SIZE 64
#define MAX_REQUEST_SIZE sizeof(REQUEST_V6)
#define WORKSTATION_NAME_BUFFER 64
// Constants for V6 time stamp interval
#define TIME_C1 0x00000022816889BDULL
#define TIME_C2 0x000000208CBAB5EDULL
#define TIME_C3 0x3156CD5AC628477AULL
#define VERSION_INFO union \
{ \
DWORD Version;\
struct { \
WORD MinorVer; \
WORD MajorVer; \
} /*__packed*/; \
} /*__packed*/
// Aliases for various KMS struct members
#define IsClientVM VMInfo
#define GraceTime BindingExpiration
#define MinutesRemaingInCurrentStatus BindingExpiration
#define ID ActID
#define ApplicationID AppID
#define SkuId ActID
#define KmsId KMSID
#define ClientMachineId CMID
#define MinimumClients N_Policy
#define TimeStamp ClientTime
#define PreviousCLientMachineId CMID_prev
#define Salt IV
#define XorSalt XoredIVs
#define ActivationInterval VLActivationInterval
#define RenewalInterval VLRenewalInterval
typedef struct {
VERSION_INFO;
DWORD VMInfo; // 0 = client is bare metal / 1 = client is VM
DWORD LicenseStatus; // 0 = Unlicensed, 1 = Licensed (Activated), 2 = OOB grace, 3 = OOT grace, 4 = NonGenuineGrace, 5 = Notification, 6 = extended grace
DWORD BindingExpiration; // Expiration of the current status in minutes (e.g. when KMS activation or OOB grace expires).
GUID AppID; // Can currently be Windows, Office2010 or Office2013 (see kms.c, table AppList).
GUID ActID; // Most detailed product list. One product key per ActID (see kms.c, table ExtendedProductList). Is ignored by KMS server.
GUID KMSID; // This is actually what the KMS server uses to grant or refuse activation (see kms.c, table BasicProductList).
GUID CMID; // Client machine id. Used by the KMS server for counting minimum clients.
DWORD N_Policy; // Minimum clients required for activation.
FILETIME ClientTime; // Current client time.
GUID CMID_prev; // previous client machine id. All zeros, if it never changed.
WCHAR WorkstationName[64]; // Workstation name. FQDN if available, NetBIOS otherwise.
} /*__packed*/ REQUEST;
typedef struct {
VERSION_INFO;
DWORD PIDSize; // Size of PIDData in bytes.
WCHAR KmsPID[PID_BUFFER_SIZE]; // ePID (must include terminating zero)
GUID CMID; // Client machine id. Must be the same as in request.
FILETIME ClientTime; // Current client time. Must be the same as in request.
DWORD Count; // Current activated machines. KMS server counts up to N_Policy << 1 then stops
DWORD VLActivationInterval; // Time in minutes when clients should retry activation if it was unsuccessful (default 2 hours)
DWORD VLRenewalInterval; // Time in minutes when clients should renew KMS activation (default 7 days)
} /*__packed*/ RESPONSE;
#ifdef _DEBUG
typedef struct {
VERSION_INFO;
DWORD PIDSize;
WCHAR KmsPID[49]; // Set this to the ePID length you want to debug
GUID CMID;
FILETIME ClientTime;
DWORD Count;
DWORD VLActivationInterval;
DWORD VLRenewalInterval;
} __packed RESPONSE_DEBUG;
#endif
typedef struct {
REQUEST RequestBase; // Base request
BYTE MAC[16]; // Aes 160 bit CMAC
} /*__packed*/ REQUEST_V4;
typedef struct {
RESPONSE ResponseBase; // Base response
BYTE MAC[16]; // Aes 160 bit CMAC
} /*__packed*/ RESPONSE_V4;
typedef struct {
VERSION_INFO; // unencrypted version info
BYTE IV[16]; // IV
REQUEST RequestBase; // Base Request
BYTE Pad[4]; // since this struct is fixed, we use fixed PKCS pad bytes
} /*__packed*/ REQUEST_V5;
typedef REQUEST_V5 REQUEST_V6; // v5 and v6 requests are identical
typedef struct {
VERSION_INFO;
BYTE IV[16];
RESPONSE ResponseBase;
BYTE RandomXoredIVs[16]; // If RequestIV was used for decryption: Random ^ decrypted Request IV ^ ResponseIV. If NULL IV was used for decryption: Random ^ decrypted Request IV
BYTE Hash[32]; // SHA256 of Random used in RandomXoredIVs
BYTE HwId[8]; // HwId from the KMS server
BYTE XoredIVs[16]; // If RequestIV was used for decryption: decrypted Request IV ^ ResponseIV. If NULL IV was used for decryption: decrypted Request IV.
BYTE HMAC[16]; // V6 Hmac (low 16 bytes only), see kms.c CreateV6Hmac
//BYTE Pad[10]; // Pad is variable sized. So do not include in struct
} /*__packed*/ RESPONSE_V6;
typedef struct { // not used except for sizeof(). Fields are the same as RESPONSE_V6
VERSION_INFO;
BYTE IV[16];
RESPONSE ResponseBase;
BYTE RandomXoredIVs[16];
BYTE Hash[32];
} /*__packed*/ RESPONSE_V5;
#ifdef _DEBUG
typedef struct { // Debug structure for direct casting of RPC data in debugger
VERSION_INFO;
BYTE IV[16];
RESPONSE_DEBUG ResponseBase;
BYTE RandomXoredIVs[16];
BYTE MAC[32];
BYTE Unknown[8];
BYTE XorSalts[16];
BYTE HMAC[16];
BYTE Pad[16];
} __packed RESPONSE_V6_DEBUG;
#endif
#define V4_PRE_EPID_SIZE ( \
sizeof(((RESPONSE*)0)->Version) + \
sizeof(((RESPONSE*)0)->PIDSize) \
)
#define V4_POST_EPID_SIZE ( \
sizeof(((RESPONSE*)0)->CMID) + \
sizeof(((RESPONSE*)0)->ClientTime) + \
sizeof(((RESPONSE*)0)->Count) + \
sizeof(((RESPONSE*)0)->VLActivationInterval) + \
sizeof(((RESPONSE*)0)->VLRenewalInterval) \
)
#define V6_DECRYPT_SIZE ( \
sizeof(((REQUEST_V6*)0)->IV) + \
sizeof(((REQUEST_V6*)0)->RequestBase) + \
sizeof(((REQUEST_V6*)0)->Pad) \
)
#define V6_UNENCRYPTED_SIZE ( \
sizeof(((RESPONSE_V6*)0)->Version) + \
sizeof(((RESPONSE_V6*)0)->IV) \
)
#define V6_PRE_EPID_SIZE ( \
V6_UNENCRYPTED_SIZE + \
sizeof(((RESPONSE*)0)->Version) + \
sizeof(((RESPONSE*)0)->PIDSize) \
)
#define V5_POST_EPID_SIZE ( \
V4_POST_EPID_SIZE + \
sizeof(((RESPONSE_V6*)0)->RandomXoredIVs) + \
sizeof(((RESPONSE_V6*)0)->Hash) \
)
#define V6_POST_EPID_SIZE ( \
V5_POST_EPID_SIZE + \
sizeof(((RESPONSE_V6*)0)->HwId) + \
sizeof(((RESPONSE_V6*)0)->XoredIVs) + \
sizeof(((RESPONSE_V6*)0)->HMAC) \
)
#define RESPONSE_RESULT_OK ((1 << 10) - 1) //(9 bits)
typedef union
{
DWORD mask;
struct
{
BOOL HashOK : 1;
BOOL TimeStampOK : 1;
BOOL ClientMachineIDOK : 1;
BOOL VersionOK : 1;
BOOL IVsOK : 1;
BOOL DecryptSuccess : 1;
BOOL HmacSha256OK : 1;
BOOL PidLengthOK : 1;
BOOL RpcOK : 1;
BOOL IVnotSuspicious : 1;
BOOL reserved3 : 1;
BOOL reserved4 : 1;
BOOL reserved5 : 1;
BOOL reserved6 : 1;
uint32_t effectiveResponseSize : 9;
uint32_t correctResponseSize : 9;
};
} RESPONSE_RESULT;
typedef BYTE hwid_t[8];
typedef struct
{
GUID guid;
const char* name;
const char* pid;
uint8_t AppIndex;
uint8_t KmsIndex;
} KmsIdList;
#define KMS_PARAM_MAJOR AppIndex
#define KMS_PARAM_REQUIREDCOUNT KmsIndex
#define APP_ID_WINDOWS 0
#define APP_ID_OFFICE2010 1
#define APP_ID_OFFICE2013 2
#define KMS_ID_VISTA 0
#define KMS_ID_WIN7 1
#define KMS_ID_WIN8_VL 2
#define KMS_ID_WIN_BETA 3
#define KMS_ID_WIN8_RETAIL 4
#define KMS_ID_WIN81_VL 5
#define KMS_ID_WIN81_RETAIL 6
#define KMS_ID_WIN2008A 7
#define KMS_ID_WIN2008B 8
#define KMS_ID_WIN2008C 9
#define KMS_ID_WIN2008R2A 10
#define KMS_ID_WIN2008R2B 11
#define KMS_ID_WIN2008R2C 12
#define KMS_ID_WIN2012 13
#define KMS_ID_WIN2012R2 14
#define KMS_ID_OFFICE2010 15
#define KMS_ID_OFFICE2013 16
#define KMS_ID_WIN_SRV_BETA 17
#define KMS_ID_OFFICE2016 18
#define KMS_ID_WIN10_VL 19
#define KMS_ID_WIN10_RETAIL 20
#define PWINGUID &AppList[APP_ID_WINDOWS].guid
#define POFFICE2010GUID &AppList[APP_ID_OFFICE2010].guid
#define POFFICE2013GUID &AppList[APP_ID_OFFICE2013].guid
typedef BOOL(__stdcall *RequestCallback_t)(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr);
size_t CreateResponseV4(REQUEST_V4 *const Request, BYTE *const response_data, const char* const ipstr);
size_t CreateResponseV6(REQUEST_V6 *restrict Request, BYTE *const response_data, const char* const ipstr);
BYTE *CreateRequestV4(size_t *size, const REQUEST* requestBase);
BYTE *CreateRequestV6(size_t *size, const REQUEST* requestBase);
void randomPidInit();
void get16RandomBytes(void* ptr);
RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* Response_v6, int responseSize, BYTE* const response, const BYTE* const request, BYTE* hwid);
RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* Response_v4, const int responseSize, BYTE* const response, const BYTE* const request);
void getUnixTimeAsFileTime(FILETIME *const ts);
__pure int64_t fileTimeToUnixTime(const FILETIME *const ts);
const char* getProductNameHE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i);
const char* getProductNameLE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i);
__pure ProdListIndex_t getExtendedProductListSize();
__pure ProdListIndex_t getAppListSize(void);
extern const KmsIdList ProductList[];
extern const KmsIdList AppList[];
extern const KmsIdList ExtendedProductList[];
extern RequestCallback_t CreateResponseBase;
#ifdef _PEDANTIC
uint16_t IsValidLcid(const uint16_t Lcid);
#endif // _PEDANTIC
#endif // __kms_h