diff --git a/py2-kms/KmsDataBase.xml b/py2-kms/KmsDataBase.xml new file mode 100644 index 0000000..8e2119b --- /dev/null +++ b/py2-kms/KmsDataBase.xml @@ -0,0 +1,798 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/py2-kms/aes.py b/py2-kms/aes.py index f952aeb..1cabcd9 100644 --- a/py2-kms/aes.py +++ b/py2-kms/aes.py @@ -4,13 +4,17 @@ # from the SlowAES project, http://code.google.com/p/slowaes/ # # Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), -# Alex Martelli ( http://www.aleax.it ) +# Alex Martelli ( http://www.aleax.it ) # # Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) # # Licensed under the Apache License, Version 2.0 # http://www.apache.org/licenses/ +""" +Modified for py-kms +""" + import os import math diff --git a/py2-kms/client.py b/py2-kms/client.py index 952d01b..5410c48 100644 --- a/py2-kms/client.py +++ b/py2-kms/client.py @@ -1,16 +1,17 @@ #!/usr/bin/env python +import re import argparse import binascii import datetime import random import socket import string -import struct import sys import uuid import logging import os +import errno import filetimes, rpcBind, rpcRequest from dcerpc import MSRPCHeader, MSRPCBindNak, MSRPCRequestHeader, MSRPCRespHeader @@ -19,6 +20,7 @@ from kmsRequestV4 import kmsRequestV4 from kmsRequestV5 import kmsRequestV5 from kmsRequestV6 import kmsRequestV6 from rpcBase import rpcBase +from kmsDB2Dict import kmsDB2Dict from formatText import shell_message, justify config = {} @@ -29,7 +31,8 @@ def main(): parser.add_argument("port", nargs="?", action="store", default=1688, help='The port the KMS service is listening on. The default is \"1688\".', type=int) parser.add_argument("-m", "--mode", dest="mode", - choices=["WindowsVista","Windows7","Windows8","Windows81","Windows10","Office2010","Office2013","Office2016"], default="Windows81", + choices=["WindowsVista","Windows7","Windows8","Windows8.1","Windows10", + "Office2010","Office2013","Office2016","Office2019"], default="Windows8.1", help='Use this flag to manually specify a Microsoft product for testing the server. The default is \"Windows81\".', type=str) parser.add_argument("-c", "--cmid", dest="cmid", default=None, help='Use this flag to manually specify a CMID to use. If no CMID is specified, a random CMID will be generated.', type=str) @@ -62,7 +65,7 @@ a random machineName will be generated.', type=str) shell_message(nshell = [-4, 7]) bindResponse = s.recv(1024) except socket.error, e: - if e[0] == 104: + if e.errno == errno.ECONNRESET: logging.error("Connection reset by peer. Exiting...") sys.exit() else: @@ -84,15 +87,13 @@ a random machineName will be generated.', type=str) parsed = MSRPCRespHeader(response) kmsData = readKmsResponse(parsed['pduData'], kmsRequest, config) kmsResp = kmsData['response'] - + try: hwid = kmsData['hwid'] - except: - hwid = None - logging.info("KMS Host ePID: %s" % kmsResp['kmsEpid'].decode('utf-16le').encode('utf-8')) - if hwid is not None: logging.info("KMS Host HWID: %s" % binascii.b2a_hex(hwid).upper()) - + except KeyError: + pass + logging.info("KMS Host ePID: %s" % kmsResp['kmsEpid'].decode('utf-16le').encode('utf-8')) logging.info("KMS Host Current Client Count: %s" % kmsResp['currentClientCount']) logging.info("KMS VL Activation Interval: %s" % kmsResp['vLActivationInterval']) logging.info("KMS VL Renewal Interval: %s" % kmsResp['vLRenewalInterval']) @@ -110,79 +111,45 @@ def checkConfig(): if config['cmid'] is not None: try: uuid.UUID(config['cmid']) - except: + except ValueError: logging.error("Bad CMID. Exiting...") sys.exit() if config['machineName'] is not None: if len(config['machineName']) < 2 or len(config['machineName']) > 63: - logging.error("machineName must be between 2 and 63 characters in length.") + logging.error("Error: machineName must be between 2 and 63 characters in length.") sys.exit() def updateConfig(): - if config['mode'] == 'WindowsVista': - config['RequiredClientCount'] = 25 - config['KMSProtocolMajorVersion'] = 4 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "55c92734-d682-4d71-983e-d6ec3f16059f" - config['KMSClientSkuID'] = "cfd8ff08-c0d7-452b-9f60-ef5c70c32094" - config['KMSClientKMSCountedID'] = "212a64dc-43b1-4d3d-a30c-2fc69d2095c6" - elif config['mode'] == 'Windows7': - config['RequiredClientCount'] = 25 - config['KMSProtocolMajorVersion'] = 4 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "55c92734-d682-4d71-983e-d6ec3f16059f" - config['KMSClientSkuID'] = "ae2ee509-1b34-41c0-acb7-6d4650168915" - config['KMSClientKMSCountedID'] = "7fde5219-fbfa-484a-82c9-34d1ad53e856" - elif config['mode'] == 'Windows8': - config['RequiredClientCount'] = 25 - config['KMSProtocolMajorVersion'] = 5 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "55c92734-d682-4d71-983e-d6ec3f16059f" - config['KMSClientSkuID'] = "458e1bec-837a-45f6-b9d5-925ed5d299de" - config['KMSClientKMSCountedID'] = "3c40b358-5948-45af-923b-53d21fcc7e79" - elif config['mode'] == 'Windows81': - config['RequiredClientCount'] = 25 - config['KMSProtocolMajorVersion'] = 6 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "55c92734-d682-4d71-983e-d6ec3f16059f" - config['KMSClientSkuID'] = "81671aaf-79d1-4eb1-b004-8cbbe173afea" - config['KMSClientKMSCountedID'] = "cb8fc780-2c05-495a-9710-85afffc904d7" - elif config['mode'] == 'Windows10': - config['RequiredClientCount'] = 25 - config['KMSProtocolMajorVersion'] = 6 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "55c92734-d682-4d71-983e-d6ec3f16059f" - config['KMSClientSkuID'] = "73111121-5638-40f6-bc11-f1d7b0d64300" - config['KMSClientKMSCountedID'] = "58e2134f-8e11-4d17-9cb2-91069c151148" - elif config['mode'] == 'Office2010': - config['RequiredClientCount'] = 5 - config['KMSProtocolMajorVersion'] = 4 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "59a52881-a989-479d-af46-f275c6370663" - config['KMSClientSkuID'] = "6f327760-8c5c-417c-9b61-836a98287e0c" - config['KMSClientKMSCountedID'] = "e85af946-2e25-47b7-83e1-bebcebeac611" - elif config['mode'] == 'Office2013': - config['RequiredClientCount'] = 5 - config['KMSProtocolMajorVersion'] = 5 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "0ff1ce15-a989-479d-af46-f275c6370663" - config['KMSClientSkuID'] = "b322da9c-a2e2-4058-9e4e-f59a6970bd69" - config['KMSClientKMSCountedID'] = "e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0" - elif config['mode'] == 'Office2016': - config['RequiredClientCount'] = 5 - config['KMSProtocolMajorVersion'] = 6 - config['KMSProtocolMinorVersion'] = 0 - config['KMSClientLicenseStatus'] = 2 - config['KMSClientAppID'] = "0ff1ce15-a989-479d-af46-f275c6370663" - config['KMSClientSkuID'] = "d450596f-894d-49e0-966a-fd39ed4c4c64" - config['KMSClientKMSCountedID'] = "85b5f61b-320b-4be3-814a-b76b2bfafc82" + kmsdb = kmsDB2Dict() + + appitems = kmsdb[2] + for appitem in appitems: + kmsitems = appitem['KmsItems'] + for kmsitem in kmsitems: + # Threshold. + try: + count = int(kmsitem['NCountPolicy']) + except KeyError: + count = 25 + + name = re.sub('\(.*\)', '', kmsitem['DisplayName']).replace('2015', '').replace(' ', '') + if name == config['mode']: + skuitems = kmsitem['SkuItems'] + # Select 'Enterprise' for Windows or 'Professional Plus' for Office. + # (improvement: choice could be also random: skuitem = random.choice(skuitems)) + for skuitem in skuitems: + if skuitem['DisplayName'].replace(' ','') == name + 'Enterprise' or \ + skuitem['DisplayName'].replace(' ','') == name[:6] + 'ProfessionalPlus' + name[6:]: + + config['KMSClientSkuID'] = skuitem['Id'] + config['RequiredClientCount'] = count + config['KMSProtocolMajorVersion'] = int(float(kmsitem['DefaultKmsProtocol'])) + config['KMSProtocolMinorVersion'] = 0 + config['KMSClientLicenseStatus'] = 2 + config['KMSClientAppID'] = appitem['Id'] + config['KMSClientKMSCountedID'] = kmsitem['Id'] + break + def createKmsRequestBase(): requestDict = kmsBase.kmsRequestStruct() @@ -198,7 +165,8 @@ def createKmsRequestBase(): requestDict['previousClientMachineId'] = '\0' * 16 #requestDict['clientMachineId'] # I'm pretty sure this is supposed to be a null UUID. requestDict['requiredClientCount'] = config['RequiredClientCount'] requestDict['requestTime'] = filetimes.dt_to_filetime(datetime.datetime.utcnow()) - requestDict['machineName'] = (config['machineName'] if (config['machineName'] is not None) else ''.join(random.choice(string.letters + string.digits) for i in range(random.randint(2,63)))).encode('utf-16le') + requestDict['machineName'] = (config['machineName'] if (config['machineName'] is not None) else + ''.join(random.choice(string.letters + string.digits) for i in range(random.randint(2,63)))).encode('utf-16le') requestDict['mnPad'] = '\0'.encode('utf-16le') * (63 - len(requestDict['machineName'].decode('utf-16le'))) # Debug Stuff @@ -242,7 +210,8 @@ def readKmsResponse(data, request, config): def readKmsResponseV4(data, request): response = kmsRequestV4.ResponseV4(data) hashed = kmsRequestV4(data, config).generateHash(bytearray(str(response['response']))) - logging.info("Response Hash has expected value: ", hashed == response['hash']) + if hashed == response['hash']: + logging.info("Response Hash has expected value !") return response def readKmsResponseV5(data): diff --git a/py2-kms/dcerpc.py b/py2-kms/dcerpc.py index dc146c5..31a14d1 100644 --- a/py2-kms/dcerpc.py +++ b/py2-kms/dcerpc.py @@ -1,14 +1,17 @@ #!/usr/bin/env python -# Copyright (c) 2003-2012 CORE Security Technologies +# Copyright (c) 2003-2016 CORE Security Technologies # # This software is provided under under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # -# $Id: dcerpc.py 917 2013-11-10 20:47:57Z bethus $ +# Description: +# Partial C706.pdf + [MS-RPCE] implementation # -# Partial C706.pdf + [MS-RPCE] implementation +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC # # ToDo: # [ ] Take out all the security provider stuff out of here (e.g. RPC_C_AUTHN_WINNT) @@ -16,7 +19,11 @@ # more SSP (e.g. NETLOGON) # -from structure import Structure,pack,unpack +""" +Stripped down version of: https://github.com/SecureAuthCorp/impacket/blob/master/impacket/dcerpc/v5/rpcrt.py +""" + +from structure import Structure # MS/RPC Constants MSRPC_REQUEST = 0x00 @@ -41,8 +48,8 @@ MSRPC_CO_CANCEL = 0x12 MSRPC_ORPHANED = 0x13 # MS/RPC Packet Flags -MSRPC_FIRSTFRAG = 0x01 -MSRPC_LASTFRAG = 0x02 +PFC_FIRST_FRAG = 0x01 +PFC_LAST_FRAG = 0x02 # For PDU types bind, bind_ack, alter_context, and # alter_context_resp, this flag MUST be interpreted as PFC_SUPPORT_HEADER_SIGN @@ -52,12 +59,11 @@ MSRPC_SUPPORT_SIGN = 0x04 #remaining PDU types, this flag MUST be interpreted as PFC_PENDING_CANCEL. MSRPC_PENDING_CANCEL= 0x04 -MSRPC_NOTAFRAG = 0x04 -MSRPC_RECRESPOND = 0x08 -MSRPC_NOMULTIPLEX = 0x10 -MSRPC_NOTFORIDEMP = 0x20 -MSRPC_NOTFORBCAST = 0x40 -MSRPC_NOUUID = 0x80 +PFC_RESERVED_1 = 0x08 +PFC_CONC_MPX = 0x10 +PFC_DID_NOT_EXECUTE = 0x20 +PFC_MAYBE = 0x40 +PFC_OBJECT_UUID = 0x80 # Auth Types - Security Providers RPC_C_AUTHN_NONE = 0x00 @@ -155,12 +161,379 @@ rpc_status_codes = { 0x1C000022L : 'nca_s_fault_tx_open_failed', 0x1C000023L : 'nca_s_fault_codeset_conv_error', 0x1C000024L : 'nca_s_fault_object_not_found ', - 0x1C000025L : 'nca_s_fault_no_client_stub' + 0x1C000025L : 'nca_s_fault_no_client_stub', + 0x16c9a000L : "rpc_s_mod", + 0x16c9a001L : "rpc_s_op_rng_error", + 0x16c9a002L : "rpc_s_cant_create_socket", + 0x16c9a003L : "rpc_s_cant_bind_socket", + 0x16c9a004L : "rpc_s_not_in_call", + 0x16c9a005L : "rpc_s_no_port", + 0x16c9a006L : "rpc_s_wrong_boot_time", + 0x16c9a007L : "rpc_s_too_many_sockets", + 0x16c9a008L : "rpc_s_illegal_register", + 0x16c9a009L : "rpc_s_cant_recv", + 0x16c9a00aL : "rpc_s_bad_pkt", + 0x16c9a00bL : "rpc_s_unbound_handle", + 0x16c9a00cL : "rpc_s_addr_in_use", + 0x16c9a00dL : "rpc_s_in_args_too_big", + 0x16c9a00eL : "rpc_s_string_too_long", + 0x16c9a00fL : "rpc_s_too_many_objects", + 0x16c9a010L : "rpc_s_binding_has_no_auth", + 0x16c9a011L : "rpc_s_unknown_authn_service", + 0x16c9a012L : "rpc_s_no_memory", + 0x16c9a013L : "rpc_s_cant_nmalloc", + 0x16c9a014L : "rpc_s_call_faulted", + 0x16c9a015L : "rpc_s_call_failed", + 0x16c9a016L : "rpc_s_comm_failure", + 0x16c9a017L : "rpc_s_rpcd_comm_failure", + 0x16c9a018L : "rpc_s_illegal_family_rebind", + 0x16c9a019L : "rpc_s_invalid_handle", + 0x16c9a01aL : "rpc_s_coding_error", + 0x16c9a01bL : "rpc_s_object_not_found", + 0x16c9a01cL : "rpc_s_cthread_not_found", + 0x16c9a01dL : "rpc_s_invalid_binding", + 0x16c9a01eL : "rpc_s_already_registered", + 0x16c9a01fL : "rpc_s_endpoint_not_found", + 0x16c9a020L : "rpc_s_invalid_rpc_protseq", + 0x16c9a021L : "rpc_s_desc_not_registered", + 0x16c9a022L : "rpc_s_already_listening", + 0x16c9a023L : "rpc_s_no_protseqs", + 0x16c9a024L : "rpc_s_no_protseqs_registered", + 0x16c9a025L : "rpc_s_no_bindings", + 0x16c9a026L : "rpc_s_max_descs_exceeded", + 0x16c9a027L : "rpc_s_no_interfaces", + 0x16c9a028L : "rpc_s_invalid_timeout", + 0x16c9a029L : "rpc_s_cant_inq_socket", + 0x16c9a02aL : "rpc_s_invalid_naf_id", + 0x16c9a02bL : "rpc_s_inval_net_addr", + 0x16c9a02cL : "rpc_s_unknown_if", + 0x16c9a02dL : "rpc_s_unsupported_type", + 0x16c9a02eL : "rpc_s_invalid_call_opt", + 0x16c9a02fL : "rpc_s_no_fault", + 0x16c9a030L : "rpc_s_cancel_timeout", + 0x16c9a031L : "rpc_s_call_cancelled", + 0x16c9a032L : "rpc_s_invalid_call_handle", + 0x16c9a033L : "rpc_s_cannot_alloc_assoc", + 0x16c9a034L : "rpc_s_cannot_connect", + 0x16c9a035L : "rpc_s_connection_aborted", + 0x16c9a036L : "rpc_s_connection_closed", + 0x16c9a037L : "rpc_s_cannot_accept", + 0x16c9a038L : "rpc_s_assoc_grp_not_found", + 0x16c9a039L : "rpc_s_stub_interface_error", + 0x16c9a03aL : "rpc_s_invalid_object", + 0x16c9a03bL : "rpc_s_invalid_type", + 0x16c9a03cL : "rpc_s_invalid_if_opnum", + 0x16c9a03dL : "rpc_s_different_server_instance", + 0x16c9a03eL : "rpc_s_protocol_error", + 0x16c9a03fL : "rpc_s_cant_recvmsg", + 0x16c9a040L : "rpc_s_invalid_string_binding", + 0x16c9a041L : "rpc_s_connect_timed_out", + 0x16c9a042L : "rpc_s_connect_rejected", + 0x16c9a043L : "rpc_s_network_unreachable", + 0x16c9a044L : "rpc_s_connect_no_resources", + 0x16c9a045L : "rpc_s_rem_network_shutdown", + 0x16c9a046L : "rpc_s_too_many_rem_connects", + 0x16c9a047L : "rpc_s_no_rem_endpoint", + 0x16c9a048L : "rpc_s_rem_host_down", + 0x16c9a049L : "rpc_s_host_unreachable", + 0x16c9a04aL : "rpc_s_access_control_info_inv", + 0x16c9a04bL : "rpc_s_loc_connect_aborted", + 0x16c9a04cL : "rpc_s_connect_closed_by_rem", + 0x16c9a04dL : "rpc_s_rem_host_crashed", + 0x16c9a04eL : "rpc_s_invalid_endpoint_format", + 0x16c9a04fL : "rpc_s_unknown_status_code", + 0x16c9a050L : "rpc_s_unknown_mgr_type", + 0x16c9a051L : "rpc_s_assoc_creation_failed", + 0x16c9a052L : "rpc_s_assoc_grp_max_exceeded", + 0x16c9a053L : "rpc_s_assoc_grp_alloc_failed", + 0x16c9a054L : "rpc_s_sm_invalid_state", + 0x16c9a055L : "rpc_s_assoc_req_rejected", + 0x16c9a056L : "rpc_s_assoc_shutdown", + 0x16c9a057L : "rpc_s_tsyntaxes_unsupported", + 0x16c9a058L : "rpc_s_context_id_not_found", + 0x16c9a059L : "rpc_s_cant_listen_socket", + 0x16c9a05aL : "rpc_s_no_addrs", + 0x16c9a05bL : "rpc_s_cant_getpeername", + 0x16c9a05cL : "rpc_s_cant_get_if_id", + 0x16c9a05dL : "rpc_s_protseq_not_supported", + 0x16c9a05eL : "rpc_s_call_orphaned", + 0x16c9a05fL : "rpc_s_who_are_you_failed", + 0x16c9a060L : "rpc_s_unknown_reject", + 0x16c9a061L : "rpc_s_type_already_registered", + 0x16c9a062L : "rpc_s_stop_listening_disabled", + 0x16c9a063L : "rpc_s_invalid_arg", + 0x16c9a064L : "rpc_s_not_supported", + 0x16c9a065L : "rpc_s_wrong_kind_of_binding", + 0x16c9a066L : "rpc_s_authn_authz_mismatch", + 0x16c9a067L : "rpc_s_call_queued", + 0x16c9a068L : "rpc_s_cannot_set_nodelay", + 0x16c9a069L : "rpc_s_not_rpc_tower", + 0x16c9a06aL : "rpc_s_invalid_rpc_protid", + 0x16c9a06bL : "rpc_s_invalid_rpc_floor", + 0x16c9a06cL : "rpc_s_call_timeout", + 0x16c9a06dL : "rpc_s_mgmt_op_disallowed", + 0x16c9a06eL : "rpc_s_manager_not_entered", + 0x16c9a06fL : "rpc_s_calls_too_large_for_wk_ep", + 0x16c9a070L : "rpc_s_server_too_busy", + 0x16c9a071L : "rpc_s_prot_version_mismatch", + 0x16c9a072L : "rpc_s_rpc_prot_version_mismatch", + 0x16c9a073L : "rpc_s_ss_no_import_cursor", + 0x16c9a074L : "rpc_s_fault_addr_error", + 0x16c9a075L : "rpc_s_fault_context_mismatch", + 0x16c9a076L : "rpc_s_fault_fp_div_by_zero", + 0x16c9a077L : "rpc_s_fault_fp_error", + 0x16c9a078L : "rpc_s_fault_fp_overflow", + 0x16c9a079L : "rpc_s_fault_fp_underflow", + 0x16c9a07aL : "rpc_s_fault_ill_inst", + 0x16c9a07bL : "rpc_s_fault_int_div_by_zero", + 0x16c9a07cL : "rpc_s_fault_int_overflow", + 0x16c9a07dL : "rpc_s_fault_invalid_bound", + 0x16c9a07eL : "rpc_s_fault_invalid_tag", + 0x16c9a07fL : "rpc_s_fault_pipe_closed", + 0x16c9a080L : "rpc_s_fault_pipe_comm_error", + 0x16c9a081L : "rpc_s_fault_pipe_discipline", + 0x16c9a082L : "rpc_s_fault_pipe_empty", + 0x16c9a083L : "rpc_s_fault_pipe_memory", + 0x16c9a084L : "rpc_s_fault_pipe_order", + 0x16c9a085L : "rpc_s_fault_remote_comm_failure", + 0x16c9a086L : "rpc_s_fault_remote_no_memory", + 0x16c9a087L : "rpc_s_fault_unspec", + 0x16c9a088L : "uuid_s_bad_version", + 0x16c9a089L : "uuid_s_socket_failure", + 0x16c9a08aL : "uuid_s_getconf_failure", + 0x16c9a08bL : "uuid_s_no_address", + 0x16c9a08cL : "uuid_s_overrun", + 0x16c9a08dL : "uuid_s_internal_error", + 0x16c9a08eL : "uuid_s_coding_error", + 0x16c9a08fL : "uuid_s_invalid_string_uuid", + 0x16c9a090L : "uuid_s_no_memory", + 0x16c9a091L : "rpc_s_no_more_entries", + 0x16c9a092L : "rpc_s_unknown_ns_error", + 0x16c9a093L : "rpc_s_name_service_unavailable", + 0x16c9a094L : "rpc_s_incomplete_name", + 0x16c9a095L : "rpc_s_group_not_found", + 0x16c9a096L : "rpc_s_invalid_name_syntax", + 0x16c9a097L : "rpc_s_no_more_members", + 0x16c9a098L : "rpc_s_no_more_interfaces", + 0x16c9a099L : "rpc_s_invalid_name_service", + 0x16c9a09aL : "rpc_s_no_name_mapping", + 0x16c9a09bL : "rpc_s_profile_not_found", + 0x16c9a09cL : "rpc_s_not_found", + 0x16c9a09dL : "rpc_s_no_updates", + 0x16c9a09eL : "rpc_s_update_failed", + 0x16c9a09fL : "rpc_s_no_match_exported", + 0x16c9a0a0L : "rpc_s_entry_not_found", + 0x16c9a0a1L : "rpc_s_invalid_inquiry_context", + 0x16c9a0a2L : "rpc_s_interface_not_found", + 0x16c9a0a3L : "rpc_s_group_member_not_found", + 0x16c9a0a4L : "rpc_s_entry_already_exists", + 0x16c9a0a5L : "rpc_s_nsinit_failure", + 0x16c9a0a6L : "rpc_s_unsupported_name_syntax", + 0x16c9a0a7L : "rpc_s_no_more_elements", + 0x16c9a0a8L : "rpc_s_no_ns_permission", + 0x16c9a0a9L : "rpc_s_invalid_inquiry_type", + 0x16c9a0aaL : "rpc_s_profile_element_not_found", + 0x16c9a0abL : "rpc_s_profile_element_replaced", + 0x16c9a0acL : "rpc_s_import_already_done", + 0x16c9a0adL : "rpc_s_database_busy", + 0x16c9a0aeL : "rpc_s_invalid_import_context", + 0x16c9a0afL : "rpc_s_uuid_set_not_found", + 0x16c9a0b0L : "rpc_s_uuid_member_not_found", + 0x16c9a0b1L : "rpc_s_no_interfaces_exported", + 0x16c9a0b2L : "rpc_s_tower_set_not_found", + 0x16c9a0b3L : "rpc_s_tower_member_not_found", + 0x16c9a0b4L : "rpc_s_obj_uuid_not_found", + 0x16c9a0b5L : "rpc_s_no_more_bindings", + 0x16c9a0b6L : "rpc_s_invalid_priority", + 0x16c9a0b7L : "rpc_s_not_rpc_entry", + 0x16c9a0b8L : "rpc_s_invalid_lookup_context", + 0x16c9a0b9L : "rpc_s_binding_vector_full", + 0x16c9a0baL : "rpc_s_cycle_detected", + 0x16c9a0bbL : "rpc_s_nothing_to_export", + 0x16c9a0bcL : "rpc_s_nothing_to_unexport", + 0x16c9a0bdL : "rpc_s_invalid_vers_option", + 0x16c9a0beL : "rpc_s_no_rpc_data", + 0x16c9a0bfL : "rpc_s_mbr_picked", + 0x16c9a0c0L : "rpc_s_not_all_objs_unexported", + 0x16c9a0c1L : "rpc_s_no_entry_name", + 0x16c9a0c2L : "rpc_s_priority_group_done", + 0x16c9a0c3L : "rpc_s_partial_results", + 0x16c9a0c4L : "rpc_s_no_env_setup", + 0x16c9a0c5L : "twr_s_unknown_sa", + 0x16c9a0c6L : "twr_s_unknown_tower", + 0x16c9a0c7L : "twr_s_not_implemented", + 0x16c9a0c8L : "rpc_s_max_calls_too_small", + 0x16c9a0c9L : "rpc_s_cthread_create_failed", + 0x16c9a0caL : "rpc_s_cthread_pool_exists", + 0x16c9a0cbL : "rpc_s_cthread_no_such_pool", + 0x16c9a0ccL : "rpc_s_cthread_invoke_disabled", + 0x16c9a0cdL : "ept_s_cant_perform_op", + 0x16c9a0ceL : "ept_s_no_memory", + 0x16c9a0cfL : "ept_s_database_invalid", + 0x16c9a0d0L : "ept_s_cant_create", + 0x16c9a0d1L : "ept_s_cant_access", + 0x16c9a0d2L : "ept_s_database_already_open", + 0x16c9a0d3L : "ept_s_invalid_entry", + 0x16c9a0d4L : "ept_s_update_failed", + 0x16c9a0d5L : "ept_s_invalid_context", + 0x16c9a0d6L : "ept_s_not_registered", + 0x16c9a0d7L : "ept_s_server_unavailable", + 0x16c9a0d8L : "rpc_s_underspecified_name", + 0x16c9a0d9L : "rpc_s_invalid_ns_handle", + 0x16c9a0daL : "rpc_s_unknown_error", + 0x16c9a0dbL : "rpc_s_ss_char_trans_open_fail", + 0x16c9a0dcL : "rpc_s_ss_char_trans_short_file", + 0x16c9a0ddL : "rpc_s_ss_context_damaged", + 0x16c9a0deL : "rpc_s_ss_in_null_context", + 0x16c9a0dfL : "rpc_s_socket_failure", + 0x16c9a0e0L : "rpc_s_unsupported_protect_level", + 0x16c9a0e1L : "rpc_s_invalid_checksum", + 0x16c9a0e2L : "rpc_s_invalid_credentials", + 0x16c9a0e3L : "rpc_s_credentials_too_large", + 0x16c9a0e4L : "rpc_s_call_id_not_found", + 0x16c9a0e5L : "rpc_s_key_id_not_found", + 0x16c9a0e6L : "rpc_s_auth_bad_integrity", + 0x16c9a0e7L : "rpc_s_auth_tkt_expired", + 0x16c9a0e8L : "rpc_s_auth_tkt_nyv", + 0x16c9a0e9L : "rpc_s_auth_repeat", + 0x16c9a0eaL : "rpc_s_auth_not_us", + 0x16c9a0ebL : "rpc_s_auth_badmatch", + 0x16c9a0ecL : "rpc_s_auth_skew", + 0x16c9a0edL : "rpc_s_auth_badaddr", + 0x16c9a0eeL : "rpc_s_auth_badversion", + 0x16c9a0efL : "rpc_s_auth_msg_type", + 0x16c9a0f0L : "rpc_s_auth_modified", + 0x16c9a0f1L : "rpc_s_auth_badorder", + 0x16c9a0f2L : "rpc_s_auth_badkeyver", + 0x16c9a0f3L : "rpc_s_auth_nokey", + 0x16c9a0f4L : "rpc_s_auth_mut_fail", + 0x16c9a0f5L : "rpc_s_auth_baddirection", + 0x16c9a0f6L : "rpc_s_auth_method", + 0x16c9a0f7L : "rpc_s_auth_badseq", + 0x16c9a0f8L : "rpc_s_auth_inapp_cksum", + 0x16c9a0f9L : "rpc_s_auth_field_toolong", + 0x16c9a0faL : "rpc_s_invalid_crc", + 0x16c9a0fbL : "rpc_s_binding_incomplete", + 0x16c9a0fcL : "rpc_s_key_func_not_allowed", + 0x16c9a0fdL : "rpc_s_unknown_stub_rtl_if_vers", + 0x16c9a0feL : "rpc_s_unknown_ifspec_vers", + 0x16c9a0ffL : "rpc_s_proto_unsupp_by_auth", + 0x16c9a100L : "rpc_s_authn_challenge_malformed", + 0x16c9a101L : "rpc_s_protect_level_mismatch", + 0x16c9a102L : "rpc_s_no_mepv", + 0x16c9a103L : "rpc_s_stub_protocol_error", + 0x16c9a104L : "rpc_s_class_version_mismatch", + 0x16c9a105L : "rpc_s_helper_not_running", + 0x16c9a106L : "rpc_s_helper_short_read", + 0x16c9a107L : "rpc_s_helper_catatonic", + 0x16c9a108L : "rpc_s_helper_aborted", + 0x16c9a109L : "rpc_s_not_in_kernel", + 0x16c9a10aL : "rpc_s_helper_wrong_user", + 0x16c9a10bL : "rpc_s_helper_overflow", + 0x16c9a10cL : "rpc_s_dg_need_way_auth", + 0x16c9a10dL : "rpc_s_unsupported_auth_subtype", + 0x16c9a10eL : "rpc_s_wrong_pickle_type", + 0x16c9a10fL : "rpc_s_not_listening", + 0x16c9a110L : "rpc_s_ss_bad_buffer", + 0x16c9a111L : "rpc_s_ss_bad_es_action", + 0x16c9a112L : "rpc_s_ss_wrong_es_version", + 0x16c9a113L : "rpc_s_fault_user_defined", + 0x16c9a114L : "rpc_s_ss_incompatible_codesets", + 0x16c9a115L : "rpc_s_tx_not_in_transaction", + 0x16c9a116L : "rpc_s_tx_open_failed", + 0x16c9a117L : "rpc_s_partial_credentials", + 0x16c9a118L : "rpc_s_ss_invalid_codeset_tag", + 0x16c9a119L : "rpc_s_mgmt_bad_type", + 0x16c9a11aL : "rpc_s_ss_invalid_char_input", + 0x16c9a11bL : "rpc_s_ss_short_conv_buffer", + 0x16c9a11cL : "rpc_s_ss_iconv_error", + 0x16c9a11dL : "rpc_s_ss_no_compat_codeset", + 0x16c9a11eL : "rpc_s_ss_no_compat_charsets", + 0x16c9a11fL : "dce_cs_c_ok", + 0x16c9a120L : "dce_cs_c_unknown", + 0x16c9a121L : "dce_cs_c_notfound", + 0x16c9a122L : "dce_cs_c_cannot_open_file", + 0x16c9a123L : "dce_cs_c_cannot_read_file", + 0x16c9a124L : "dce_cs_c_cannot_allocate_memory", + 0x16c9a125L : "rpc_s_ss_cleanup_failed", + 0x16c9a126L : "rpc_svc_desc_general", + 0x16c9a127L : "rpc_svc_desc_mutex", + 0x16c9a128L : "rpc_svc_desc_xmit", + 0x16c9a129L : "rpc_svc_desc_recv", + 0x16c9a12aL : "rpc_svc_desc_dg_state", + 0x16c9a12bL : "rpc_svc_desc_cancel", + 0x16c9a12cL : "rpc_svc_desc_orphan", + 0x16c9a12dL : "rpc_svc_desc_cn_state", + 0x16c9a12eL : "rpc_svc_desc_cn_pkt", + 0x16c9a12fL : "rpc_svc_desc_pkt_quotas", + 0x16c9a130L : "rpc_svc_desc_auth", + 0x16c9a131L : "rpc_svc_desc_source", + 0x16c9a132L : "rpc_svc_desc_stats", + 0x16c9a133L : "rpc_svc_desc_mem", + 0x16c9a134L : "rpc_svc_desc_mem_type", + 0x16c9a135L : "rpc_svc_desc_dg_pktlog", + 0x16c9a136L : "rpc_svc_desc_thread_id", + 0x16c9a137L : "rpc_svc_desc_timestamp", + 0x16c9a138L : "rpc_svc_desc_cn_errors", + 0x16c9a139L : "rpc_svc_desc_conv_thread", + 0x16c9a13aL : "rpc_svc_desc_pid", + 0x16c9a13bL : "rpc_svc_desc_atfork", + 0x16c9a13cL : "rpc_svc_desc_cma_thread", + 0x16c9a13dL : "rpc_svc_desc_inherit", + 0x16c9a13eL : "rpc_svc_desc_dg_sockets", + 0x16c9a13fL : "rpc_svc_desc_timer", + 0x16c9a140L : "rpc_svc_desc_threads", + 0x16c9a141L : "rpc_svc_desc_server_call", + 0x16c9a142L : "rpc_svc_desc_nsi", + 0x16c9a143L : "rpc_svc_desc_dg_pkt", + 0x16c9a144L : "rpc_m_cn_ill_state_trans_sa", + 0x16c9a145L : "rpc_m_cn_ill_state_trans_ca", + 0x16c9a146L : "rpc_m_cn_ill_state_trans_sg", + 0x16c9a147L : "rpc_m_cn_ill_state_trans_cg", + 0x16c9a148L : "rpc_m_cn_ill_state_trans_sr", + 0x16c9a149L : "rpc_m_cn_ill_state_trans_cr", + 0x16c9a14aL : "rpc_m_bad_pkt_type", + 0x16c9a14bL : "rpc_m_prot_mismatch", + 0x16c9a14cL : "rpc_m_frag_toobig", + 0x16c9a14dL : "rpc_m_unsupp_stub_rtl_if", + 0x16c9a14eL : "rpc_m_unhandled_callstate", + 0x16c9a14fL : "rpc_m_call_failed", + 0x16c9a150L : "rpc_m_call_failed_no_status", + 0x16c9a151L : "rpc_m_call_failed_errno", + 0x16c9a152L : "rpc_m_call_failed_s", + 0x16c9a153L : "rpc_m_call_failed_c", + 0x16c9a154L : "rpc_m_errmsg_toobig", + 0x16c9a155L : "rpc_m_invalid_srchattr", + 0x16c9a156L : "rpc_m_nts_not_found", + 0x16c9a157L : "rpc_m_invalid_accbytcnt", + 0x16c9a158L : "rpc_m_pre_v2_ifspec", + 0x16c9a159L : "rpc_m_unk_ifspec", + 0x16c9a15aL : "rpc_m_recvbuf_toosmall", + 0x16c9a15bL : "rpc_m_unalign_authtrl", + 0x16c9a15cL : "rpc_m_unexpected_exc", + 0x16c9a15dL : "rpc_m_no_stub_data", + 0x16c9a15eL : "rpc_m_eventlist_full", + 0x16c9a15fL : "rpc_m_unk_sock_type", + 0x16c9a160L : "rpc_m_unimp_call", + 0x16c9a161L : "rpc_m_invalid_seqnum", + 0x16c9a162L : "rpc_m_cant_create_uuid", + 0x16c9a163L : "rpc_m_pre_v2_ss", + 0x16c9a164L : "rpc_m_dgpkt_pool_corrupt", + 0x16c9a165L : "rpc_m_dgpkt_bad_free", + 0x16c9a166L : "rpc_m_lookaside_corrupt", + 0x16c9a167L : "rpc_m_alloc_fail", + 0x16c9a168L : "rpc_m_realloc_fail", + 0x16c9a169L : "rpc_m_cant_open_file", + 0x16c9a16aL : "rpc_m_cant_read_addr", + 0x16c9a16bL : "rpc_svc_desc_libidl", + 0x16c9a16cL : "rpc_m_ctxrundown_nomem", + 0x16c9a16dL : "rpc_m_ctxrundown_exc", + 0x16c9a16eL : "rpc_s_fault_codeset_conv_error", + 0x16c9a16fL : "rpc_s_no_call_active", + 0x16c9a170L : "rpc_s_cannot_support", + 0x16c9a171L : "rpc_s_no_context_available", } -class Exception(Exception): - pass - # Context Item class CtxItem(Structure): structure = ( @@ -195,15 +568,15 @@ class MSRPCHeader(Structure): ('type','B=0'), # 2 ('flags','B=0'), # 3 ('representation',' 0 else 0)+len(pduData)+len(pad)+len(sec_trailer)'), # 8 ('auth_len',' 0 else 0)'), + ('dataLen','_-pduData','self["frag_len"]-self["auth_len"]-self._SIZE-(8 if self["auth_len"] > 0 else 0)'), ('pduData',':'), - ('_pad', '_-pad','(4 - ((self._SIZE + len(self["pduData"])) & 3) & 3)'), + ('_pad', '_-pad','(4 - ((self._SIZE + (16 if (self["flags"] & 0x80) > 0 else 0) + len(self["pduData"])) & 3) & 3)'), ('pad', ':'), ('_sec_trailer', '_-sec_trailer', '8 if self["auth_len"] > 0 else 0'), ('sec_trailer',':'), @@ -216,7 +589,7 @@ class MSRPCHeader(Structure): if data is None: self['ver_major'] = 5 self['ver_minor'] = 0 - self['flags'] = MSRPC_FIRSTFRAG | MSRPC_LASTFRAG + self['flags'] = PFC_FIRST_FRAG | PFC_LAST_FRAG self['type'] = MSRPC_REQUEST self.__frag_len_set = 0 self['auth_len'] = 0 @@ -226,7 +599,7 @@ class MSRPCHeader(Structure): self['pad'] = '' def get_header_size(self): - return self._SIZE + return self._SIZE + (16 if (self["flags"] & PFC_OBJECT_UUID) > 0 else 0) def get_packet(self): if self['auth_data'] != '': @@ -244,6 +617,8 @@ class MSRPCRequestHeader(MSRPCHeader): ('alloc_hint',' 0 else 0' ), # 22 + ('uuid',':'), # 22 ) def __init__(self, data = None, alignment = 0): @@ -251,6 +626,7 @@ class MSRPCRequestHeader(MSRPCHeader): if data is None: self['type'] = MSRPC_REQUEST self['ctx_id'] = 0 + self['uuid'] = '' class MSRPCRespHeader(MSRPCHeader): _SIZE = 24 @@ -299,19 +675,9 @@ class MSRPCBind(Structure): self['ctx_items'] += i.getData() return Structure.getData(self) -class MSRPCBindAck(Structure): +class MSRPCBindAck(MSRPCHeader): _SIZE = 26 # Up to SecondaryAddr _CTX_ITEM_LEN = len(CtxItemResult()) - commonHdr = ( - ('ver_major','B=5'), # 0 - ('ver_minor','B=0'), # 1 - ('type','B=0'), # 2 - ('flags','B=0'), # 3 - ('representation',' This line was returning garbage in the pidGenerator + if not self.config["epid"]: - response["kmsEpid"] = kmsPidGenerator.epidGenerator(applicationId, kmsRequest['versionMajor'], self.config["lcid"]).encode('utf-16le') + response["kmsEpid"] = kmsPidGenerator.epidGenerator(kmsRequest['kmsCountedId'].get(), kmsRequest['versionMajor'], + self.config["lcid"]).encode('utf-16le') else: response["kmsEpid"] = self.config["epid"].encode('utf-16le') response['clientMachineId'] = kmsRequest['clientMachineId'] response['responseTime'] = kmsRequest['requestTime'] - response['currentClientCount'] = self.config["CurrentClientCount"] + response['currentClientCount'] = currentClientCount response['vLActivationInterval'] = self.config["VLActivationInterval"] response['vLRenewalInterval'] = self.config["VLRenewalInterval"] @@ -607,18 +285,18 @@ class kmsBase: cur.execute("SELECT * FROM clients WHERE clientMachineId=?;", [str(kmsRequest['clientMachineId'].get())]) try: data = cur.fetchone() - #print "Data:", data if data[6]: response["kmsEpid"] = data[6].encode('utf-16le') else: - cur.execute("UPDATE clients SET kmsEpid=? WHERE clientMachineId=?;", (str(response["kmsEpid"].decode('utf-16le')), str(kmsRequest['clientMachineId'].get()))) + cur.execute("UPDATE clients SET kmsEpid=? WHERE clientMachineId=?;", + (str(response["kmsEpid"].decode('utf-16le')), str(kmsRequest['clientMachineId'].get()))) except sqlite3.Error, e: - logging.error("%s:" % e.args[0]) + logging.error("Error %s:" % e.args[0]) except sqlite3.Error, e: - logging.error("%s:" % e.args[0]) - sys.exit(1) + logging.error("Error %s:" % e.args[0]) + sys.exit(1) finally: if con: con.commit() @@ -633,22 +311,19 @@ import kmsRequestV4, kmsRequestV5, kmsRequestV6, kmsRequestUnknown def generateKmsResponseData(data, config): version = kmsBase.GenericRequestHeader(data)['versionMajor'] - currentDate = datetime.datetime.now().ctime() + currentDate = time.strftime("%a %b %d %H:%M:%S %Y") if version == 4: logging.info("Received V%d request on %s." % (version, currentDate)) - messagehandler = kmsRequestV4.kmsRequestV4(data, config) - messagehandler.executeRequestLogic() + messagehandler = kmsRequestV4.kmsRequestV4(data, config) elif version == 5: logging.info("Received V%d request on %s." % (version, currentDate)) messagehandler = kmsRequestV5.kmsRequestV5(data, config) - messagehandler.executeRequestLogic() elif version == 6: logging.info("Received V%d request on %s." % (version, currentDate)) messagehandler = kmsRequestV6.kmsRequestV6(data, config) - messagehandler.executeRequestLogic() else: logging.info("Unhandled KMS version V%d." % version) messagehandler = kmsRequestUnknown.kmsRequestUnknown(data, config) - return messagehandler.getResponse() + return messagehandler.executeRequestLogic() diff --git a/py2-kms/kmsDB2Dict.py b/py2-kms/kmsDB2Dict.py new file mode 100644 index 0000000..6f9b0f4 --- /dev/null +++ b/py2-kms/kmsDB2Dict.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import os +import xml.etree.ElementTree as ET + +def kmsDB2Dict(): + path = os.path.join(os.path.dirname(__file__), 'KmsDataBase.xml') + root = ET.parse(path).getroot() + + kmsdb, child1, child2, child3 = [ [] for _ in range(4) ] + + ## Get winbuilds. + for winbuild in root.iter('WinBuild'): + child1.append(winbuild.attrib) + + kmsdb.append(child1) + + ## Get csvlkitem data. + child1 = [] + for csvlk in root.iter('CsvlkItem'): + for activ in csvlk.iter('Activate'): + child2.append(activ.attrib['KmsItem']) + csvlk.attrib.update({'Activate' : child2}) + child1.append(csvlk.attrib) + child2 = [] + + kmsdb.append(child1) + + ## Get appitem data. + child1 = [] + for app in root.iter('AppItem'): + for kms in app.iter('KmsItem'): + for sku in kms.iter('SkuItem'): + child3.append(sku.attrib) + kms.attrib.update({'SkuItems' : child3}) + child2.append(kms.attrib) + child3 = [] + + app.attrib.update({'KmsItems' : child2}) + child1.append(app.attrib) + child2 = [] + + kmsdb.append(child1) + + return kmsdb diff --git a/py2-kms/kmsPidGenerator.py b/py2-kms/kmsPidGenerator.py index bfe9c7a..63f98c0 100644 --- a/py2-kms/kmsPidGenerator.py +++ b/py2-kms/kmsPidGenerator.py @@ -4,122 +4,74 @@ import datetime import random import time import uuid +from ast import literal_eval -APP_ID_WINDOWS = uuid.UUID("55C92734-D682-4D71-983E-D6EC3F16059F") -APP_ID_OFFICE14 = uuid.UUID("59A52881-A989-479D-AF46-F275C6370663") -APP_ID_OFFICE15 = uuid.UUID("0FF1CE15-A989-479D-AF46-F275C6370663") +from kmsDB2Dict import kmsDB2Dict -# KMS Host OS Type -hostOsList = {} -# Windows Server 2008 R2 SP1 -hostOsList["HOST_SERVER2008R2"] = { - "type" : 55041, - "osBuild" : 7601 -} -# Windows Server 2012 RTM -hostOsList["HOST_SERVER2012"] = { - "type" : 5426, - "osBuild" : 9200 -} -# Windows Server 2012 R2 RTM -hostOsList["HOST_SERVER2012R2"] = { - "type" : 6401, - "osBuild" : 9600 -} -# Windows Server 2016 RTM -hostOsList["HOST_SERVER2016"] = { - "type" : 3612, - "osBuild" : 14393 -} - - -# Product Specific KeyConfig -pkeyConfigList = {} -# Windows Server KMS Host PID, actual PIDRangeMax = 191999999 -pkeyConfigList["windows"] = { - "GroupID" : 206, - "PIDRangeMin" : 152000000, - "PIDRangeMax" : 191999999 -} -# Windows Server 2012 R2 KMS Host PID, actual PIDRangeMax = 310999999 -pkeyConfigList["windows2012r2"] = { - "GroupID" : 206, - "PIDRangeMin" : 271000000, - "PIDRangeMax" : 310999999 -} -# Office 2010 KMSHost Class PID, actual PIDRangeMax = 217999999 -pkeyConfigList["office14"] = { - "GroupID" : 96, - "PIDRangeMin" : 199000000, - "PIDRangeMax" : 217999999 -} -# Office 2013 KMSHost Class PID, actual PIDRangeMax = 255999999 -pkeyConfigList["office15"] = { - "GroupID" : 206, - "PIDRangeMin" : 234000000, - "PIDRangeMax" : 255999999 -} - - -def epidGenerator(appId, version, lcid): - # Generate Part 1 & 7: Host Type and KMS Server OS Build - hostOsType = random.choice(hostOsList.keys()) - hostOsDict = hostOsList[hostOsType] +def epidGenerator(kmsId, version, lcid): + kmsdb = kmsDB2Dict() + winbuilds, csvlkitems, appitems = kmsdb[0], kmsdb[1], kmsdb[2] + hosts, pkeys = [ [] for _ in range(2) ] + # Product Specific Detection (Get all CSVLK GroupID and PIDRange good for EPID generation), then # Generate Part 2: Group ID and Product Key ID Range - if appId == APP_ID_OFFICE14: - keyConfig = pkeyConfigList["office14"] - elif appId == APP_ID_OFFICE15: - keyConfig = pkeyConfigList["office15"] - else: - # Default to Windows - if hostOsDict['osBuild'] == 14393: - keyConfig = pkeyConfigList["windows2012r2"] - elif hostOsDict['osBuild'] == 9600: - keyConfig = pkeyConfigList["windows2012r2"] - else: - keyConfig = pkeyConfigList["windows"] + for csvlkitem in csvlkitems: + try: + if kmsId in [ uuid.UUID(kmsitem) for kmsitem in csvlkitem['Activate'] ]: + pkeys.append( (csvlkitem['GroupId'], csvlkitem['MinKeyId'], csvlkitem['MaxKeyId'], csvlkitem['InvalidWinBuild']) ) + except IndexError: + # fallback to Windows Server 2019 parameters. + GroupId, MinKeyId, MaxKeyId, Invalid = 206, 551000000, 570999999, [0,1,2] + + pkey = random.choice(pkeys) + GroupId, MinKeyId, MaxKeyId, Invalid = int(pkey[0]), int(pkey[1]), int(pkey[2]), literal_eval(pkey[3]) + + # Get all KMS Server Host Builds good for EPID generation, then + # Generate Part 1 & 7: Host Type and KMS Server OS Build + # https://www.itprotoday.com/windows-78/volume-activation-server-2008 + # https://docs.microsoft.com/en-us/windows-server/get-started-19/activation-19 + # https://docs.microsoft.com/en-us/windows-server/get-started/windows-server-release-info + # https://support.microsoft.com/en-us/help/13853/windows-lifecycle-fact-sheet + for winbuild in winbuilds: + try: + # Check versus "InvalidWinBuild". + if int(winbuild['WinBuildIndex']) not in Invalid: + # Re-check versus "version" protocol. + if ((version == 4 and int(winbuild['BuildNumber']) >= 7601) or + (version == 5 and int(winbuild['BuildNumber']) >= 9200) or + (version == 6 and int(winbuild['BuildNumber']) >= 9600)): + hosts.append(winbuild) + except KeyError: + # fallback to Windows Server 2019 parameters. + BuildNumber, PlatformId, MinDate = '17763', '3612', '02/10/2018' + + host = random.choice(hosts) + BuildNumber, PlatformId, MinDate = host['BuildNumber'], host['PlatformId'], host['MinDate'] # Generate Part 3 and Part 4: Product Key ID - productKeyID = random.randint(keyConfig["PIDRangeMin"], keyConfig["PIDRangeMax"]) + productKeyID = random.randint(MinKeyId, MaxKeyId) - # Generate Part 5: License Channel (00=Retail, 01=Retail, 02=OEM, - # 03=Volume(GVLK,MAK)) - always 03 + # Generate Part 5: License Channel (00=Retail, 01=Retail, 02=OEM, 03=Volume(GVLK,MAK)) - always 03 licenseChannel = 3 - # Generate Part 6: Language - use system default language - # 1033 is en-us - languageCode = lcid # C# CultureInfo.InstalledUICulture.LCID + # Generate Part 6: Language - use system default language, 1033 is en-us + languageCode = lcid # (C# CultureInfo.InstalledUICulture.LCID) # Generate Part 8: KMS Host Activation Date - # Get Minimum Possible Date: Newer Products first - if hostOsType == "HOST_SERVER2016": - # Microsoft Windows Server 2016 RTM - minTime = datetime.date(2016, 7, 27) - elif hostOsType == "HOST_SERVER2012R2" or version == 6: - # Microsoft Windows Server 2012 R2 RTM (October 17, 2013) - minTime = datetime.date(2013, 10, 17) - elif appId == APP_ID_OFFICE15: - # Microsoft Office 2013 RTM (October 24, 2012) - minTime = datetime.date(2012, 10, 24) - elif hostOsType == "HOST_SERVER2012" or version == 5: - # Microsoft Windows Server 2012 RTM (September 4, 2012) - minTime = datetime.date(2012, 9, 4) - else: - # Windows Server 2008 R2 SP1 (February 16, 2011) - minTime = datetime.date(2011, 2, 16) + d = datetime.datetime.strptime(MinDate, "%d/%m/%Y") + minTime = datetime.date(d.year, d.month, d.day) # Generate Year and Day Number randomDate = datetime.date.fromtimestamp(random.randint(time.mktime(minTime.timetuple()), time.mktime(datetime.datetime.now().timetuple()))) firstOfYear = datetime.date(randomDate.year, 1, 1) randomDayNumber = int((time.mktime(randomDate.timetuple()) - time.mktime(firstOfYear.timetuple())) / 86400 + 0.5) - # generate the epid string + # Generate the EPID string result = [] - result.append(str(hostOsDict["type"]).rjust(5, "0")) + result.append(str(PlatformId).rjust(5, "0")) result.append("-") - result.append(str(keyConfig["GroupID"]).rjust(5, "0")) + result.append(str(GroupId).rjust(5, "0")) result.append("-") result.append(str(productKeyID / 1000000).rjust(3, "0")) result.append("-") @@ -129,8 +81,9 @@ def epidGenerator(appId, version, lcid): result.append("-") result.append(str(languageCode)) result.append("-") - result.append(str(hostOsDict["osBuild"]).rjust(4, "0")) + result.append(str(BuildNumber).rjust(4, "0")) result.append(".0000-") result.append(str(randomDayNumber).rjust(3, "0")) result.append(str(randomDate.year).rjust(4, "0")) + return "".join(result) diff --git a/py2-kms/kmsRequestUnknown.py b/py2-kms/kmsRequestUnknown.py index 4342902..d727f30 100644 --- a/py2-kms/kmsRequestUnknown.py +++ b/py2-kms/kmsRequestUnknown.py @@ -5,7 +5,7 @@ import struct from kmsBase import kmsBase class kmsRequestUnknown(kmsBase): - def getResponse(self): + def executeRequestLogic(self): finalResponse = bytearray() finalResponse.extend(bytearray(struct.pack(' 16: - logging.error("HWID \"%s\" is invalid. Hex string is too long." % binascii.b2a_hex(config['hwid']).upper()) - return - except TypeError: - logging.error("HWID \"%s\" is invalid. Odd-length hex string." % binascii.b2a_hex(config['hwid']).upper()) - return logging.basicConfig(level=config['loglevel'], format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename=config['logfile'], filemode='w') + # Random HWID. + if config['hwid'] == "random": + randomhwid = uuid.uuid4().hex + config['hwid'] = randomhwid[:16] + + # Sanitize HWID. try: - import sqlite3 - config['dbSupport'] = True + config['hwid'] = binascii.a2b_hex(re.sub(r'[^0-9a-fA-F]', '', config['hwid'].strip('0x'))) + if len(binascii.b2a_hex(config['hwid'])) < 16: + logging.error("Error: HWID \"%s\" is invalid. Hex string is too short." % binascii.b2a_hex(config['hwid']).upper()) + return + elif len(binascii.b2a_hex(config['hwid'])) > 16: + logging.error("Error: HWID \"%s\" is invalid. Hex string is too long." % binascii.b2a_hex(config['hwid']).upper()) + return + except TypeError: + logging.error("Error: HWID \"%s\" is invalid. Odd-length hex string." % binascii.b2a_hex(config['hwid']).upper()) + return + + # Check LCID. + # http://stackoverflow.com/questions/3425294/how-to-detect-the-os-default-language-in-python + if not config['lcid'] or (config['lcid'] not in ValidLcid): + if hasattr(sys, 'implementation') and sys.implementation.name == 'cpython': + config['lcid'] = 1033 + elif os.name == 'nt': + import ctypes + + config['lcid'] = ctypes.windll.kernel32.GetUserDefaultUILanguage() # TODO: or GetSystemDefaultUILanguage? + else: + import locale + + try: + config['lcid'] = next(k for k, v in locale.windows_locale.items() if v == locale.getdefaultlocale()[0]) + except StopIteration: + config['lcid'] = 1033 + + try: + import sqlite3 except: logging.warning("Module \"sqlite3\" is not installed, database support disabled.") config['dbSupport'] = False + else: + config['dbSupport'] = True + server = SocketServer.TCPServer((config['ip'], config['port']), kmsServer) server.timeout = 5 logging.info("TCP server listening at %s on port %d." % (config['ip'], config['port'])) logging.info("HWID: %s" % binascii.b2a_hex(config['hwid']).upper()) server.serve_forever() + class kmsServer(SocketServer.BaseRequestHandler): def setup(self): - self.connection = self.request logging.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1])) def handle(self): while True: # self.request is the TCP socket connected to the client try: - self.data = self.connection.recv(1024) + data = self.request.recv(1024) except socket.error, e: - if e[0] == 104: + if e.errno == errno.ECONNRESET: logging.error("Connection reset by peer.") break else: raise - if self.data == '' or not self.data: + if not data: logging.warning("No data received !") break - # self.data = bytearray(self.data.strip()) - # logging.debug(binascii.b2a_hex(str(self.data))) - packetType = MSRPCHeader(self.data)['type'] + # data = bytearray(self.data.strip()) + # logging.debug(binascii.b2a_hex(str(data))) + packetType = MSRPCHeader(data)['type'] if packetType == rpcBase.packetType['bindReq']: logging.info("RPC bind request received.") shell_message(nshell = [-2, 2]) - handler = rpcBind.handler(self.data, config) + handler = rpcBind.handler(data, config) elif packetType == rpcBase.packetType['request']: logging.info("Received activation request.") shell_message(nshell = [-2, 13]) - handler = rpcRequest.handler(self.data, config) + handler = rpcRequest.handler(data, config) else: - logging.error("Invalid RPC request type ", packetType) + logging.error("Error: Invalid RPC request type ", packetType) break - handler.populate() - res = str(handler.getResponse()) - self.connection.send(res) + res = str(handler.populate()) + self.request.send(res) if packetType == rpcBase.packetType['bindReq']: logging.info("RPC bind acknowledged.") @@ -127,7 +167,7 @@ class kmsServer(SocketServer.BaseRequestHandler): break def finish(self): - self.connection.close() + self.request.close() logging.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1])) if __name__ == "__main__": diff --git a/py2-kms/structure.py b/py2-kms/structure.py index c8f738c..3b90ba4 100644 --- a/py2-kms/structure.py +++ b/py2-kms/structure.py @@ -7,9 +7,9 @@ # for more information. # -""" Version of https://github.com/CoreSecurity/impacket/blob/master/impacket/structure.py - with modifications in the function dump(...). - Copyright 2018 Matteo Fan +""" +Stripped down version of: https://github.com/CoreSecurity/impacket/blob/master/impacket/structure.py +with modifications in the function dump(...). """ from struct import pack, unpack, calcsize @@ -90,18 +90,6 @@ class Structure: else: self.data = None - @classmethod - def fromFile(self, file): - answer = self() - answer.fromString(file.read(len(answer))) - return answer - - def setAlignment(self, alignment): - self.alignment = alignment - - def setData(self, data): - self.data = data - def packField(self, fieldName, format = None): if self.debug: print "packField( %s | %s )" % (fieldName, format) @@ -363,7 +351,7 @@ class Structure: return unpack(format, data)[0] def calcPackSize(self, format, data, field = None): -# # print " calcPackSize %s:%r" % (format, data) + # print " calcPackSize %s:%r" % (format, data) if field: addressField = self.findAddressFieldFor(field) if addressField is not None: @@ -544,26 +532,10 @@ class Structure: if field[1][-l:] == descriptor: return field[0] return None - - def zeroValue(self, format): - two = format.split('*') - if len(two) == 2: - if two[0].isdigit(): - return (self.zeroValue(two[1]),)*int(two[0]) - - if not format.find('*') == -1: return () - if 's' in format: return '' - if format in ['z',':','u']: return '' - if format == 'w': return '\x00\x00' - - return 0 - - def clear(self): - for field in self.commonHdr + self.structure: - self[field[0]] = self.zeroValue(field[1]) def dump(self, msg = None, indent = 0, print_to_stdout = True): - if msg is None: msg = self.__class__.__name__ + if msg is None: + msg = self.__class__.__name__ ind = ' '*indent allstr = "\n%s" % msg fixedFields = []