Browse Source

vlmcsd-1113-2020-03-28-Hotbird64

pull/38/head svn1113
Rouben Tchakhmakhtchian 2 years ago
parent
commit
e599080486
No known key found for this signature in database GPG Key ID: 8032EA4BFC7DEEC0
  1. 2
      GNUmakefile
  2. BIN
      etc/vlmcsd.kmd
  3. 5
      man/vlmcsd-floppy.7
  4. 6
      man/vlmcsd.8
  5. 6
      src/endian.c
  6. 88
      src/endian.h
  7. 27
      src/helpers.c
  8. 209
      src/kms.c
  9. 68
      src/kms.h
  10. 1853
      src/kmsdata-full.c
  11. 2195
      src/kmsdata.c
  12. 2
      src/msrpc-client.c
  13. 2
      src/msrpc-server.c
  14. 2
      src/ns_name.c
  15. 2
      src/ns_name.h
  16. 12
      src/ns_parse.c
  17. 10
      src/ns_parse.h
  18. 4
      src/output.c
  19. 4
      src/output.h
  20. 9
      src/rpc.c
  21. 1
      src/shared_globals.h
  22. 95
      src/vlmcs.c
  23. 189
      src/vlmcsd.c
  24. 2
      src/vlmcsd.h
  25. 28
      src/wintap.c

2
GNUmakefile

@ -225,9 +225,9 @@ help:
@echo " DNS_PARSER=internal Use $(BASE_CLIENT_NAME) internal DNS parsing routines. No effect on MingW (native Windows)."
@echo ""
@echo "Other useful CFLAGS"
@echo " -DNO_COMPILER_UAA Do not use compiler support for byte swapping and unaligned access"
@echo " -DFULL_INTERNAL_DATA Embed full internal KMS data in $(BASE_PROGRAM_NAME)."
@echo " -DSUPPORT_WINE Add code that the Windows version of $(BASE_PROGRAM_NAME) runs on Wine if MSRPC=1"
@echo " -D_PEDANTIC Report rare error/warning conditions instead of silently ignoring them."
@echo " -DINCLUDE_BETAS Include SKU / activation IDs for obsolete beta/preview products."
@echo " -DFD_SETSIZE=<x> Allow <x> -L statements in $(BASE_PROGRAM_NAME) (default: 64 on Windows, 1024 on most Unixes)."

BIN
etc/vlmcsd.kmd

5
man/vlmcsd-floppy.7

@ -1,5 +1,5 @@
.mso www.tmac
.TH "VLMCSD-FLOPPY" 7 "May 2017" "Hotbird64" "KMS Activation Manual"
.TH "VLMCSD-FLOPPY" 7 "February 2019" "Hotbird64" "KMS Activation Manual"
.LO 8
.SH NAME
@ -107,6 +107,9 @@ Defines the ePID that is used for Office 2016 activations. If you ommit this par
.IP "\fBOFFICE2016=\fIepid\fR"
Defines the ePID that is used for Office 2016 activations. If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.
.IP "\fBOFFICE2019=\fIepid\fR"
Defines the ePID that is used for Office 2019 activations. If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.
.IP "\fBWINCHINAGOV=\fIepid\fR"
Defines the ePID that is used for Windows China Government Edition activations (Enterprise G/GN). If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.

6
man/vlmcsd.8

@ -1,5 +1,5 @@
.mso www.tmac
.TH VLMCSD 8 "October 2018" "Hotbird64" "KMS Activation Manual"
.TH VLMCSD 8 "February 2019" "Hotbird64" "KMS Activation Manual"
.LO 8
.SH NAME
@ -312,9 +312,9 @@ Signaling is not available in the native Windows version and in the Cygwin versi
\fBvlmcsd\fR compiles and runs on Linux, Windows (no Cygwin required but explicitly supported), Mac OS X, FreeBSD, NetBSD, OpenBSD, Dragonfly BSD, Minix, Solaris, OpenIndiana, Android and iOS. Other POSIX or unixoid OSses may work with unmodified sources or may require minor porting efforts.
.SH SUPPORTED PRODUCTS
\fBvlmcsd\fR can answer activation requests for the following products: Windows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10 (up to 1703), Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server 2016, Office 2010, Project 2010, Visio 2010, Office 2013, Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016. Newer products may work as long as the KMS protocol does not change. A complete list of fully supported products can be obtained using the \fB-x\fR option of \fBvlmcs\fR(1).
\fBvlmcsd\fR can answer activation requests for the following products: Windows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10 (up to 1809), Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server 2016, Office 2010, Project 2010, Visio 2010, Office 2013, Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016, Office 2019, Project 2019, Visio 2019. Newer products may work as long as the KMS protocol does not change. A complete list of fully supported products can be obtained using the \fB-x\fR option of \fBvlmcs\fR(1).
.PP
Office, Project and Visio must be volume license versions.
Windows Vista, Windows 7, Office, Project and Visio must be volume license versions.
.SH FILES
.IP "\fBvlmcsd.ini\fR(5)"

6
src/endian.c

