From 7c14eb10dc5522dc6ace93f9cd2eb001eeeb4eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20=E2=84=B1an?= Date: Sat, 2 Nov 2019 00:26:20 +0100 Subject: [PATCH] Auto-align pretty messages messages syncronization client-server simplified pretty print function arguments --- py-kms/pykms_Base.py | 28 ++++++------ py-kms/pykms_Client.py | 77 +++++++++++++++++++-------------- py-kms/pykms_Format.py | 88 ++++++++++++++++++++++++++++++-------- py-kms/pykms_Misc.py | 52 ++++++++++++++-------- py-kms/pykms_RequestV4.py | 4 +- py-kms/pykms_RequestV5.py | 4 +- py-kms/pykms_RpcBind.py | 6 +-- py-kms/pykms_RpcRequest.py | 6 +-- py-kms/pykms_Server.py | 81 +++++++++++++++++------------------ py-kms/pykms_Sql.py | 21 +++++---- 10 files changed, 227 insertions(+), 140 deletions(-) diff --git a/py-kms/pykms_Base.py b/py-kms/pykms_Base.py index 92fc8a3..501a272 100644 --- a/py-kms/pykms_Base.py +++ b/py-kms/pykms_Base.py @@ -2,8 +2,6 @@ import binascii import logging -import os -import sys import time import uuid import socket @@ -113,7 +111,7 @@ class kmsBase: if self.srv_config['sqlite'] and self.srv_config['dbSupport']: self.dbName = sql_initialize() - pretty_printer(None, num_text = 15) + pretty_printer(num_text = 15) kmsRequest = byterize(kmsRequest) loggersrv.debug("KMS Request Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(kmsRequest), 'latin-1')), 'latin-1'))) loggersrv.debug("KMS Request: \n%s\n" % justify(kmsRequest.dump(print_to_stdout = False))) @@ -131,12 +129,12 @@ class kmsBase: tz = get_localzone() local_dt = tz.localize(requestDatetime) except UnknownTimeZoneError: - pretty_printer(loggersrv.warning, get_text = True, log_text = True, - put_text = "{yellow}{bold}Unknown time zone ! Request time not localized.{end}") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Unknown time zone ! Request time not localized.{end}") local_dt = requestDatetime except ImportError: - pretty_printer(loggersrv.warning, get_text = True, log_text = True, - put_text = "{yellow}{bold}Module 'tzlocal' not available ! Request time not localized.{end}") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Module 'tzlocal' not available ! Request time not localized.{end}") local_dt = requestDatetime # Activation threshold. @@ -147,15 +145,19 @@ class kmsBase: if 0 < self.srv_config["CurrentClientCount"] < MinClients: # fixed to 6 (product server) or 26 (product desktop) currentClientCount = MinClients + 1 - loggersrv.warning("Not enough clients ! Fixed with %s, but activated client could be detected as not genuine !" %currentClientCount) + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Not enough clients ! Fixed with %s, but activated client \ +could be detected as not genuine !{end}" %currentClientCount) elif MinClients <= self.srv_config["CurrentClientCount"] < RequiredClients: currentClientCount = self.srv_config["CurrentClientCount"] - loggersrv.warning("With count = %s, activated client could be detected as not genuine !" %currentClientCount) + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}With count = %s, activated client could be detected as not genuine !{end}" %currentClientCount) elif self.srv_config["CurrentClientCount"] >= RequiredClients: # fixed to 10 (product server) or 50 (product desktop) currentClientCount = RequiredClients if self.srv_config["CurrentClientCount"] > RequiredClients: - loggersrv.warning("Too many clients ! Fixed with %s" %currentClientCount) + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Too many clients ! Fixed with %s{end}" %currentClientCount) else: # fixed to 10 (product server) or 50 (product desktop) currentClientCount = RequiredClients @@ -176,14 +178,16 @@ class kmsBase: break except: skuName = skuId - loggersrv.warning("Can't find a name for this product !!") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Can't find a name for this product !{end}") try: if uuid.UUID(appitem['Id']) == applicationId: appName = appitem['DisplayName'] except: appName = applicationId - loggersrv.warning("Can't find a name for this application group !!") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Can't find a name for this application group !{end}") infoDict = { "machineName" : kmsRequest.getMachineName(), diff --git a/py-kms/pykms_Client.py b/py-kms/pykms_Client.py index 3f754e7..5513bdc 100644 --- a/py-kms/pykms_Client.py +++ b/py-kms/pykms_Client.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import re -import argparse import binascii import datetime import random @@ -11,7 +10,6 @@ import sys import uuid import logging import os -import errno import pykms_RpcBind, pykms_RpcRequest from pykms_Filetimes import dt_to_filetime @@ -23,6 +21,7 @@ from pykms_RequestV6 import kmsRequestV6 from pykms_RpcBase import rpcBase from pykms_DB2Dict import kmsDB2Dict from pykms_Misc import logger_create, check_logfile, pretty_printer +from pykms_Misc import KmsParser, KmsException from pykms_Format import justify, byterize, enco, deco, ShellMessage clt_description = 'KMS Client Emulator written in Python' @@ -53,7 +52,7 @@ log info on stdout. Type \"FILESTDOUT\" to combine previous actions.', } def client_options(): - parser = argparse.ArgumentParser(description = clt_description, epilog = 'version: ' + clt_version) + parser = KmsParser(description = clt_description, epilog = 'version: ' + clt_version) parser.add_argument("ip", nargs = "?", action = "store", default = clt_options['ip']['def'], help = clt_options['ip']['help'], type = str) parser.add_argument("port", nargs = "?", action = "store", default = clt_options['port']['def'], help = clt_options['port']['help'], type = int) parser.add_argument("-m", "--mode", dest = clt_options['mode']['des'], default = clt_options['mode']['def'], choices = clt_options['mode']['choi'], @@ -62,15 +61,17 @@ def client_options(): parser.add_argument("-n", "--name", dest = clt_options['name']['des'] , default = clt_options['name']['def'], help = clt_options['name']['help'], type = str) parser.add_argument("-V", "--loglevel", dest = clt_options['llevel']['des'], action = "store", choices = clt_options['llevel']['choi'], default = clt_options['llevel']['def'], help = clt_options['llevel']['help'], type = str) - parser.add_argument("-F", "--logfile", nargs = "+", dest = clt_options['lfile']['des'], default = clt_options['lfile']['def'], + parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = clt_options['lfile']['des'], default = clt_options['lfile']['def'], help = clt_options['lfile']['help'], type = str) parser.add_argument("-S", "--logsize", dest = clt_options['lsize']['des'], action = "store", default = clt_options['lsize']['def'], help = clt_options['lsize']['help'], type = float) - - clt_config.update(vars(parser.parse_args())) - # Check logfile. - clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def'], loggerclt) - + + try: + clt_config.update(vars(parser.parse_args())) + # Check logfile. + clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def']) + except KmsException as e: + pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) def client_check(): # Setup hidden or not messages. @@ -83,14 +84,13 @@ def client_check(): try: uuid.UUID(clt_config['cmid']) except ValueError: - loggerclt.error("Bad CMID. Exiting...") - sys.exit() - + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}Bad CMID. Exiting...{end}") # Check machineName. if clt_config['machineName'] is not None: if len(clt_config['machineName']) < 2 or len(clt_config['machineName']) > 63: - loggerclt.error("machineName must be between 2 and 63 characters in length.") - sys.exit() + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}machineName must be between 2 and 63 characters in length. Exiting...{end}") clt_config['call_id'] = 1 @@ -125,31 +125,46 @@ def client_create(): loggerclt.info("Connection successful !") binder = pykms_RpcBind.handler(None, clt_config) RPC_Bind = enco(str(binder.generateRequest()), 'latin-1') - loggerclt.info("Sending RPC bind request...") - pretty_printer(None, num_text = [-1, 1]) - s.send(RPC_Bind) + try: + loggerclt.info("Sending RPC bind request...") + s.send(RPC_Bind) + pretty_printer(num_text = [-1, 1]) + except socket.error as e: + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) try: bindResponse = s.recv(1024) if bindResponse == '' or not bindResponse: - pretty_printer(loggerclt.warning, get_text = True, log_text = True, to_exit = True, - put_text = "{yellow}{bold}No data received.{end}") - pretty_printer(None, num_text = [-4, 7]) + pretty_printer(log_obj = loggerclt.warning, to_exit = True, + put_text = "{reverse}{yellow}{bold}No data received.{end}") + pretty_printer(num_text = [-4, 7]) except socket.error as e: - pretty_printer(loggerclt.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}While receiving: %s{end}" %str(e)) + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) packetType = MSRPCHeader(bindResponse)['type'] if packetType == rpcBase.packetType['bindAck']: loggerclt.info("RPC bind acknowledged.") - pretty_printer(None, num_text = 8) + pretty_printer(num_text = 8) kmsRequest = createKmsRequest() requester = pykms_RpcRequest.handler(kmsRequest, clt_config) - s.send(enco(str(requester.generateRequest()), 'latin-1')) - pretty_printer(None, num_text = [-1, 12]) - response = s.recv(1024) + + try: + loggerclt.info("Sending RPC activation request...") + s.send(enco(str(requester.generateRequest()), 'latin-1')) + pretty_printer(num_text = [-1, 12]) + except socket.error as e: + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) + try: + response = s.recv(1024) + pretty_printer(num_text = [-4, 20]) + except socket.error as e: + pretty_printer(log_obj = loggerclt.error, to_exit = True, + put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) + loggerclt.debug("Response: \n%s\n" % justify(deco(binascii.b2a_hex(response), 'latin-1'))) - pretty_printer(None, num_text = [-4, 20]) parsed = MSRPCRespHeader(response) kmsData = readKmsResponse(parsed['pduData'], kmsRequest, clt_config) kmsResp = kmsData['response'] @@ -169,14 +184,14 @@ def client_create(): 'status' : "Activated", 'product' : clt_config["mode"]}) - pretty_printer(None, num_text = 21) + pretty_printer(num_text = 21) elif packetType == rpcBase.packetType['bindNak']: loggerclt.info(justify(MSRPCBindNak(bindResponse).dump(print_to_stdout = False))) sys.exit(0) else: - pretty_printer(loggerclt.warning, get_text = True, log_text = True, to_exit = True, - put_text = "{magenta}{bold}Something went wrong.{end}") + pretty_printer(log_obj = loggerclt.warning, to_exit = True, + put_text = "{reverse}{magenta}{bold}Something went wrong.{end}") def clt_main(with_gui = False): if not with_gui: @@ -209,7 +224,7 @@ def createKmsRequestBase(): requestDict['mnPad'] = '\0'.encode('utf-16le') * (63 - len(requestDict['machineName'].decode('utf-16le'))) # Debug Stuff - pretty_printer(None, num_text = 9) + pretty_printer(num_text = 9) requestDict = byterize(requestDict) loggerclt.debug("Request Base Dictionary: \n%s\n" % justify(requestDict.dump(print_to_stdout = False))) diff --git a/py-kms/pykms_Format.py b/py-kms/pykms_Format.py index cc04672..03b6726 100644 --- a/py-kms/pykms_Format.py +++ b/py-kms/pykms_Format.py @@ -3,6 +3,7 @@ from __future__ import print_function, unicode_literals import re import sys +import os import threading try: @@ -101,29 +102,29 @@ MsgMap = {0 : {'text' : "{yellow}\n\t\t\tClient generating RPC Bind Request...{ 3 : {'text' : "{yellow}Server parsing RPC Bind Request...{end}", 'where' : "srv"}, 4 : {'text' : "{yellow}Server generating RPC Bind Response...{end}", 'where' : "srv"}, 5 : {'text' : "{yellow}Server sending RPC Bind Response...\t\t\t\t{end}{white}===============>{end}", 'where' : "srv"}, - 6 : {'text' : "{green}{bold}RPC Bind acknowledged !!!\n\n{end}", 'where' : "srv"}, + 6 : {'text' : "{green}{bold}\nRPC Bind acknowledged !!!{end}", 'where' : "srv"}, 7 : {'text' : "{white}===============>{end}{yellow}\tClient received RPC Bind Response !!!{end}", 'where' : "clt"}, - 8 : {'text' : "{green}{bold}\t\t\tRPC Bind acknowledged !!!\n{end}", 'where' : "clt"}, + 8 : {'text' : "{green}{bold}\t\t\tRPC Bind acknowledged !!!{end}", 'where' : "clt"}, 9 : {'text' : "{blue}\t\t\tClient generating Activation Request dictionary...{end}", 'where' : "clt"}, 10 : {'text' : "{blue}\t\t\tClient generating Activation Request data...{end}", 'where' : "clt"}, 11 : {'text' : "{blue}\t\t\tClient generating RPC Activation Request...{end}", 'where' : "clt"}, - 12 : {'text' : "{white}<==============={end}{blue}\tClient sending RPC Activation Request...\n\n{end}", 'where' : "clt"}, + 12 : {'text' : "{white}<==============={end}{blue}\tClient sending RPC Activation Request...{end}", 'where' : "clt"}, 13 : {'text' : "{blue}Server received RPC Activation Request !!!\t\t\t{end}{white}<==============={end}", 'where' : "srv"}, 14 : {'text' : "{blue}Server parsing RPC Activation Request...{end}", 'where' : "srv"}, 15 : {'text' : "{blue}Server processing KMS Activation Request...{end}", 'where' : "srv"}, 16 : {'text' : "{blue}Server processing KMS Activation Response...{end}", 'where' : "srv"}, 17 : {'text' : "{blue}Server generating RPC Activation Response...{end}", 'where' : "srv"}, 18 : {'text' : "{blue}Server sending RPC Activation Response...\t\t\t{end}{white}===============>{end}", 'where' : "srv"}, - 19 : {'text' : "{green}{bold}Server responded, now in Stand by...\n{end}", 'where' : "srv"}, + 19 : {'text' : "{green}{bold}\nServer responded, now in Stand by...\n{end}", 'where' : "srv"}, 20 : {'text' : "{white}===============>{end}{blue}\tClient received Response !!!{end}", 'where' : "clt"}, 21 : {'text' : "{green}{bold}\t\t\tActivation Done !!!{end}", 'where' : "clt"}, -1 : {'text' : "{white}Server receiving{end}", 'where' : "clt"}, - -2 : {'text' : "{white}\n\n\n\t\t\t\t\t\t\t\tClient sending{end}", 'where' : "srv"}, + -2 : {'text' : "{white}\t\t\t\t\t\t\t\tClient sending{end}", 'where' : "srv"}, -3 : {'text' : "{white}\t\t\t\t\t\t\t\tClient receiving{end}", 'where' : "srv"}, - -4 : {'text' : "{white}\n\nServer sending{end}", 'where' : "clt"}, + -4 : {'text' : "{white}Server sending{end}", 'where' : "clt"}, } -def pick_MsgMap(messagelist): +def MsgMap_unformat(messagelist): pattern = r"(?= 0: + ShellMessage.numlist.append(num) + if self.continuecount: + # Note: bypassed '\n' counted after message with arrow, + # isn't: str(len(ShellMessage.numlist) + ShellMessage.count) + towrite = str(len(ShellMessage.numlist)) + '\n' + self.newlines_file('a', towrite) + ShellMessage.count, ShellMessage.numlist = (0, []) + else: + ShellMessage.count += (len(ShellMessage.numlist) - ShellMessage.remain) * 2 + if num in [-1, -3]: + towrite = str(ShellMessage.count) + '\n' + self.newlines_file('w', towrite) + ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, []) + self.continuecount = True + elif num in [-2 ,-4]: + self.newlines_file('r') + if num == 21: + os.remove(self.path) + def spawn(self): # Save everything that would otherwise go to stdout. outstream = ShellMessage.Collect() sys.stdout = outstream try: + self.continuecount = False + self.newlines = 0 + # Print something. if self.put_text is not None: - for mess in self.put_text: - self.formatter(mess) + for msg in self.put_text: + ShellMessage.count += msg.count('\n') + ShellMessage.numlist.append('put') + self.formatter(msg) print(self.msgfrmt, end = '\n', flush = True) else: for num in self.nshell: - self.formatter(MsgMap[num]['text']) + self.newlines_count(num) + self.formatter(MsgMap[num]) print(self.msgfrmt, end = '\n', flush = True) finally: # Restore stdout and send content. diff --git a/py-kms/pykms_Misc.py b/py-kms/pykms_Misc.py index fcf5041..5a863d8 100644 --- a/py-kms/pykms_Misc.py +++ b/py-kms/pykms_Misc.py @@ -3,6 +3,7 @@ import sys import logging import os +import argparse from logging.handlers import RotatingFileHandler from pykms_Format import ColorExtraMap, ShellMessage @@ -132,20 +133,20 @@ def logger_create(log_obj, config, mode = 'a'): #---------------------------------------------------------------------------------------------------------------------------------------------------------- -def check_logfile(optionlog, defaultlog, log_obj): +def check_logfile(optionlog, defaultlog): if not isinstance(optionlog, list): optionlog = [optionlog] lenopt = len(optionlog) - msg_long = "{red}{bold}Argument logfile: Too much arguments{end}" + msg_dir = "{reverse}{red}{bold}argument logfile: no such file or directory: %s. Exiting...{end}" + msg_long = "{reverse}{red}{bold}argument logfile: too much arguments. Exiting...{end}" def checkdir(path): if not os.path.isdir(os.path.dirname(path)): - pretty_printer(log_obj, to_exit = True, - put_text = "{red}{bold}Argument logfile: No such file or directory: %s{end}" %path) + pretty_printer(put_text = msg_dir %path, to_exit = True) if lenopt > 2: - pretty_printer(log_obj, to_exit = True, put_text = msg_long) + pretty_printer(put_text = msg_long, to_exit = True) if 'FILESTDOUT' in optionlog: if lenopt == 1: @@ -156,30 +157,30 @@ def check_logfile(optionlog, defaultlog, log_obj): checkdir(optionlog[1]) else: if lenopt == 2: - pretty_printer(46, log_obj, to_exit = True, put_text = msg_long) + pretty_printer(put_text = msg_long, to_exit = True) elif lenopt == 1 and 'STDOUT' not in optionlog: # check directory path. checkdir(optionlog[0]) return optionlog -def pretty_printer(log_obj, **kwargs): - """ `log_obj` --> logging object. - kwargs: +def pretty_printer(**kwargs): + """kwargs: + `log_obj` --> if logging object specified the text not ansi + formatted is logged. `get_text` --> if True obtain text not ansi formatted, after printing it with ansi formattation. `put_text` --> a string or list of strings with ansi formattation. if None refer to `num_text` for printing process. - `num_text` --> a number or list of numbers of numbered message map. + `num_text` --> a number or list of numbers refering numbered message map. if None `put_text` must be defined for printing process. - `log_text` --> if True the text not ansi formatted is logged. `to_exit ` --> if True system exit is called. """ # Set defaults for not defined options. - options = {'get_text' : False, + options = {'log_obj' : None, + 'get_text' : False, 'put_text' : None, 'num_text' : None, - 'log_text' : False, 'to_exit' : False, } options.update(kwargs) @@ -194,12 +195,18 @@ def pretty_printer(log_obj, **kwargs): if (options['put_text'] is not None) and (not isinstance(options['put_text'], list)): options['put_text'] = [options['put_text']] - # Process errors. + # Overwrite `get_text` (used as hidden). + if options['put_text']: + options['get_text'] = True + elif options['num_text']: # further check. + options['get_text'] = False + + # Process messages. plain_messages = ShellMessage.Process(options['num_text'], get_text = options['get_text'], put_text = options['put_text']).run() - if options['log_text']: + if options['log_obj']: for plain_message in plain_messages: - log_obj(plain_message) + options['log_obj'](plain_message) if options['to_exit']: sys.exit(1) @@ -242,13 +249,22 @@ def check_lcid(lcid, log_obj): fixlcid = next(k for k, v in locale.windows_locale.items() if v == locale.getdefaultlocale()[0]) except StopIteration: fixlcid = 1033 - pretty_printer(log_obj, get_text = True, log_text = True, - put_text = "{yellow}{bold}lcid %s auto-fixed with lcid %s{end}" %(lcid, fixlcid)) + pretty_printer(log_obj = log_obj, + put_text = "{reverse}{yellow}{bold}LCID %s auto-fixed with LCID %s{end}" %(lcid, fixlcid)) return fixlcid return lcid #---------------------------------------------------------------------------------------------------------------------------------------------------------- +class KmsException(Exception): + pass + +class KmsParser(argparse.ArgumentParser): + def error(self, message): + raise KmsException(message) + +#---------------------------------------------------------------------------------------------------------------------------------------------------------- + # http://joshpoley.blogspot.com/2011/09/hresults-user-0x004.html (slerror.h) ErrorCodes = { 'SL_E_SRV_INVALID_PUBLISH_LICENSE' : (0xC004B001, 'The activation server determined that the license is invalid.'), diff --git a/py-kms/pykms_RequestV4.py b/py-kms/pykms_RequestV4.py index 8ca0a0e..a4807b2 100644 --- a/py-kms/pykms_RequestV4.py +++ b/py-kms/pykms_RequestV4.py @@ -106,7 +106,7 @@ class kmsRequestV4(kmsBase): response['padding'] = bytes(bytearray(self.getPadding(bodyLength))) ## Debug stuff. - pretty_printer(None, num_text = 16) + pretty_printer(num_text = 16) response = byterize(response) loggersrv.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False))) loggersrv.debug("KMS V4 Response Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8'))) @@ -125,7 +125,7 @@ class kmsRequestV4(kmsBase): request['padding'] = bytes(bytearray(self.getPadding(bodyLength))) ## Debug stuff. - pretty_printer(None, num_text = 10) + pretty_printer(num_text = 10) request = byterize(request) loggersrv.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False))) loggersrv.debug("Request V4: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(request), 'latin-1')), 'utf-8'))) diff --git a/py-kms/pykms_RequestV5.py b/py-kms/pykms_RequestV5.py index 32ca101..6ed56c9 100644 --- a/py-kms/pykms_RequestV5.py +++ b/py-kms/pykms_RequestV5.py @@ -141,7 +141,7 @@ class kmsRequestV5(kmsBase): response['encrypted'] = bytes(bytearray(encryptedResponse)) response['padding'] = bytes(bytearray(self.getPadding(bodyLength))) - pretty_printer(None, num_text = 16) + pretty_printer(num_text = 16) response = byterize(response) loggersrv.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False)))) loggersrv.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8')))) @@ -173,7 +173,7 @@ class kmsRequestV5(kmsBase): request['versionMajor'] = requestBase['versionMajor'] request['message'] = message - pretty_printer(None, num_text = 10) + pretty_printer(num_text = 10) request = byterize(request) loggersrv.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False)))) loggersrv.info("Request V%d: \n%s\n" % (self.ver, justify(deco(binascii.b2a_hex(enco(str(request), 'latin-1')), 'utf-8')))) diff --git a/py-kms/pykms_RpcBind.py b/py-kms/pykms_RpcBind.py index dd4a486..83fd34a 100644 --- a/py-kms/pykms_RpcBind.py +++ b/py-kms/pykms_RpcBind.py @@ -78,7 +78,7 @@ class MSRPCBind(Structure): class handler(pykms_RpcBase.rpcBase): def parseRequest(self): request = MSRPCHeader(self.data) - pretty_printer(None, num_text = 3) + pretty_printer(num_text = 3) request = byterize(request) loggersrv.debug("RPC Bind Request Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(self.data), 'utf-8'))) loggersrv.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)), @@ -122,7 +122,7 @@ class handler(pykms_RpcBase.rpcBase): resp = preparedResponses[ts_uuid] response['ctx_items'] += str(resp) - pretty_printer(None, num_text = 4) + pretty_printer(num_text = 4) response = byterize(response) loggersrv.debug("RPC Bind Response: \n%s\n" % justify(response.dump(print_to_stdout = False))) loggersrv.debug("RPC Bind Response Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8'))) @@ -163,7 +163,7 @@ class handler(pykms_RpcBase.rpcBase): request['call_id'] = self.srv_config['call_id'] request['pduData'] = str(bind) - pretty_printer(None, num_text = 0) + pretty_printer(num_text = 0) bind = byterize(bind) request = byterize(request) loggersrv.debug("RPC Bind Request: \n%s\n%s\n" % (justify(request.dump(print_to_stdout = False)), diff --git a/py-kms/pykms_RpcRequest.py b/py-kms/pykms_RpcRequest.py index 1f654f3..4ff26d2 100644 --- a/py-kms/pykms_RpcRequest.py +++ b/py-kms/pykms_RpcRequest.py @@ -16,7 +16,7 @@ loggersrv = logging.getLogger('logsrv') class handler(pykms_RpcBase.rpcBase): def parseRequest(self): request = MSRPCRequestHeader(self.data) - pretty_printer(None, num_text = 14) + pretty_printer(num_text = 14) request = byterize(request) loggersrv.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8'))) loggersrv.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False))) @@ -41,7 +41,7 @@ class handler(pykms_RpcBase.rpcBase): response['pduData'] = responseData - pretty_printer(None, num_text = 17) + pretty_printer(num_text = 17) response = byterize(response) loggersrv.debug("RPC Message Response: \n%s\n" % justify(response.dump(print_to_stdout = False))) loggersrv.debug("RPC Message Response Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8'))) @@ -60,7 +60,7 @@ class handler(pykms_RpcBase.rpcBase): request['alloc_hint'] = len(self.data) request['pduData'] = str(self.data) - pretty_printer(None, num_text = 11) + pretty_printer(num_text = 11) request = byterize(request) loggersrv.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout = False))) loggersrv.debug("RPC Message Request Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(request), 'latin-1')), 'utf-8'))) diff --git a/py-kms/pykms_Server.py b/py-kms/pykms_Server.py index 701856f..96bc2f4 100755 --- a/py-kms/pykms_Server.py +++ b/py-kms/pykms_Server.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import argparse import binascii import re import sys @@ -8,7 +7,6 @@ import socket import uuid import logging import os -import errno import threading try: @@ -24,6 +22,7 @@ import pykms_RpcBind, pykms_RpcRequest from pykms_RpcBase import rpcBase from pykms_Dcerpc import MSRPCHeader from pykms_Misc import logger_create, check_logfile, check_lcid, pretty_printer +from pykms_Misc import KmsParser, KmsException from pykms_Format import enco, deco, ShellMessage srv_description = 'KMS Server Emulator written in Python' @@ -36,8 +35,8 @@ class KeyServer(socketserver.ThreadingMixIn, socketserver.TCPServer): allow_reuse_address = True def handle_timeout(self): - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}Server connection timed out. Exiting...{end}") + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}Server connection timed out. Exiting...{end}") def handle_error(self, request, client_address): pass @@ -101,16 +100,8 @@ log info on stdout. Type \"FILESTDOUT\" to combine previous actions.', 'lsize' : {'help' : 'Use this flag to set a maximum size (in MB) to the output log file. Desactivated by default.', 'def' : 0, 'des': "logsize"}, } - -class KmsSrvException(Exception): - pass - -class KmsSrvParser(argparse.ArgumentParser): - def error(self, message): - raise KmsSrvException(message) - def server_options(): - parser = KmsSrvParser(description = srv_description, epilog = 'version: ' + srv_version) + parser = KmsParser(description = srv_description, epilog = 'version: ' + srv_version) parser.add_argument("ip", nargs = "?", action = "store", default = srv_options['ip']['def'], help = srv_options['ip']['help'], type = str) parser.add_argument("port", nargs = "?", action = "store", default = srv_options['port']['def'], help = srv_options['port']['help'], type = int) parser.add_argument("-e", "--epid", dest = srv_options['epid']['des'], default = srv_options['epid']['def'], help = srv_options['epid']['help'], type = str) @@ -129,7 +120,7 @@ def server_options(): help = srv_options['time']['help'], type = int) parser.add_argument("-V", "--loglevel", dest = srv_options['llevel']['des'], action = "store", choices = srv_options['llevel']['choi'], default = srv_options['llevel']['def'], help = srv_options['llevel']['help'], type = str) - parser.add_argument("-F", "--logfile", nargs = "+", dest = srv_options['lfile']['des'], default = srv_options['lfile']['def'], + parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = srv_options['lfile']['des'], default = srv_options['lfile']['def'], help = srv_options['lfile']['help'], type = str) parser.add_argument("-S", "--logsize", dest = srv_options['lsize']['des'], action = "store", default = srv_options['lsize']['def'], help = srv_options['lsize']['help'], type = float) @@ -137,9 +128,9 @@ def server_options(): try: srv_config.update(vars(parser.parse_args())) # Check logfile. - srv_config['logfile'] = check_logfile(srv_config['logfile'], srv_options['lfile']['def'], loggersrv.error) - except KmsSrvException as e: - pretty_printer(loggersrv.error, to_exit = True, put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + srv_config['logfile'] = check_logfile(srv_config['logfile'], srv_options['lfile']['def']) + except KmsException as e: + pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) def server_check(): # Setup hidden or not messages. @@ -159,19 +150,19 @@ def server_check(): if len(diff) != 0: diff = str(diff).replace('{', '').replace('}', '') - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}HWID '%s' is invalid. Digit %s non hexadecimal. Exiting...{end}" %(hexstr.upper(), diff)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Digit %s non hexadecimal. Exiting...{end}" %(hexstr.upper(), diff)) else: lh = len(hexsub) if lh % 2 != 0: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}HWID '%s' is invalid. Hex string is odd length. Exiting...{end}" %hexsub.upper()) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is odd length. Exiting...{end}" %hexsub.upper()) elif lh < 16: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}HWID '%s' is invalid. Hex string is too short. Exiting...{end}" %hexsub.upper()) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too short. Exiting...{end}" %hexsub.upper()) elif lh > 16: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}HWID '%s' is invalid. Hex string is too long. Exiting...{end}" %hexsub.upper()) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too long. Exiting...{end}" %hexsub.upper()) else: srv_config['hwid'] = binascii.a2b_hex(hexsub) @@ -182,15 +173,15 @@ def server_check(): try: import sqlite3 except: - pretty_printer(loggersrv.warning, get_text = True, log_text = True, - put_text = "Module 'sqlite3' is not installed, database support disabled.") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}Module 'sqlite3' is not installed, database support disabled.{end}") srv_config['dbSupport'] = False else: srv_config['dbSupport'] = True # Check port. if not 1 <= srv_config['port'] <= 65535: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, + pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{red}{bold}Port number '%s' is invalid. Enter between 1 - 65535. Exiting...{end}" %srv_config['port']) def server_create(): @@ -233,37 +224,45 @@ class kmsServerHandler(socketserver.BaseRequestHandler): try: self.data = self.request.recv(1024) if self.data == '' or not self.data: - pretty_printer(loggersrv.warning, get_text = True, log_text = True, - put_text = "{yellow}{bold}No data received.{end}") + pretty_printer(log_obj = loggersrv.warning, + put_text = "{reverse}{yellow}{bold}No data received.{end}") break except socket.error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, - put_text = "{red}{bold}While receiving: %s{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, + put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) break packetType = MSRPCHeader(self.data)['type'] if packetType == rpcBase.packetType['bindReq']: loggersrv.info("RPC bind request received.") - pretty_printer(None, num_text = [-2, 2]) + pretty_printer(num_text = [-2, 2]) handler = pykms_RpcBind.handler(self.data, srv_config) elif packetType == rpcBase.packetType['request']: loggersrv.info("Received activation request.") - pretty_printer(None, num_text = [-2, 13]) + pretty_printer(num_text = [-2, 13]) handler = pykms_RpcRequest.handler(self.data, srv_config) else: - pretty_printer(loggersrv.error, get_text = True, log_text = True, - put_text = "Invalid RPC request type %s" %packetType) - break - + pretty_printer(log_obj = loggersrv.error, + put_text = "{reverse}{red}{bold}Invalid RPC request type %s.{end}" %packetType) + break + res = enco(str(handler.populate()), 'latin-1') - self.request.send(res) if packetType == rpcBase.packetType['bindReq']: loggersrv.info("RPC bind acknowledged.") - pretty_printer(None, num_text = [-3, 5, 6]) + pretty_printer(num_text = [-3, 5, 6]) elif packetType == rpcBase.packetType['request']: loggersrv.info("Responded to activation request.") - pretty_printer(None, num_text = [-3, 18, 19]) + pretty_printer(num_text = [-3, 18, 19]) + + try: + self.request.send(res) + except socket.error as e: + pretty_printer(log_obj = loggersrv.error, + put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) + break + + if packetType == rpcBase.packetType['request']: break def finish(self): diff --git a/py-kms/pykms_Sql.py b/py-kms/pykms_Sql.py index f448dd0..91a3755 100644 --- a/py-kms/pykms_Sql.py +++ b/py-kms/pykms_Sql.py @@ -2,7 +2,6 @@ import os import logging -import sys # sqlite3 is optional. try: @@ -28,8 +27,8 @@ def sql_initialize(): licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)") except sqlite3.Error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) finally: if con: con.commit() @@ -65,11 +64,11 @@ skuId, licenseStatus, lastRequestTime, requestCount) VALUES (:clientMachineId, : cur.execute("UPDATE clients SET requestCount=requestCount+1 WHERE clientMachineId=:clientMachineId;", infoDict) except sqlite3.Error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) except sqlite3.Error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) finally: if con: con.commit() @@ -90,11 +89,11 @@ def sql_update_epid(dbName, kmsRequest, response): cur.execute("UPDATE clients SET kmsEpid=? WHERE clientMachineId=?;", (str(response["kmsEpid"].decode('utf-16le')), cmid)) except sqlite3.Error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) except sqlite3.Error as e: - pretty_printer(loggersrv.error, get_text = True, log_text = True, to_exit = True, - put_text = "{red}{bold}%s. Exiting...{end}" %str(e)) + pretty_printer(log_obj = loggersrv.error, to_exit = True, + put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) finally: if con: con.commit()