mirror of
https://github.com/shmilylty/OneForAll.git
synced 2026-08-25 20:37:48 +08:00
202 lines
7.2 KiB
Python
202 lines
7.2 KiB
Python
"""
|
|
Reference: https://github.com/ProjectAnte/dnsgen
|
|
"""
|
|
import re
|
|
import time
|
|
import itertools
|
|
|
|
from config import settings
|
|
|
|
from common import utils
|
|
from common import resolve
|
|
from common import request
|
|
from common.domain import Domain
|
|
from common.module import Module
|
|
from config.log import logger
|
|
|
|
|
|
def split_domain(domain):
|
|
"""
|
|
Split domain base on subdomain levels
|
|
Root+TLD is taken as one part, regardless of its levels
|
|
"""
|
|
|
|
# test.1.foo.example.com -> [test, 1, foo, example.com]
|
|
# test.2.foo.example.com.cn -> [test, 2, foo, example.com.cn]
|
|
# test.example.co.uk -> [test, example.co.uk]
|
|
|
|
ext = Domain(domain).extract()
|
|
subname = ext.subdomain
|
|
parts = ext.subdomain.split('.') + [ext.registered_domain]
|
|
return subname, parts
|
|
|
|
|
|
class Altdns(Module):
|
|
def __init__(self, domain):
|
|
Module.__init__(self)
|
|
self.module = 'Altdns'
|
|
self.source = 'Altdns'
|
|
self.start = time.time()
|
|
self.domain = domain
|
|
self.words = set()
|
|
self.now_subdomains = set()
|
|
self.new_subdomains = set()
|
|
self.wordlen = 6 # Min length of custom words extracted from domains
|
|
self.num_count = 3
|
|
|
|
def get_words(self):
|
|
path = settings.data_storage_dir.joinpath('altdns_wordlist.txt')
|
|
with open(path) as fd:
|
|
for line in fd:
|
|
word = line.lower().strip()
|
|
if word:
|
|
self.words.add(word)
|
|
|
|
def extract_words(self):
|
|
"""
|
|
Extend the dictionary based on target's domain naming conventions
|
|
"""
|
|
|
|
for subdomain in self.now_subdomains:
|
|
_, parts = split_domain(subdomain)
|
|
tokens = set(itertools.chain(*[word.lower().split('-') for word in parts]))
|
|
tokens = tokens.union({word.lower() for word in parts})
|
|
for token in tokens:
|
|
if len(token) >= self.wordlen:
|
|
self.words.add(token)
|
|
|
|
def increase_num(self, subname):
|
|
"""
|
|
If number is found in existing subdomain,
|
|
increase this number without any other alteration.
|
|
"""
|
|
|
|
# test.1.foo.example.com -> test.2.foo.example.com, test.3.foo.example.com, ...
|
|
# test1.example.com -> test2.example.com, test3.example.com, ...
|
|
# test01.example.com -> test02.example.com, test03.example.com, ...
|
|
|
|
digits = re.findall(r'\d{1,3}', subname)
|
|
|
|
for d in digits:
|
|
for m in range(self.num_count):
|
|
replacement = str(int(d) + 1 + m).zfill(len(d))
|
|
tmp_domain = subname.replace(d, replacement)
|
|
new_domain = f'{tmp_domain}.{self.domain}'
|
|
self.new_subdomains.add(new_domain)
|
|
|
|
def decrease_num(self, subname):
|
|
"""
|
|
If number is found in existing subdomain,
|
|
decrease this number without any other alteration.
|
|
"""
|
|
|
|
# test.4.foo.example.com -> test.3.foo.example.com, test.2.foo.example.com, ...
|
|
# test4.example.com -> test3.example.com, test2.example.com, ...
|
|
# test04.example.com -> test03.example.com, test02.example.com, ...
|
|
|
|
digits = re.findall(r'\d{1,3}', subname)
|
|
|
|
for d in digits:
|
|
for m in range(self.num_count):
|
|
new_digit = (int(d) - 1 - m)
|
|
if new_digit < 0:
|
|
break
|
|
|
|
replacement = str(new_digit).zfill(len(d))
|
|
tmp_domain = subname.replace(d, replacement)
|
|
new_domain = f'{tmp_domain}.{self.domain}'
|
|
self.new_subdomains.add(new_domain)
|
|
|
|
def insert_word(self, parts):
|
|
"""
|
|
Create new subdomain levels by inserting the words between existing levels
|
|
"""
|
|
|
|
# test.1.foo.example.com -> WORD.test.1.foo.example.com,
|
|
# test.WORD.1.foo.example.com,
|
|
# test.1.WORD.foo.example.com,
|
|
# test.1.foo.WORD.example.com,
|
|
# ...
|
|
|
|
for word in self.words:
|
|
for index in range(len(parts)):
|
|
tmp_parts = parts.copy()
|
|
tmp_parts.insert(index, word)
|
|
new_domain = '.'.join(tmp_parts)
|
|
self.new_subdomains.add(new_domain)
|
|
|
|
def add_word(self, subnames):
|
|
"""
|
|
On every subdomain level, prepend existing content with WORD-`,
|
|
append existing content with `-WORD`
|
|
"""
|
|
|
|
for word in self.words:
|
|
for index, name in enumerate(subnames):
|
|
# Prepend with `-`
|
|
# test.1.foo.example.com -> WORD-test.1.foo.example.com
|
|
tmp_subnames = subnames.copy()
|
|
tmp_subnames[index] = f'{word}-{name}'
|
|
new_subname = '.'.join(tmp_subnames + [self.domain])
|
|
self.new_subdomains.add(new_subname)
|
|
|
|
# Prepend with `-`
|
|
# test.1.foo.example.com -> test-WORD.1.foo.example.com
|
|
tmp_subnames = subnames.copy()
|
|
tmp_subnames[index] = f'{name}-{word}'
|
|
new_subname = '.'.join(tmp_subnames + [self.domain])
|
|
self.new_subdomains.add(new_subname)
|
|
|
|
def replace_word(self, subname):
|
|
"""
|
|
If word longer than 3 is found in existing subdomain,
|
|
replace it with other words from the dictionary
|
|
"""
|
|
|
|
# WORD1.1.foo.example.com -> WORD2.1.foo.example.com,
|
|
# WORD3.1.foo.example.com,
|
|
# WORD4.1.foo.example.com,
|
|
# ..
|
|
|
|
for word in self.words:
|
|
if word not in subname:
|
|
continue
|
|
for word_alt in self.words:
|
|
if word == word_alt:
|
|
continue
|
|
new_subname = subname.replace(word, word_alt)
|
|
new_subdomain = f'{new_subname}.{self.domain}'
|
|
self.new_subdomains.add(new_subdomain)
|
|
|
|
def gen_new_subdomains(self):
|
|
for subdomain in self.now_subdomains:
|
|
subname, parts = split_domain(subdomain)
|
|
subnames = subname.split('.')
|
|
self.increase_num(subname)
|
|
self.decrease_num(subname)
|
|
self.replace_word(subname)
|
|
if not settings.enable_fast_alt:
|
|
self.insert_word(parts)
|
|
self.add_word(subnames)
|
|
count = len(self.new_subdomains)
|
|
logger.log('DEBUG', f'The altdns module generated {count} subdomains')
|
|
|
|
def run(self, data, port):
|
|
logger.log('INFOR', f'Start altdns module')
|
|
self.now_subdomains = utils.get_subdomains(data)
|
|
self.get_words()
|
|
self.extract_words()
|
|
self.gen_new_subdomains()
|
|
self.subdomains = self.new_subdomains - self.now_subdomains
|
|
count = len(self.subdomains)
|
|
logger.log('INFOR', f'The altdns module generated {count} new subdomains')
|
|
self.end = time.time()
|
|
self.elapse = round(self.end - self.start, 1)
|
|
self.gen_result()
|
|
temp_data = resolve.run_resolve(self.domain, self.results)
|
|
fina_data = request.run_request(self.domain, temp_data, port)
|
|
data = data + fina_data
|
|
logger.log('INFOR', f'Saving altdns results')
|
|
utils.save_db(self.domain, data, 'altdns')
|
|
return data
|