Skip to content

Commit 4a3a8a6

Browse files
committed
Python tools: Print errors and usage to stderr
The concept of stderr was invented about 60 years ago.
1 parent be60bc5 commit 4a3a8a6

29 files changed

+170
-167
lines changed

run/DPAPImk2john.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ def decryptWithPassword(self, userSID, pwd, context):
548548
if context == "domain1607-" or context == "domain":
549549
self.decryptWithHash(userSID, hashlib.new("md4", pwd.encode('UTF-16LE')).digest())
550550
if self.decrypted:
551-
print("Decrypted succesfully as domain1607-")
551+
print("Decrypted succesfully as domain1607-", file=sys.stderr)
552552
return
553553
if context == "domain1607+" or context == "domain":
554554
SIDenc = userSID.encode("UTF-16LE")
@@ -557,7 +557,7 @@ def decryptWithPassword(self, userSID, pwd, context):
557557
derived = pbkdf2(derived, SIDenc, 16, 1, digest='sha256')
558558
self.decryptWithHash(userSID, derived)
559559
if self.decrypted:
560-
print("Decrypted succesfully as domain1607+")
560+
print("Decrypted succesfully as domain1607+", file=sys.stderr)
561561
return
562562
if context == "local":
563563
self.decryptWithHash(userSID, hashlib.new("sha1", pwd.encode('UTF-16LE')).digest())
@@ -656,10 +656,10 @@ def __repr__(self):
656656
debug = options.debug
657657

658658
if options.preferred and (options.masterkey or options.sid or options.context):
659-
print("'Preferred' option cannot be used combined with any other, exiting.")
659+
print("'Preferred' option cannot be used combined with any other, exiting.", file=sys.stderr)
660660
sys.exit(1)
661661
elif not options.preferred and not (options.masterkey and options.sid and options.context):
662-
print("masterkey file, SID and context are mandatory in order to extract hash from masterkey file, exiting.")
662+
print("masterkey file, SID and context are mandatory in order to extract hash from masterkey file, exiting.", file=sys.stderr)
663663
sys.exit(1)
664664
elif options.preferred:
665665
Preferred = open(options.preferred,'rb')

run/androidfde2john.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def parse_footer(data):
140140
while True:
141141
footer = fh.read(CryptMntFtr.struct_size())
142142
if len(footer) < CryptMntFtr.struct_size():
143-
print("Cannot read disk image footer")
143+
print("Cannot read disk image footer", file=sys.stderr)
144144
return
145145
idx = footer.find(b"\xC4\xB1\xB5\xD0")
146146
if idx == 0:
@@ -151,13 +151,12 @@ def parse_footer(data):
151151
crypt_ftr = CryptMntFtr(footer)
152152

153153
if crypt_ftr.magic != CRYPT_MNT_MAGIC:
154-
print(
155-
data, crypt_ftr, "Bad magic in disk image footer")
154+
print(data, crypt_ftr, "Bad magic in disk image footer", file=sys.stderr)
156155
if crypt_ftr.major_version != 1:
157156
print(data, crypt_ftr,
158157
"Cannot understand major version {} in "
159158
"disk image footer".format(
160-
crypt_ftr.major_version))
159+
crypt_ftr.major_version), file=sys.stderr)
161160
if crypt_ftr.minor_version != 0:
162161
warn("crypto footer minor version {}, expected 0".format(
163162
crypt_ftr.minor_version), UserWarning)
@@ -169,17 +168,17 @@ def parse_footer(data):
169168
if crypt_ftr.keysize != KEY_LEN_BYTES:
170169
print(data, crypt_ftr,
171170
"Keysize of {} bits not supported".format(
172-
crypt_ftr.keysize*8))
171+
crypt_ftr.keysize*8), file=sys.stderr)
173172
key = fh.read(crypt_ftr.keysize)
174173
if len(key) != crypt_ftr.keysize:
175174
print(data, crypt_ftr,
176-
"Cannot read key from disk image footer")
175+
"Cannot read key from disk image footer", file=sys.stderr)
177176

