forked from openwall/john
-
Notifications
You must be signed in to change notification settings - Fork 0
/
adxcsouf2john.py
executable file
·123 lines (100 loc) · 3.71 KB
/
adxcsouf2john.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
# This utility extracts ADXCRYPT password hashes from IBM/Toshiba 4690 OS
# ADXCSOUF.DAT (more well-known, hence the name of the utility) and SHA-1
# hashes from ADXEPW0F.DAT files.
#
# This software is Copyright (c) 2018, Dhiru Kholia <dhiru at openwall.com> and
# it is hereby released to the general public under the following terms:
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted.
#
# Notes,
#
# 1. IBM/Toshiba 4690 v6.3 OS runs fine under VMware ESXi 6.7 (Select "Other
# (64-bit)" as the Guest OS type), which itself is running under KVM using
# nested virtualization.
#
# 2. Boot Linux on the 4690 system and use the following steps to extract the
# ADXCSOUF.DAT and ADXEPW0F.DAT files. The ADXEPW0F.DAT file has the new
# "Enhanced Security" SHA-1 hashes.
#
# $ mkdir mnt/outer
#
# $ mkdir mnt/inner
#
# $ sudo mount /dev/sda3 mnt/outer # change according to your setup
#
# $ sudo mount -o loop mnt/outer/disk_c mnt/inner
#
# # sudo cp mnt/inner/ADX_IDT1/ADXCSOUF.DAT ~
# $ sudo cp mnt/inner/ADX_SDT1/ADXEPW0F.DAT ~
import re
import os
import sys
import math
import binascii
PY3 = sys.version_info[0] == 3
# Borrowed from https://stackoverflow.com/ (How do I compute the approximate entropy of a bit string?)
def entropy(string):
"Calculates the Shannon entropy of a string"
# get probability of chars in string
prob = [ float(string.count(c)) / len(string) for c in dict.fromkeys(list(string)) ]
# calculate the entropy
entropy = - sum([ p * math.log(p) / math.log(2.0) for p in prob ])
return entropy
def process_other_file(filename):
"""
Parser for ADXEPW0F.DATA files. Based on some heavy guessing.
I am assuming that username appears on a line whose position is aligned to
16 bytes. I am probably biased by looking at ADXEPW0F.DATA using xxd.
"""
data = open(filename, "rb").read()
for pos in range(0, len(data), 16):
line = data[pos:pos+16]
# find "lines" containing usernames
if line.startswith(b"\x20\x20\x20\x20\x20\x20\x20") and line[-1] != 0x20 and line[-1] != 0x00:
idx = line.rfind(b'\x20') + 1
username = line[idx:]
h = data[pos+16:pos+16+20]
# check entropy of the hash
if entropy(h) < 2.5:
continue
h = binascii.hexlify(h)
if PY3:
h = h.decode("ascii")
username = username.decode("ascii")
print("%s:{SHA}%s" % (username, h))
def process_file(filename):
"""
Parser for ADXCSOUF.DAT files. Based on some trial-and-error.
"""
data = open(filename, "rb").read()
# lousy heuristics to detect ADXEPW0F.DAT file
count = 0
length = 2048 if len(data) > 2048 else len(data)
for i in range(0, length):
if data[i] == 0x20 or data[i] == 0x00:
count = count + 1
if count > 128:
return process_other_file(filename)
# find (username hash) pairs
matches = re.findall(b'([a-zA-Z0-9_-]{3,9})\ (\d{8})', data)
for items in matches:
try:
username = items[0]
h = items[1]
except:
pass
if PY3:
username = username.decode("ascii")
h = h.decode("ascii")
sys.stdout.write("%s:$adxcrypt$%s\n" % (username, h))
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.stderr.write("Usage: %s <ADXCSOUF.DAT / ADXEPW0F.DAT file(s)>\n" % sys.argv[0])
sys.exit(1)
# print a pro-tip
sys.stderr.write("Tip: Maxmium password length is 8 on IBM/Toshiba 4690 systems\n\n")
for i in range(1, len(sys.argv)):
process_file(sys.argv[i])