-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathp44_chapter_03_scanner.py
More file actions
151 lines (115 loc) · 4.67 KB
/
Copy pathp44_chapter_03_scanner.py
File metadata and controls
151 lines (115 loc) · 4.67 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# /usr/bin/python python3
# -*- coding:utf-8 -*-
##################################################
# Filename: p43_chapter_03_scanner.py
# Author: jerry_0824
# Email: 63935127##qq.com
# Phone: +86-155-8287-7999
# Date: 2016-03-07
# Version: v1.0.0
##################################################
import socket
import os
import struct
import threading
from netaddr import IPNetwork,IPAddress
from ctypes import *
# host to listen on
host = "192.168.1.140"
# subnet to target
subnet = "192.168.1.0/24"
# magic we'll check ICMP responses for
magic_message = "PYTHONRULES!"
def udp_sender(subnet,magic_message):
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 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)
("src", c_uint32),
("dst", c_uint32)
]
def __new__(self, socket_buffer=None):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer=None):
# map protocol constants to their names
self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}
# human readable IP addresses
self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
# human readable protocol
try:
self.protocol = self.protocol_map[self.protocol_num]
except:
self.protocol = str(self.protocol_num)
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
# 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 some ioctls
# to setup promiscuous mode
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
# start sending packets
t = threading.Thread(target=udp_sender,args=(subnet,magic_message))
t.start()
try:
while True:
# read in a single packet
raw_buffer = sniffer.recvfrom(65535)[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)
# now check for the TYPE 3 and CODE 3 which indicates
# a host is up but no port available to talk to
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)
# handle CTRL-C
except KeyboardInterrupt:
# if we're on Windows turn off promiscuous mode
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)