2015-11-29 17:30:52 +08:00
#ifndef __kms_h
#define __kms_h
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
2016-10-08 13:35:48 +08:00
#if _MSC_VER
2016-12-02 15:56:18 +08:00
//#include <time.h>
2016-10-08 13:35:48 +08:00
#else
2015-11-29 17:30:52 +08:00
#include <sys/time.h>
2016-10-08 13:35:48 +08:00
#endif // _MSC_VER
2016-12-02 15:56:18 +08:00
//#include <stdlib.h>
2015-11-29 17:30:52 +08:00
#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
2016-10-31 20:59:15 +08:00
#define MAX_CLIENTS 671
typedef struct
{
GUID Guid [ MAX_CLIENTS ];
int_fast16_t CurrentCount ;
int_fast16_t MaxCount ;
int_fast16_t CurrentPosition ;
} ClientList_t , * PClientList_t ;
2015-11-29 17:30:52 +08:00
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 {
2016-12-02 15:56:18 +08:00
VERSION_INFO ;
2015-11-29 17:30:52 +08:00
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 ];
2016-12-02 15:56:18 +08:00
typedef struct CsvlkData
{
union
{
uint64_t EPidOffset ;
char * EPid ;
};
uint32_t GroupId ;
uint32_t MinKeyId ;
uint32_t MaxKeyId ;
uint8_t MinActiveClients ;
uint8_t Reserved [ 3 ];
} CsvlkData_t , * PCsvlkData_t ;
typedef struct VlmcsdData
2015-11-29 17:30:52 +08:00
{
2016-12-02 15:56:18 +08:00
union
{
GUID Guid ;
uint8_t GuidBytes [ 16 ];
};
union
{
uint64_t NameOffset ;
char * Name ;
};
//union
//{
// uint64_t X_EPidOffset;
// char* X_EPid;
//};
2015-11-29 17:30:52 +08:00
uint8_t AppIndex ;
uint8_t KmsIndex ;
2016-12-02 15:56:18 +08:00
uint8_t ProtocolVersion ;
uint8_t NCountPolicy ;
uint8_t IsRetail ;
uint8_t IsPreview ;
uint8_t EPidIndex ;
uint8_t reserved ;
2015-11-29 17:30:52 +08:00
2016-12-02 15:56:18 +08:00
} VlmcsdData_t , * PVlmcsdData_t ;
2015-11-29 17:30:52 +08:00
2016-12-02 15:56:18 +08:00
typedef struct
{
union
{
uint64_t Offset ;
void * Pointer ;
};
} DataPointer_t ;
2015-11-29 17:30:52 +08:00
2016-12-02 15:56:18 +08:00
typedef struct VlmcsdHeader
{
BYTE Magic [ 4 ];
VERSION_INFO ;
uint8_t CsvlkCount ;
uint8_t Reserved [ 3 ];
2016-09-18 11:30:46 +08:00
2016-12-02 15:56:18 +08:00
union
{
int32_t Counts [ 3 ];
struct
{
int32_t AppItemCount ;
int32_t KmsItemCount ;
int32_t SkuItemCount ;
};
};
union
{
DataPointer_t Datapointers [ 3 ];
struct
{
union
{
uint64_t AppItemOffset ;
PVlmcsdData_t AppItemList ;
};
union
{
uint64_t KmsItemOffset ;
PVlmcsdData_t KmsItemList ;
};
union
{
uint64_t SkuItemOffset ;
PVlmcsdData_t SkuItemList ;
};
CsvlkData_t CsvlkData [ 1 ];
};
};
} VlmcsdHeader_t , * PVlmcsdHeader_t ;
#define EPID_INDEX_WINDOWS 0
#define EPID_INDEX_OFFICE2010 1
#define EPID_INDEX_OFFICE2013 2
#define EPID_INDEX_OFFICE2016 3
2015-11-29 17:30:52 +08:00
2016-10-24 21:32:24 +08:00
typedef HRESULT ( __stdcall * RequestCallback_t )( const REQUEST * const baseRequest , RESPONSE * const baseResponse , BYTE * const hwId , const char * const ipstr );
2015-11-29 17:30:52 +08:00
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 );
2016-12-02 15:56:18 +08:00
#ifndef IS_LIBRARY
int32_t getProductIndex ( const GUID * guid , const PVlmcsdData_t list , const int32_t count , char ** name , char ** ePid );
#endif // IS_LIBRARY
2015-11-29 17:30:52 +08:00
2016-10-31 20:59:15 +08:00
#ifndef NO_STRICT_MODES
void InitializeClientLists ();
void CleanUpClientLists ();
#endif // !NO_STRICT_MODES
2015-11-29 17:30:52 +08:00
extern RequestCallback_t CreateResponseBase ;
#ifdef _PEDANTIC
uint16_t IsValidLcid ( const uint16_t Lcid );
#endif // _PEDANTIC
#endif // __kms_h