Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Impacket - Collection of Python classes for working with network protocols. 

2# 

3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved. 

4# 

5# This software is provided under a slightly modified version 

6# of the Apache Software License. See the accompanying LICENSE file 

7# for more information. 

8# 

9# Description: 

10# RFC 4493 implementation (https://www.ietf.org/rfc/rfc4493.txt) 

11# RFC 4615 implementation (https://www.ietf.org/rfc/rfc4615.txt) 

12# 

13# NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 implementation 

14# (https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108) 

15# 

16# [MS-LSAD] Section 5.1.2 

17# [MS-SAMR] Section 2.2.11.1.1 

18# 

19# Author: 

20# Alberto Solino (@agsolino) 

21# 

22 

23from __future__ import division 

24from __future__ import print_function 

25from impacket import LOG 

26try: 

27 from Cryptodome.Cipher import DES, AES 

28except Exception: 

29 LOG.error("Warning: You don't have any crypto installed. You need pycryptodomex") 

30 LOG.error("See https://pypi.org/project/pycryptodomex/") 

31from struct import pack, unpack 

32from impacket.structure import Structure 

33import hmac, hashlib 

34from six import b 

35 

36def Generate_Subkey(K): 

37 

38# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

39# + Algorithm Generate_Subkey + 

40# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

41# + + 

42# + Input : K (128-bit key) + 

43# + Output : K1 (128-bit first subkey) + 

44# + K2 (128-bit second subkey) + 

45# +-------------------------------------------------------------------+ 

46# + + 

47# + Constants: const_Zero is 0x00000000000000000000000000000000 + 

48# + const_Rb is 0x00000000000000000000000000000087 + 

49# + Variables: L for output of AES-128 applied to 0^128 + 

50# + + 

51# + Step 1. L := AES-128(K, const_Zero); + 

52# + Step 2. if MSB(L) is equal to 0 + 

53# + then K1 := L << 1; + 

54# + else K1 := (L << 1) XOR const_Rb; + 

55# + Step 3. if MSB(K1) is equal to 0 + 

56# + then K2 := K1 << 1; + 

57# + else K2 := (K1 << 1) XOR const_Rb; + 

58# + Step 4. return K1, K2; + 

59# + + 

60# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

61 

62 AES_128 = AES.new(K, AES.MODE_ECB) 

63 

64 L = AES_128.encrypt(bytes(bytearray(16))) 

65 

66 LHigh = unpack('>Q',L[:8])[0] 

67 LLow = unpack('>Q',L[8:])[0] 

68 

69 K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF 

70 K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF 

71 

72 if (LHigh >> 63): 

73 K1Low ^= 0x87 

74 

75 K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF 

76 K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF 

77 

78 if (K1High >> 63): 

79 K2Low ^= 0x87 

80 

81 K1 = bytearray(pack('>QQ', K1High, K1Low)) 

82 K2 = bytearray(pack('>QQ', K2High, K2Low)) 

83 

84 return K1, K2 

85 

86def XOR_128(N1,N2): 

87 

88 J = bytearray() 

89 for i in range(len(N1)): 

90 #J.append(indexbytes(N1,i) ^ indexbytes(N2,i)) 

91 J.append(N1[i] ^ N2[i]) 

92 return J 

93 

94def PAD(N): 

95 padLen = 16-len(N) 

96 return N + b'\x80' + b'\x00'*(padLen-1) 

97 

98def AES_CMAC(K, M, length): 

99 

100# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

101# + Algorithm AES-CMAC + 

102# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

103# + + 

104# + Input : K ( 128-bit key ) + 

105# + : M ( message to be authenticated ) + 

106# + : len ( length of the message in octets ) + 

107# + Output : T ( message authentication code ) + 

108# + + 

109# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

110# + Constants: const_Zero is 0x00000000000000000000000000000000 + 

111# + const_Bsize is 16 + 

112# + + 

113# + Variables: K1, K2 for 128-bit subkeys + 

114# + M_i is the i-th block (i=1..ceil(len/const_Bsize)) + 

115# + M_last is the last block xor-ed with K1 or K2 + 

116# + n for number of blocks to be processed + 

117# + r for number of octets of last block + 

118# + flag for denoting if last block is complete or not + 

119# + + 

120# + Step 1. (K1,K2) := Generate_Subkey(K); + 

121# + Step 2. n := ceil(len/const_Bsize); + 

122# + Step 3. if n = 0 + 

123# + then + 

124# + n := 1; + 

125# + flag := false; + 

126# + else + 

127# + if len mod const_Bsize is 0 + 

128# + then flag := true; + 

