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# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

2# 

3# This software is provided under under a slightly modified version 

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

5# for more information. 

6# 

7# Author: Alberto Solino (@agsolino) 

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# 

21from __future__ import division 

22from __future__ import print_function 

23import binascii 

24import random 

25 

26from impacket import nt_errors 

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

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

29from impacket.dcerpc.v5.rpcrt import DCERPCException 

30from impacket.uuid import uuidtup_to_bin 

31from impacket.structure import Structure 

32 

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

34 

35class DCERPCSessionError(DCERPCException): 

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

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

38 

39 def __str__( self ): 

40 key = self.error_code 

41 if key in nt_errors.ERROR_MESSAGES: 

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

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

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

45 else: 

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

47 

48################################################################################ 

49# CONSTANTS 

50################################################################################ 

51CALG_DH_EPHEM = 0x0000aa02 

52TPUBLICKEYBLOB = 0x6 

53CUR_BLOB_VERSION = 0x2 

54ALG_ID = DWORD 

55CALG_RC4 = 0x6801 

56 

57################################################################################ 

58# STRUCTURES 

59################################################################################ 

60class PUBLICKEYSTRUC(Structure): 

61 structure = ( 

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

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

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

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

66 ) 

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

68 Structure.__init__(self,data,alignment) 

69 self['bType'] = TPUBLICKEYBLOB 

70 self['bVersion'] = CUR_BLOB_VERSION 

71 self['aiKeyAlg'] = CALG_DH_EPHEM 

72 

73class DHPUBKEY(Structure): 

74 structure = ( 

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

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

77 ) 

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

79 Structure.__init__(self,data,alignment) 

80 self['magic'] = 0x31484400 

81 self['bitlen'] = 1024 

82 

83class PUBLICKEYBLOB(Structure): 

84 structure = ( 

85 ('publickeystruc',':', PUBLICKEYSTRUC), 

86 ('dhpubkey',':', DHPUBKEY), 

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

88 ('y',':'), 

89 ) 

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

91 Structure.__init__(self,data,alignment) 

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

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

94 

95class MIMI_HANDLE(NDRSTRUCT): 

96 structure = ( 

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

98 ) 

99 def getAlignment(self): 

100 if self._isNDR64 is True: 

101 return 8 

102 else: 

103 return 4 

104 

105class BYTE_ARRAY(NDRUniConformantArray): 

106 item = 'c' 

107 

108class PBYTE_ARRAY(NDRPOINTER): 

109 referent = ( 

110 ('Data',BYTE_ARRAY), 

111 ) 

112 

113class MIMI_PUBLICKEY(NDRSTRUCT): 

114 structure = ( 

115 ('sessionType',ALG_ID), 

116 ('cbPublicKey',DWORD), 

117 ('pbPublicKey',PBYTE_ARRAY), 

118 ) 

119 

120class PMIMI_PUBLICKEY(NDRPOINTER): 

121 referent = ( 

122 ('Data',MIMI_PUBLICKEY), 

123 ) 

124 

125################################################################################ 

126# RPC CALLS 

127################################################################################ 

128class MimiBind(NDRCALL): 

129 opnum = 0 

130 structure = ( 

131 ('clientPublicKey',MIMI_PUBLICKEY), 

132 ) 

133 

134class MimiBindResponse(NDRCALL): 

135 structure = ( 

136 ('serverPublicKey',MIMI_PUBLICKEY), 

137 ('phMimi',MIMI_HANDLE), 

138 ('ErrorCode',ULONG), 

139 ) 

140 

141class MimiUnbind(NDRCALL): 

142 opnum = 1 

143 structure = ( 

144 ('phMimi',MIMI_HANDLE), 

145 ) 

146 

147class MimiUnbindResponse(NDRCALL): 

148 structure = ( 

149 ('phMimi',MIMI_HANDLE), 

150 ('ErrorCode',ULONG), 

151 ) 

152 

153class MimiCommand(NDRCALL): 

154 opnum = 2 

155 structure = ( 

156 ('phMimi',MIMI_HANDLE), 

157 ('szEncCommand',DWORD), 

158 ('encCommand',PBYTE_ARRAY), 

159 ) 

160 

161class MimiCommandResponse(NDRCALL): 

162 structure = ( 

163 ('szEncResult',DWORD), 

164 ('encResult',PBYTE_ARRAY), 

165 ('ErrorCode',ULONG), 

166 ) 

167 

168 

169################################################################################ 

170# OPNUMs and their corresponding structures 

171################################################################################ 

172OPNUMS = { 

173 0 : (MimiBind, MimiBindResponse), 

174 1 : (MimiUnbind, MimiUnbindResponse), 

175 2 : (MimiCommand, MimiCommandResponse), 

176} 

177 

178################################################################################ 

179# HELPER FUNCTIONS 

180################################################################################ 

181 

182class MimiDiffeH: 

183 def __init__(self): 

184 self.G = 2 

185 self.P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF 

186 self.privateKey = random.getrandbits(1024) 

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

188 

189 def genPublicKey(self): 

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

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

192 if len(tmp) & 1: 

193 tmp = '0' + tmp 

194 return binascii.unhexlify(tmp) 

195 

196 def getSharedSecret(self, serverPublicKey): 

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

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

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

200 if len(tmp) & 1: 

201 tmp = '0' + tmp 

202 return binascii.unhexlify(tmp) 

203 

204 

205def hMimiBind(dce, clientPublicKey): 

206 request = MimiBind() 

207 request['clientPublicKey'] = clientPublicKey 

208 return dce.request(request) 

209 

210def hMimiCommand(dce, phMimi, encCommand): 

211 request = MimiCommand() 

212 request['phMimi'] = phMimi 

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

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

215 return dce.request(request) 

216 

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

218 from impacket.winregistry import hexdump 

219 alice = MimiDiffeH() 

220 alice.G = 5 

221 alice.P = 23 

222 alice.privateKey = 6 

223 

224 bob = MimiDiffeH() 

225 bob.G = 5 

226 bob.P = 23 

227 bob.privateKey = 15 

228 

229 print('Alice pubKey') 

230 hexdump(alice.genPublicKey()) 

231 print('Bob pubKey') 

232 hexdump(bob.genPublicKey()) 

233 

234 print('Secret') 

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

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