-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
unknown
authored and
unknown
committed
Apr 1, 2015
0 parents
commit 2857881
Showing
11 changed files
with
113,257 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# subDomainsBrute | ||
|
||
A simple and fast sub domain brute tool for pentesters | ||
|
||
##Dependencies | ||
First you need install [dnspython](http://www.dnspython.org/kits/1.12.0/) to do DNS query | ||
|
||
## Improvements | ||
* 用小字典递归地发现三级域名,四级域名、五级域名等不容易被探测到的域名 | ||
* 字典较为全面,小字典就包括3万多条,大字典多达8万条 | ||
* 默认使用114DNS、百度DNS、阿里DNS这几个快速又可靠的公共DNS进行查询,可随时修改配置文件添加你认为可靠的DNS服务器 | ||
* 自动筛选泛解析的域名,当前规则是: 超过10个域名指向同一IP,则此后发现的其他指向该IP的域名将被丢弃 | ||
* 整体速度还过得去,在我的PC上,每秒稳定扫描100到200个域名(10个线程) | ||
|
||
##Usage | ||
``` | ||
Usage: subDomainsBrute.py [options] target | ||
Options: | ||
-h, --help show this help message and exit | ||
-t THREADS_NUM, --threads=THREADS_NUM | ||
Number of threads. default = 10 | ||
-f NAMES_FILE, --file=NAMES_FILE | ||
Dict file used to brute sub names | ||
-o OUTPUT, --output=OUTPUT | ||
Output file name. default is {target}.txt | ||
``` | ||
|
||
Output file could be like: [http://www.lijiejie.com/wp-content/uploads/2015/04/baidu.com_.txt](http://www.lijiejie.com/wp-content/uploads/2015/04/baidu.com_.txt) | ||
|
||
my[at]lijiejie.com ([http://www.lijiejie.com](http://www.lijiejie.com)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
114.114.114.114 | ||
114.114.115.115 | ||
180.76.76.76 | ||
223.5.5.5 | ||
223.6.6.6 |
Binary file not shown.
Empty file.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
""" getTerminalSize() | ||
- get width and height of console | ||
- works on linux,os x,windows,cygwin(windows) | ||
""" | ||
|
||
__all__=['getTerminalSize'] | ||
|
||
|
||
def getTerminalSize(): | ||
import platform | ||
current_os = platform.system() | ||
tuple_xy=None | ||
if current_os == 'Windows': | ||
tuple_xy = _getTerminalSize_windows() | ||
if tuple_xy is None: | ||
tuple_xy = _getTerminalSize_tput() | ||
# needed for window's python in cygwin's xterm! | ||
if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'): | ||
tuple_xy = _getTerminalSize_linux() | ||
if tuple_xy is None: | ||
print "default" | ||
tuple_xy = (80, 25) # default value | ||
return tuple_xy | ||
|
||
def _getTerminalSize_windows(): | ||
res=None | ||
try: | ||
from ctypes import windll, create_string_buffer | ||
|
||
# stdin handle is -10 | ||
# stdout handle is -11 | ||
# stderr handle is -12 | ||
|
||
h = windll.kernel32.GetStdHandle(-12) | ||
csbi = create_string_buffer(22) | ||
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) | ||
except: | ||
return None | ||
if res: | ||
import struct | ||
(bufx, bufy, curx, cury, wattr, | ||
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) | ||
sizex = right - left + 1 | ||
sizey = bottom - top + 1 | ||
return sizex, sizey | ||
else: | ||
return None | ||
|
||
def _getTerminalSize_tput(): | ||
# get terminal width | ||
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window | ||
try: | ||
import subprocess | ||
proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE) | ||
output=proc.communicate(input=None) | ||
cols=int(output[0]) | ||
proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE) | ||
output=proc.communicate(input=None) | ||
rows=int(output[0]) | ||
return (cols,rows) | ||
except: | ||
return None | ||
|
||
|
||
def _getTerminalSize_linux(): | ||
def ioctl_GWINSZ(fd): | ||
try: | ||
import fcntl, termios, struct, os | ||
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234')) | ||
except: | ||
return None | ||
return cr | ||
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) | ||
if not cr: | ||
try: | ||
fd = os.open(os.ctermid(), os.O_RDONLY) | ||
cr = ioctl_GWINSZ(fd) | ||
os.close(fd) | ||
except: | ||
pass | ||
if not cr: | ||
try: | ||
cr = (env['LINES'], env['COLUMNS']) | ||
except: | ||
return None | ||
return int(cr[1]), int(cr[0]) | ||
|
||
if __name__ == "__main__": | ||
sizex,sizey=getTerminalSize() | ||
print 'width =',sizex,'height =',sizey |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
test | ||
test2 | ||
t | ||
dev | ||
1 | ||
2 | ||
3 | ||
s1 | ||
s2 | ||
s3 | ||
admin | ||
adm | ||
a | ||
ht | ||
adminht | ||
webht | ||
web | ||
gm | ||
sys | ||
system | ||
manage | ||
manager | ||
mgr | ||
b | ||
c | ||
passport | ||
bata | ||
wei | ||
weixin | ||
wx | ||
wiki | ||
upload | ||
ftp | ||
pic | ||
jira | ||
zabbix | ||
nagios | ||
bug | ||
bugzilla | ||
sql | ||
mysql | ||
db | ||
stmp | ||
pop | ||
imap | ||
zimbra | ||
exchange | ||
forum | ||
bbs | ||
list | ||
count | ||
counter | ||
img | ||
img01 | ||
img02 | ||
img03 | ||
img04 | ||
api | ||
cache | ||
js | ||
css | ||
app | ||
apps | ||
wap | ||
m | ||
sms | ||
zip | ||
monitor | ||
proxy | ||
proxy1 | ||
proxy2 | ||
update | ||
upgrade | ||
stat | ||
data | ||
portal | ||
blog | ||
autodiscover | ||
en | ||
search | ||
so | ||
oa | ||
database | ||
home | ||
sso | ||
help | ||
vip | ||
s | ||
w | ||
down | ||
download | ||
downloads | ||
dl | ||
svn | ||
git | ||
log | ||
staff | ||
vpn | ||
ssl-vpn | ||
sslvpn | ||
ssh | ||
scanner | ||
sandbox | ||
ldap | ||
lab | ||
go | ||
demo | ||
console | ||
cms | ||
auth | ||
crm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#!/usr/bin/env python | ||
# -*- encoding: utf-8 -*- | ||
# A simple and fast sub domain brute tool | ||
# my[at]lijiejie.com (http://www.lijiejie.com) | ||
|
||
import optparse | ||
import Queue | ||
import sys | ||
import dns.resolver | ||
import threading | ||
import time | ||
import optparse | ||
from lib.consle_width import getTerminalSize | ||
|
||
|
||
class DNSBrute: | ||
def __init__(self, target, names_file, threads_num, output): | ||
self.target = target.strip() | ||
self.names_file = names_file | ||
self.threads_num = threads_num | ||
self.scan_count = 0; self.found_count = 0 | ||
self.lock = threading.Lock() | ||
self.console_width, _ = getTerminalSize(); self.console_width -= 2 # Cal width when starts up | ||
self.resolvers = [dns.resolver.Resolver() for i in range(threads_num)] | ||
self._load_dns_servers(); self._load_sub_names(); self._load_next_sub() | ||
outfile = target + '.txt' if not output else output; self.outfile = open(outfile, 'w') # won't close manually | ||
self.ip_dict = {} | ||
|
||
def _load_dns_servers(self): | ||
dns_servers = [] | ||
with open('dns_servers.txt') as f: | ||
for line in f: | ||
server = line.strip() | ||
if server.count('.') == 3 and server not in dns_servers: | ||
dns_servers.append(server) | ||
self.dns_servers = dns_servers | ||
self.dns_count = len(dns_servers) | ||
|
||
def _load_sub_names(self): | ||
self.queue = Queue.Queue() | ||
with open(self.names_file) as f: | ||
for line in f: | ||
sub = line.strip() | ||
if sub: self.queue.put(sub) | ||
|
||
def _load_next_sub(self): | ||
next_subs = [] | ||
with open('next_sub.txt') as f: | ||
for line in f: | ||
sub = line.strip() | ||
if sub and sub not in next_subs: | ||
next_subs.append(sub) | ||
self.next_subs = next_subs | ||
|
||
def _update_scan_count(self): | ||
self.lock.acquire() | ||
self.scan_count += 1 | ||
self.lock.release() | ||
|
||
def _print_progress(self): | ||
self.lock.acquire() | ||
sys.stdout.write('\r' + '\0' * self.console_width) | ||
msg = '%s found | %s remaining | %s scanned in %.2f seconds' % ( | ||
self.found_count, self.queue.qsize(), self.scan_count, time.time() - self.start_time) | ||
sys.stdout.write('\r' + ' ' * (self.console_width -len(msg)) + msg) | ||
sys.stdout.flush() | ||
self.lock.release() | ||
|
||
def _scan(self): | ||
thread_id = int( threading.currentThread().getName() ) | ||
self.resolvers[thread_id].nameservers = [self.dns_servers[thread_id % self.dns_count]] # must be a list object | ||
while self.queue.qsize() > 0: | ||
sub = self.queue.get(timeout=1.0) | ||
try: | ||
cur_sub_domain = sub + '.' + self.target | ||
answers = d.resolvers[thread_id].query(cur_sub_domain) | ||
is_wildcard_record = False | ||
if answers: | ||
for answer in answers: | ||
self.lock.acquire() | ||
if answer.address not in self.ip_dict: | ||
self.ip_dict[answer.address] = 1 | ||
else: | ||
self.ip_dict[answer.address] += 1 | ||
if self.ip_dict[answer.address] > 10: # a wildcard DNS record | ||
is_wildcard_record = True | ||
self.lock.release() | ||
if is_wildcard_record: self._update_scan_count(); self._print_progress(); continue | ||
self.lock.acquire() | ||
self.found_count += 1 | ||
sys.stdout.write('\r' + '\0' * self.console_width) # clear line | ||
ips = ', '.join([answer.address for answer in answers]) | ||
sys.stdout.write('\r' + cur_sub_domain + '\t' + ips + '\n') | ||
self.outfile.write(cur_sub_domain.ljust(30) + '\t' + ips + '\n') | ||
self.lock.release() | ||
for i in self.next_subs: | ||
self.queue.put(i + '.' + sub) | ||
except Exception, e: | ||
pass | ||
self._update_scan_count() | ||
self._print_progress() | ||
self._print_progress() | ||
|
||
def run(self): | ||
self.start_time = time.time() | ||
for i in range(self.threads_num): | ||
t = threading.Thread(target=self._scan, name=str(i)) | ||
t.start() | ||
|
||
if __name__ == '__main__': | ||
parser = optparse.OptionParser('usage: %prog [options] target') | ||
parser.add_option('-t', '--threads', dest='threads_num', | ||
default=10, type='int', | ||
help='Number of threads. default = 10') | ||
parser.add_option('-f', '--file', dest='names_file', default='subnames.txt', | ||
type='string', help='Dict file used to brute sub names') | ||
parser.add_option('-o', '--output', dest='output', default=None, | ||
type='string', help='Output file name. default is {target}.txt') | ||
|
||
(options, args) = parser.parse_args() | ||
if len(args) < 1: | ||
parser.print_help() | ||
sys.exit(0) | ||
|
||
d = DNSBrute(target=args[0], names_file=options.names_file, | ||
threads_num=options.threads_num, | ||
output=options.output) | ||
d.run() | ||
|
||
|
Oops, something went wrong.