前言

由于没有学习python编程,web的脚本编写题一直是个空缺,虽然之前简单学习了些python基础,但是毕竟没有实战编写过脚本,理解和更改脚本总感觉有些吃力,正好马上就是国庆假期,赶上三个雨天还真是巧,出去玩就不要想了,在学校学习一下python脚本的编写吧 这篇文章先从一个简单的端口扫描脚本开始,作为初学者,我尽可能将过程写的详细一些

思路

端口扫描脚本的作用说白了就是模拟人工去依次访问65536个端口,想编写出这个脚本还是要参照人工是如何操作的 人工去测试的话,首先我会找到能够连接目标服务器的浏览器,这里在python中的体现就是建立通信

1
2
import socket //socket模块用于计算机通信
client=socket.socket()//形成一个可以和目标端口连接的客户端

这两行代码就模拟了对目标访问前的准备,正好刚学习了java,发现这一部分和java的scanner输入代码比较相似,可以类比理解一下:

1
2
import java.util.Scanner
Scanner sc=new Scanner(System.in);

然后我会在浏览器输入目标域名加端口测试,是否能够连通,连通就代表开放,没有连通就代表不开放

1
2
3
4
client.connect(('www.baidu.com',port)) 
//连接目标端口,将端口设置为变量接受队列的传入便于爆破
print(port)
//连接成功就打印出端口号

由于我们需要测试65536个端口,所以在没有测试完前不能让代码停下来,这里就引入python的异常处理try: except:

1
2
3
4
5
6
7
try: //设置异常处理,没有成功连接则进入except执行
client=socket.socket()
client.connect(('www.baidu.com',port))
print(port)

except:
pass //无操作,继续向下执行

还有一个问题就是这里端口我是用port变量来表示,要想访问65536个端口还需要不断给port传参,这里我们使用python中的队列来实现

1
2
3
q=queue.Queue() //定义一个q队列
for i in range(65536): //共有65536个端口
q.put(i) //将65536个端口循环放入队列

执行后得到了65536个数字的队列q,再使用循环不断将q的值传入port变量就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import socket
import queue//引入队列
def scan(q): //将访问端口代码封装成scan函数,传入队列q
while not q.empty():
port=q.get() //队列不为空就从队列中拿出一个数字传给port
try:
socket.setdefaulttimeout(1) //设置1秒超时
client=socket.socket()
client.connect(('www.baidu.com',port))
print(port)
except:
pass

q=queue.Queue()
for i in range(65536):
q.put(i)

这样一个简单的扫描就做好了,但是作为脚本还要求短时间内快速完成大量重复性任务,所以下面要写入多线程去执行

多线程

多线程,是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。

threading.thread()的简单使用

threading模块是Python里面常用的线程模块 用法:

1
threading.Thread(target``=``xxxx,args``=``(xxxx)).start()

target:线程要执行的方法 args:要传入的参数 在上面我们已经把扫描的代码块封装成scan方法,而传入的参数就是q队列,为了让脚本快一点,这里我把线程设置为10000

1
2
3
for j in range(10000): //创建一万个线程
threading.Thread(target=scan,args=(q,)).start()
//调用Thread方法

这样一个完整的脚本就完成了,这里用这个脚本测试一下百度开放的端口:

完整代码

import socket //socket用于计算机通讯
import threading,queue //调用线程模块和队列模块

def scan(q): //将访问端口代码封装成scan函数,传入队列q
while not q.empty():
port=q.get() //队列不为空就从队列中拿出一个数字传给port
try: //设置异常处理,没有成功连接则进入except执行
socket.setdefaulttimeout(1) //设置1秒超时
client=socket.socket()
//形成一个可以和目标端口连接的客户端
client.connect((‘www.baidu.com',port))
//连接目标端口,将端口设置为变量接受队列的传入便于爆破
print(port) //连接成功即打印出来
except:
pass //无操作,继续向下执行

q=queue.Queue() //定义一个q队列
for i in range(65536): //共有65536个端口
q.put(i) //将65536个端口循环放入队列

for j in range(10000): //创建一万个线程
threading.Thread(target=scan,args=(q,)).start()
//调用Thread方法