Python之端口扫描器编写
其实,写个扫描器也挺好玩的,牵涉到了RAW Socket编程,可以尽情地DIY数据包(当然,不符合数据包规则,比如checksum错误就没办法了),收获颇深。其中,我觉得用C语言写更有利于在编写过程中对加深对计算机网络的理解,特别是数据包细节。但是由于效率问题,还有Python真是太好用了(自从用了python,日常再也不想去碰C/C++了,虽然python也写的挺烂的)。话不多说,言归正传。
学习信息安全的自然听说过nmap这种网络扫描神器,其中功能选项多,老少咸宜,不仅能满足网络管理员的日常,还能满足网络安全工程师的渗透测试,这个课程设计程度的扫描器自然不会有那么多功能,主要实现利用TCP和UDP的一些特性的进行IP段主机存活情况以及端口扫描。
基本功能如下:
1.发送udp包,检测一个极少使用的端口,对回传的ICMP包的进行分析,从而判断主机是否存活。
2.利用TCP三次握手,通过是否连接成功,来判定端口是否开放,其中采用了多线程加快了扫描速度。
3.通过RAW Socket的原生编程,对TCP标志位进行人工设置,对回复数据包的标志位进行分析,从而不需要TCP三次握手就可以对端口是否开放进行判定。部分方式如下
i:通过SYN置1,检测回传的数据包的标志位是否为SYN/ACK
ii:通过ACK置1,查看是否回传数据包,且数据包的标志位是否为RST
iii:通过将所有标志位都置0,查看是否回传数据包,且数据包的标志位是否为RST
iv:通过FIN+URG+PSH置1,查看是否回传数据包,且数据包的标志位是否为RST
在编写功能之前,有必要写对IP,ICMP,TCP的包头进行解析,直接看代码:
IP数据包头:
_fields_ = [
("ihl", c_ubyte, 4),
("version", c_ubyte, 4),
("tos", c_ubyte),
("len", c_ushort),
("id", c_ushort),
("offset", c_ushort),
("ttl", c_ubyte),
("protocol_num", c_ubyte),
("sum", c_ushort),
("src", c_ulong),
("dst", c_ulong)
]
ICMP数据包头:
_fields_ = [
("type", c_ubyte),
("code", c_ubyte),
("checksum", c_ushort),
("unused", c_ushort),
("next_hop_mtu", c_ushort)
]
TCP数据包头:
_fields_ = [
("src_port", c_ushort),
("dst_port", c_ushort),
("seq", c_ulong),
("ack_seq", c_ulong),
("offset", c_ubyte),
("flag", c_ubyte),
("windows", c_ushort),
("checksum", c_ushort),
("point", c_ushort),
]
TCP数据包头的 offset,flag 并不是真正的数据包结构,但是由于单字节细节处不好处理,直接写成上文那样了,所有结构非一言两语可以说完的,详情可参考《IP/TCP详解》。
1.先从最简单的TCPconnect多线程端口扫描开始,基于部分防火墙的策略,应该对需要扫描的端口区间进行随机分配算法,来干扰防火墙的判断。当然,由于太懒了,就直接一路扫下去了。具体代码如下:
def portTest(ip,port,num):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
i = 0
while i <num:
try:
myport = i + port
s.connect(( "%s" %ip, myport ))
s.close()
print "%s:%d is open" % (ip,myport)
except BaseException,e:
pass
i = i+1 def TcpConnect(subnet,port,num=1):
Port = int(port)
if num > 8:
for ip in IPNetwork(subnet):
for i in range(0,THREADNUM):
t = threading.Thread(target=portTest, args=(ip,Port+i*num/THREADNUM,num/THREADNUM)) #开了8个线程,
t.start()
else:
for ip in IPNetwork(subnet): #方便对区段进行扫描
portTest(ip,Port,num)
总共开了八个线程,将端口段分成8份进行扫描。通过异常来退出对位打开的端口的连接,但是实际使用中,容易被网络发现,这种方法只能说是最为简单,但是不推荐使用。
2.利用udp进行扫描。
这里需要涉及到RAW socket的编程,《python黑帽》里关于udp扫描的代码写的非常好(其它的代码也写的不错,在里面也学习了很多python的技巧)。基本原理就是通过setsocketopt函数来设置网卡的混杂模式。进行嗅探,直接贴里面的代码:
def udp_sender(subnet,magic_message):
time.sleep(5)
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for ip in IPNetwork(subnet):
try:
sender.sendto(magic_message, ("%s" % ip, 65211)) #对每个ip地址进行发包
except:
pass def ICMPecho(subnet):
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if os.name == "nt": #跨平台必备
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
t = threading.Thread(target=udp_sender, args=(subnet,magic_message)) #线程用于发送数据包
t.start()
try:
while True:
raw_buffer = sniffer.recvfrom(65565)[0] #对收到的数据包进行检测
ip_header = IP(raw_buffer[0:20])
if ip_header.protocol == "ICMP":
offset = ip_header.ihl * 4
buf = raw_buffer[offset:offset+sizeof(ICMP)]
icmp_header = ICMP(buf)
if icmp_header.type == 3 and icmp_header.code == 3:
if IPAddress(ip_header.src_address) in IPNetwork(subnet):
if raw_buffer[len(raw_buffer) - len(magic_message):] == magic_message:
print "Host Up: %s" % ip_header.src_address
except KeyboardInterrupt:
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
3:最好玩的当然是构造数据包,通过自己构造数据包可以做很多非常geek的事情,比如DNS欺骗,ARP欺骗,SYN洪泛等等。先来看看怎么构造标志位。
def createTcpFlag(fin=0,syn=0,rst=0,psh=0,ack=0,urg=0):
tcp_flags = fin + (syn<<1) + (rst<<2) + (psh<<3) + (ack<<4) + (urg<<5)
return tcp_flags
简单的移位操作就可以实现了对符号位的操作了。
再看看怎么创建TCP数据包头。
def create_tcp_header(source_ip, dest_ip, dest_port,tcp_flag):
source = random.randrange(32000,62000,1)
seq = 0
ack_seq = 0
doff = 5
window = socket.htons (8192)
check = 0 #先将数据包的校验位置0
urg_ptr = 0
offset_res = (doff << 4) + 0
tcp_flags = tcp_flag
tcp_header = struct.pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, check, urg_ptr)
#TCP头在进行校验和时,需要有一个伪IP头,基本细节如下
source_address = socket.inet_aton( source_ip )
dest_address = socket.inet_aton( dest_ip )
placeholder = 0
protocol = socket.IPPROTO_TCP
tcp_length = len(tcp_header)
psh = struct.pack('!4s4sBBH', source_address, dest_address, placeholder, protocol, tcp_length);
psh = psh + tcp_header;
tcp_checksum = checksum(psh)
tcp_header = struct.pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, tcp_checksum, urg_ptr)
return tcp_header
IP数据包头部基本如上。可以结合
create_tcp_header()和createTcpFlag()来操作数据包符号位,以实现基本功能3下的功能了。
Python之端口扫描器编写的更多相关文章
- python实现端口扫描器/DoS/DDoS
整理github,梳理下Python小工具.以下是python实现的DoS/DDoS/端口扫描器(github). 一.DoS SYN Flood是当前最流行的DoS(拒绝服务攻击)与DdoS(分布式 ...
- Python开发端口扫描器
首先是最常用的端口扫描器: 虽说有nmap等强大的工具,不过如果由于条件限制无法安装Nmap呢? 我这个脚本写的比较简单,默认扫描1-65535全部的端口 实际的话,可以根据需要自己修改脚本来实现定制 ...
- 再议perl写多线程端口扫描器
再议perl写多线程端口扫描器 http://blog.csdn.net/sx1989827/article/details/4642179 perl写端口多线程扫描器 http://blog.csd ...
- 使用Python编写简单的端口扫描器的实例分享【转】
转自 使用Python编写简单的端口扫描器的实例分享_python_脚本之家 http://www.jb51.net/article/76630.htm -*- coding:utf8 -*- #!/ ...
- Python脚本写端口扫描器(socket,python-nmap)
目录 Socket模块编写 扫描给定主机是否开放了指定的端口 python-nmap模块编写 扫描给定ip或给定网段内指定端口是否开放 一个用python写的简单的端口扫描器,python环境为 3. ...
- Python与Hack之window下运行带参数的Python脚本,实现一个简单的端口扫描器
1.前提是:windows已经配置好Python的环境变量: 2.进入cmd命令行模式: **输入python命令,检测是否环境配置好:显示这样说明配置环境变量没问题 **用cd命令进入Python脚 ...
- 『Python』 多线程 端口扫描器
0x 00 Before Coding 当端口打开时,向端口发送 TCP SYN 请求,会返回一个 ACK 响应: 当端口关闭,返回的是 RST 响应: 0x 01 Coding 可以用 socke ...
- python端口扫描器
吃了个火鸡面后感觉到了怀疑人生!!!!!!!!!妈耶,在也不吃了.思路都给辣没了!!! python端口扫描器代码如下: #-*-coding:utf-8 from socket import * i ...
- python实现FTP弱口令扫描器与简单端口扫描器
python实现FTP弱口令扫描器与简单端口扫描器 目录 FTP弱口令扫描器 简单端口扫描器 参考: https://blog.csdn.net/rebelqsp/article/details/22 ...
随机推荐
- Jmeter编码问题
问题现象:1.利用csv data set config参数化数据后,在beanshell中引用,能正常引用到,但是传给服务器时,还是报手机号格式不对 将jmeter日志级别打成debug(jmete ...
- OpenStack Heat 介绍
Heat 是一个基于模板来编排复合云应用的服务. 它目前支持亚马逊的 CloudFormation 模板格式,也支持 Heat 自有的 Hot 模板格式.模板的使用简化了复杂基础设施,服务和应用的定义 ...
- [Ceres]C++优化库
官网教程: http://ceres-solver.org/nnls_tutorial.html 定义了一个最小二乘法求解器 自动求导的功能
- 课时21:函数:lambda表达式
目录: 一.lambda表达式 二.介绍两个BIF:filter()和map() 三.课时21课后习题及答案 ********************* 一.lambda表达式 *********** ...
- RelativeLayout布局属性
Android RelativeLayout属性 // 相对于给定ID控件 android:layout_above 将该控件的底部置于给定ID的控件之上; android:layout_below ...
- NodeJs01 文件浏览器
ES6常用新语法 前言 是时候学点新的JS了! 为了在学习NodeJs之前,能及时用上语言的新特性,我们打算从一开始先学习一下JavaScript语言的最基本最常用新语法.本课程的内容,是已经假设你有 ...
- Spring Web MVC 笔记
Spring Web MVC 流程 Dispatcher Servlet 这是一个前端分派 Servlet(前端控制器模式),外部所有的请求都会先到达这里,然后由其将请求分派给其他组件进行实际的处理. ...
- select chosen 禁用下拉框某一个option
$("#tbParBudCode option[value='" + budCodeId + "']").attr("disabled", ...
- 【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa
题目描述 有n个点.m条边.和k种商品.第$i$个点可以以$B_{ij}$的价格买入商品$j$,并以$S_{ij}$的价格卖出.任何时候只能持有一个商品.求一个环,使得初始不携带商品时以某种交易方式走 ...
- BZOJ 1208 [HNOI2004]宠物收养所 | SPlay模板题
题目: 洛谷也能评 题解: 记录一下当前树维护是宠物还是人,用Splay维护插入和删除. 对于任何一次询问操作都求一下value的前驱和后继(这里前驱和后继是可以和value相等的),比较哪个差值绝对 ...