Merge pull request #21 from Taknok/master

Add an option to limit the maximum size of the log file
This commit is contained in:
Matteo ℱan 2019-04-15 23:39:52 +02:00 committed by GitHub
commit 80641822bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 293 additions and 119 deletions

128
.gitignore vendored Normal file
View File

@ -0,0 +1,128 @@
# App files
py2kms_server.log*
py3kms_server.log*
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that dont work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/

View File

@ -19,6 +19,8 @@ try:
except ImportError:
pass
logger = logging.getLogger('root')
class UUID(Structure):
commonHdr = ()
structure = (
@ -131,7 +133,7 @@ class kmsBase:
skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)")
except sqlite3.Error, e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
@ -140,8 +142,8 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
con.close()
shell_message(nshell = 15)
logging.debug("KMS Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(kmsRequest))))
logging.debug("KMS Request: \n%s\n" % justify(kmsRequest.dump(print_to_stdout = False)))
logger.debug("KMS Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(kmsRequest))))
logger.debug("KMS Request: \n%s\n" % justify(kmsRequest.dump(print_to_stdout = False)))
clientMachineId = kmsRequest['clientMachineId'].get()
applicationId = kmsRequest['applicationId'].get()
@ -156,10 +158,10 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
tz = get_localzone()
local_dt = tz.localize(requestDatetime)
except UnknownTimeZoneError:
logging.warning('Unknown time zone ! Request time not localized.')
logger.warning('Unknown time zone ! Request time not localized.')
local_dt = requestDatetime
except ImportError:
logging.warning('Module "tzlocal" not available ! Request time not localized.')
logger.warning('Module "tzlocal" not available ! Request time not localized.')
local_dt = requestDatetime
# Get SkuId, AppId and client threshold.
@ -206,12 +208,12 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
"kmsEpid" : None
}
logging.info("Machine Name: %s" % infoDict["machineName"])
logging.info("Client Machine ID: %s" % infoDict["clientMachineId"])
logging.info("Application ID: %s" % infoDict["appId"])
logging.info("SKU ID: %s" % infoDict["skuId"])
logging.info("License Status: %s" % infoDict["licenseStatus"])
logging.info("Request Time: %s" % local_dt.strftime('%Y-%m-%d %H:%M:%S %Z (UTC%z)'))
logger.info("Machine Name: %s" % infoDict["machineName"])
logger.info("Client Machine ID: %s" % infoDict["clientMachineId"])
logger.info("Application ID: %s" % infoDict["appId"])
logger.info("SKU ID: %s" % infoDict["skuId"])
logger.info("License Status: %s" % infoDict["licenseStatus"])
logger.info("Request Time: %s" % local_dt.strftime('%Y-%m-%d %H:%M:%S %Z (UTC%z)'))
if self.config['sqlite'] and self.config['dbSupport']:
con = None
@ -247,10 +249,10 @@ clientMachineId=:clientMachineId;", infoDict)
clientMachineId=:clientMachineId;", infoDict)
except sqlite3.Error, e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
except sqlite3.Error, e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
if con:
@ -292,17 +294,17 @@ clientMachineId=:clientMachineId;", infoDict)
(str(response["kmsEpid"].decode('utf-16le')), str(kmsRequest['clientMachineId'].get())))
except sqlite3.Error, e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
except sqlite3.Error, e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
if con:
con.commit()
con.close()
logging.info("Server ePID: %s" % response["kmsEpid"].decode('utf-16le').encode('utf-8'))
logger.info("Server ePID: %s" % response["kmsEpid"].decode('utf-16le').encode('utf-8'))
return response
@ -314,16 +316,16 @@ def generateKmsResponseData(data, config):
currentDate = time.strftime("%a %b %d %H:%M:%S %Y")
if version == 4:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV4.kmsRequestV4(data, config)
elif version == 5:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV5.kmsRequestV5(data, config)
elif version == 6:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV6.kmsRequestV6(data, config)
else:
logging.info("Unhandled KMS version V%d." % version)
logger.info("Unhandled KMS version V%d." % version)
messagehandler = kmsRequestUnknown.kmsRequestUnknown(data, config)
return messagehandler.executeRequestLogic()

View File