178177
fh.seek(KEY_TO_SALT_PADDING, os.SEEK_CUR)
179178
salt = fh.read(SALT_LEN)
180179
if len(salt) != SALT_LEN:
181180
print(data, crypt_ftr,
182-
"Cannot read salt from disk image footer")
181+
"Cannot read salt from disk image footer", file=sys.stderr)
183182

184183
return (crypt_ftr, key, salt)
185184

run/apop2john.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
try:
1515
from scapy.all import *
1616
except ImportError:
17-
print("scapy is missing, run 'pip install --user scapy' to install it!")
17+
print("scapy is missing, run 'pip install --user scapy' to install it!", file=sys.stderr)
1818
exit(1)
1919

2020
from binascii import hexlify
@@ -23,7 +23,7 @@
2323
import re
2424

2525
if len(argv) < 2:
26-
print('Usage: ./apop2john.py <pcap files>')
26+
print('Usage: ./apop2john.py <pcap files>', file=sys.stderr)
2727
exit(1)
2828

2929
filenames = argv[1:]

run/authenticator2john.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from binascii import hexlify
1414

1515
if len(sys.argv) < 2:
16-
print('Usage: ./authenticator2john.py <authenticator.data files>')
16+
print('Usage: ./authenticator2john.py <authenticator.data files>', file=sys.stderr)
1717
exit(1)
1818

1919
filenames = sys.argv[1:]

run/axcrypt2john.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def parse_axxfile(axxfile):
9898
sizeof_file = len(axxdata)
9999

100100
if axxdata[:16] != GUID:
101-
print("Be careful, GUID is different from AxCrypt's one...")
101+
print("Be careful, GUID is different from AxCrypt's one...", file=sys.stderr)
102102

103103
header_datalen_offset = 16
104104
headertype = b'\x02' # first type encountered
@@ -133,7 +133,7 @@ def parse_axxfile(axxfile):
133133
header_datalen_offset += header_datalen
134134

135135
if header_datalen_offset >= sizeof_file:
136-
print("Could not parse file, exiting...")
136+
print("Could not parse file, exiting...", file=sys.stderr)
137137
sys.exit(0)
138138

139139
return version, StructKeys[0]['KeyData'], StructKeys[0]['salt'], StructKeys[0]['Iteration'], None, None

run/bestcrypt2john.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def process_file(filename):
187187
N = DATA_BLOCK_64_size
188188
data = f.read(N)
189189
if len(data) != N:
190-
sys.stdout.write("%s : parsing failed\n" % filename)
190+
sys.stderr.write("%s : parsing failed\n" % filename)
191191
return -1
192192

193193
data = struct.unpack(DATA_BLOCK_64_fmt, data)
@@ -200,7 +200,7 @@ def process_file(filename):
200200
# libs/multi-lib/keygens/kgghost/datablock.cpp -> DataBlock_DecodeKey
201201
# libs/multi-lib/keygens/kgghost/datablock.cpp -> walkNotEncrypted
202202
if signature != DB_HEADER_SIGNATURE or volumeLabel != b"BC_KeyGenID":
203-
print("%s: encrypted header found, not yet supported, patches welcome!" % os.path.basename(filename))
203+
print("%s: encrypted header found, not yet supported, patches welcome!" % os.path.basename(filename), file=sys.stderr)
204204
# look at libs/multi-lib/keygens/kgghost/datablock.cpp -> DataBlock_DecodeKey
205205
return
206206

@@ -211,20 +211,20 @@ def process_file(filename):
211211
else:
212212
resolved_version = iterations # union of iterations and version
213213
if (resolved_version != 3) or wKeyGenId != kKGID:
214-
print("Invalid header version %s, id %s" % (resolved_version, wKeyGenId))
214+
print("Invalid header version %s, id %s" % (resolved_version, wKeyGenId), file=sys.stderr)
215215
return
216216

217217
if alg_id != bcsaRIJN:
218-
print("%s: cipher alg_id %s not supported, patches welcome!" % (os.path.basename(filename), alg_id))
218+
print("%s: cipher alg_id %s not supported, patches welcome!" % (os.path.basename(filename), alg_id), file=sys.stderr)
219219
return
220220

