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# Mimikatz Interface implementation, based on @gentilkiwi IDL 

11# 

12# Best way to learn how to use these calls is to grab the protocol standard 

13# so you understand what the call does, and then read the test case located 

14# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC 

15# 

16# Some calls have helper functions, which makes it even easier to use. 

17# They are located at the end of this file. 

18# Helper functions start with "h"<name of the call>. 

19# There are test cases for them too. 

20# 

21# Author: 

22# Alberto Solino (@agsolino) 

23# 

24from __future__ import division 

25from __future__ import print_function 

26import binascii 

27import random 

28 

29from impacket import nt_errors 

30from impacket.dcerpc.v5.dtypes import DWORD, ULONG 

31from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray 

32from impacket.dcerpc.v5.rpcrt import DCERPCException 

33from impacket.uuid import uuidtup_to_bin 

34from impacket.structure import Structure 

35 

36MSRPC_UUID_MIMIKATZ = uuidtup_to_bin(('17FC11E9-C258-4B8D-8D07-2F4125156244', '1.0')) 

37 

38class DCERPCSessionError(DCERPCException): 

39 def __init__(self, error_string=None, error_code=None, packet=None): 

40 DCERPCException.__init__(self, error_string, error_code, packet) 

41 

42 def __str__( self ): 

43 key = self.error_code 

44 if key in nt_errors.ERROR_MESSAGES: 

45 error_msg_short = nt_errors.ERROR_MESSAGES[key][0] 

46 error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] 

47 return 'Mimikatz SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 

48 else: 

49 return 'Mimikatz SessionError: unknown error code: 0x%x' % self.error_code 

50 

51################################################################################ 

52# CONSTANTS 

53################################################################################ 

54CALG_DH_EPHEM = 0x0000aa02 

55TPUBLICKEYBLOB = 0x6 

56CUR_BLOB_VERSION = 0x2 

57ALG_ID = DWORD 

58CALG_RC4 = 0x6801 

59 

60################################################################################ 

61# STRUCTURES 

62################################################################################ 

63class PUBLICKEYSTRUC(Structure): 

64 structure = ( 

65 ('bType','B=0'), 

66 ('bVersion','B=0'), 

67 ('reserved','<H=0'), 

68 ('aiKeyAlg','<L=0'), 

69 ) 

70 def __init__(self, data = None, alignment = 0): 

71 Structure.__init__(self,data,alignment) 

72 self['bType'] = TPUBLICKEYBLOB 

73 self['bVersion'] = CUR_BLOB_VERSION 

74 self['aiKeyAlg'] = CALG_DH_EPHEM 

75 

76class DHPUBKEY(Structure): 

77 structure = ( 

78 ('magic','<L=0'), 

79 ('bitlen','<L=0'), 

80 ) 

81 def __init__(self, data = None, alignment = 0): 

82 Structure.__init__(self,data,alignment) 

83 self['magic'] = 0x31484400 

84 self['bitlen'] = 1024 

85 

86class PUBLICKEYBLOB(Structure): 

87 structure = ( 

88 ('publickeystruc',':', PUBLICKEYSTRUC), 

89 ('dhpubkey',':', DHPUBKEY), 

90 ('yLen', '_-y','128'), 

91 ('y',':'), 

92 ) 

93 def __init__(self, data = None, alignment = 0): 

94 Structure.__init__(self,data,alignment) 

95 self['publickeystruc'] = PUBLICKEYSTRUC().getData() 

96 self['dhpubkey'] = DHPUBKEY().getData() 

97 

98class MIMI_HANDLE(NDRSTRUCT): 

99 structure = ( 

100 ('Data','20s=""'), 

101 ) 

102 def getAlignment(self): 

103 if self._isNDR64 is True: 

104 return 8 

105 else: 

106 return 4 

107 

108class BYTE_ARRAY(NDRUniConformantArray): 

109 item = 'c' 

110 

111class PBYTE_ARRAY(NDRPOINTER): 

112 referent = ( 

113 ('Data',BYTE_ARRAY), 

114 ) 

115 

116class MIMI_PUBLICKEY(NDRSTRUCT): 

117 structure = ( 

118 ('sessionType',ALG_ID), 

119 ('cbPublicKey',DWORD), 

120 ('pbPublicKey',PBYTE_ARRAY), 

121 ) 