@ -9,6 +9,8 @@ from structure import Structure
from aes import AES
from formatText import shell_message, justify
logger = logging.getLogger('root')
# v4 AES Key
key = bytearray([0x05, 0x3D, 0x83, 0x07, 0xF9, 0xE5, 0xF0, 0x88, 0xEB, 0x5E, 0xA6, 0x68, 0x6C, 0xF0, 0x37, 0xC7, 0xE4, 0xEF, 0xD2, 0xD6])
@ -102,8 +104,8 @@ class kmsRequestV4(kmsBase):
## Debug stuff.
shell_message(nshell = 16)
logging.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("KMS V4 Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
logger.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("KMS V4 Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
return str(response)
@ -120,7 +122,7 @@ class kmsRequestV4(kmsBase):
## Debug stuff.
shell_message(nshell = 10)
logging.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logging.debug("Request V4: \n%s\n" % justify(binascii.b2a_hex(str(request))))
logger.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("Request V4: \n%s\n" % justify(binascii.b2a_hex(str(request))))
return request

View File

@ -10,6 +10,8 @@ from kmsBase import kmsBase
from structure import Structure
from formatText import justify, shell_message
logger = logging.getLogger('root')
class kmsRequestV5(kmsBase):
class RequestV5(Structure):
class Message(Structure):
@ -135,8 +137,8 @@ class kmsRequestV5(kmsBase):
response['padding'] = bytearray(self.getPadding(bodyLength))
shell_message(nshell = 16)
logging.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False))))
logging.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(response)))))
logger.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False))))
logger.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(response)))))
return str(response)
@ -166,7 +168,7 @@ class kmsRequestV5(kmsBase):
request['message'] = message
shell_message(nshell = 10)
logging.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False))))
logging.info("Request V%d: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(request)))))
logger.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False))))
logger.info("Request V%d: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(request)))))
return request

View File

@ -9,6 +9,8 @@ from dcerpc import MSRPCHeader, MSRPCBindAck
from structure import Structure
from formatText import shell_message, justify
logger = logging.getLogger('root')
uuidNDR32 = uuid.UUID('8a885d04-1ceb-11c9-9fe8-08002b104860')
uuidNDR64 = uuid.UUID('71710533-beba-4937-8319-b5dbef9ccc36')
uuidTime = uuid.UUID('6cb71c2c-9812-4540-0300-000000000000')
@ -74,8 +76,8 @@ class handler(rpcBase.rpcBase):
def parseRequest(self):
request = MSRPCHeader(self.data)
shell_message(nshell = 3)
logging.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data)))
logging.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
logger.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data)))
logger.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
justify(MSRPCBind(request['pduData']).dump(print_to_stdout = False))))
return request
@ -117,8 +119,8 @@ class handler(rpcBase.rpcBase):
response['ctx_items'] += str(resp)
shell_message(nshell = 4)
logging.debug("RPC Bind Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("RPC Bind Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
logger.debug("RPC Bind Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("RPC Bind Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
return response
@ -157,9 +159,9 @@ class handler(rpcBase.rpcBase):
request['pduData'] = str(bind)
shell_message(nshell = 0)
logging.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
logger.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
justify(MSRPCBind(request['pduData']).dump(print_to_stdout = False))))
logging.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request))))
logger.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request))))
return request

View File

@ -8,12 +8,14 @@ import kmsBase
import rpcBase
from formatText import justify, shell_message
logger = logging.getLogger('root')
class handler(rpcBase.rpcBase):
def parseRequest(self):
request = MSRPCRequestHeader(self.data)
shell_message(nshell = 14)
logging.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data)))
logging.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data)))
logger.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
return request
@ -36,8 +38,8 @@ class handler(rpcBase.rpcBase):
response['pduData'] = responseData
shell_message(nshell = 17)
logging.debug("RPC Message Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("RPC Message Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
logger.debug("RPC Message Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("RPC Message Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response))))
return response
@ -54,8 +56,8 @@ class handler(rpcBase.rpcBase):
request['pduData'] = str(self.data)
shell_message(nshell = 11)
logging.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logging.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request))))
logger.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request))))
return request

View File

