-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathamplispy.py
179 lines (138 loc) · 5.5 KB
/
amplispy.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env Python2.7
import sys
import argparse
import random
import mechanize
import dns.resolver
from time import sleep
from blessings import Terminal
t = Terminal()
# Input validation, usage
if not len(sys.argv[1:]):
print t.cyan("""
_ _ _ __
/_\ _ __ ___ _ __ | (_) _\_ __ _ _
//_\\\| '_ ` _ \| '_ \| | \ \ |'_ \| | | |
/ _ \ | | | | | |_) | | |\ \ |_) | |_| |
\_/ \_/_| |_| |_| .__/|_|_\__/ .__/ \__, |
|_| |_| |___/
Welcome to AmpliSpy
The purpose of this program is to check a local or remote list of DNS servers
for potential suitability with DNS Amplification attacks.
The program comes with the option to provide your own custom DNS server list
or to fetch one remotely from public-dns.info.
Type -h or --help to display all options.
Example:
amplispy.py -h
amplispy.py -l /tmp/dns_list.txt --url target.com """)
sys.exit(0)
# Handle command line arguments
parser = argparse.ArgumentParser(description=" probe for DNS AMP suitable servers.\n")
group = parser.add_mutually_exclusive_group()
group.add_argument("-l", "--local", help=" select locally saved list of name servers\n")
group.add_argument("-r", "--remote", action="store_true", help="fetch remote list of name servers from public-dns.info\n")
parser.add_argument("-u", "--url", type=str, help=" provide the URL for a domain to test against\n")
args = parser.parse_args()
if not args.url:
print "\n[" + t.red("!") + "]Critical, the '-u' option is mandatory.\n"
sys.exit(1)
# Random user-agent selector
def select_UA():
UAs = ["'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'",
"'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'",
"'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'",
"'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'",
"'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'",
"'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12'",
"'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'",
"'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'",
"'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'",
"'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0'"
]
return random.choice(tuple(UAs))
# Fetch list
def mech_ops():
br = mechanize.Browser()
br.set_handle_robots(False)
br.addheaders = [('user-agent', select_UA()), ('accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')]
try:
response = br.open("http://public-dns.info//nameservers.txt")
except Exception as e:
print "\n[" + t.red("!") + "]Critical, could not open public-dns.info"
print "[" + t.green("+") + "]The following status code was recieved:"
print "\n %s" % (e)
sys.exit(1)
result = response.read()
proc = result.rstrip().split('\n')
return proc
# If args, read list, else fetch
if args.local:
RHOSTS = []
print "\n[" + t.green("+") + "]Reading in list from: " + args.local + "\n"
try:
with open(args.local, "r") as infile:
text = infile.read()
proc = text.rstrip().split('\n')
for line in proc:
RHOSTS.append(line)
except IOError as e:
print "\n[" + t.red("!") + "]Critical. Unable to read list"
print "An IO Error was raised with the following error message: "
print "\n %s" % (e)
else:
RHOSTS = mech_ops()
known_pubs = {"8.8.8.8","8.8.4.4","209.244.0.3","209.244.0.4",
"64.6.64.6","64.6.65.6","84.200.69.80","84.200.70.40","8.26.56.26",
"8.20.247.20","208.67.222.222","208.67.220.220","156.154.70.1",
"156.154.71.1","199.85.126.10","199.85.127.10","81.218.119.11",
"209.88.198.133","195.46.39.39","195.46.39.40","50.116.23.211",
"107.170.95.180","208.76.50.50","208.76.51.51", "216.146.35.35",
"216.146.36.36","37.235.1.174","37.235.1.177","198.101.242.72",
"23.253.163.53","77.88.8.8","77.88.8.1","91.239.100.100",
"74.82.42.42","109.69.8.51"}
R_checked = []
# Validate
def query(address):
dnsserver = address
resolver = dns.resolver.Resolver()
resolver.nameservers = [dnsserver]
try:
answer = resolver.query(args.url, "A")
return True
except dns.resolver.NoNameservers:
return False
except dns.resolver.NoAnswer:
return False
except dns.resolver.NXDOMAIN:
return False
except dns.exception.Timeout:
return False
# Sort
def start(known_pubs):
pub = ""
delay = raw_input("[" + t.magenta("?") + "]Set delay? (default is 0): ")
if delay == "" or delay == "0":
delay = 0
else:
delay = int(delay)
print "\n[" + t.green("+") + "]Potentially suitable for DNS Amplification:\n"
for address in RHOSTS:
if address in known_pubs:
pub = True
else:
pub = False
if not pub:
valid = query(address)
if valid:
print "[" + t.magenta("~") + "] %s " % address
R_checked.append(address)
else:
continue
elif pub:
continue
sleep(delay)
start(known_pubs)
with open("amplispy.log", "w") as outfile:
for item in R_checked:
outfile.write("%s\n" % item)
print "\n[" + t.green("+") + "]Done. Results saved to %s in the current directory" % outfile