Python黑帽子 黑客与渗透测试编程之道(六)Windows和Linux上的包嗅探

Windows和Linu的区别是Windows允许我们嗅探所有协议的所有数据包,但Linux只能嗅探到ICMP数据。

因为使用混杂模式,在Windows上要使用管理员权限,在Linux上需要root权限。

在这个例子中,只需要设置原始套接字嗅探器,读取一个数据包,然后退出即可。代码如下:
host里面的主机,可以在Windows上用ipconfig查出来,如果写教材上的IP,会报错。

比如:return getattr(self._sock,name)(*args) socket.error: [Errno 10049] 或者 [Errno 10013]

10013这个,用管理员模式开启就行了。
10049这个,把代码中的IP地址改成自己的IP地址或者127.0.0.1即可

import socket
import os

#coding=utf-8
# host to listen on
host = "192.168.***.***"

# create a raw socket and bind it to the public interface
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))

# we want the IP headers included in the capture
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# if we're on Windows we need to send an IOCTL
# to setup promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# read in a single packet
print sniffer.recvfrom(65565)

# if we're on Windows turn off promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

测试:
1.用管理员打开CMD,运行代码:
此处用的是127.0.0.1的IP (那些代码是在另一个CMD输入之后才出现的,刚开始什么也没有,此处我已经输入完毕)

在这里插入图片描述

打开第二个CMD,输入:
在这里插入图片描述
再看第一个CMD,会有数据回馈。

可以试着改以下IP地址试试,就是用本机IP地址,数据有点不同。
感觉这个书上不说清楚,查半天错误。。真滴脑阔痛

解码IP层

解码数据包中的IP头的部分,提取诸如协议类型(TCP,UDP和ICMP),源地址和目的地址等有用信息。
创建sniffer_ip_header_decode.py 如下:

import socket

import os
import struct
from ctypes import *

host = "192.168.233.131"

class IP(Structure):
    _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)
    ]
    
    def __new__(self, socket_buffer=None):
        return self.from_buffer_copy(socket_buffer)
    
    def __init__(self, socket_buffer=None):
        self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}
        
        self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
        self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
        
        # type of protocol
        try:
            self.protocol = self.protocol_map[self.protocol_num]
        except:
            self.protocol = str(self.protocol_num)
            
    
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)
    
    
try:
    
    while True:
        
        # read data
        raw_buffer = sniffer.recvfrom(65565)[0]
        
        ip_header = IP(raw_buffer[0:20])
        
        print "Protocl: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)
        
except KeyboardInterrupt:
    if os.name == "nt":
        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
      

主机地址修改一下,然后分别在Windows和Linux上运行:
window:

在这里插入图片描述
然后打开浏览器,随便输入一个网站,将在原来的CMD里看到输出:
在这里插入图片描述

在Linux上:
在这里插入图片描述
在这里插入图片描述

Linux上只输出了ICMP的头部解析

解析ICMP

在以上的代码上添加一些代码为sniffer_with_icmp.py,用于解析ICMP报文。输出类型,可通过此知道连接状态。

import socket

import os
import struct
from ctypes import *

host = "192.168.233.131"

class ICMP(Structure):
    
    _fields_ = [
        ("type",               c_ubyte),
        ("code",               c_ubyte),
        ("checksum",           c_ushort),
        ("unused",             c_ushort),
        ("next_hop_mtu",       c_ushort)
    ]
    
    def __new__(self, socket_buffer):
        return self.from_buffer_copy(socket_buffer)
    
    def __init__(self, socket_buffer):
        pass
    
    
class IP(Structure):
    _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)
    ]
    
    def __new__(self, socket_buffer=None):
        return self.from_buffer_copy(socket_buffer)
    
    def __init__(self, socket_buffer=None):
        self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}
        
        self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
        self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
        
        # type of protocol
        try:
            self.protocol = self.protocol_map[self.protocol_num]
        except:
            self.protocol = str(self.protocol_num)
            
    
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)

  
    
try:
    
    while True:
        
       # read in a single packet
        raw_buffer = sniffer.recvfrom(65565)[0]
        
        # create an IP header from the first 20 bytes of the buffer
        ip_header = IP(raw_buffer[0:20])
      
        print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)
    
        # if it's ICMP we want it
        if ip_header.protocol == "ICMP":
            
            # calculate where our ICMP packet starts
            offset = ip_header.ihl * 4
            buf = raw_buffer[offset:offset + sizeof(ICMP)]
            
            # create our ICMP structure
            icmp_header = ICMP(buf)
            
            print "ICMP -> Type: %d Code: %d" % (icmp_header.type, icmp_header.code)
        
except KeyboardInterrupt:
    if os.name == "nt":
        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

在Linux上测试:

在这里插入图片描述

在这里插入图片描述

添加netaddr

实现发送UDP数据和获取扫描结果

需要添加netaddr模块,实现对整个子网扫描。在以上代码的基础上修改,保存为scanner.py
首先确认安装了netaddr:在这里插入图片描述

import socket
import threading
import time
from netaddr import IPAddress, IPNetwork

import os
import struct
from ctypes import *

host = "192.168.233.131"

subnet = "192.168.233.0/24"

# to tell the recieced data from icmp 
magic_message = "Welcome to the jungle!"

# send udp
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, 65212))
        except:
            pass
        
        
class ICMP(Structure):
    
    _fields_ = [
        ("type",               c_ubyte),
        ("code",               c_ubyte),
        ("checksum",           c_ushort),
        ("unused",             c_ushort),
        ("next_hop_mtu",       c_ushort)
    ]
    
    def __new__(self, socket_buffer):
        return self.from_buffer_copy(socket_buffer)
    
    def __init__(self, socket_buffer):
        pass
    
    
class IP(Structure):
    _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)
    ]
    
    def __new__(self, socket_buffer=None):
        return self.from_buffer_copy(socket_buffer)
    
    def __init__(self, socket_buffer=None):
        self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}
        
        self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
        self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
        
        # type of protocol
        try:
            self.protocol = self.protocol_map[self.protocol_num]
        except:
            self.protocol = str(self.protocol_num)
            
    
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)

  
# begin to send data
t = threading.Thread(target=udp_sender,args=(subnet,magic_message))
t.start()
    
try:
    
    while True:
        
       # read in a single packet
        raw_buffer = sniffer.recvfrom(65565)[0]
        
        # create an IP header from the first 20 bytes of the buffer
        ip_header = IP(raw_buffer[0:20])
      
      #  print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)
    
        # if it's ICMP we want it
        if ip_header.protocol == "ICMP":
            
            # calculate where our ICMP packet starts
            offset = ip_header.ihl * 4
            buf = raw_buffer[offset:offset + sizeof(ICMP)]
            
            # create our ICMP structure
            icmp_header = ICMP(buf)
            
        #    print "ICMP -> Type: %d Code: %d" % (icmp_header.type, icmp_header.code)
        if icmp_header.code == 3 and icmp_header.type == 3:
                      
            # check to make sure we are receiving the response 
            # that lands in our subnet
            if IPAddress(ip_header.src_address) in IPNetwork(subnet):
                
                # test for our magic message
                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)

修改主机IP和子网地址,测试如下:
在这里插入图片描述
这里我只返回了一条信息。。。也不知道为啥。。先放着。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值