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

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

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

# 

# This software is provided under under a slightly modified version 

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

# for more information. 

# 

# Author: Alberto Solino (@agsolino) 

# 

# Description: 

# Mimikatz Interface implementation, based on @gentilkiwi IDL 

# 

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

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

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

# 

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

# They are located at the end of this file.  

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

# There are test cases for them too.  

# 

from __future__ import division 

from __future__ import print_function 

import binascii 

import random 

 

from impacket import nt_errors 

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

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

from impacket.dcerpc.v5.rpcrt import DCERPCException 

from impacket.uuid import uuidtup_to_bin 

from impacket.structure import Structure 

 

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

 

class DCERPCSessionError(DCERPCException): 

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

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

 

def __str__( self ): 

key = self.error_code 

if key in nt_errors.ERROR_MESSAGES: 

error_msg_short = nt_errors.ERROR_MESSAGES[key][0] 

error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] 

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

else: 

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

 

################################################################################ 

# CONSTANTS 

################################################################################ 

CALG_DH_EPHEM = 0x0000aa02 

TPUBLICKEYBLOB = 0x6 

CUR_BLOB_VERSION = 0x2 

ALG_ID = DWORD 

CALG_RC4 = 0x6801 

 

################################################################################ 

# STRUCTURES 

################################################################################ 

class PUBLICKEYSTRUC(Structure): 

structure = ( 

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

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

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

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

) 

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

Structure.__init__(self,data,alignment) 

self['bType'] = TPUBLICKEYBLOB 

self['bVersion'] = CUR_BLOB_VERSION 

self['aiKeyAlg'] = CALG_DH_EPHEM 

 

class DHPUBKEY(Structure): 

structure = ( 

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

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

) 

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

Structure.__init__(self,data,alignment) 

self['magic'] = 0x31484400 

self['bitlen'] = 1024 

 

class PUBLICKEYBLOB(Structure): 

structure = ( 

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

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

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

('y',':'), 

) 

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

Structure.__init__(self,data,alignment) 

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

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

 

class MIMI_HANDLE(NDRSTRUCT): 

structure = ( 

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

) 

def getAlignment(self): 

if self._isNDR64 is True: 

return 8 

else: 

return 4 

 

class BYTE_ARRAY(NDRUniConformantArray): 

item = 'c' 

 

class PBYTE_ARRAY(NDRPOINTER): 

referent = ( 

('Data',BYTE_ARRAY), 

) 

 

class MIMI_PUBLICKEY(NDRSTRUCT): 

structure = ( 

('sessionType',ALG_ID), 

('cbPublicKey',DWORD), 

('pbPublicKey',PBYTE_ARRAY), 

) 

 

class PMIMI_PUBLICKEY(NDRPOINTER): 

referent = ( 

('Data',MIMI_PUBLICKEY), 

) 

 

################################################################################ 

# RPC CALLS 

################################################################################ 

class MimiBind(NDRCALL): 

opnum = 0 

structure = ( 

('clientPublicKey',MIMI_PUBLICKEY), 

) 

 

class MimiBindResponse(NDRCALL): 

structure = ( 

('serverPublicKey',MIMI_PUBLICKEY), 

('phMimi',MIMI_HANDLE), 

('ErrorCode',ULONG), 

) 

 

class MimiUnbind(NDRCALL): 

opnum = 1 

structure = ( 

('phMimi',MIMI_HANDLE), 

) 

 

class MimiUnbindResponse(NDRCALL): 

structure = ( 

('phMimi',MIMI_HANDLE), 

('ErrorCode',ULONG), 

) 

 

class MimiCommand(NDRCALL): 

opnum = 2 

structure = ( 

('phMimi',MIMI_HANDLE), 

('szEncCommand',DWORD), 

('encCommand',PBYTE_ARRAY), 

) 

 

class MimiCommandResponse(NDRCALL): 

structure = ( 

('szEncResult',DWORD), 

('encResult',PBYTE_ARRAY), 

('ErrorCode',ULONG), 

) 

 

 

################################################################################ 

# OPNUMs and their corresponding structures 

################################################################################ 

OPNUMS = { 

0 : (MimiBind, MimiBindResponse), 

1 : (MimiUnbind, MimiUnbindResponse), 

2 : (MimiCommand, MimiCommandResponse), 

} 

 

################################################################################ 

# HELPER FUNCTIONS 

################################################################################ 

 

class MimiDiffeH: 

def __init__(self): 

self.G = 2 

self.P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF 

self.privateKey = random.getrandbits(1024) 

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

 

def genPublicKey(self): 

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

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

if len(tmp) & 1: 

tmp = '0' + tmp 

return binascii.unhexlify(tmp) 

 

def getSharedSecret(self, serverPublicKey): 

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

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

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

if len(tmp) & 1: 

tmp = '0' + tmp 

return binascii.unhexlify(tmp) 

 

 

def hMimiBind(dce, clientPublicKey): 

request = MimiBind() 

request['clientPublicKey'] = clientPublicKey 

return dce.request(request) 

 

def hMimiCommand(dce, phMimi, encCommand): 

request = MimiCommand() 

request['phMimi'] = phMimi 

request['szEncCommand'] = len(encCommand) 

request['encCommand'] = list(encCommand) 

return dce.request(request) 

 

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

from impacket.winregistry import hexdump 

alice = MimiDiffeH() 

alice.G = 5 

alice.P = 23 

alice.privateKey = 6 

 

bob = MimiDiffeH() 

bob.G = 5 

bob.P = 23 

bob.privateKey = 15 

 

print('Alice pubKey') 

hexdump(alice.genPublicKey()) 

print('Bob pubKey') 

hexdump(bob.genPublicKey()) 

 

print('Secret') 

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

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