Revert "run smbv1 scan in runfinger"

This commit is contained in:
lgandx 2022-11-08 09:22:41 -03:00 committed by GitHub
parent 8d25d04f13
commit f39079da77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -32,9 +32,7 @@ parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None)
parser.add_option('-o','--outfile', action="store", help="Output file", dest="OutFilename", metavar="output.txt", default=None)
parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2)
parser.add_option('-s','--smbv1', action='store_true', help="Enable smbv1 scan", dest="Smbv1", default=False)
options, args = parser.parse_args()
@ -46,11 +44,9 @@ if options.TARGET == None and options.Filename == None:
Timeout = options.Timeout
Host = options.TARGET
Filename = options.Filename
Outputfile = None if options.OutFilename==None else open(options.OutFilename,"w")
SMB1 = "True"
SMB2signing = "False"
DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db"
SCAN_SMBV1 = options.Smbv1
class Packet():
fields = OrderedDict([
@ -73,10 +69,10 @@ else:
if not os.path.exists(DB):
cursor = sqlite3.connect(DB)
cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)')
cursor.commit()
cursor.close()
cursor = sqlite3.connect(DB)
cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)')
cursor.commit()
cursor.close()
def StructWithLenPython2or3(endian,data):
#Python2...
@ -103,108 +99,104 @@ def longueur(payload):
return length
def ParseNegotiateSMB2Ans(data):
if data[4:8] == b"\xfeSMB":
return True
else:
return False
if data[4:8] == b"\xfeSMB":
return True
else:
return False
def SMB2SigningMandatory(data):
global SMB2signing
if data[70] == "\x03":
SMB2signing = "True"
else:
SMB2signing = "False"
global SMB2signing
if data[70] == "\x03":
SMB2signing = "True"
else:
SMB2signing = "False"
def WorkstationFingerPrint(data):
return {
b"\x04\x00" :"Windows 95",
b"\x04\x0A" :"Windows 98",
b"\x04\x5A" :"Windows ME",
b"\x05\x00" :"Windows 2000",
b"\x05\x01" :"Windows XP",
b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003",
b"\x06\x00" :"Windows Vista/Server 2008",
b"\x06\x01" :"Windows 7/Server 2008R2",
b"\x06\x02" :"Windows 8/Server 2012",
b"\x06\x03" :"Windows 8.1/Server 2012R2",
b"\x0A\x00" :"Windows 10/Server 2016/2019 (check build)",
}.get(data, 'Other than Microsoft')
return {
b"\x04\x00" :"Windows 95",
b"\x04\x0A" :"Windows 98",
b"\x04\x5A" :"Windows ME",
b"\x05\x00" :"Windows 2000",
b"\x05\x01" :"Windows XP",
b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003",
b"\x06\x00" :"Windows Vista/Server 2008",
b"\x06\x01" :"Windows 7/Server 2008R2",
b"\x06\x02" :"Windows 8/Server 2012",
b"\x06\x03" :"Windows 8.1/Server 2012R2",
b"\x0A\x00" :"Windows 10/Server 2016/2019 (check build)",
}.get(data, 'Other than Microsoft')
def GetOsBuildNumber(data):
ProductBuild = struct.unpack("<h",data)[0]
return ProductBuild
ProductBuild = struct.unpack("<h",data)[0]
return ProductBuild
def SaveRunFingerToDb(result):
for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn', 'SMB1','MSSQL']:
if not k in result:
result[k] = ''
for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn', 'SMB1','MSSQL']:
if not k in result:
result[k] = ''
cursor = sqlite3.connect(DB)
cursor.text_factory = sqlite3.Binary
res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=? AND SMB1=? AND MSSQL=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
(count,) = res.fetchone()
if not count:
cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
cursor.commit()
cursor.close()
cursor = sqlite3.connect(DB)
cursor.text_factory = sqlite3.Binary
res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=? AND SMB1=? AND MSSQL=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
(count,) = res.fetchone()
if not count:
cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
cursor.commit()
cursor.close()
def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Response
data = data.encode('latin-1')
SSPIStart = data.find(b'NTLMSSP')
SSPIString = data[SSPIStart:]
TargetNameLen = struct.unpack('<H',data[SSPIStart+12:SSPIStart+14])[0]
TargetNameOffset = struct.unpack('<L',data[SSPIStart+16:SSPIStart+20])[0]
Domain = SSPIString[TargetNameOffset:TargetNameOffset+TargetNameLen].decode('UTF-16LE')
data = data.encode('latin-1')
SSPIStart = data.find(b'NTLMSSP')
SSPIString = data[SSPIStart:]
TargetNameLen = struct.unpack('<H',data[SSPIStart+12:SSPIStart+14])[0]
TargetNameOffset = struct.unpack('<L',data[SSPIStart+16:SSPIStart+20])[0]
Domain = SSPIString[TargetNameOffset:TargetNameOffset+TargetNameLen].decode('UTF-16LE')
AvPairsLen = struct.unpack('<H',data[SSPIStart+40:SSPIStart+42])[0]
AvPairsOffset = struct.unpack('<L',data[SSPIStart+44:SSPIStart+48])[0]
#AvPairs = SSPIString[AvPairsOffset:AvPairsOffset+AvPairsLen].decode('UTF-16LE')
WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50])
WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52])
Hostname, DomainJoined = DomainGrab((host, 445))
RDP = IsServiceOn((host,3389))
SQL = IsServiceOn((host,1433))
outstr = (f"[SMB2]:['{host}', Os:'{WindowsVers}', Hostname:'{Hostname}' Build:'{str(WindowsBuildVers)}', Domain:'{Domain}', Bootime: '{Bootime}', Signing:'{signing}', RDP:'{RDP}', SMB1:'{SMB1}', MSSQL:'{SQL}']")
print(outstr)
if Outputfile != None:
Outputfile.write(outstr+"\n") # save result in file
SaveRunFingerToDb({
'Protocol': '[SMB2]',
'Host': host,
'Hostname':Hostname,
'WindowsVersion': WindowsVers,
'OsVer': str(WindowsBuildVers),
'DomainJoined': Domain,
'Bootime': Bootime,
'Signing': signing,
'NullSess': 'N/A',
'IsRDPOn':RDP,
'SMB1': SMB1,
'MSSQL': SQL
})
AvPairsLen = struct.unpack('<H',data[SSPIStart+40:SSPIStart+42])[0]
AvPairsOffset = struct.unpack('<L',data[SSPIStart+44:SSPIStart+48])[0]
#AvPairs = SSPIString[AvPairsOffset:AvPairsOffset+AvPairsLen].decode('UTF-16LE')
WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50])
WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52])
DomainGrab((host, 445))
RDP = IsServiceOn((host,3389))
SQL = IsServiceOn((host,1433))
print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}', MSSQL:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, RDP,SMB1, SQL)))
SaveRunFingerToDb({
'Protocol': '[SMB2]',
'Host': host,
'WindowsVersion': WindowsVers,
'OsVer': str(WindowsBuildVers),
'DomainJoined': Domain,
'Bootime': Bootime,
'Signing': signing,
'NullSess': 'N/A',
'IsRDPOn':RDP,
'SMB1': SMB1,
'MSSQL': SQL
})
def GetBootTime(data):
data = data.encode('latin-1')
Filetime = int(struct.unpack('<q',data)[0])
if Filetime == 0: # server may not disclose this info
return 0, "Unknown"
t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
data = data.encode('latin-1')
Filetime = int(struct.unpack('<q',data)[0])
if Filetime == 0: # server may not disclose this info
return 0, "Unknown"
t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
def IsDCVuln(t, host):
if t[0] == 0:
return ("Unknown")
Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date:
return("This system may be vulnerable to MS14-068")
Date = datetime.datetime(2017, 3, 14, 0, 30)
if t[0] < Date:
return("This system may be vulnerable to MS17-010")
return(t[1])
if t[0] == 0:
return ("Unknown")
Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date:
return("This system may be vulnerable to MS14-068")
Date = datetime.datetime(2017, 3, 14, 0, 30)
if t[0] < Date:
return("This system may be vulnerable to MS17-010")
return(t[1])
#####################
@ -248,26 +240,26 @@ def GetHostnameAndDomainName(data):
return "Could not get Hostname.", "Could not get Domain joined"
def DomainGrab(Host):
global SMB1
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout)
try:
s.connect(Host)
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
n = SMBNegoDataLanMan()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
s.close()
if data[8:10] == b'\x72\x00':
return GetHostnameAndDomainName(data)
except IOError as e:
if e.errno == errno.ECONNRESET:
SMB1 = "False"
return False
else:
return False
global SMB1
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout)
try:
s.connect(Host)
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
n = SMBNegoDataLanMan()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
s.close()
if data[8:10] == b'\x72\x00':
return GetHostnameAndDomainName(data)
except IOError as e:
if e.errno == errno.ECONNRESET:
SMB1 = "False"
return False
else:
return False
def SmbFinger(Host):
s = socket(AF_INET, SOCK_STREAM)
@ -336,104 +328,91 @@ def check_smb_null_session(host):
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
if data[8:10] == b'\x75\x00':
h = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),mid="\xc0\x00")
n = SMBTransRAPData()
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
if data[9:13] == b"\x05\x02\x00\xc0":
return ('True', 'True')
return ('True', 'False')
return 'True'
else:
return ('False', 'False')
except Exception as e:
print(f"Test on null session and ms17 fail on {host[0]} Error: {e}", file=sys.stderr)
return 'False'
except Exception:
return False
##################
#SMB2 part:
def ConnectAndChoseSMB(host):
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout)
try:
s.connect(host)
h = SMBHeader(cmd="\x72",flag1="\x00")
n = SMBNego(Data = SMB2NegoData())
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(4096)
except:
return False
if ParseNegotiateSMB2Ans(data):
try:
while True:
s.send(NetworkSendBufferPython2or3(handle(data.decode('latin-1'), host)))
data = s.recv(4096)
if not data:
break
except Exception:
pass
else:
return False
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout)
try:
s.connect(host)
h = SMBHeader(cmd="\x72",flag1="\x00")
n = SMBNego(Data = SMB2NegoData())
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(4096)
except:
return False
if ParseNegotiateSMB2Ans(data):
try:
while True:
s.send(NetworkSendBufferPython2or3(handle(data.decode('latin-1'), host)))
data = s.recv(4096)
if not data:
break
except Exception:
pass
else:
return False
def handle(data, host):
if data[28] == "\x00":
a = SMBv2Head()
a.calculate()
b = SMBv2Negotiate()
b.calculate()
packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0
return buffer0
if data[28] == "\x00":
a = SMBv2Head()
a.calculate()
b = SMBv2Negotiate()
b.calculate()
packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0
return buffer0
if data[28] == "\x01":
global Bootime
SMB2SigningMandatory(data)
Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0])
a = SMBv2Head(SMBv2Command="\x01\x00",CommandSequence= "\x02\x00\x00\x00\x00\x00\x00\x00")
a.calculate()
b = SMBv2Session1()
b.calculate()
packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0
return buffer0
if data[28] == "\x01":
global Bootime
SMB2SigningMandatory(data)
Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0])
a = SMBv2Head(SMBv2Command="\x01\x00",CommandSequence= "\x02\x00\x00\x00\x00\x00\x00\x00")
a.calculate()
b = SMBv2Session1()
b.calculate()
packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0
return buffer0
if data[28] == "\x02":
ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing)
if data[28] == "\x02":
ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing)
##################
def ShowSmallResults(Host):
ConnectAndChoseSMB((Host,445))
if SCAN_SMBV1 and SMB1 == "True":
try:
Hostname, DomainJoined = DomainGrab((Host, 445))
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
NullSess, ms17_10_ready = check_smb_null_session((Host, 445))
RDP = IsServiceOn((Host,3389))
SQL = IsServiceOn((Host,1433))
outstr = f"[SMB1]:['{Host}', Hostname:'{Hostname}', Os:'{OsVer}', Domain:'{DomainJoined}', Null Session: '{NullSess}', Vulnerable to MS17-010: '{ms17_10_ready}', Lanman Client: '{LanManClient}', RDP:'{RDP}', MSSQL:'{SQL}']"
print(outstr)
if Outputfile != None:
Outputfile.write(outstr+"\n") # save result in file
SaveRunFingerToDb({
'Protocol': '[SMB1]',
'Host': Host,
'WindowsVersion':OsVer,
'OsVer': OsVer,
'DomainJoined':DomainJoined,
'Bootime': 'N/A',
'Signing': Signing,
'NullSess': NullSess,
'IsRDPOn':RDP,
'SMB1': 'True',
'MSSQL': SQL
})
except:
return False
if ConnectAndChoseSMB((Host,445)) == False:
try:
Hostname, DomainJoined = DomainGrab((Host, 445))
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
NullSess = check_smb_null_session((Host, 445))
RDP = IsServiceOn((Host,3389))
SQL = IsServiceOn((Host,1433))
print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}', MSSQL:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,RDP, SQL)))
SaveRunFingerToDb({
'Protocol': '[SMB1]',
'Host': Host,
'WindowsVersion':OsVer,
'OsVer': OsVer,
'DomainJoined':DomainJoined,
'Bootime': 'N/A',
'Signing': Signing,
'NullSess': NullSess,
'IsRDPOn':RDP,
'SMB1': 'True',
'MSSQL': SQL
})
except:
return False
def IsServiceOn(Host):
@ -470,7 +449,7 @@ def RunFinger(Host):
proc.get()
else:
ShowSmallResults(Ln)
if Filename == None:
m = re.search("/", str(Host))
if m:
@ -487,6 +466,6 @@ def RunFinger(Host):
proc.get()
else:
ShowSmallResults(Host)
RunFinger(Host)