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 ...
随机推荐
- MQ消息中间件
MQ是什么? MQ是Message Queue消息队列的缩写.消息队列是一种应用程序对应用程序的通信方法.应用程序通过写和检索入列队的针对应用程序的数据(消息)来进行通信,而不需要专用连接来链接它们. ...
- ASP.NET Core ---异常处理
一.局部异常处理: 在Action里面catch 二.全局异常处理: 1.默认的异常处理配置: 默认配置在StartUp文件的Configure中注册错误处理,显示开发者错误页面: public vo ...
- Python全栈 MySQL 数据库 (引擎、事物、pymysql模块、orm)
ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 为了梦想为了信仰 开局一张图 存储引擎(处理表的处理器) 基本操作: ...
- Leetcode 668.乘法表中第k小的数
乘法表中第k小的数 几乎每一个人都用 乘法表.但是你能在乘法表中快速找到第k小的数字吗? 给定高度m .宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第k 小的数字. 例 1: 输入 ...
- KindleEditor insertfile初始化多个
KindEditor.ready(function (K) { var editor = K.editor({ allowFileManager: true }); K('#insertfile'). ...
- c#中RadioButtonList选中后不整体刷新页面保持选中状态
c#中用asp的RadioButtonList控件总会遇到选中了,然后跟着就刷新整体页面,又变为没有选中状态. <%@ Page Language="C#" AutoEven ...
- jQuery选择器示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- cd,PATH,alias,man,快捷键
5. cd命令cd 后面不加东西,就是进入到当前用户的家目录cd ~ 这里的~符号也表示用户的家目录cd - 切换到上一次所在的目录cd . .. 其中.表示当前目录, ..表示上一级目录注意区分绝对 ...
- redis各种数据结构使用场景
一.redis 数据结构使用场景 原来看过 redisbook 这本书,对 redis 的基本功能都已经熟悉了,从上周开始看 redis 的源码.目前目标是吃透 redis 的数据结构.我们都知道,在 ...
- nodejs & docker
nodejs & docker https://github.com/xgqfrms-GitHub/Node.js/blob/master/Docker-Nodejs/translation. ...