@ -6,7 +6,7 @@
#include "endian.h"
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64)
&& defined(BS16) && defined(BS32) && defined(BS64) && !defined(NO_COMPILER_UAA)
#else // ! defined(__BYTE_ORDER)
@ -136,8 +136,12 @@ unsigned short GET_UAA16LE(void *p, unsigned int i)
(unsigned short)_p[ 0 ] |
(unsigned short)_p[ 1 ] << 8;
}
#endif
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64)
#else
unsigned short BE16(unsigned short x)
{
return GET_UAA16BE(&x, 0);

88
src/endian.h

@ -9,17 +9,17 @@
//
// Unaligned access
//
#if !defined(NO_COMPILER_UAA)
#define UAA16(p, i) (((PACKED16*)p)->val[i])
#define UAA32(p, i) (((PACKED32*)p)->val[i])
#define UAA64(p, i) (((PACKED64*)p)->val[i])
#define UA64(p) UAA64(p, 0)
#define UA32(p) UAA32(p, 0)
#define UA16(p) UAA16(p, 0)
#endif
//
//Byteswap: Use compiler support if available
//
#ifndef NO_COMPILER_UAA
#ifdef __has_builtin // Clang supports this
#if __has_builtin(__builtin_bswap16)
@ -56,6 +56,7 @@
#endif // GNU C > 4.7
#endif // __GNUC__ > 4
#endif // __GNUC__
#endif // NO_COMPILER_UAA
//
// Byteorder
@ -198,6 +199,10 @@
#define __BE64(x) BS64(x)
#define __LE64(x) (x)
#define PUT_UA16(p, v) PUT_UA16LE(p, v)
#define PUT_UA32(p, v) PUT_UA32LE(p, v)
#define PUT_UA64(p, v) PUT_UA64LE(p, v)
#else // __BYTE_ORDER == __BIG_ENDIAN
#define __BE16(x) (x)
@ -207,8 +212,38 @@
#define __BE64(x) (x)
#define __LE64(x) BS64(x)
#define PUT_UA16(p, v) PUT_UA16BE(p, v)
#define PUT_UA32(p, v) PUT_UA32BE(p, v)
#define PUT_UA64(p, v) PUT_UA64BE(p, v)
#endif // __BYTE_ORDER
#define BE16(x) __BE16(x)
#define LE16(x) __LE16(x)
#define BE32(x) __BE32(x)
#define LE32(x) __LE32(x)
#define BE64(x) __BE64(x)
#define LE64(x) __LE64(x)
#else
extern unsigned short BE16(unsigned short x);
extern unsigned short LE16(unsigned short x);
extern unsigned int BE32(unsigned int x);
extern unsigned int LE32(unsigned int x);
extern unsigned long long BE64(unsigned long long x);
extern unsigned long long LE64(unsigned long long x);
#endif // defined(__BYTE_ORDER)
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64) &&!defined(NO_COMPILER_UAA)
#define PUT_UAA64BE(p, v, i) ( UAA64(p, i) = __BE64(v) )
#define PUT_UAA32BE(p, v, i) ( UAA32(p, i) = __BE32(v) )
#define PUT_UAA16BE(p, v, i) ( UAA16(p, i) = __BE16(v) )
@ -225,56 +260,37 @@
#define GET_UAA32LE(p, i) __LE32(UAA32(p, i))
#define GET_UAA16LE(p, i) __LE16(UAA16(p, i))
#define BE16(x) __BE16(x)
#define LE16(x) __LE16(x)
#define BE32(x) __BE32(x)
#define LE32(x) __LE32(x)
#define BE64(x) __BE64(x)
#define LE64(x) __LE64(x)
#else // ! defined(__BYTE_ORDER)
extern void PUT_UAA64BE(void *p, unsigned long long v, unsigned int i);
extern void PUT_UAA64BE(void* p, unsigned long long v, unsigned int i);
extern void PUT_UAA32BE(void *p, unsigned int v, unsigned int i);
extern void PUT_UAA32BE(void* p, unsigned int v, unsigned int i);
extern void PUT_UAA16BE(void *p, unsigned short v, unsigned int i);
extern void PUT_UAA16BE(void* p, unsigned short v, unsigned int i);
extern void PUT_UAA64LE(void *p, unsigned long long v, unsigned int i);
extern void PUT_UAA64LE(void* p, unsigned long long v, unsigned int i);
extern void PUT_UAA32LE(void *p, unsigned int v, unsigned int i);
extern void PUT_UAA32LE(void* p, unsigned int v, unsigned int i);
extern void PUT_UAA16LE(void *p, unsigned short v, unsigned int i);
extern void PUT_UAA16LE(void* p, unsigned short v, unsigned int i);
extern unsigned long long GET_UAA64BE(void *p, unsigned int i);
extern unsigned long long GET_UAA64BE(void* p, unsigned int i);
extern unsigned int GET_UAA32BE(void *p, unsigned int i);
extern unsigned int GET_UAA32BE(void* p, unsigned int i);
extern unsigned short GET_UAA16BE(void *p, unsigned int i);
extern unsigned short GET_UAA16BE(void* p, unsigned int i);
extern unsigned long long GET_UAA64LE(void *p, unsigned int i);
extern unsigned long long GET_UAA64LE(void* p, unsigned int i);
extern unsigned int GET_UAA32LE(void *p, unsigned int i);
extern unsigned int GET_UAA32LE(void* p, unsigned int i);
extern unsigned short GET_UAA16LE(void *p, unsigned int i);
extern unsigned short BE16(unsigned short x);
extern unsigned short LE16(unsigned short x);
extern unsigned int BE32(unsigned int x);
extern unsigned int LE32(unsigned int x);
extern unsigned long long BE64(unsigned long long x);
extern unsigned long long LE64(unsigned long long x);
extern unsigned short GET_UAA16LE(void* p, unsigned int i);
#endif
#endif // defined(__BYTE_ORDER)
#define PUT_UA64BE(p, v) PUT_UAA64BE(p, v, 0)

27
src/helpers.c

