Repository navigation
Expand file tree
/
Copy pathpingscan.py
More file actions
106 lines (83 loc) · 2.81 KB
/
Copy pathpingscan.py
File metadata and controls
106 lines (83 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#! /usr/bin/env python3
import socket
import argparse
import ipaddress
import random
import struct
import time
import select
ICMP_ECHO_REQUEST = 8
ICMP_CODE = socket.getprotobyname("icmp")
def ones_comp_add16_list(list):
s = 0
for byte in list:
c = 0
s = byte + s
c += s >> 16
s = (s & 0xffff) + c
return s
def checksum(data):
"""Generates checksum for ICMP packet"""
# reference: https://tools.ietf.org/html/rfc1071
if len(data) % 2:
data += (0).to_bytes(1, byteorder="big", signed=False)
d = []
for i in range(0, len(data), 2):
n = (data[i:i+2])
d.append((n[1] << 8) + n[0]) # Swap bytes
s = ones_comp_add16_list(d).to_bytes(2, byteorder="big", signed=False)
# Swap bytes back
sum = (s[1] << 8) + s[0]
sum = sum
# Not sure why this needs to be XOR'd
return (sum ^ 0xffff)
def receive_ping(sock, packet_id, time_sent, timeout):
while True:
ready = select.select([sock], [], [], timeout)
if ready[0] == []:
return None
packet, addr = sock.recvfrom(1024)
icmp_header = packet[20:28]
type, code, checksum, p_id, sequence = struct.unpack(
'bbHHh', icmp_header)
if p_id == packet_id:
return time.time()
return None
def create_packet(id):
"""Create new ICMP echo packet with the given ID"""
header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, socket.htons(1))
data = ('A'*8).encode()
cksum = checksum(header + data)
header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(cksum), id, socket.htons(1))
return header + data
def icmp_scan_host(host):
"""ICMP scan a given host"""
dest_addr = host.exploded
print("{}: ".format(dest_addr), end="")
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE)
packet_id = int(random.random() * 65534) # correct?
packet = create_packet(packet_id)
time_sent = time.time()
while packet:
sent = sock.sendto(packet, (dest_addr, 1))
packet = packet[sent:]
time_recv = receive_ping(sock, packet_id, time.time(), 5)
if time_recv:
ms = (time_recv - time_sent) * 1000
print("{0} ms".format(ms))
else:
print("! Timeout")
def icmp_scan_net(net):
""""ICMP scan a given network"""
for host in net.hosts():
#import pdb; pdb.set_trace()
icmp_scan_host(host)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Scan IP addresses with ICMP")
parser.add_argument('--network', type=ipaddress.ip_network, help="Network to scan")
parser.add_argument('--host', type=ipaddress.ip_address, help="Network to scan")
args = parser.parse_args()
if args.host:
icmp_scan_host(args.host)
else:
icmp_scan_net(args.network)