221221
if mode_id != kBCMode_CBC and mode_id != kBCMode_XTS:
222-
print("%s: cipher mode_id %s not supported, patches welcome!" % (os.path.basename(filename), hex(mode_id)))
222+
print("%s: cipher mode_id %s not supported, patches welcome!" % (os.path.basename(filename), hex(mode_id)), file=sys.stderr)
223223
return
224224

225225
# handle hash_id and salt
226226
if hash_id != bchaWhirlpool512 and hash_id != bchaSHA256 and hash_id != pgphaSHA512:
227-
print("%s: hash_id %s not supported, patches welcome!" % (os.path.basename(filename), hash_id))
227+
print("%s: hash_id %s not supported, patches welcome!" % (os.path.basename(filename), hash_id), file=sys.stderr)
228228
return 0
229229
salt_size = -1
230230
if hash_id == bchaWhirlpool512:
@@ -236,7 +236,7 @@ def process_file(filename):
236236
salt = hexlify(keys[0:salt_size]).decode("ascii") # this uses data from keys corresponding to slotnum = 0
237237
size, _type, param = struct.unpack(keymap_fmt, keymap[:keymap_size]) # this uses data from keymap with slotnum = 0
238238
if _type != kBCKeyType_Salt:
239-
print("%s: internal error while processing salt, please report this problem!" % os.path.basename(filename))
239+
print("%s: internal error while processing salt, please report this problem!" % os.path.basename(filename), file=sys.stderr)
240240
return
241241

242242
dbsize = kBCV8_InitialDataBlockSize

run/bitlocker2john.py

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -60,29 +60,29 @@ def uint_to_int(b):
6060
def try_read_fp(fp, bytes_to_read):
6161
out = fp.read(bytes_to_read)
6262
if len(out) != bytes_to_read:
63-
print("Error reading out of bounds of file, exiting.")
63+
print("Error reading out of bounds of file, exiting.", file=sys.stderr)
6464
sys.exit(1)
6565

6666
return out
6767

6868
def parse_FVEK(fvek_data):
69-
print("\nParsing FVEK...")
69+
print("\nParsing FVEK...", file=sys.stderr)
7070
nonce = fvek_data[:12]
7171
mac = fvek_data[12:28]
7272
enc_data = fvek_data[28:]
7373

74-
print("Mac:", mac.hex())
75-
print("Nonce:", nonce.hex())
76-
print("Encrypted data:", enc_data.hex())
74+
print("Mac:", mac.hex(), file=sys.stderr)
75+
print("Nonce:", nonce.hex(), file=sys.stderr)
76+
print("Encrypted data:", enc_data.hex(), file=sys.stderr)
7777

7878
return nonce, mac, enc_data
7979

8080
def parse_stretch_key(data):
81-
print("\nParsing stretch key...")
81+
print("\nParsing stretch key...", file=sys.stderr)
8282
encryption_method = hex(uint_to_int(data[0:4]))
8383
salt = data[4:20]
84-
print("Encryption method:", encryption_method)
85-
print("Salt:", salt.hex())
84+
print("Encryption method:", encryption_method, file=sys.stderr)
85+
print("Salt:", salt.hex(), file=sys.stderr)
8686
current_pos = 0
8787
aes_ccm_data = data[20:]
8888
current_pos, data, value_type = parse_fve_metadata_entry(current_pos, aes_ccm_data)
@@ -91,7 +91,7 @@ def parse_stretch_key(data):
9191
return salt, nonce, mac, enc_data
9292

9393
def generate_hash(salt, nonce, mac, enc_data, protection_type):
94-
print("\nFound hash!")
94+
print("\nFound hash!", file=sys.stderr)
9595
if protection_type == 0x2000:
9696
versions = BITLOCKER_PASSWORD_HASH_VERSIONS
9797
if protection_type == 0x800:
@@ -102,29 +102,29 @@ def generate_hash(salt, nonce, mac, enc_data, protection_type):
102102
HASHES.append(generated_hash)
103103