@ -434,14 +434,14 @@ __pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
#ifndef NO_EXTERNAL_DATA
__noreturn static void dataFileReadError()
{
int error = errno;
const int error = errno;
errorout("Fatal: Could not read %s: %s\n", fn_data, strerror(error));
exit(error);
}
__noreturn static void dataFileFormatError()
{
errorout("Fatal: %s is not a KMS data file\n", fn_data);
errorout("Fatal: %s is not a KMS data file version 2.x\n", fn_data);
exit(VLMCSD_EINVAL);
}
#endif // NO_EXTERNAL_DATA
@ -526,7 +526,7 @@ static void getDefaultDataFile()
getExeName();
strncpy(fileName, fn_exe, MAX_PATH);
PathRemoveFileSpec(fileName);
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH);
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH - 11);
fn_data = vlmcsd_strdup(fileName);
}
#else // !_WIN32
@ -588,12 +588,12 @@ void loadKmsData()
KmsData = (PVlmcsdHeader_t)vlmcsd_malloc(size);
if (fseek(file, 0, SEEK_SET)) dataFileReadError();
size_t bytesRead = fread(KmsData, 1, size, file);
const size_t bytesRead = fread(KmsData, 1, size, file);
if ((long)bytesRead != size) dataFileReadError();
fclose(file);
# if !defined(NO_LOG) && !defined(NO_SOCKETS)
if (!InetdMode) logger("Read KMS data file version %u.%u %s\n", (unsigned int)KmsData->MajorVer, (unsigned int)KmsData->MinorVer, fn_data);
if (!InetdMode) logger("Read KMS data file version %u.%u %s\n", (unsigned int)LE16(KmsData->MajorVer), (unsigned int)LE16(KmsData->MinorVer), fn_data);
# endif // NO_LOG
}
}
@ -610,6 +610,7 @@ void loadKmsData()
KmsData->AppItemCount = LE32(KmsData->AppItemCount);
KmsData->KmsItemCount = LE32(KmsData->KmsItemCount);
KmsData->SkuItemCount = LE32(KmsData->SkuItemCount);
KmsData->HostBuildCount = LE32(KmsData->HostBuildCount);
uint32_t i;
@ -625,6 +626,7 @@ void loadKmsData()
{
PCsvlkData_t csvlkData = &KmsData->CsvlkData[i];
csvlkData->EPid = (char*)KmsData + LE64(csvlkData->EPidOffset);
csvlkData->ReleaseDate = LE64(csvlkData->ReleaseDate);
# ifndef UNSAFE_DATA_LOAD
if (csvlkData->EPid > (char*)KmsData + size) dataFileFormatError();
# endif // UNSAFE_DATA_LOAD
@ -636,12 +638,25 @@ void loadKmsData()
# endif // NO_RANDOM_EPID
}
for (i = 0; i < (uint32_t)KmsData->HostBuildCount; i++)
{
PHostBuild_t hostBuild = &KmsData->HostBuildList[i];
hostBuild->BuildNumber = LE32(hostBuild->BuildNumber);
hostBuild->Flags = LE32(hostBuild->Flags);
hostBuild->PlatformId = LE32(hostBuild->PlatformId);
hostBuild->ReleaseDate = LE64(hostBuild->ReleaseDate);
hostBuild->DisplayName = (char*)KmsData + LE64(hostBuild->DisplayNameOffset);
# ifndef UNSAFE_DATA_LOAD
if (hostBuild->DisplayName > (char*)KmsData + size) dataFileFormatError();
# endif // UNSAFE_DATA_LOAD
}
const uint32_t totalItemCount = KmsData->AppItemCount + KmsData->KmsItemCount + KmsData->SkuItemCount;
# ifndef NO_EXTERNAL_DATA
if (
memcmp(KmsData->Magic, "KMD", sizeof(KmsData->Magic)) ||
KmsData->MajorVer != 1
KmsData->MajorVer != 2
# ifndef UNSAFE_DATA_LOAD
||
sizeof(VlmcsdHeader_t) + totalItemCount * sizeof(VlmcsdData_t) >= ((uint64_t)size)

209
src/kms.c

@ -57,16 +57,23 @@ int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_
}
}
if (name) *name = "Unknown";
if (ePid) *ePid = KmsData->CsvlkData[EPID_INDEX_WINDOWS].EPid;
if (name) *name = (char*)"Unknown";
if (ePid) *ePid = KmsData->CsvlkData->EPid;
return i;
}
#if !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
const char* getNextString(const char* s)
{
return s + strlen(s) + 1;
}
#endif //!defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
#endif // IS_LIBRARY
#ifndef NO_RANDOM_EPID
static const uint16_t HostBuilds[] = { 6002, 7601, 9200, 9600, 14393, 17763 };
//static const uint16_t HostBuilds[] = { 6002, 7601, 9200, 9600, 14393, 17763 };
// Valid language identifiers to be used in the ePID
static const uint16_t LcidList[] = {
@ -80,14 +87,38 @@ static const uint16_t LcidList[] = {
17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077
};
uint16_t getPlatformId(uint16_t hostBuild)
int32_t getPlatformId(int32_t hostBuild)
{
if (hostBuild < 9000) return 55041;
if (hostBuild <= 9500) return 5426;
if (hostBuild <= 10000) return 6401;
return 3612;
int32_t i;
for (i = 0; i < KmsData->HostBuildCount; i++)
{
if (KmsData->HostBuildList[i].BuildNumber <= hostBuild)
{
return KmsData->HostBuildList[i].PlatformId;
}
}
return KmsData->HostBuildList[KmsData->HostBuildCount - 1].PlatformId;
}
time_t getReleaseDate(int32_t hostBuild)
{
int32_t i;
for (i = KmsData->HostBuildCount - 1; i >= 0; i--)
{
if (KmsData->HostBuildList[i].BuildNumber >= hostBuild)
{
return (time_t)KmsData->HostBuildList[i].ReleaseDate;
}
}
return (time_t)KmsData->HostBuildList->ReleaseDate;
}
#ifdef _PEDANTIC
uint16_t IsValidLcid(const uint16_t lcid)
{
@ -102,13 +133,13 @@ uint16_t IsValidLcid(const uint16_t lcid)
}
uint16_t IsValidHostBuild(const uint16_t hostBuild)
uint32_t IsValidHostBuild(const int32_t hostBuild)
{
const uint16_t *hostOS;
PHostBuild_t hostOS;
for (hostOS = HostBuilds; hostOS < HostBuilds + vlmcsd_countof(HostBuilds); hostOS++)
for (hostOS = KmsData->HostBuildList; hostOS < KmsData->HostBuildList + KmsData->HostBuildCount; hostOS++)
{
if (hostBuild == *hostOS) return hostBuild;
if (hostBuild == hostOS->BuildNumber) return hostBuild;
}
return 0;
@ -119,7 +150,7 @@ uint16_t IsValidHostBuild(const uint16_t hostBuild)
// Unix time is seconds from 1970-01-01. Should be 64 bits to avoid year 2038 overflow bug.
// FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits.
void getUnixTimeAsFileTime(FILETIME *const ts)
void getUnixTimeAsFileTime(FILETIME* ts)
{
const int64_t unixtime = (int64_t)time(NULL);
int64_t *filetime = (int64_t*)ts;
@ -127,7 +158,7 @@ void getUnixTimeAsFileTime(FILETIME *const ts)
PUT_UA64LE(filetime, (unixtime + 11644473600LL) * 10000000LL);
}
__pure int64_t fileTimeToUnixTime(const FILETIME *const ts)
__pure int64_t fileTimeToUnixTime(FILETIME* ts)
{
return GET_UA64LE(ts) / 10000000LL - 11644473600LL;
}
@ -255,19 +286,18 @@ static uint8_t getRandomServerType()
{
# if defined(USE_MSRPC) || defined(SIMPLE_RPC)
return rand() % vlmcsd_countof(HostBuilds);
return rand() % KmsData->HostBuildCount;
# else // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
if (!UseServerRpcBTFN)
while (TRUE)
{
// This isn't possible at all, e.g. KMS host on XP
return rand() % (int)vlmcsd_countof(HostBuilds);
}
// return 9200/9600/14393/17763 if NDR64 is in use, otherwise 6002/7601
if (UseServerRpcNDR64) return rand() % ((int)vlmcsd_countof(HostBuilds) - 2) + 2;
return rand() % 2;
const uint32_t buildIndex = rand() % KmsData->HostBuildCount;
if (!(KmsData->HostBuildList[buildIndex].Flags & UseNdr64) == !UseServerRpcNDR64)
{
return (uint8_t)buildIndex;
}
}
# endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
}
@ -275,13 +305,13 @@ static uint8_t getRandomServerType()
/*
* Generates a random ePID
*/
static void generateRandomPid(const int index, char *const szPid, int16_t lang, uint16_t hostBuild)
static void generateRandomPid(const int index, char *const szPid, int16_t lang, int32_t hostBuild)
{
char numberBuffer[12];
if (!hostBuild)
{
hostBuild = HostBuilds[getRandomServerType()];
hostBuild = KmsData->HostBuildList[getRandomServerType()].BuildNumber;
}
@ -290,7 +320,7 @@ static void generateRandomPid(const int index, char *const szPid, int16_t lang,
//if (index > 3) index = 0;
const PCsvlkData_t csvlkData = &KmsData->CsvlkData[index];
PCsvlkData_t csvlkData = &KmsData->CsvlkData[index];
strcat(szPid, itoc(numberBuffer, csvlkData->GroupId, 5));
strcat(szPid, "-");
@ -307,7 +337,8 @@ static void generateRandomPid(const int index, char *const szPid, int16_t lang,
strcat(szPid, itoc(numberBuffer, hostBuild, 0));
strcat(szPid, ".0000-");
# define minTime ((time_t)1538490811) /* Release Date Win 2019 */
const time_t hostBuildReleaseDate = getReleaseDate(hostBuild);
const time_t minTime = csvlkData->ReleaseDate < hostBuildReleaseDate ? hostBuildReleaseDate : csvlkData->ReleaseDate;
time_t maxTime;
time(&maxTime);
@ -343,11 +374,33 @@ void randomPidInit()
char Epid[PID_BUFFER_SIZE];
if (!HostBuild)
{
uint8_t index;
#if defined(USE_MSRPC) || defined(SIMPLE_RPC)
index = getRandomServerType();
#else // !(defined(USE_MSRPC) || defined(SIMPLE_RPC))
if (IsNDR64Defined)
{
index = getRandomServerType();
}
else
{
index = (uint8_t)(rand() % KmsData->HostBuildCount);
UseServerRpcNDR64 = !!(KmsData->HostBuildList[index].Flags & UseNdr64);
}
#endif // !(defined(USE_MSRPC) || defined(SIMPLE_RPC))
HostBuild = (uint16_t)KmsData->HostBuildList[index].BuildNumber;
}
generateRandomPid(i, Epid, lang, HostBuild);
KmsResponseParameters[i].Epid = (const char*)vlmcsd_strdup(Epid);
#ifndef NO_LOG
KmsResponseParameters[i].EpidSource = "randomized at program start";
KmsResponseParameters[i].IsRandom = TRUE;
#endif // NO_LOG
}
}
@ -364,7 +417,7 @@ static int32_t getProductIndexFromAllLists(const GUID* guid, char** productName)
/*
* Logs a Request
*/
static void logRequest(const REQUEST *const baseRequest)
static void logRequest(REQUEST* baseRequest)
{
#ifndef NO_VERBOSE_LOG
if (logverbose)
@ -376,7 +429,7 @@ static void logRequest(const REQUEST *const baseRequest)
#endif // NO_VERBOSE_LOG
char *productName;
char clientname[64];
char clientName[64];
int32_t index = getProductIndexFromAllLists(&baseRequest->ActID, &productName);
if (index < 0) index = getProductIndexFromAllLists(&baseRequest->KMSID, &productName);
@ -388,8 +441,8 @@ static void logRequest(const REQUEST *const baseRequest)
uuid2StringLE(&baseRequest->ActID, productName);
}
ucs2_to_utf8(baseRequest->WorkstationName, clientname, 64, 64);
logger("KMS v%i.%i request from %s for %s\n", LE16(baseRequest->MajorVer), LE16(baseRequest->MinorVer), clientname, productName);
ucs2_to_utf8(baseRequest->WorkstationName, clientName, 64, 64);
logger("KMS v%i.%i request from %s for %s\n", LE16(baseRequest->MajorVer), LE16(baseRequest->MinorVer), clientName, productName);
}
#endif // NO_LOG
@ -493,7 +546,7 @@ static void CheckRequest(const REQUEST *const Request)
/*
* Logs the Response
*/
static void logResponse(const RESPONSE *const baseResponse, const BYTE *const hwId, const char *const EpidSource)
static void logResponse(RESPONSE* baseResponse, const BYTE *const hwId, const char *const EpidSource)
{
char utf8pid[PID_BUFFER_SIZE * 3];
ucs2_to_utf8(baseResponse->KmsPID, utf8pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
@ -525,7 +578,7 @@ long long int llabs(long long int j);
* Creates the unencrypted base response
*/
#ifndef IS_LIBRARY
static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr_unused)
static HRESULT __stdcall CreateResponseBaseCallback(REQUEST* baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr_unused)
{
const char* EpidSource;
#ifndef NO_LOG
@ -539,7 +592,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
const DWORD minClients = LE32(baseRequest->N_Policy);
const DWORD required_clients = minClients < 1 ? 1 : minClients << 1;
int32_t index = getProductIndex(&baseRequest->KMSID, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, &ePid);
const int32_t index = getProductIndex(&baseRequest->KMSID, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, &ePid);
# ifndef NO_STRICT_MODES
@ -554,7 +607,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
if (CheckClientTime)
{
const time_t requestTime = (time_t)fileTimeToUnixTime(&baseRequest->ClientTime);
time_t requestTime = (time_t)fileTimeToUnixTime(&baseRequest->ClientTime);
if (llabs(requestTime - time(NULL)) > 60 * 60 * 4)
{
@ -705,21 +758,21 @@ void get16RandomBytes(void* ptr)
/*
* Creates v4 response
*/
size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipstr)
size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipString)
{
RESPONSE_V4* Response = (RESPONSE_V4*)responseBuffer;
RESPONSE_V4* response = (RESPONSE_V4*)responseBuffer;
HRESULT hResult;
if (FAILED(hResult = CreateResponseBase(&request_v4->RequestBase, &Response->ResponseBase, NULL, ipstr))) return hResult;
if (FAILED(hResult = CreateResponseBase(&request_v4->RequestBase, &response->ResponseBase, NULL, ipString))) return hResult;
const DWORD pidSize = LE32(Response->ResponseBase.PIDSize);
const DWORD pidSize = LE32(response->ResponseBase.PIDSize);
BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize;
memmove(postEpidPtr, &Response->ResponseBase.CMID, V4_POST_EPID_SIZE);
memmove(postEpidPtr, &response->ResponseBase.CMID, V4_POST_EPID_SIZE);
const size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize;
AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize);
return encryptSize + sizeof(Response->MAC);
return encryptSize + sizeof(response->MAC);
}
/*
@ -736,7 +789,7 @@ __pure static uint64_t TimestampInterval(void *ts)
/*
* Creates the HMAC for v6
*/
static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, int_fast8_t tolerance)
static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, const int_fast8_t tolerance)
{
BYTE hash[32];
const uint8_t halfHashSize = sizeof(hash) >> 1;
@ -746,7 +799,7 @@ static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptS
FILETIME* ft = (FILETIME*)(responseEnd - V6_POST_EPID_SIZE + sizeof(((RESPONSE*)0)->CMID));
// Generate a time slot that changes every 4.11 hours.
// Request and repsonse time must match +/- 1 slot.
// Request and response time must match +/- 1 slot.
// When generating a response tolerance must be 0.
// If verifying the hash, try tolerance -1, 0 and +1. One of them must match.
@ -775,7 +828,7 @@ static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptS
/*
* Creates v5 or v6 response
*/
size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipstr)
size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipString)
{
// The response will be created in a fixed sized struct to
// avoid unaligned access macros and packed structs on RISC systems
@ -784,15 +837,15 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
// The fixed sized struct with 64 WCHARs for the ePID will be converted
// to a variable sized struct later and requires unaligned access macros.
RESPONSE_V6* Response = (RESPONSE_V6*)responseBuffer;
RESPONSE* baseResponse = &Response->ResponseBase;
RESPONSE_V6* response = (RESPONSE_V6*)responseBuffer;
RESPONSE* baseResponse = &response->ResponseBase;
#ifdef _DEBUG
// ReSharper disable once CppEntityNeverUsed
// ReSharper disable once CppDeclaratorNeverUsed
RESPONSE_V6_DEBUG* xxx_unused = (RESPONSE_V6_DEBUG*)responseBuffer;
#endif
static const BYTE DefaultHwid[8] = { HWID };
static const BYTE DefaultHwId[8] = { HWID };
const int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
AesCtx aesCtx;
@ -800,35 +853,35 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
AesDecryptCbc(&aesCtx, NULL, request_v6->IV, V6_DECRYPT_SIZE);
// get random salt and SHA256 it
get16RandomBytes(Response->RandomXoredIVs);
Sha256(Response->RandomXoredIVs, sizeof(Response->RandomXoredIVs), Response->Hash);
get16RandomBytes(response->RandomXoredIVs);
Sha256(response->RandomXoredIVs, sizeof(response->RandomXoredIVs), response->Hash);
if (v6) // V6 specific stuff
{
// In v6 a random IV is generated
Response->Version = request_v6->Version;
get16RandomBytes(Response->IV);
response->Version = request_v6->Version;
get16RandomBytes(response->IV);
// pre-fill with default HwId (not required for v5)
memcpy(Response->HwId, DefaultHwid, sizeof(Response->HwId));
memcpy(response->HwId, DefaultHwId, sizeof(response->HwId));
// Just copy decrypted request IV (using Null IV) here. Note this is identical
// to XORing non-decrypted request and reponse IVs
memcpy(Response->XoredIVs, request_v6->IV, sizeof(Response->XoredIVs));
// to XORing non-decrypted request and response IVs
memcpy(response->XoredIVs, request_v6->IV, sizeof(response->XoredIVs));
}
else // V5 specific stuff
{
// In v5 IVs of request and response must be identical (MS client checks this)
// The following memcpy copies Version and IVs at once
memcpy(Response, request_v6, V6_UNENCRYPTED_SIZE);
memcpy(response, request_v6, V6_UNENCRYPTED_SIZE);
}
// Xor Random bytes with decrypted request IV
XorBlock(request_v6->IV, Response->RandomXoredIVs);
XorBlock(request_v6->IV, response->RandomXoredIVs);
// Get the base response
HRESULT hResult;
if (FAILED(hResult = CreateResponseBase(&request_v6->RequestBase, baseResponse, Response->HwId, ipstr))) return hResult;
if (FAILED(hResult = CreateResponseBase(&request_v6->RequestBase, baseResponse, response->HwId, ipString))) return hResult;
// Convert the fixed sized struct into variable sized
const DWORD pidSize = LE32(baseResponse->PIDSize);
@ -840,17 +893,17 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
// number of bytes to encrypt
size_t encryptSize =
V6_PRE_EPID_SIZE
- sizeof(Response->Version)
- sizeof(response->Version)
+ pidSize
+ post_epid_size;
//AesDecryptBlock(&aesCtx, Response->IV);
if (v6 && !CreateV6Hmac(Response->IV, encryptSize, 0)) return 0;
if (v6 && !CreateV6Hmac(response->IV, encryptSize, 0)) return 0;
// Padding auto handled by encryption func
AesEncryptCbc(&aesCtx, NULL, Response->IV, &encryptSize);
AesEncryptCbc(&aesCtx, NULL, response->IV, &encryptSize);
return encryptSize + sizeof(Response->Version);
return encryptSize + sizeof(response->Version);
}
@ -895,10 +948,10 @@ BYTE* CreateRequestV6(size_t *size, const REQUEST* requestBase)
// Encrypt KMS Client Request
size_t encryptSize = sizeof(request->RequestBase);
AesCtx Ctx;
int_fast8_t v6 = LE16(request->MajorVer) > 5;
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16);
AesEncryptCbc(&Ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize);
AesCtx ctx;
const int_fast8_t v6 = LE16(request->MajorVer) > 5;
AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16);
AesEncryptCbc(&ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize);
// Return Proper Request Data
return (BYTE*)request;
@ -1045,11 +1098,11 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
// Decrypt KMS Server Response (encrypted part starts after RequestIV)
responseSize -= copySize1;
AesCtx Ctx;
AesCtx ctx;
const int_fast8_t v6 = LE16(((RESPONSE_V6*)response)->MajorVer) > 5;
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
AesDecryptCbc(&Ctx, NULL, response + copySize1, responseSize);
AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
AesDecryptCbc(&ctx, NULL, response + copySize1, responseSize);
// Check padding
BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1;
@ -1073,7 +1126,7 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
}
// Add size of Version, KmsPIDLen and variable size PID
DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize);
const DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize);
copySize1 +=
V6_UNENCRYPTED_SIZE +
@ -1097,9 +1150,9 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
REQUEST_V6* request_v6 = (REQUEST_V6*)rawRequest;
const DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad);
AesDecryptCbc(&Ctx, NULL, request_v6->IV, decryptSize);
AesDecryptCbc(&ctx, NULL, request_v6->IV, decryptSize);
// Check that all version informations are the same
// Check that all version information is the same
result.VersionOK =
request_v6->Version == response_v6->ResponseBase.Version &&
request_v6->Version == response_v6->Version &&
@ -1111,14 +1164,14 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
result.ClientMachineIDOK = IsEqualGUID(&response_v6->ResponseBase.CMID, &request_v6->RequestBase.CMID);
// Rebuild Random Key and Sha256 Hash
BYTE HashVerify[sizeof(response_v6->Hash)];
BYTE RandomKey[sizeof(response_v6->RandomXoredIVs)];
BYTE hashVerify[sizeof(response_v6->Hash)];
BYTE randomKey[sizeof(response_v6->RandomXoredIVs)];
memcpy(RandomKey, request_v6->IV, sizeof(RandomKey));
XorBlock(response_v6->RandomXoredIVs, RandomKey);
Sha256(RandomKey, sizeof(RandomKey), HashVerify);
memcpy(randomKey, request_v6->IV, sizeof(randomKey));
XorBlock(response_v6->RandomXoredIVs, randomKey);
Sha256(randomKey, sizeof(randomKey), hashVerify);
result.HashOK = !memcmp(response_v6->Hash, HashVerify, sizeof(HashVerify));
result.HashOK = !memcmp(response_v6->Hash, hashVerify, sizeof(hashVerify));
// size before encryption (padding not included)
result.correctResponseSize =

