2.ICMP+模块探测

IMCP

自己在学习IMCP之前,在网上看了很多文章,发现有一篇文章很适合初学者学习,里面整理很全面,虽然没有涉及到后续代码扫描窗口,但是仍然值得学习:
这里放上师傅的链接:
https://blog.csdn.net/qq_41983709/article/details/102894165

因为上面那篇文章讲述很全面,下面我将概述部分主流内容

IMCP存在的意义:

封装在IP数据报里面,如果传输出现了差错,ICMP就会返回相应的错误类型

IMCP利用的原理:

ICMP协议规定:目的主机必须返回ICMP回送应答消息给源主机。如果源主机在一定时间内收到应答,则认为主机可达。
发送IMCP包的方法就是PING

浅谈IMCP的部分作用:

1.ping:
方便我们查询判断主机端口,这里我们也可以直接在CMD上ping + ip 后面也可以跟上我们的具体的命令类型
2.用过TTL的值判断对方主机类型:
Windows 使用的是与ping 同样的ICMP 回送请求报文。但是,有一点和通常的回送请求不一样。那是,最初将IP 首部的TTL(生存时间)字段设为1 这一点。
路由器每转送一次数据包就将TTL 的值减1。当TTL 变为0 的时候,按规定将丢弃这个数据包。正如这样,与其说TTL 是时间,还不如说TTL 是经过路由器的个数。对于计算机发送出去的数据包,只要它与目标服务器不在同一局域网内,一定会被哪儿的路由器中继。这时如果TTL 的值是1,由于路由器的处理会变为0,则该数据包将会被丢弃,那么我们可以通过返回的TTL值来判断对面是什么操作系统,方便我们进行攻击
下面是常见的TTL值
1、WINDOWS NT/2000 TTL:128
2、WINDOWS 95/98 TTL:32
3、UNIX TTL:255
4、LINUX TTL:64
5、WIN7 TTL:64

先了解用scapy构造数据包:

发现:

这一部分在第一关:SYN_FLOOD的时候遇到过,当时并没有仔细的看如何构造的数据包先来,先来看看上次的报告:
在这里插入图片描述当时并没有注意packet=IPlayer/TCPlayer,以为就是一个固定写法,在这次学习ICMP中,同样在写脚本的时候遇到了,因此,这里小计一下如何用scapy构造数据包。

思考:

首先我们来看一张图:图源网络
在这里插入图片描述这是我们IP数据包的封装过程
好了下面继续思考:
我们都知道IP协议仅仅是实现发送到达目的端口的作用,他不能传递发送信息,只是一个携带的作用。而真正传递信息的是什么?是后面我们使用的TCP、UDP、ICMP等等协议,这些协议里面带的信息,比如TCP里面包含SYN,ACK等等信息,UDP里面包含了UDP数据等等。
其次我们需要知道一个概念:UDP、TCP、ICMP等等协议都是封装在IP数据包的,所以当我们在自己构造包的时候,也要自己手动’封装‘

总结:发包的包格式: 层的协议(参数)/上一层的协议(参数) /要发送的数据 ,比如如下

用scapy构造数据包:

构造TCP数据包:

IP(src='10.96.10.208',dst='10.96.10.209')/TCP(sport=12345,dport=12345)/data
packet=IP(src=src,dst=dst)/TCP()
recv = sr1(IP(dst="220.181.51.53")/TCP(dport=80,flags="S"))

构造ICMP数据包:

 packet= IP(dst="192.168.1.108")/ICMP()

这里面前面的IP()里面的参数我们都有了解,是发送IP和目的IP,而后面的ICMP()或者tcp()这里面的参数就是由我们自己选择
这里需要注意的是:’/‘ 这个符号 不是除,而是表示连接!!!千万不要弄错了

代码实现探测端口:

首先我们由很多种方法去实现端口探测,python里面的socket、request、pwn、scapy等等 方法都可以进行端口探测,这里我例举几种方法,并看看他们的优缺点:

request模块:
import requests

for port in range(1,5000):
    urls='url'+port
    code= requests.get(urls).status_code
    if code ==200:
        print(urls+' 端口存活');

写了一个简易的代码,那么我们说一说这个模块的优缺点:
优点:简单易懂,配上多线程扫描起来很快
缺点:request的请求方式是对HTTP的请求。比如说我们在做CTF比赛,你要扫描服务器端口,这个时候肯定就扫不出来,因为不是一个HTTP请求,当然,request模块对于扫描网站其他目录还是很不错的

PWN模块:
from pwn import *
fo=open("2.txt","w")
for i in range(1000,1005):
    try:
        sh=remote("https://www.baidu.com",i)
        io=sh.recvall()
        fo.write(str(i)+' '+'io'+'\n')
    except:
        continue