104104
def parse_aes_ccm_encrypted_key(data):
105-
print("Parsing AES CCM key...")
105+
print("Parsing AES CCM key...", file=sys.stderr)
106106
nonce, mac, enc_data = parse_FVEK(data)
107107
return nonce, mac, enc_data
108108

109109
def parse_description(data):
110-
print("\nParsing description...")
111-
print(f"Info: {data.decode('utf-16')}")
110+
print("\nParsing description...", file=sys.stderr)
111+
print(f"Info: {data.decode('utf-16')}", file=sys.stderr)
112112
return
113113

114114
def parse_volume_header_block(data):
115-
print("\nParsing volume header block...")
115+
print("\nParsing volume header block...", file=sys.stderr)
116116
block_offset = uint_to_int(data[0:8])
117117
block_size = uint_to_int(data[8:16])
118-
print(f"Block offset: {hex(block_offset)}")
119-
print(f"Block size: {block_size}")
118+
print(f"Block offset: {hex(block_offset)}", file=sys.stderr)
119+
print(f"Block size: {block_size}", file=sys.stderr)
120120

121121
def parse_VMK(VMK_data):
122-
print("\nParsing VMK...")
122+
print("\nParsing VMK...", file=sys.stderr)
123123
guid = hex_to_guid(VMK_data[:16].hex())
124124
protection_type = uint_to_int(VMK_data[26:28])
125125
properties = VMK_data[28:]
126-
print("GUID:", guid)
127-
print(f"Protection type: {hex(protection_type)} = {PROTECTION_TYPES.get(protection_type)}")
126+
print("GUID:", guid, file=sys.stderr)
127+
print(f"Protection type: {hex(protection_type)} = {PROTECTION_TYPES.get(protection_type)}", file=sys.stderr)
128128

129129
# only try parse properties if correct protection type
130130
protection_type_str = PROTECTION_TYPES.get(protection_type)
@@ -143,7 +143,7 @@ def parse_VMK(VMK_data):
143143
return
144144

145145
def parse_fve_metadata_block(block):
146-
print('\nParsing FVE block...')
146+
print('\nParsing FVE block...', file=sys.stderr)
147147
metadata_size = len(block)
148148

149149
entry_size = uint_to_int(block[112:114])
@@ -166,16 +166,16 @@ def parse_fve_metadata_block(block):
166166
return
167167

168168
def parse_fve_metadata_entry(current_pos, block):
169-
print("\nParsing FVE metadata entry...")
169+
print("\nParsing FVE metadata entry...", file=sys.stderr)
170170
entry_size = uint_to_int(block[0:2])
171171
entry_type = uint_to_int(block[2:4])
172172
value_type = uint_to_int(block[4:6])
173173
version = hex(uint_to_int(block[6:8]))
174174
data = block[8:entry_size]
175175

176-
print(f"Entry size: {entry_size}")
177-
print(f"Entry type: {hex(entry_type)} = {FVE_ENTRY_TYPES.get(entry_type)}")
178-
print(f"Value type: {hex(value_type)} = {FVE_VALUE_TYPES.get(value_type)}")
176+
print(f"Entry size: {entry_size}", file=sys.stderr)
177+
print(f"Entry type: {hex(entry_type)} = {FVE_ENTRY_TYPES.get(entry_type)}", file=sys.stderr)
178+
print(f"Value type: {hex(value_type)} = {FVE_VALUE_TYPES.get(value_type)}", file=sys.stderr)
179179

180180
current_pos = current_pos + entry_size
181181

@@ -189,15 +189,15 @@ def parse_fve_metadata_header_data(header_data):
189189
return metadata_size
190190

191191
def parse_fve_metadata_header(block):
192-
print("\nParsing FVE metadata header...")
192+
print("\nParsing FVE metadata header...", file=sys.stderr)
193193
metadata_size = uint_to_int(block[0:4])
194194
volume_guid = hex_to_guid(block[16:32].hex())
195195
nonce_counter = uint_to_int(block[32:36])
196196
encryption_method = hex(uint_to_int(block[36:40]))
197197