@ -15,9 +15,12 @@ import rpcBind, rpcRequest
from dcerpc import MSRPCHeader
from rpcBase import rpcBase
from formatText import shell_message
from logging.handlers import RotatingFileHandler
config = {}
logger = logging.getLogger('root')
# Valid language identifiers to be used in the EPID (see "kms.c" in vlmcsd)
ValidLcid = [1025, 1026, 1027, 1028, 1029,
1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
@ -39,6 +42,15 @@ ValidLcid = [1025, 1026, 1027, 1028, 1029,
10241, 10249, 10250, 11265, 11273, 11274, 12289, 12297, 12298,
13313, 13321, 13322, 14337, 14346, 15361, 15370, 16385, 16394, 17418, 18442, 19466, 20490]
def createLogger(config):
logger.setLevel(config['loglevel'])
log_formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S')
log_handler = RotatingFileHandler(filename=config['logfile'], mode='a', maxBytes=int(config['logsize']*1024*512), backupCount=1, encoding=None, delay=0)
print int(config['logsize']*1024*512)
log_handler.setFormatter(log_formatter)
logger.addHandler(log_handler)
def main():
parser = argparse.ArgumentParser(description='py2-kms: KMS Server Emulator written in Python2', epilog="version: py2-kms_2018-11-15")
@ -66,12 +78,13 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
help='Use this flag to set a Loglevel. The default is \"ERROR\".', type=str)
parser.add_argument("-f", "--logfile", dest="logfile", action="store", default=os.path.dirname(os.path.abspath( __file__ )) + "/py2kms_server.log",
help='Use this flag to set an output Logfile. The default is \"pykms_server.log\".', type=str)
parser.add_argument("-S", "--logsize", dest="logsize", action="store", default=0,
help='Use this flag to set a maximum size (in MB) to the output Logfile. Desactivated by default.', type=float)
config.update(vars(parser.parse_args()))
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')
createLogger(config)
# Random HWID.
if config['hwid'] == "random":
randomhwid = uuid.uuid4().hex
@ -81,13 +94,13 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
try:
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())
logger.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())
logger.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())
logger.error("Error: HWID \"%s\" is invalid. Odd-length hex string." % binascii.b2a_hex(config['hwid']).upper())
return
# Check LCID.
@ -110,21 +123,21 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
try:
import sqlite3
except:
logging.warning("Module \"sqlite3\" is not installed, database support disabled.")
logger.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())
logger.info("TCP server listening at %s on port %d." % (config['ip'], config['port']))
logger.info("HWID: %s" % binascii.b2a_hex(config['hwid']).upper())
server.serve_forever()
class kmsServer(SocketServer.BaseRequestHandler):
def setup(self):
logging.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1]))
logger.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1]))
def handle(self):
while True:
@ -133,42 +146,42 @@ class kmsServer(SocketServer.BaseRequestHandler):
data = self.request.recv(1024)
except socket.error, e:
if e.errno == errno.ECONNRESET:
logging.error("Connection reset by peer.")
logger.error("Connection reset by peer.")
break
else:
raise
if not data:
logging.warning("No data received !")
logger.warning("No data received !")
break
# data = bytearray(self.data.strip())
# logging.debug(binascii.b2a_hex(str(data)))
# logger.debug(binascii.b2a_hex(str(data)))
packetType = MSRPCHeader(data)['type']
if packetType == rpcBase.packetType['bindReq']:
logging.info("RPC bind request received.")
logger.info("RPC bind request received.")
shell_message(nshell = [-2, 2])
handler = rpcBind.handler(data, config)
elif packetType == rpcBase.packetType['request']:
logging.info("Received activation request.")
logger.info("Received activation request.")
shell_message(nshell = [-2, 13])
handler = rpcRequest.handler(data, config)
else:
logging.error("Error: Invalid RPC request type ", packetType)
logger.error("Error: Invalid RPC request type ", packetType)
break
res = str(handler.populate())
self.request.send(res)
if packetType == rpcBase.packetType['bindReq']:
logging.info("RPC bind acknowledged.")
logger.info("RPC bind acknowledged.")
shell_message(nshell = [-3, 5, 6])
elif packetType == rpcBase.packetType['request']:
logging.info("Responded to activation request.")
logger.info("Responded to activation request.")
shell_message(nshell = [-3, 18, 19])
break
def finish(self):
self.request.close()
logging.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1]))
logger.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1]))
if __name__ == "__main__":
main()

View File