68
src/kms.h

@ -228,6 +228,14 @@ typedef union
typedef BYTE hwid_t[8];
typedef enum
{
None = 0,
UseNdr64 = 1 << 0,
UseForEpid = 1 << 1,
MayBeServer = 1 << 2,
} HostBuildFlag;
typedef struct CsvlkData
{
union
@ -236,6 +244,7 @@ typedef struct CsvlkData
char* EPid;
};
int64_t ReleaseDate;
uint32_t GroupId;
uint32_t MinKeyId;
uint32_t MaxKeyId;
@ -280,6 +289,22 @@ typedef struct
#define KMS_OPTIONS_USENDR64 1 << 0
typedef struct HostBuild
{
union
{
uint64_t DisplayNameOffset;
char* DisplayName;
};
int64_t ReleaseDate;
int32_t BuildNumber;
int32_t PlatformId;
HostBuildFlag Flags;
uint8_t reserved[4];
} HostBuild_t, *PHostBuild_t;
typedef struct VlmcsdHeader
{
BYTE Magic[4];
@ -290,19 +315,21 @@ typedef struct VlmcsdHeader
union
{
int32_t Counts[3];
int32_t Counts[5];
struct
{
int32_t AppItemCount;
int32_t KmsItemCount;
int32_t SkuItemCount;
int32_t HostBuildCount;
int32_t reserved2Counts;
};
};
union
{
DataPointer_t Datapointers[3];
DataPointer_t Datapointers[5];
struct
{
@ -324,19 +351,31 @@ typedef struct VlmcsdHeader
PVlmcsdData_t SkuItemList;
};
union
{
uint64_t HostBuildOffset;
PHostBuild_t HostBuildList;
};
union
{
uint64_t Reserved2Offset;
void* Reserved2List;
};
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
#define EPID_INDEX_WINCHINAGOV 4
//#define EPID_INDEX_WINDOWS 0
//#define EPID_INDEX_OFFICE2010 1
//#define EPID_INDEX_OFFICE2013 2
//#define EPID_INDEX_OFFICE2016 3
//#define EPID_INDEX_WINCHINAGOV 4
typedef HRESULT(__stdcall *RequestCallback_t)(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr);
typedef HRESULT(__stdcall *RequestCallback_t)(REQUEST* 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);
@ -344,13 +383,16 @@ 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);
RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BYTE* const response, const BYTE* const rawRequest, BYTE* hwid);
RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* response_v4, const int responseSize, BYTE* const rawResponse, const BYTE* const rawRequest);
void getUnixTimeAsFileTime(FILETIME* ts);
__pure int64_t fileTimeToUnixTime(FILETIME* ts);
#ifndef IS_LIBRARY
int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_t count, char** name, char** ePid);
#if !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
const char* getNextString(const char* s);
#endif // !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
#endif // IS_LIBRARY
#ifndef NO_STRICT_MODES
@ -362,7 +404,7 @@ extern RequestCallback_t CreateResponseBase;
#ifdef _PEDANTIC
uint16_t IsValidLcid(const uint16_t lcid);
uint16_t IsValidHostBuild(const uint16_t hostBuild);
uint32_t IsValidHostBuild(const int32_t hostBuild);
#endif // _PEDANTIC
#endif // __kms_h