198-
print("Metadata size:", metadata_size)
199-
print("Volume GUID:", volume_guid)
200-
print("Encryption method:", encryption_method)
198+
print("Metadata size:", metadata_size, file=sys.stderr)
199+
print("Volume GUID:", volume_guid, file=sys.stderr)
200+
print("Encryption method:", encryption_method, file=sys.stderr)
201201

202202
return metadata_size
203203

@@ -222,9 +222,9 @@ def main():
222222

223223
header = try_read_fp(fp, 8)
224224
if header.decode('latin-1') not in [BITLOCKER_SIGNATURE, BITLOCKER_TO_GO_SIGNATURE]:
225-
print("[!] Supplied image path is not a BitLocker partition. Try specifiying the offset of the BitLocker partition with -o")
225+
print("[!] Supplied image path is not a BitLocker partition. Try specifiying the offset of the BitLocker partition with -o", file=sys.stderr)
226226
exit()
227-
print(f'[+] BitLocker signature found: {header.decode()}')
227+
print(f'[+] BitLocker signature found: {header.decode()}', file=sys.stderr)
228228
sector_size = uint_to_int(try_read_fp(fp, 2))
229229

230230
if header.decode('latin-1') == BITLOCKER_SIGNATURE:
@@ -237,13 +237,13 @@ def main():
237237
volume_guid = hex_to_guid(volume_guid.hex())
238238
volume_guid_id = BITLOCKER_GUIDS.get(volume_guid)
239239
if volume_guid_id == None:
240-
print("[!] Volume GUID not recognised. Exiting.")
240+
print("[!] Volume GUID not recognised. Exiting.", file=sys.stderr)
241241
sys.exit(1)
242-
print(f'[+] Identified volume GUID: {volume_guid} = {volume_guid_id}')
242+
print(f'[+] Identified volume GUID: {volume_guid} = {volume_guid_id}', file=sys.stderr)
243243

244244
# get FVE metadata block addresses
245245
FVE_metadata_offsets = [hex(uint_to_int(try_read_fp(fp, 8)) + bitlocker_offset) for _ in range(3)]
246-
print(f'[+] FVE metadata info found at offsets {FVE_metadata_offsets}')
246+
print(f'[+] FVE metadata info found at offsets {FVE_metadata_offsets}', file=sys.stderr)
247247

248248
# all metadata blocks should be the same
249249
for f in FVE_metadata_offsets:
@@ -259,9 +259,10 @@ def main():
259259
break
260260

261261
if HASHES == []:
262-
print("\nNo hashes associated with the user password or recovery password found. Exiting...")
262+
print("\nNo hashes associated with the user password or recovery password found. Exiting...", file=sys.stderr)
263263
else:
264-
print("\nThe following hashes were found:")
264+
if sys.stdout.isatty():
265+
print("\nThe following hashes were found:")
265266
for bitlocker_hash in HASHES:
266267
print(bitlocker_hash)
267268

run/ccache2john.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,8 +745,8 @@ def swap32(i):
745745

746746
if __name__ == "__main__":
747747
if len(sys.argv) < 2:
748-
print("Usage: {0} <input credential cache file>".format(sys.argv[0]))
749-
print("\nExample: {0} /tmp/krb5cc_1000".format(sys.argv[0]))
748+
print("Usage: {0} <input credential cache file>".format(sys.argv[0]), file=sys.stderr)
749+
print("\nExample: {0} /tmp/krb5cc_1000".format(sys.argv[0]), file=sys.stderr)
750750
sys.exit(0)
751751

752752
with open(sys.argv[1], 'rb') as f:
@@ -885,5 +885,5 @@ def swap32(i):
885885
o.write(credential.tostring())
886886
sys.exit(0)
887887
else:
888-
print('Unknown File Type!')
888+
print('Unknown File Type!', file=sys.stderr)
889889
sys.exit(0)

0 commit comments

Comments
 (0)