@ -19,6 +19,8 @@ try:
except ImportError:
pass
logger = logging.getLogger('root')
class UUID(Structure):
commonHdr = ()
structure = (
@ -130,7 +132,7 @@ class kmsBase:
skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)")
except sqlite3.Error as e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
@ -140,8 +142,8 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
shell_message(nshell = 15)
kmsRequest = byterize(kmsRequest)
logging.debug("KMS Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(kmsRequest).encode('latin-1')).decode('utf-8')))
logging.debug("KMS Request: \n%s\n" % justify(kmsRequest.dump(print_to_stdout = False)))
logger.debug("KMS Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(kmsRequest).encode('latin-1')).decode('utf-8')))
logger.debug("KMS Request: \n%s\n" % justify(kmsRequest.dump(print_to_stdout = False)))
clientMachineId = kmsRequest['clientMachineId'].get()
applicationId = kmsRequest['applicationId'].get()
@ -156,10 +158,10 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
tz = get_localzone()
local_dt = tz.localize(requestDatetime)
except UnknownTimeZoneError:
logging.warning('Unknown time zone ! Request time not localized.')
logger.warning('Unknown time zone ! Request time not localized.')
local_dt = requestDatetime
except ImportError:
logging.warning('Module "tzlocal" not available ! Request time not localized.')
logger.warning('Module "tzlocal" not available ! Request time not localized.')
local_dt = requestDatetime
# Get SkuId, AppId and client threshold.
@ -205,12 +207,12 @@ skuId TEXT, licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCo
}
#print infoDict
logging.info("Machine Name: %s" % infoDict["machineName"])
logging.info("Client Machine ID: %s" % infoDict["clientMachineId"])
logging.info("Application ID: %s" % infoDict["appId"])
logging.info("SKU ID: %s" % infoDict["skuId"])
logging.info("License Status: %s" % infoDict["licenseStatus"])
logging.info("Request Time: %s" % local_dt.strftime('%Y-%m-%d %H:%M:%S %Z (UTC%z)'))
logger.info("Machine Name: %s" % infoDict["machineName"])
logger.info("Client Machine ID: %s" % infoDict["clientMachineId"])
logger.info("Application ID: %s" % infoDict["appId"])
logger.info("SKU ID: %s" % infoDict["skuId"])
logger.info("License Status: %s" % infoDict["licenseStatus"])
logger.info("Request Time: %s" % local_dt.strftime('%Y-%m-%d %H:%M:%S %Z (UTC%z)'))
if self.config['sqlite'] and self.config['dbSupport']:
con = None
@ -246,10 +248,10 @@ clientMachineId=:clientMachineId;", infoDict)
clientMachineId=:clientMachineId;", infoDict)
except sqlite3.Error as e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
except sqlite3.Error as e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
if con:
@ -290,17 +292,17 @@ clientMachineId=:clientMachineId;", infoDict)
(str(response["kmsEpid"].decode('utf-16le')), str(kmsRequest['clientMachineId'].get())))
except sqlite3.Error as e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
except sqlite3.Error as e:
logging.error("Error %s:" % e.args[0])
logger.error("Error %s:" % e.args[0])
sys.exit(1)
finally:
if con:
con.commit()
con.close()
logging.info("Server ePID: %s" % response["kmsEpid"].decode('utf-16le'))
logger.info("Server ePID: %s" % response["kmsEpid"].decode('utf-16le'))
return response
@ -312,16 +314,16 @@ def generateKmsResponseData(data, config):
currentDate = time.strftime("%a %b %d %H:%M:%S %Y")
if version == 4:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV4.kmsRequestV4(data, config)
elif version == 5:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV5.kmsRequestV5(data, config)
elif version == 6:
logging.info("Received V%d request on %s." % (version, currentDate))
logger.info("Received V%d request on %s." % (version, currentDate))
messagehandler = kmsRequestV6.kmsRequestV6(data, config)
else:
logging.info("Unhandled KMS version V%d." % version)
logger.info("Unhandled KMS version V%d." % version)
messagehandler = kmsRequestUnknown.kmsRequestUnknown(data, config)
return messagehandler.executeRequestLogic()

View File