122 

123class PMIMI_PUBLICKEY(NDRPOINTER): 

124 referent = ( 

125 ('Data',MIMI_PUBLICKEY), 

126 ) 

127 

128################################################################################ 

129# RPC CALLS 

130################################################################################ 

131class MimiBind(NDRCALL): 

132 opnum = 0 

133 structure = ( 

134 ('clientPublicKey',MIMI_PUBLICKEY), 

135 ) 

136 

137class MimiBindResponse(NDRCALL): 

138 structure = ( 

139 ('serverPublicKey',MIMI_PUBLICKEY), 

140 ('phMimi',MIMI_HANDLE), 

141 ('ErrorCode',ULONG), 

142 ) 

143 

144class MimiUnbind(NDRCALL): 

145 opnum = 1 

146 structure = ( 

147 ('phMimi',MIMI_HANDLE), 

148 ) 

149 

150class MimiUnbindResponse(NDRCALL): 

151 structure = ( 

152 ('phMimi',MIMI_HANDLE), 

153 ('ErrorCode',ULONG), 

154 ) 

155 

156class MimiCommand(NDRCALL): 

157 opnum = 2 

158 structure = ( 

159 ('phMimi',MIMI_HANDLE), 

160 ('szEncCommand',DWORD), 

161 ('encCommand',PBYTE_ARRAY), 

162 ) 

163 

164class MimiCommandResponse(NDRCALL): 

165 structure = ( 

166 ('szEncResult',DWORD), 

167 ('encResult',PBYTE_ARRAY), 

168 ('ErrorCode',ULONG), 

169 ) 

170 

171 

172################################################################################ 

173# OPNUMs and their corresponding structures 

174################################################################################ 

175OPNUMS = { 

176 0 : (MimiBind, MimiBindResponse), 

177 1 : (MimiUnbind, MimiUnbindResponse), 

178 2 : (MimiCommand, MimiCommandResponse), 

179} 

180 

181################################################################################ 

182# HELPER FUNCTIONS 

183################################################################################ 

184 

185class MimiDiffeH: 

186 def __init__(self): 

187 self.G = 2 

188 self.P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF 

189 self.privateKey = random.getrandbits(1024) 

190 #self.privateKey = int('A'*128, base=16) 

191 

192 def genPublicKey(self): 

193 self.publicKey = pow(self.G, self.privateKey, self.P) 

194 tmp = hex(self.publicKey)[2:].rstrip('L') 

195 if len(tmp) & 1: 

196 tmp = '0' + tmp 

197 return binascii.unhexlify(tmp) 

198 

199 def getSharedSecret(self, serverPublicKey): 

200 pubKey = int(binascii.hexlify(serverPublicKey), base=16) 

201 self.sharedSecret = pow(pubKey, self.privateKey, self.P) 

202 tmp = hex(self.sharedSecret)[2:].rstrip('L') 

203 if len(tmp) & 1: 

204 tmp = '0' + tmp 

205 return binascii.unhexlify(tmp) 

206 

207 

208def hMimiBind(dce, clientPublicKey): 

209 request = MimiBind() 

210 request['clientPublicKey'] = clientPublicKey 

211 return dce.request(request) 

212 

213def hMimiCommand(dce, phMimi, encCommand): 

214 request = MimiCommand() 

215 request['phMimi'] = phMimi 

216 request['szEncCommand'] = len(encCommand) 

217 request['encCommand'] = list(encCommand) 

218 return dce.request(request) 

219 

220if __name__ == '__main__': 220 ↛ 221line 220 didn't jump to line 221, because the condition on line 220 was never true

221 from impacket.winregistry import hexdump 

222 alice = MimiDiffeH() 

223 alice.G = 5 

224 alice.P = 23 

225 alice.privateKey = 6 

226 

227 bob = MimiDiffeH() 

228 bob.G = 5 

229 bob.P = 23 

230 bob.privateKey = 15 

231 

232 print('Alice pubKey') 

233 hexdump(alice.genPublicKey()) 

234 print('Bob pubKey') 

235 hexdump(bob.genPublicKey()) 

236 

237 print('Secret') 

238 hexdump(alice.getSharedSecret(bob.genPublicKey())) 

239 hexdump(bob.getSharedSecret(alice.genPublicKey()))