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 ...
随机推荐
- 导出csv用excel打开后数字不用科学计数法显示(0123456显示123456)
从这儿抄过来的: http://zhejiangyinghui.iteye.com/blog/1149526 最近写了一个生成csv的程序,生成的csv其中有一列数字长度为13位,csv中查看没有问题 ...
- STL之priority_queue使用简介
优先队列容器也是一种从一端入队,另一端出对的队列.不同于一般队列的是,队列中最大的元素总是位于队首位置,因此,元素的出对并非按照先进先出的要求,将最先入队的元素出对,而是将当前队列中的最大元素出对. ...
- 2013 ACM/ICPC Asia Regional Changsha Online – C题 Color Representation Conversion (坑爹模拟题)
题意:给你三种颜色表示模式,RGB,HSV和HSL,实现任意模式之间两两转化. 1.最好别看题目中给的转化公式描述,我觉得叙述的一点也不清楚,看维基百科,把维基百科上的公式一句一句翻译过来就好 2.在 ...
- 201621123033 《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 父类 子类 继承 覆盖 抽象 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. 1.3 可选: ...
- 利用反射修改final数据域
当final修饰一个数据域时,意义是声明该数据域是最终的,不可修改的.常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的. 另外还可以构造线程安全(thre ...
- hdu 1535 Invitation Cards (最短路径)
Invitation Cards Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- HDU 6034 Balala Power!(贪心+排序)
Balala Power! Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- vue数组对象修改触发视图更新
直接修改数组元素是无法触发视图更新的,如 this.array[0] = { name: 'meng', age: 22 } 修改array的length也无法触发视图更新,如 this.array. ...
- 【CF edu 27 G. Shortest Path Problem?】
time limit per test 3 seconds memory limit per test 512 megabytes input standard input output standa ...
- 论文笔记《Tracking Using Dynamic Programming for Appearance-Based Sign Language Recognition》
一.概述 这是我在做手势识别的时候,在解决手势画面提取的时候看的一篇paper,这里关键是使用了动态规划来作为跟踪算法,效果是可以比拟cameshift和kf的,但在occlusion,gaps或者离 ...