@ -9,6 +9,8 @@ from structure import Structure
from aes import AES
from formatText import shell_message, justify, byterize
logger = logging.getLogger('root')
# v4 AES Key
key = bytearray([0x05, 0x3D, 0x83, 0x07, 0xF9, 0xE5, 0xF0, 0x88, 0xEB, 0x5E, 0xA6, 0x68, 0x6C, 0xF0, 0x37, 0xC7, 0xE4, 0xEF, 0xD2, 0xD6])
@ -103,8 +105,8 @@ class kmsRequestV4(kmsBase):
## Debug stuff.
shell_message(nshell = 16)
response = byterize(response)
logging.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("KMS V4 Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
logger.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("KMS V4 Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
return str(response)
@ -122,7 +124,7 @@ class kmsRequestV4(kmsBase):
## Debug stuff.
shell_message(nshell = 10)
request = byterize(request)
logging.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logging.debug("Request V4: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
logger.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("Request V4: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
return request

View File

@ -10,6 +10,8 @@ from kmsBase import kmsBase
from structure import Structure
from formatText import justify, shell_message, byterize
logger = logging.getLogger('root')
class kmsRequestV5(kmsBase):
class RequestV5(Structure):
class Message(Structure):
@ -138,8 +140,8 @@ class kmsRequestV5(kmsBase):
shell_message(nshell = 16)
response = byterize(response)
logging.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False))))
logging.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8'))))
logger.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False))))
logger.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8'))))
return str(response)
@ -170,7 +172,7 @@ class kmsRequestV5(kmsBase):
shell_message(nshell = 10)
request = byterize(request)
logging.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False))))
logging.info("Request V%d: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8'))))
logger.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False))))
logger.info("Request V%d: \n%s\n" % (self.ver, justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8'))))
return request

View File

@ -9,6 +9,8 @@ from dcerpc import MSRPCHeader, MSRPCBindAck
from structure import Structure
from formatText import shell_message, justify, byterize
logger = logging.getLogger('root')
uuidNDR32 = uuid.UUID('8a885d04-1ceb-11c9-9fe8-08002b104860')
uuidNDR64 = uuid.UUID('71710533-beba-4937-8319-b5dbef9ccc36')
uuidTime = uuid.UUID('6cb71c2c-9812-4540-0300-000000000000')
@ -75,8 +77,8 @@ class handler(rpcBase.rpcBase):
request = MSRPCHeader(self.data)
shell_message(nshell = 3)
request = byterize(request)
logging.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8')))
logging.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
logger.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8')))
logger.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
justify(MSRPCBind(request['pduData']).dump(print_to_stdout = False))))
return request
@ -119,8 +121,8 @@ class handler(rpcBase.rpcBase):
shell_message(nshell = 4)
response = byterize(response)
logging.debug("RPC Bind Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("RPC Bind Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
logger.debug("RPC Bind Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("RPC Bind Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
return response
@ -161,9 +163,9 @@ class handler(rpcBase.rpcBase):
shell_message(nshell = 0)
bind = byterize(bind)
request = byterize(request)
logging.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
logger.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)),
justify(MSRPCBind(request['pduData']).dump(print_to_stdout = False))))
logging.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
logger.debug("RPC Bind Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
return request

View File

@ -8,13 +8,15 @@ import kmsBase
import rpcBase
from formatText import justify, shell_message, byterize
logger = logging.getLogger('root')
class handler(rpcBase.rpcBase):
def parseRequest(self):
request = MSRPCRequestHeader(self.data)
shell_message(nshell = 14)
request = byterize(request)
logging.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8')))
logging.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8')))
logger.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
return request
@ -38,8 +40,8 @@ class handler(rpcBase.rpcBase):
shell_message(nshell = 17)
response = byterize(response)
logging.debug("RPC Message Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logging.debug("RPC Message Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
logger.debug("RPC Message Response: \n%s\n" % justify(response.dump(print_to_stdout = False)))
logger.debug("RPC Message Response Bytes: \n%s\n" % justify(binascii.b2a_hex(str(response).encode('latin-1')).decode('utf-8')))
return response
@ -57,8 +59,8 @@ class handler(rpcBase.rpcBase):
shell_message(nshell = 11)
request = byterize(request)
logging.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logging.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
logger.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False)))
logger.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(str(request).encode('latin-1')).decode('utf-8')))
return request

View File