129# + else flag := false; + 

130# + + 

131# + Step 4. if flag is true + 

132# + then M_last := M_n XOR K1; + 

133# + else M_last := padding(M_n) XOR K2; + 

134# + Step 5. X := const_Zero; + 

135# + Step 6. for i := 1 to n-1 do + 

136# + begin + 

137# + Y := X XOR M_i; + 

138# + X := AES-128(K,Y); + 

139# + end + 

140# + Y := M_last XOR X; + 

141# + T := AES-128(K,Y); + 

142# + Step 7. return T; + 

143# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

144 

145 const_Bsize = 16 

146 const_Zero = bytearray(16) 

147 

148 AES_128= AES.new(K, AES.MODE_ECB) 

149 M = bytearray(M[:length]) 

150 K1, K2 = Generate_Subkey(K) 

151 n = len(M)//const_Bsize 

152 

153 if n == 0: 

154 n = 1 

155 flag = False 

156 else: 

157 if (length % const_Bsize) == 0: 

158 flag = True 

159 else: 

160 n += 1 

161 flag = False 

162 

163 M_n = M[(n-1)*const_Bsize:] 

164 if flag is True: 

165 M_last = XOR_128(M_n,K1) 

166 else: 

167 M_last = XOR_128(PAD(M_n),K2) 

168 

169 X = const_Zero 

170 for i in range(n-1): 

171 M_i = M[(i)*const_Bsize:][:16] 

172 Y = XOR_128(X, M_i) 

173 X = bytearray(AES_128.encrypt(bytes(Y))) 

174 Y = XOR_128(M_last, X) 

175 T = AES_128.encrypt(bytes(Y)) 

176 

177 return T 

178 

179def AES_CMAC_PRF_128(VK, M, VKlen, Mlen): 

180# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

181# + AES-CMAC-PRF-128 + 

182# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

183# + + 

184# + Input : VK (Variable-length key) + 

185# + : M (Message, i.e., the input data of the PRF) + 

186# + : VKlen (length of VK in octets) + 

187# + : len (length of M in octets) + 

188# + Output : PRV (128-bit Pseudo-Random Variable) + 

189# + + 

190# +-------------------------------------------------------------------+ 

191# + Variable: K (128-bit key for AES-CMAC) + 

192# + + 

193# + Step 1. If VKlen is equal to 16 + 

194# + Step 1a. then + 

195# + K := VK; + 

196# + Step 1b. else + 

197# + K := AES-CMAC(0^128, VK, VKlen); + 

198# + Step 2. PRV := AES-CMAC(K, M, len); + 

199# + return PRV; + 

200# + + 

201# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 

202 if VKlen == 16: 

203 K = VK 

204 else: 

205 K = AES_CMAC(bytes(bytearray(16)), VK, VKlen) 

206 

207 PRV = AES_CMAC(K, M, Mlen) 

208 

209 return PRV 

210 

211def KDF_CounterMode(KI, Label, Context, L): 

212# Implements NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 

213# https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108 

214# Fixed values: 

215# 1. h - The length of the output of the PRF in bits, and 

216# 2. r - The length of the binary representation of the counter i. 

217# Input: KI, Label, Context, and L. 

218# Process: 

219# 1. n := [L/h] 

220# 2. If n > 2r-1, then indicate an error and stop. 

221# 3. result(0):= empty . 

222# 4. For i = 1 to n, do 

223# a. K(i) := PRF (KI, [i]2 || Label || 0x00 || Context || [L]2) 

224# b. result(i) := result(i-1) || K(i). 

225# 5. Return: KO := the leftmost L bits of result(n). 

226 h = 256 

227 r = 32 

228 

229 n = L // h 

230 

231 if n == 0: 231 ↛ 234line 231 didn't jump to line 234, because the condition on line 231 was never false

232 n = 1 

233 

234 if n > (pow(2,r)-1): 234 ↛ 235line 234 didn't jump to line 235, because the condition on line 234 was never true

235 raise Exception("Error computing KDF_CounterMode") 

236 

237 result = b'' 

238 K = b'' 

239 

240 for i in range(1,n+1): 

241 input = pack('>L', i) + Label + b'\x00' + Context + pack('>L',L) 

242 K = hmac.new(KI, input, hashlib.sha256).digest() 

243 result = result + K 

244 