1853
src/kmsdata-full.c
File diff suppressed because it is too large
View File

2195
src/kmsdata.c
File diff suppressed because it is too large
View File

2
src/msrpc-client.c

@ -171,7 +171,7 @@ RpcStatus closeRpc(const RpcCtx handle)
#if !MULTI_CALL_BINARY
// Memory allocation function for RPC.
void *__RPC_USER midl_user_allocate(SIZE_T len)
void *__RPC_USER midl_user_allocate(size_t len)
{
return vlmcsd_malloc(len);
}

2
src/msrpc-server.c

@ -294,7 +294,7 @@ int ProcessActivationRequest(handle_t IDL_handle, int requestSize, unsigned char
// Memory allocation function for RPC.
void *__RPC_USER midl_user_allocate(SIZE_T len)
void *__RPC_USER midl_user_allocate(size_t len)
{
return vlmcsd_malloc(len);
}

2
src/ns_name.c

@ -247,7 +247,7 @@ ns_name_unpack_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src
* Root domain returns as "." not "".
*/
int
ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
ns_name_uncompress_vlmcsd(uint8_t *msg, uint8_t *eom, uint8_t *src,
char *dst, size_t dstsiz)
{
uint8_t tmp[NS_MAXCDNAME];

2
src/ns_name.h

@ -3,7 +3,7 @@
#define NS_NAME_H_
int
ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
ns_name_uncompress_vlmcsd(uint8_t *msg, uint8_t *eom, uint8_t *src,
char *dst, size_t dstsiz);
#endif /* NS_NAME_H_ */

12
src/ns_parse.c

@ -57,9 +57,9 @@
static void setsection_vlmcsd(ns_msg_vlmcsd *msg, ns_sect_vlmcsd sect);
static int dn_skipname_vlmcsd(const unsigned char *s, const unsigned char *end)
static int dn_skipname_vlmcsd(unsigned char *s, unsigned char *end)
{
const unsigned char *p;
unsigned char *p;
for (p=s; p<end; p++)
if (!*p) return p-s+1;
else if (*p>=192)
@ -69,8 +69,8 @@ static int dn_skipname_vlmcsd(const unsigned char *s, const unsigned char *end)
}
static int
ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section, int count) {
const uint8_t *optr = ptr;
ns_skiprr_vlmcsd(uint8_t *ptr, uint8_t *eom, ns_sect_vlmcsd section, int count) {
uint8_t *optr = ptr;
for ((void)NULL; count > 0; count--) {
int b, rdlength;
@ -93,8 +93,8 @@ ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section,
}
int
ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
const uint8_t *eom = msg + msglen;
ns_initparse_vlmcsd(uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
uint8_t *eom = msg + msglen;
int i;
memset(handle, 0x5e, sizeof *handle);

10
src/ns_parse.h

@ -46,12 +46,12 @@ typedef enum __ns_sect_vlmcsd {
} ns_sect_vlmcsd;
typedef struct __ns_msg_vlmcsd {
const uint8_t *_msg, *_eom;
uint8_t *_msg, *_eom;
uint16_t _id, _flags, _counts[ns_s_max_vlmcsd];
const uint8_t *_sections[ns_s_max_vlmcsd];
uint8_t *_sections[ns_s_max_vlmcsd];
ns_sect_vlmcsd _sect;
int _rrnum;
const uint8_t *_msg_ptr;
uint8_t *_msg_ptr;
} ns_msg_vlmcsd;
@ -61,10 +61,10 @@ typedef struct __ns_rr_vlmcsd {
uint16_t rr_class;
uint32_t ttl;
uint16_t rdlength;
const uint8_t * rdata;
uint8_t * rdata;
} ns_rr_vlmcsd;
int ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle);
int ns_initparse_vlmcsd(uint8_t *msg, int msglen, ns_msg_vlmcsd *handle);
int ns_parserr_vlmcsd(ns_msg_vlmcsd *handle, ns_sect_vlmcsd section, int rrnum, ns_rr_vlmcsd *rr);

4
src/output.c

@ -180,7 +180,7 @@ void uuid2StringLE(const GUID *const guid, char *const string)
}
#if !defined(NO_VERBOSE_LOG) && !defined(NO_LOG)
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
void logRequestVerbose(REQUEST* Request, const PRINTFUNC p)
{
char guidBuffer[GUID_STRING_LENGTH + 1];
char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
@ -222,7 +222,7 @@ void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
p("N count policy (minimum clients): %u\n", (uint32_t)LE32(Request->N_Policy));
}
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p)
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, RESPONSE* response, const PRINTFUNC p)
{
char guidBuffer[GUID_STRING_LENGTH + 1];

4
src/output.h

@ -14,8 +14,8 @@ typedef int (*PRINTFUNC)(const char *const fmt, ...);
int printerrorf(const char *const fmt, ...);
int errorout(const char* fmt, ...);
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p);
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p);
void logRequestVerbose(REQUEST* Request, const PRINTFUNC p);
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, RESPONSE* response, const PRINTFUNC p);
#ifndef NO_VERSION_INFORMATION
void printPlatform();