@ -15,6 +15,9 @@ import rpcBind, rpcRequest
from dcerpc import MSRPCHeader
from rpcBase import rpcBase
from formatText import shell_message
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('root')
config = {}
@ -39,6 +42,14 @@ ValidLcid = [1025, 1026, 1027, 1028, 1029,
10241, 10249, 10250, 11265, 11273, 11274, 12289, 12297, 12298,
13313, 13321, 13322, 14337, 14346, 15361, 15370, 16385, 16394, 17418, 18442, 19466, 20490]
def createLogger(config):
logger.setLevel(config['loglevel'])
log_formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S')
log_handler = RotatingFileHandler(filename=config['logfile'], mode='a', maxBytes=int(config['logsize']*1024*512), backupCount=1, encoding=None, delay=0)
log_handler.setFormatter(log_formatter)
logger.addHandler(log_handler)
def main():
parser = argparse.ArgumentParser(description='py3-kms: KMS Server Emulator written in Python3', epilog="version: py3-kms_2018-11-15")
@ -66,11 +77,13 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
help='Use this flag to set a Loglevel. The default is \"ERROR\".', type=str)
parser.add_argument("-f", "--logfile", dest="logfile", action="store", default=os.path.dirname(os.path.abspath( __file__ )) + "/py3kms_server.log",
help='Use this flag to set an output Logfile. The default is \"pykms_server.log\".', type=str)
config.update(vars(parser.parse_args()))
parser.add_argument("-S", "--logsize", dest="logsize", action="store", default=0,
help='Use this flag to set a maximum size (in MB) to the output Logfile. Desactivated by default.', type=float)
config.update(vars(parser.parse_args()))
createLogger(config)
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
@ -80,13 +93,13 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
try:
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']).decode('utf-8').upper())
logger.error("Error: HWID \"%s\" is invalid. Hex string is too short." % binascii.b2a_hex(config['hwid']).decode('utf-8').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']).decode('utf-8').upper())
logger.error("Error: HWID \"%s\" is invalid. Hex string is too long." % binascii.b2a_hex(config['hwid']).decode('utf-8').upper())
return
except TypeError:
logging.error("Error: HWID \"%s\" is invalid. Odd-length hex string." % binascii.b2a_hex(config['hwid']).decode('utf-8').upper())
logger.error("Error: HWID \"%s\" is invalid. Odd-length hex string." % binascii.b2a_hex(config['hwid']).decode('utf-8').upper())
return
# Check LCID.
@ -109,21 +122,21 @@ The default is \"364F463A8863D35F\" or type \"random\" to auto generate the HWID
try:
import sqlite3
except:
logging.warning("Module \"sqlite3\" is not installed, database support disabled.")
logger.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']).decode('utf-8').upper())
logger.info("TCP server listening at %s on port %d." % (config['ip'], config['port']))
logger.info("HWID: %s" % binascii.b2a_hex(config['hwid']).decode('utf-8').upper())
server.serve_forever()
class kmsServer(socketserver.BaseRequestHandler):
def setup(self):
logging.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1]))
logger.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1]))
def handle(self):
while True:
@ -132,42 +145,42 @@ class kmsServer(socketserver.BaseRequestHandler):
self.data = self.request.recv(1024)
except socket.error as e:
if e.errno == errno.ECONNRESET:
logging.error("Connection reset by peer.")
logger.error("Connection reset by peer.")
break
else:
raise
if self.data == '' or not self.data:
logging.warning("No data received !")
logger.warning("No data received !")
break
# data = bytearray(self.data.strip())
# logging.debug(binascii.b2a_hex(str(data)))
# logger.debug(binascii.b2a_hex(str(data)))
packetType = MSRPCHeader(self.data)['type']
if packetType == rpcBase.packetType['bindReq']:
logging.info("RPC bind request received.")
logger.info("RPC bind request received.")
shell_message(nshell = [-2, 2])
handler = rpcBind.handler(self.data, config)
elif packetType == rpcBase.packetType['request']:
logging.info("Received activation request.")
logger.info("Received activation request.")
shell_message(nshell = [-2, 13])
handler = rpcRequest.handler(self.data, config)
else:
logging.error("Error: Invalid RPC request type ", packetType)
logger.error("Error: Invalid RPC request type ", packetType)
break
res = str(handler.populate()).encode('latin-1')
self.request.send(res)
if packetType == rpcBase.packetType['bindReq']:
logging.info("RPC bind acknowledged.")
logger.info("RPC bind acknowledged.")
shell_message(nshell = [-3, 5, 6])
elif packetType == rpcBase.packetType['request']:
logging.info("Responded to activation request.")
logger.info("Responded to activation request.")
shell_message(nshell = [-3, 18, 19])
break
def finish(self):
self.request.close()
logging.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1]))
logger.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1]))
if __name__ == "__main__":
main()