anything is possible if you try hard enough
变量
在 Python 中,数据类型有整型,实数,布尔值,字符串,列表,字典,元组,集合。可以使用 type
方法查看变量的类型。
port = 21
banner = "FreeFloat FTP Server"
# 字符串之间可以用“+”号进行拼接,所以 port 要从 int 型转换为 string
print("[+] Checking for " + banner + " on port " + str(port))
portList = [21,22,80,110]
portOpen = True
print(type(port))
print(type(banner))
print(type(portList))
print(type(portOpen))
结果
[+] Checking for FreeFloat FTP Server on port 21
<class 'int'>
<class 'str'>
<class 'list'>
<class 'bool'>
Process finished with exit code 0
字符串
字符串的详细用法请看 python 文档
upper()
方法将字符串中的小写字母转为大写字母,lower()
方法转换字符串中所有大写字母为小写,replace(old,new)
方法把字符串中的old
(旧字符串) 替换成 new
(新字符串),find()
方法检测字符串中是否包含指定的子字符串。
banner = "FreeFloat FTP Server"
print(banner.upper())
print(banner.lower())
print(banner.replace('FreeFloat','Ability'))
'''
# 返回的是字符串第一个字母出现的位置,如果是字符串是单字母,
# 则返回单字母第一次出现的位置;字符串的索引是以 0 开始
'''
print(banner.find('F'))
print(banner.find('FTP'))
结果
FREEFLOAT FTP SERVER
freefloat ftp server
Ability FTP Server
0
10
Process finished with exit code 0
列表
列表可以容纳任何的数据类型,常见的列表内置操作方法如:添加,删除,插入,弹出,获取索引,排序,计数,排序和反转。
portList = []
# 添加
portList.append(21)
portList.append(80)
portList.append(443)
portList.append(25)
print('初始列表:',portList)
# 排序
portList.sort()
print('排序之后的列表:' + str(portList))
# 索引
pos = portList.index(80)
print("[+] There are " + str(pos) + " ports to scan before 80")
# 删除
portList.remove(443)
print('删除443之后的列表:{}'.format(portList))
# 长度
cnt = len(portList)
print("[+] Scanning " + str(cnt) + " Total Ports.")
结果
初始列表: [21, 80, 443, 25]
排序之后的列表:[21, 25, 80, 443]
[+] There are 2 ports to scan before 80
删除443之后的列表:[21, 25, 80]
[+] Scanning 3 Total Ports.
Process finished with exit code 0
字典
字典的元素由键
和值
组成,keys
方法返回字典所有键的列表,items
方法返回字典的元素的一系列列表。
services = {'ftp':20,'ssh':22,'smtp':25,'http':80}
print('键:',services.keys()) # 返回字典所有的键值列表
print('值:',services.items())
# 查看 ftp 是否在该字典的键列表中
if 'ftp' in services.keys():
print('True')
print('ftp' in services.keys())
print('ftp 对应的值:',services['ftp']) #查看 ftp 对应的值
print("[+] Found vuln with FTP on port " + str(services['ftp']))
结果
键: dict_keys(['smtp', 'ftp', 'http', 'ssh'])
值: dict_items([('smtp', 25), ('ftp', 20), ('http', 80), ('ssh', 22)])
True
True
ftp 对应的值: 20
[+] Found vuln with FTP on port 20
Process finished with exit code 0
网络
win10 ftp 配置
套接字(socket)模块提供了一个可以使 python 建立网络连接的库,使用connect
方法连接到 IP 地址和端口,如果连接成功即可通过套接字进行读写,recv(1024)
方法将读取在套接字中返回1024 字节的数据。setdefaulttimeout
方法设置了建立连接的时间,如果在规定时间内还不能连接上对应的主机和端口,则抛出异常。
import socket
socket.setdefaulttimeout(2) #默认建立连接的时间
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定义套接字的类型
host = "192.168.43.7" #连接的主机
port = 21 #连接的端口
message = 'zhutou' #发送的信息
s.connect((host,port)) #建立连接,如果不成功则抛出异常
s.send(message.encode()) #发送信息,以比特流的形式
ans = s.recv(1024) #接收反馈
print(ans.decode())
结果
220 Microsoft FTP Service
Process finished with exit code 0
选择
使用if
语句将当前ftp
服务器对应的版本和已知的易受攻击的ftp
服务器版本比较。
import socket
socket.setdefaulttimeout(2)
s = socket.socket()
host = "192.168.43.7"
port = 21
s.connect((host,port))
banner = s.recv(1024)
banner = banner.decode()
if "FreeFloat Ftp Server (Version 1.00)" in banner:
print("[+] FreeFloat FTP Server is vulnerable")
elif "3Com 3CDaemon FTP Server Version 2.0" in banner:
print ("[+] 3CDaemon FTP Server is vulnerable.")
elif "Ability Server 2.34" in banner:
print ("[+] Ability FTP Server is vulnerable.")
elif "Sami FTP Server 2.0.2" in banner:
print ("[+] Sami FTP Server is vulnerable.")
else:
print ("[-] FTP Server is not vulnerable.")
结果
[-] FTP Server is not vulnerable.
Process finished with exit code 0
异常处理
如果在try
的代码段中等待连接超时(出现错误/异常),则会执行except
代码段,finally
代码段无论有无异常都会执行。strip
方法默认去换行符
import socket
socket.setdefaulttimeout(2)
s = socket.socket()
host = "192.168.43.7"
ports = [21,25]
for port in ports:
print('\nScanning for ' + str(port))
try:
s.connect((host,port))
ans = s.recv(1024)
print('[+] ' + ans.decode().strip())
except Exception as e:
print("[-] Error = " + str(e))
finally:
print('无论如何都会输出的语句')
s.close()
结果
Scanning for 21
[+] 220 Microsoft FTP Service
无论如何都会输出的语句
Scanning for 25
[-] Error = [WinError 10038] 在一个非套接字上尝试了一个操作。
无论如何都会输出的语句
Process finished with exit code 0
函数-v1
下面定义的retBanner()
函数用于接收由端口返回的信息,checkVulns()
函数用于检测端口所使用的服务是否是存在已知有漏洞的一种,main()
函数将分别检测三个IP
对应的端口所使用的服务是否存在已知漏洞。
import socket
def retBanner(ip,port):
try:
socket.setdefaulttimeout(2)
s = socket.socket()
s.connect((ip,port))
banner = s.recv(1024)
banner = banner.decode()
return banner
except:
return
def checkVulns(banner):
if "FreeFloat Ftp Server (Version 1.00)" in banner:
print("[+] FreeFloat FTP Server is vulnerable")
elif "3Com 3CDaemon FTP Server Version 2.0" in banner:
print ("[+] 3CDaemon FTP Server is vulnerable.")
elif "Ability Server 2.34" in banner:
print ("[+] Ability FTP Server is vulnerable.")
elif "Sami FTP Server 2.0.2" in banner:
print ("[+] Sami FTP Server is vulnerable.")
else:
print ("[-] FTP Server is not vulnerable.")
return
def main():
ip1 = '192.168.43.6'
ip2 = '192.168.43.7'
ip3 = '192.168.43.8'
port = 21
banner1 = retBanner(ip1,port)
banner2 = retBanner(ip2,port)
banner3 = retBanner(ip3,port)
banner1 = str(banner1).strip()
banner2 = str(banner2).strip()
banner3 = str(banner3).strip()
if banner1:
print('[+] ' + ip1 + ':' + banner1)
checkVulns(banner1)
if banner2:
print('[+] ' + ip2 + ':' + banner2)
checkVulns(banner2)
if banner3:
print('[+] ' + ip3 + ':' + banner3)
checkVulns(banner3)
if __name__ == '__main__':
main()
结果
[+] 192.168.43.6:None
[-] FTP Server is not vulnerable.
[+] 192.168.43.7:220 Microsoft FTP Service
[-] FTP Server is not vulnerable.
[+] 192.168.43.8:None
[-] FTP Server is not vulnerable.
Process finished with exit code 0
迭代
使用for
循环去遍历多个主机的多个端口。
portList = [21,22,80,443]
for x in range(1,3):
for port in portList:
print("[+] Checking 192.168.43." + str(x) +
': ' + str(port))
结果
[+] Checking 192.168.43.1: 21
[+] Checking 192.168.43.1: 22
[+] Checking 192.168.43.1: 80
[+] Checking 192.168.43.1: 443
[+] Checking 192.168.43.2: 21
[+] Checking 192.168.43.2: 22
[+] Checking 192.168.43.2: 80
[+] Checking 192.168.43.2: 443
Process finished with exit code 0
文件I/O
将上面的函数-v1
的代码进行优化:
将存在漏洞的对应的服务版本信息保存在 vuln_banners.txt 文件中,这样就不需要使用多个 if 语句
使用两个 for 循环遍历 192.168.43.1-9 的 21 和 22 端口
import socket
def retBanner(ip,port):
try:
socket.setdefaulttimeout(2)
s = socket.socket()
s.connect((ip,port))
banner = s.recv(1024)
banner = banner.decode()
return banner
except:
return
def checkVulns(banner):
with open('vuln_banners.txt','r') as f:
lines = f.readlines()
for line in lines:
if line in banner:
print("[+] Server is vulnerable: " + banner.strip())
else:
print("[-] Server is not vulnerable")
def main():
portList = [21,22]
for x in range(1,10):
ip = '192.168.43.' + str(x)
for port in portList:
banner = retBanner(ip,port)
if banner:
print("\n[+] " + ip + ": " + str(port) + '\n'+ '[+] '+ banner.strip())
checkVulns(banner)
if __name__ == '__main__':
main()
结果
[+] 192.168.43.7: 21
[+] 220 Microsoft FTP Service
[-] Server is not vulnerable
[+] 192.168.43.7: 22
[+] SSH-2.0-OpenSSH_for_Windows_7.7
[-] Server is not vulnerable
Process finished with exit code 0
SYS 模块
关于 sys 模块更详细的用法可以参考 python文档
使用sys
模块可以实现将代码中的参数作为命令行参数进行传递,将 python 脚本名称和所有的参数保存在 sys.argv
列表中,其中 sys.argv[0]
代表脚本文件的名称,列表中剩余的元素包含了以下全部的命令行参数。
import sys
if len(sys.argv) == 2:
filename = sys.argv[1]
print("[+] Reading Vulnerabilities From: " + filename)
结果
~$> python 11-SYS模块.py book.txt
[+] Reading Vulnerabilities From: book.txt
OS 模块
os 模块允许程序独立的与操作系统环境,文件系统,用户数据库和权限进行交互,下面验证文件是否存在以及当前用户是否有权限读这个文件。
import sys
import os
if len(sys.argv) == 2:
filename = sys.argv[1]
if not os.path.isfile(filename): #检测文件是否存在当前路径
print('[-] ' + filename + ' does not exit.')
exit(0)
if not os.access(filename,os.R_OK): #检测文件是否可读
print('[-] ' + filename + ' access denied.')
exit(0)
print('[+] Reading Vulnerablities From: ' + filename.strip())
函数-v2
将sys
模块和os
模块结合进函数-v1
代码中。
import socket
import os
import sys
def retBanner(ip,port):
try:
socket.setdefaulttimeout(2)
s = socket.socket()
s.connect((ip,port))
banner = s.recv(1024)
banner = banner.decode()
return banner
except:
return
def checkVulns(banner,filename):
with open(filename,'r') as f:
lines = f.readlines()
for line in lines:
if line in banner:
print('[+] Server is vulnerable: ' + banner.strip())
else:
print('[-] Server is not vulnerable')
def main():
if len(sys.argv) == 2 :
filename = sys.argv[1]
if not os.path.isfile(filename):
print('[-] ' + filename + ' does not exist.')
exit(0)
if not os.access(filename,os.R_OK):
print('[-] ' + filename + ' access denied.')
exit(0)
portList = [21,22]
for x in range(1,10):
ip = '192.168.43.' + str(x)
for port in portList:
banner = retBanner(ip,port)
banner = banner.strip()
if banner:
print('\n[+] ' + ip + ': ' + str(port) + '\n' + '[+] ' + str(banner))
checkVulns(banner,filename)
if __name__ == '__main__':
main()
结果
~$> python 13-函数.py vuln_banners.txt
[+] 192.168.43.7: 21
[+] 220 Microsoft FTP Service
[-] Server is not vulnerable
[+] 192.168.43.7: 22
[+] SSH-2.0-OpenSSH_for_Windows_7.7
[-] Server is not vulnerable
猪头
2020.4.7