-
Notifications
You must be signed in to change notification settings - Fork 61
/
gateway-finder.py
executable file
·159 lines (139 loc) · 6.51 KB
/
gateway-finder.py
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
152
153
154
155
156
157
158
159
#!/usr/bin/env python
# gateway-finder - Tool to identify routers on the local LAN and paths to the Internet
# Copyright (C) 2011 [email protected]
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# This tool may be used for legal purposes only. Users take full responsibility
# for any actions performed using this tool. If these terms are not acceptable to
# you, then do not use this tool.
#
# You are encouraged to send comments, improvements or suggestions to
# me at pentestmonkey at pentestmonkey.net
#
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
import sys
import os
from time import sleep
import signal
from optparse import OptionParser
parser = OptionParser(usage="Usage: %prog [ -I interface ] -i ip -f macs.txt\n\nTries to find a layer-3 gateway to the Internet. Attempts to reach an IP\naddress using ICMP ping and TCP SYN to port 80 via each potential gateway\nin macs.txt (ARP scan to find MACs)")
parser.add_option("-i", "--ip", dest="ip", help="Internet IP to probe")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="Verbose output")
parser.add_option("-I", "--interface", dest="interface", default="eth0", help="Network interface to use")
parser.add_option("-f", "--macfil", dest="macfile", help="File containing MAC addresses")
(options, args) = parser.parse_args()
if not options.macfile:
print "[E] No macs.txt specified. -h for help."
sys.exit(0)
if not options.ip:
print "[E] No target IP specified. -h for help."
sys.exit(0)
version = "1.1"
print "gateway-finder v%s http://pentestmonkey.net/tools/gateway-finder" % version
print
print "[+] Using interface %s (-I to change)" % options.interface
macfh = open(options.macfile, 'r')
lines = map(lambda x: x.rstrip(), macfh.readlines())
macs = []
ipofmac = {}
for line in lines:
m = re.search('([a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2})', line)
if m and m.group(1):
ipofmac[m.group(1).upper()] = "UnknownIP"
m = re.search('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?([a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2})', line)
if m and m.group(1) and m.group(2):
ipofmac[m.group(2).upper()] = m.group(1)
else:
m = re.search('([a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}).*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', line)
if m and m.group(1) and m.group(2):
ipofmac[m.group(1).upper()] = m.group(2)
macs = ipofmac.keys()
print "[+] Found %s MAC addresses in %s" % (len(macs), options.macfile)
if len(macs) == 0:
print "[E] No MAC addresses found in %s" % options.macfile
sys.exit(0)
def handler(signum, frame):
vprint("Child process received signal %s. Exiting." % signum)
sys.exit(0)
def vprint(message):
if options.verbose:
print "[-] %s" % message
signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGINT, handler)
def processreply(p):
# This might error if the packet isn't what we're expecting
try:
if p[IP].proto == 1: # ICMP
if p[ICMP].type == 11 and p[ICMP].code == 0:
if p[IPerror].proto == 1: # response to ICMP packet
seq = p[ICMP][ICMPerror].seq
vprint("Received reply: %s" % p.summary())
print "[+] %s" % packets[seq]['message']
if p[IPerror].proto == 6: # response to TCP packet
seq = p[ICMP][TCPerror].seq
vprint("Received reply: %s" % p.summary())
print "[+] %s" % packets[seq]['message']
else:
seq = p[ICMP].seq
vprint("Received reply: %s" % p.summary())
print "[+] %s" % packets[seq]['message']
if p[IP].proto == 6: # TCP
if p[IP].src == options.ip and p[TCP].sport == 80:
seq = p[TCP].ack - 1 # remote end increments our seq by 1
vprint("Received reply: %s" % p.summary())
print "[+] %s" % packets[seq]['message']
except:
print "[E] Received unexpected packet. Ignoring."
return False
# Build list of packets to send
seq = 0
packets = []
for mac in macs:
# Echo request, TTL=1
packets.append({ 'packet': Ether(dst=mac)/IP(dst=options.ip,ttl=1)/ICMP(seq=seq),'type': 'ping', 'dstip': options.ip, 'dstmac': mac, 'seq': seq, 'message': '%s [%s] appears to route ICMP Ping packets to %s. Received ICMP TTL Exceeded in transit response.' % (mac, ipofmac[mac], options.ip) })
seq = seq + 1
# TCP SYN to port 80, TTL=1
packets.append({ 'packet': Ether(dst=mac)/IP(dst=options.ip,ttl=1)/TCP(seq=seq), 'type': 'tcpsyn', 'dstip': options.ip, 'dstmac': mac, 'seq': seq, 'message': '%s [%s] appears to route TCP packets %s:80. Received ICMP TTL Exceeded in transit response.' % (mac, ipofmac[mac], options.ip) })
seq = seq + 1
# Echo request
packets.append({ 'packet': Ether(dst=mac)/IP(dst=options.ip)/ICMP(seq=seq),'type': 'ping', 'dstip': options.ip, 'dstmac': mac, 'seq': seq, 'message': 'We can ping %s via %s [%s]' % (options.ip, mac, ipofmac[mac]) })
seq = seq + 1
# TCP SYN to port 80
packets.append({ 'packet': Ether(dst=mac)/IP(dst=options.ip)/TCP(seq=seq), 'type': 'tcpsyn', 'dstip': options.ip, 'dstmac': mac, 'seq': seq, 'message': 'We can reach TCP port 80 on %s via %s [%s]' % (options.ip, mac, ipofmac[mac]) })
seq = seq + 1
pid = os.fork()
if pid:
# parent will send packets
sleep(2) # give child time to start sniffer
vprint("Parent processing sending packets...")
for packet in packets:
sendp(packet['packet'], verbose=0)
vprint("Parent finished sending packets")
sleep(2) # give child time to capture last reply
vprint("Parent killing sniffer process")
os.kill(pid, signal.SIGTERM)
vprint("Parent reaping sniffer process")
os.wait()
vprint("Parent exiting")
print "[+] Done"
print
sys.exit(0)
else:
# child will sniff
filter="ip and not arp and ((icmp and icmp[0] = 11 and icmp[1] = 0) or (src host %s and (icmp or (tcp and port 80))))" % options.ip
vprint("Child process sniffing on %s with filter '%s'" % (options.interface, filter))
sniff(iface=options.interface, store = 0, filter=filter, prn=None, lfilter=lambda x: processreply(x))