1
0
mirror of https://github.com/ThunderEX/py-kms.git synced 2025-04-18 07:44:00 +03:00
py-kms/client.py
2018-12-10 01:05:18 +08:00

240 lines
10 KiB
Python

import argparse
import binascii
import time
import random
import socket
import string
import sys
import uuid
import errno
try:
import codecs
except ImportError:
import upy.codecs as codecs
import filetimes, rpcBind, rpcRequest
from dcerpc import MSRPCHeader, MSRPCBindNak, MSRPCRespHeader, MSRPC_BINDACK, MSRPC_BINDNAK
from kmsBase import kmsRequestStruct, UUID
from kmsRequestV4 import kmsRequestV4, generateHash
from kmsRequestV5 import kmsRequestV5
from kmsRequestV6 import kmsRequestV6
config = {}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("ip", action="store", help="The IP address or hostname of the KMS host.", type=str)
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="Windows7")
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)
parser.add_argument("-n", "--name", dest="machineName", default=None, help="Use this flag to manually specify an ASCII machineName to use. If no machineName is specified, a random machineName will be generated.", type=str)
parser.add_argument("-v", "--verbose", dest="verbose", action="store_const", const=True, default=False, help="Use this flag to enable verbose output.")
parser.add_argument("-d", "--debug", dest="debug", action="store_const", const=True, default=False, help="Use this flag to enable debug output. Implies \"-v\".")
config.update(vars(parser.parse_args()))
checkConfig()
config['call_id'] = 1
if config['debug']:
config['verbose'] = True
updateConfig()
print("Connecting to %s on port %d..." % (config['ip'], config['port']))
s = socket.create_connection((config['ip'], config['port']))
if config['verbose']:
print("Connection successful!")
binder = rpcBind.handler(None, config)
RPC_Bind = bytes(binder.generateRequest())
if config['verbose']:
print("Sending RPC bind request...")
s.send(RPC_Bind)
try:
bindResponse = s.recv(1024)
except socket.error as e:
if e.errno == errno.ECONNRESET:
print("Error: Connection reset by peer. Exiting...")
sys.exit()
else:
raise
if bindResponse == '' or not bindResponse:
print("No data received! Exiting...")
sys.exit()
packetType = MSRPCHeader(bindResponse)['type']
if packetType == MSRPC_BINDACK:
if config['verbose']:
print("RPC bind acknowledged.")
kmsRequest = createKmsRequest()
requester = rpcRequest.handler(kmsRequest, config)
s.send(bytes(requester.generateRequest()))
response = s.recv(1024)
if config['debug']:
print("Response:", binascii.b2a_hex(response))
parsed = MSRPCRespHeader(response)
kmsData = readKmsResponse(parsed['pduData'], kmsRequest, config)
kmsResp = kmsData['response']
try:
hwid = kmsData['hwid']
print("KMS Host HWID:", binascii.b2a_hex(hwid).upper())
except KeyError:
pass
print("KMS Host ePID:", kmsResp['kmsEpid'])
print("KMS Host Current Client Count:", kmsResp['currentClientCount'])
print("KMS VL Activation Interval:", kmsResp['vLActivationInterval'])
print("KMS VL Renewal Interval:", kmsResp['vLRenewalInterval'])
elif packetType == MSRPC_BINDNAK:
print(MSRPCBindNak(bindResponse).dump())
sys.exit()
else:
print("Something went wrong.")
sys.exit()
def checkConfig():
if config['cmid'] is not None:
try:
uuid.UUID(config['cmid'])
except ValueError:
print("Error: Bad CMID. Exiting...")
raise
if config['machineName'] is not None:
if len(config['machineName']) < 2 or len(config['machineName']) > 63:
print("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"
def createKmsRequestBase():
requestDict = kmsRequestStruct()
requestDict['versionMinor'] = config['KMSProtocolMinorVersion']
requestDict['versionMajor'] = config['KMSProtocolMajorVersion']
requestDict['isClientVm'] = 0
requestDict['licenseStatus'] = config['KMSClientLicenseStatus']
requestDict['graceTime'] = 43200
requestDict['applicationId'] = UUID(uuid.UUID(config['KMSClientAppID']).bytes_le)
requestDict['skuId'] = UUID(uuid.UUID(config['KMSClientSkuID']).bytes_le)
requestDict['kmsCountedId'] = UUID(uuid.UUID(config['KMSClientKMSCountedID']).bytes_le)
requestDict['clientMachineId'] = UUID(uuid.UUID(config['cmid']).bytes_le if (config['cmid'] is not None) else uuid.uuid4().bytes_le)
requestDict['previousClientMachineId'] = b'\0' * 16 #requestDict['clientMachineId'] # I'm pretty sure this is supposed to be a null UUID.
requestDict['requiredClientCount'] = config['RequiredClientCount']
requestDict['requestTime'] = filetimes.timestamp2filetime(time.time())
requestDict['machineName'] = codecs.encode(config['machineName'] or ''.join(random.choice(string.ascii_letters + string.digits) for i in range(random.randint(2,63))), 'utf_16_le')
requestDict['mnPad'] = codecs.encode('\0', 'utf_16_le') * (63 - len(codecs.decode(requestDict['machineName'], 'utf_16_le')))
# Debug Stuff
if config['debug']:
print("Request Base Dictionary:", requestDict.dump())
return requestDict
def createKmsRequest():
# Update the call ID
config['call_id'] += 1
# KMS Protocol Major Version
if config['KMSProtocolMajorVersion'] == 4:
handler = kmsRequestV4(None, config)
elif config['KMSProtocolMajorVersion'] == 5:
handler = kmsRequestV5(None, config)
elif config['KMSProtocolMajorVersion'] == 6:
handler = kmsRequestV6(None, config)
else:
return None
requestBase = createKmsRequestBase()
return handler.generateRequest(requestBase)
def readKmsResponse(data, request, config):
if config['KMSProtocolMajorVersion'] == 4:
print("Received V4 response")
response = readKmsResponseV4(data)
elif config['KMSProtocolMajorVersion'] == 5:
print("Received V5 response")
response = readKmsResponseV5(data)
elif config['KMSProtocolMajorVersion'] == 6:
print("Received V6 response")
response = readKmsResponseV6(data)
else:
print("Unhandled response version: %d.%d" % (config['KMSProtocolMajorVersion'], config['KMSProtocolMinorVersion']))
print("I'm not even sure how this happened...")
return response
def readKmsResponseV4(data):
response = kmsRequestV4.ResponseV4(data)
hashed = generateHash(bytearray(bytes(response['response'])))
print("Response Hash has expected value:", hashed == response['hash'])
return response
def readKmsResponseV5(data):
response = kmsRequestV5.ResponseV5(data)
decrypted = kmsRequestV5(data, config).decryptResponse(response)
return decrypted
def readKmsResponseV6(data):
response = kmsRequestV6.ResponseV5(data)
decrypted = kmsRequestV6(data, config).decryptResponse(response)
message = decrypted['message']
return message
if __name__ == "__main__":
main()