Files
OneForAll-mirror/modules/altdns.py
T
Jing Ling 3fbbd1dc25 1.重构请求,边请求边存入数据库,解决内存占用过大问题。
2.format参数改为fmt。
3.添加信息富化模块。
4.优化iscdn模块代码。
5.移除数据库new字段。
2020-11-09 09:01:06 +08:00

200 lines
7.1 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()
resolved_data = resolve.run_resolve(self.domain, self.results)
request.run_request(self.domain, resolved_data, port)
logger.log('INFOR', f'Saving altdns results')
utils.save_db(self.domain, data, 'altdns')