245 return result[:(L//8)] 

246 

247# [MS-LSAD] Section 5.1.2 / 5.1.3 

248class LSA_SECRET_XP(Structure): 

249 structure = ( 

250 ('Length','<L=0'), 

251 ('Version','<L=0'), 

252 ('_Secret','_-Secret', 'self["Length"]'), 

253 ('Secret', ':'), 

254 ) 

255 

256 

257def transformKey(InputKey): 

258 # Section 5.1.3 

259 OutputKey = [] 

260 OutputKey.append( chr(ord(InputKey[0:1]) >> 0x01) ) 

261 OutputKey.append( chr(((ord(InputKey[0:1])&0x01)<<6) | (ord(InputKey[1:2])>>2)) ) 

262 OutputKey.append( chr(((ord(InputKey[1:2])&0x03)<<5) | (ord(InputKey[2:3])>>3)) ) 

263 OutputKey.append( chr(((ord(InputKey[2:3])&0x07)<<4) | (ord(InputKey[3:4])>>4)) ) 

264 OutputKey.append( chr(((ord(InputKey[3:4])&0x0F)<<3) | (ord(InputKey[4:5])>>5)) ) 

265 OutputKey.append( chr(((ord(InputKey[4:5])&0x1F)<<2) | (ord(InputKey[5:6])>>6)) ) 

266 OutputKey.append( chr(((ord(InputKey[5:6])&0x3F)<<1) | (ord(InputKey[6:7])>>7)) ) 

267 OutputKey.append( chr(ord(InputKey[6:7]) & 0x7F) ) 

268 

269 for i in range(8): 

270 OutputKey[i] = chr((ord(OutputKey[i]) << 1) & 0xfe) 

271 

272 return b("".join(OutputKey)) 

273 

274def decryptSecret(key, value): 

275 # [MS-LSAD] Section 5.1.2 

276 plainText = b'' 

277 key0 = key 

278 for i in range(0, len(value), 8): 

279 cipherText = value[:8] 

280 tmpStrKey = key0[:7] 

281 tmpKey = transformKey(tmpStrKey) 

282 Crypt1 = DES.new(tmpKey, DES.MODE_ECB) 

283 plainText += Crypt1.decrypt(cipherText) 

284 key0 = key0[7:] 

285 value = value[8:] 

286 # AdvanceKey 

287 if len(key0) < 7: 

288 key0 = key[len(key0):] 

289 

290 secret = LSA_SECRET_XP(plainText) 

291 return (secret['Secret']) 

292 

293def encryptSecret(key, value): 

294 # [MS-LSAD] Section 5.1.2 

295 cipherText = b'' 

296 key0 = key 

297 value0 = pack('<LL', len(value), 1) + value 

298 for i in range(0, len(value0), 8): 

299 if len(value0) < 8: 

300 value0 = value0 + b'\x00'*(8-len(value0)) 

301 plainText = value0[:8] 

302 tmpStrKey = key0[:7] 

303 print(type(tmpStrKey)) 

304 print(tmpStrKey) 

305 tmpKey = transformKey(tmpStrKey) 

306 Crypt1 = DES.new(tmpKey, DES.MODE_ECB) 

307 cipherText += Crypt1.encrypt(plainText) 

308 key0 = key0[7:] 

309 value0 = value0[8:] 

310 # AdvanceKey 

311 if len(key0) < 7: 

312 key0 = key[len(key0):] 

313 

314 return cipherText 

315 

316def SamDecryptNTLMHash(encryptedHash, key): 

317 # [MS-SAMR] Section 2.2.11.1.1 

318 Block1 = encryptedHash[:8] 

319 Block2 = encryptedHash[8:] 

320 

321 Key1 = key[:7] 

322 Key1 = transformKey(Key1) 

323 Key2 = key[7:14] 

324 Key2 = transformKey(Key2) 

325 

326 Crypt1 = DES.new(Key1, DES.MODE_ECB) 

327 Crypt2 = DES.new(Key2, DES.MODE_ECB) 

328 

329 plain1 = Crypt1.decrypt(Block1) 

330 plain2 = Crypt2.decrypt(Block2) 

331 

332 return plain1 + plain2 

333 

334def SamEncryptNTLMHash(encryptedHash, key): 

335 # [MS-SAMR] Section 2.2.11.1.1 

336 Block1 = encryptedHash[:8] 

337 Block2 = encryptedHash[8:] 

338 

339 Key1 = key[:7] 

340 Key1 = transformKey(Key1) 

341 Key2 = key[7:14] 

342 Key2 = transformKey(Key2) 

343 

344 Crypt1 = DES.new(Key1, DES.MODE_ECB) 

345 Crypt2 = DES.new(Key2, DES.MODE_ECB) 

346 

347 plain1 = Crypt1.encrypt(Block1) 

348 plain2 = Crypt2.encrypt(Block2) 

349 

350 return plain1 + plain2