0x01 基础概念
ICMP(Internet control Message Protocal)Internet报文协议,是TCP/IP的一种子协议,属于网络层协议,其目的是用于在IP主机、路由器之间传递控制信息
0x02 程序
程序
# -*- coding:utf-8 -*-
from scapy.all import *
from random import randint
from optparse import OptionParserdef Scan(ip):'''Scan函数通过调用ICMP,将构造好的请求包发送到目的地址,并根据目的地址的应答数据判断目标主机是否存活。存活的IP地址打印出“xx.xx.xx.xx--->Host is up",不存活的主机打印出"xx.xx.xx.xx--->Host is down"::param ip::return:'''ip_id = randint(1,65535)icmp_id = randint(1,65535)icmp_seq = randint(1,65535)packet = IP(dst=ip,ttl=64,id=ip_id)/ICMP(id=icmp_id,seq = icmp_seq)/b'rootkit'result = sr1(packet,timeout=1,verbose=False)if result:for rcv in result:scan_ip = rcv[IP].srcprint(scan_ip+'--->''Host is up')else:pass# print(ip+'---> host is down')def main():parser = OptionParser("usage:%prog -i <target host>")#输出帮助信息parser.add_option("-i",type='string',dest='IP',help='specify target host')#获取IP地址参数options,args = parser.parse_args()print("Scan report for"+options.IP+"\n")#判断是单台主机还是多台主机#IP中存在-,说明是要扫描多台主机if '-' in options.IP:#代码举例:192.168.1.1-120#通过'-'进行分割,把192.168.1.1和120分开#把192.168.1.1通过','进行分割,取最后一个数作为range函数的start,然后把120+1作为range函数的stop#这样循环遍历出需要扫描的IP地址for i in range(int(options.IP.split('-')[0].split('.')[3]),int(options.IP.split('-')[1])+1):Scan(options.IP.split('.')[0]+'.'+options.IP.split('.')[1]+'.'+options.IP.split('.')[2]+'.'+str(i))time.sleep(0.2)else:Scan(options.IP)print("\nScan finished!...\n")if __name__ == '__main__':try:main()except KeyboardInterrupt:print("interrupted by user,killing all threads...")
结果:
0x03 分析
关于optionparser的使用
- 创建parser实例
- 使用add_option添加我们要处理的命令行参数
- 得到解析sys.argv后的options对象,查看用户的输入
from optparse import OptionParserparser = OptionParser(...)parser.add_option(.....)
- OptionParser()不要求一定要传递参数
OptionParser(usage="%prog",version="%prog 1.0",description="hello")#%prog 在这里会自动替换为程序名字#usage 可以打印用法#version 在使用%prog --version的时候输出版本信息#description 描述信息
- add_option添加命令行参数
#action 指示optparser解析参数时候该如何处理。默认是'store',表示将命令行参数值保存options 对象里 。<br>action的值有:store,store_true,store_false,store_const,append,count,callback.
#type 默认是“string",也可以是"int","float"等
#dest 如果没有指定dest参数,将用命令行参数名来对options对象的值进行存取。
#store store可以为store_true和store_false两种形式。用于处理命令行参数后面不带值的情况。如-v,-q等命令行参数。
#default 设置默认值
#help 指定帮助文档
#metavar 提示用户期望参数
- 最后调用parse_args()解析命令行形参
(options, args) = parser.parse_args()可以传递一个参数列表给parse_args(),否则,默认使用命令行参数(sysargv[1:])。
parse_args()返回两个值:options, 这是一个对象(optpars.Values),保存有命令行参数值。只要知道命令行参数名,如file,就可以访问其对应的值:options.file。args,一个由positional arguments组成的列表。
这里要特别注意options和args,options访问值是options.参数名
,args是一个列表
例如:
from optparse import OptionParser
#创建parser实例
parser = OptionParser()
#添加参数
parser.add_option('-s','--server',dest='server',help='server ip_address')
parser.add_option('-P','--port',type='int',dest='port',help='server port')
parser.add_option('-u','--username',dest='username',help='username info')
parser.add_option('-p','--password',dest='password',help='password info')
#获取值
options,args=parser.parse_args()
print(options)
print(args)
#获取特定参数
serv = options.server
user = options.username
print(serv)
print(user)
我们命令行输入:
python test.py -s 192.168.142.145 -P 80 -u name -p 123456 111 22 333
输出结果:
这里重点看懂:
- options获取的是哪些值?就是我们dest值以及参数值,比如
-p 80
,options里的值是'port':80
- args获取的是哪些值?就是除了参数和参数值以外的,这里是
['111', '22', '333']
,这个是列表类型 - 如何获取特定参数值?使用
options.dest值
- 使用OptionParser的三步骤,创建对象—》添加参数----》获取输入值
虽然我们没有添加-h,我们依然可以使用-h获取帮助文档
这里看明白,main函数基本就能看懂了,对于Scan函数,使用的是scapy模块的一些知识,可以这篇文章:
https://blog.csdn.net/qq_41683305/article/details/117436197
main主要用来获取IP地址的,并将IP地址依次传入Scan函数进行就行判断,是否存在该主机
0x04 参看文章
https://www.cnblogs.com/blacksunny/p/5315545.html