fo.close

代码也很简单
优点:依然是简单方便,并且可以扫描无协议的端口
个人感觉很好用,有时候比赛的时候还是蛮方便,这个模块感觉很少人用
缺点:就目前而言能满足我的需求,没有深入去了解过

scapy模块:

下面的代码是从网上,找了一个比较简单的代码,截取下来进行分析,不是我自己写的,我们先来看看。

from scapy.all import * 
from random import randint #调用随机数
import sys  #主要是从外部传进参数
def ping_one(host):#定义函数
    id_ip = randint(1,65535)
    id_ping = randint(1,65535)
    seq_ping = randint(1,65535)#随机使用一个数,当做数据报里面的参数

    packet = IP(dst = host,ttl = 64,id = id_ip)/ICMP(id = id_ping,seq = seq_ping)/b'Hello'
    #构造包,因为ICMP协议是需要IP协议传输的,所以需要先构造IP协议,/b是发送的数据,里面的参数如果不了解的话,可以用packet.show(),查看里面可以修改的参数,运行成功后可以查看。
    result = sr1(packet,timeout = 2,verbose = False)#发送三层数据包,并仅仅只等待接收一个数据包的响应,timeout定义超时的时间,如果超出时间范围就说明该主机不存活或者其他原因没有返回数据包,verbose如果不将该参数定义为False,那么屏幕将会打印一些不相关的字符串,定义为False之后,就可以print自己想看到的字符串
    result.show()
    if result:
        os.exit(1)#接收成功后退出码为1
if __name__ == '__main__':
    ping_one(sys.argv[1]) #实现从程序外部向程序传递参数 sys.argv[1] 也可以改成IP地址,如'192.168.1.1'

从上面的代码和注释,以及我们自己的思考,我们可以得出以下结论:要想ping目标端口,首先我们要构造ICMP数据包,然后发送数据包,然后根据返回信息的type来判断端口是否开放

有了上面的思路,我们再来补充一点基础知识:
问:srp、srp1是什么函数,有什么用:
在这里插入图片描述这是scapy模块里面,srp函数作用:发包并且只返回第一个回复,这里只返回了第一个回复。那么我们有了这个函数就不需要其他的接受消息的函数,方便了很多
自己写了一个简易的扫描:

from scapy.all import *
ip_one='11.22.33.1' ##目标端口自己修改
for port in range(1,5000):
    ip_dst=in_one+port;
    pkt = Ether()/IP(dst=ip_dst)/ICMP(type=8) ## 构造包
    res=srp1(pkt,timeout=2,verbose=False)  ## 设置超时时间
    if res==0:
        print('%s'+ 'is down ',ip_dst)
    else:
        print('%s'+'is open',ip_dst)

代码很简单,就不过多解释了

但是上面是一个非常难看的脚本,难道每次运行的时候都要我们手动去修改参数吗?
所以我们为什么不做成函数体的形式呢?
看看升级之后的代码:


from scapy.all import *
import ipaddress

#ICMP请求,返回响应包
def icmp_requset(ip_dst):
    pkt = Ether()/IP(dst=ip_dst)/ICMP(type=8) #ICMP类型为
    req = srp1(pkt,timeout=2,verbose=False) #timeou:超时时间设置 verbose:设置自带消息反馈
    return req

#判断是否存活
def icmp_scan(ip_dst):
    req = icmp_requset(ip_dst)
    #判断是否响应包是否为空
    if req:
         print('[+]',ip_dst,'    Host is up')
            
def main(network):
    network = list(ipaddress.ip_network(network))

    for ip in network:
        icmp_scan(ip)
    
if __name__ == '__main__':
    main('10.35.68.0/24')

当我学习到这里的时候就有一个疑问了:
问:我们难道不是通过判断ICMP返回信息的type类型来判断端口是否开启的吗?
答:先看看下面的图:
在这里插入图片描述
我们可以很清楚的看见:如果我们ICMP报文送达了,那么服务器则会返回和请求的相同的值,这样一来,我们的相应包就不为空了,自然就可以判断了

思考:我认为ICMP返回的TYPE类型,是方便我们判断是何种错误,到底是服务器端口没开,还是路由器抑源等等,仅仅是拿来判断错误的,如果我们拿type来判断端口开放情况,就有点大材小用了

参考链接:
https://blog.csdn.net/qq_41725312/article/details/89537727
https://blog.csdn.net/qq_40909772/article/details/103427146
https://blog.csdn.net/qq_41983709/article/details/102894165
https://blog.csdn.net/scau_lth/article/details/83903674

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值