9
src/rpc.c

@ -325,7 +325,7 @@ static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const
# endif // !SIMPLE_RPC
pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
UA32(pRpcReturnCode) = ResponseSize < 0 ? LE32(ResponseSize) : 0;
PUT_UA32LE(pRpcReturnCode, ResponseSize < 0 ? ResponseSize : 0);
len += sizeof(DWORD);
// Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
@ -371,7 +371,7 @@ static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const uns
if (ctxItem->InterfaceVerMajor != LE16(1) || ctxItem->InterfaceVerMinor != 0)
logger("Warning: Interface version is %u.%u but should be 1.0.\n",
(unsigned int)LE16(ctxItem->InterfaceVerMajor),
(unsigned int)LE16(ctxItem->InterfaceVerMajor),
(unsigned int)LE16(ctxItem->InterfaceVerMinor)
);
@ -494,7 +494,7 @@ static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Res
for (i = 0; i < numCtxItems; i++)
{
struct CtxResults* result = Response->Results+i;
struct CtxResults* result = Response->Results + i;
const GUID* ctxTransferSyntax = &Request->CtxItems[i].TransferSyntax;
# ifndef SIMPLE_RPC
@ -970,7 +970,8 @@ RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const kmsRequest, const
}
pReturnCode = (DWORD*)(*kmsResponse + *responseSize + pad);
status = LE32(UA32(pReturnCode));
status = GET_UA32LE(pReturnCode);
//status = LE32(UA32(pReturnCode));
break;
}

1
src/shared_globals.h

@ -55,6 +55,7 @@ typedef struct
const BYTE* HwId;
#ifndef NO_LOG
const char* EpidSource;
uint8_t IsRandom;
#endif // NO_LOG
} KmsResponseParam_t, *PKmsResponseParam_t;

95
src/vlmcs.c

@ -52,8 +52,6 @@
#define VLMCS_OPTION_GRAB_INI 1
#define VLMCS_OPTION_NO_GRAB_INI 2
//#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
#ifndef IS_LIBRARY
// Function Prototypes
@ -83,24 +81,19 @@ static int AddressFamily = 0;
static int_fast8_t incompatibleOptions = 0;
static const char* fn_ini_client = NULL;
//static int_fast16_t kmsVersionMinor = 0;
static const char* ePidGroup[] = { "Windows", "Office2010", "Office2013", "Office2016" };
//static const char* ePidGroup[] = { "Windows", "Office2010", "Office2013", "Office2016" };
static int32_t ActiveProductIndex = 0;
static int32_t NCountPolicy = 0;
static GUID AppGuid, KmsGuid, SkuGuid;
static uint16_t MinorVersion = 0;
static uint16_t MajorVersion;
//#if !MULTI_CALL_BINARY
//uint8_t DefaultKmsData[]={0};
//__pure size_t getDefaultKmsDataSize() { return (size_t)0; }
//#endif // !MULTI_CALL_BINARY
#ifndef NO_DNS
static int_fast8_t NoSrvRecordPriority = FALSE;
#endif // NO_DNS
typedef char iniFileEpidLines[4][256];
//typedef char iniFileEpidLines[4][256];
typedef struct
{
@ -943,7 +936,6 @@ static void displayRequestError(RpcCtx *const s, const int status, const int cur
}
}
static void newIniBackupFile(const char* const restrict fname)
{
FILE *restrict f = fopen(fname, "wb");
@ -965,9 +957,9 @@ static void newIniBackupFile(const char* const restrict fname)
}
static void updateIniFile(iniFileEpidLines* const restrict lines)
static void updateIniFile(char*** restrict lines)
{
int_fast8_t lineWritten[vlmcsd_countof(*lines)];
int_fast8_t* lineWritten = (int_fast8_t*)malloc(KmsData->CsvlkCount * sizeof(int_fast8_t));
# if !_MSC_VER
struct stat statbuf;
# endif
@ -975,7 +967,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
int_fast8_t iniFileExistedBefore = TRUE;
unsigned int lineNumber;
memset(lineWritten, FALSE, sizeof(lineWritten));
memset(lineWritten, FALSE, KmsData->CsvlkCount * sizeof(int_fast8_t));
char* restrict fn_bak = (char*)vlmcsd_malloc(strlen(fn_ini_client) + 2);
@ -1009,7 +1001,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
vlmcsd_unlink(fn_bak); // Required for Windows. Most Unix systems don't need it.
if (rename(fn_ini_client, fn_bak))
{
int error = errno;
const int error = errno;
errorout("Fatal: Cannot create %s: %s\n", fn_bak, strerror(error));
exit(error);
}
@ -1023,7 +1015,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (!in)
{
int error = errno;
const int error = errno;
errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(error));
exit(error);
}
@ -1032,7 +1024,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (!out)
{
int error = errno;
const int error = errno;
errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(error));
exit(error);
}
@ -1041,9 +1033,9 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
for (lineNumber = 1; fgets(sourceLine, sizeof(sourceLine), in); lineNumber++)
{
for (i = 0; i < vlmcsd_countof(*lines); i++)
for (i = 0; i < KmsData->CsvlkCount; i++)
{
if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], strlen(ePidGroup[i])))
if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], strlen(getNextString((KmsData->CsvlkData[i].EPid)))))
{
if (lineWritten[i]) break;
@ -1054,7 +1046,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
}
}
if (i >= vlmcsd_countof(*lines))
if (i >= KmsData->CsvlkCount)
{
fprintf(out, "%s", sourceLine);
}
@ -1069,7 +1061,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
fclose(in);
for (i = 0; i < vlmcsd_countof(*lines); i++)
for (i = 0; i < KmsData->CsvlkCount; i++)
{
if (!lineWritten[i] && *(*lines)[i])
{
@ -1080,7 +1072,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (fclose(out))
{
int error = errno;
const int error = errno;
errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(error));
exit(error);
}
@ -1095,18 +1087,27 @@ static void grabServerData()
{
RpcCtx s = INVALID_RPCCTX;
WORD MajorVer = 6;
iniFileEpidLines lines;
int32_t i;
int32_t j;
char** lines = (char**)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(char*));
GUID* kmsGuids = (GUID*)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(GUID));
static char* Licenses[vlmcsd_countof(lines)] =
for (i = 0; i < KmsData->CsvlkCount; i++)
{
(char*)"212a64dc-43b1-4d3d-a30c-2fc69d2095c6", // Vista
(char*)"e85af946-2e25-47b7-83e1-bebcebeac611", // Office 2010
(char*)"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0", // Office 2013
(char*)"85b5f61b-320b-4be3-814a-b76b2bfafc82", // Office 2016
};
lines[i] = (char*)vlmcsd_malloc(256);
*lines[i] = 0;
for (j = 0; j < KmsData->KmsItemCount; j++)
{
if (KmsData->KmsItemList[j].EPidIndex == i)
{
kmsGuids[i] = KmsData->KmsItemList[j].Guid;
break;
}