- Регистрация
- 30.11.2020
- Сообщения
- 496
- Благодарностей
- 314
- Баллы
- 63
Содержание
1. INTRO
2. Регистрация на сервисе и автоматическое получение данных.
3. Получение уникальных доменов во всех зонах.
4. Получение уникальных NS серверов во всех зонах.
5. Получение уникальных доменов с принадлежащими им NS серверами с во всех зонах.
6. Заключение.
1. INTRO
Здравствуйте форумчане и гости форума. В этом небольшом кейсе мы рассмотрим как получать бесплатные наборы доменов от организации ICANN, как при помощи Zennoposter быстро и легко их обрабатывать.
Наборы тематических доменов и обогащенные данные необходимы для самых различных целей, для аналитики, сбора технической и коммерческой информации, для составление интернет каталогов сайтов, для пентеста по программам Bug Bounty , ну и для продажи заинтересованным в них лицам. Причем данные должны быть “свежие”, актуализированные, по возможности максимально обогащенные дополнительными данными. Но к сожалению, такие данные которые присутствуют в интернете, либо предоставляются на платной основе, либо являются не актуальными (устаревшими,) либо не обладают нужным объемом данных которые они содержат. В этом мини кейсе мы закроем в этом потребность и сделаем это бесплатно.
2. Регистрация на сервисе и автоматическое получение данных.
Для того, чтобы приступить к работе, нам необходимо, конечно же, в первую очередь зарегистрироваться на сервисе ICANN (ICANN — некоммерческая общественная корпорация. В ее работе участвуют люди со всего мира в деле обеспечения безопасного, стабильного и отказоустойчивого функционирования интернета. ), провести все необходимые авторизации, отправить запросы администраторам доменных зон и по завершению всех действий получить все списки и архивы с доменами в автоматическом режиме. Звучит устрашающе, но поверьте это проще некуда, а во избежание ошибок допущенных мною и дальнейших автоматизации действий - была записана видеоинструкция.
Как вы смогли убедиться - это довольно просто, а в спойлере ниже код Powershell для получения списков заапрувленных и автоматическому скачиванию архивов.
Код для получения токена и списков заапрувленных зон
Код для скачивания архивов заапрувленных зон. Не работает без предыдущего
Powershell код для получения заапрувленных список:
cd desktop # Можете убрать если запускаете Powershell сразу в нужной папке
$headers = @{
"Accept" = "application/json"
"Content-Type" = "application/json"
}
$body = @{
"username" = "Ваша почта на ICANN"
"password" = 'Ваш пароль на ICANN' #Пароль обязательно в одинарных кавычках
} | ConvertTo-Json
$url = "https://account-api.icann.org/api/authenticate"
$response = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body
$accessToken = $response.accessToken
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
$a = Invoke-WebRequest -Uri "https://czds-api.icann.org/czds/downloads/links" -Headers $headers -Method GET
$urls = $a.Content
$urls = $urls -replace '\[|\]|"'
$urls = $urls -split ','
$queue = [System.Collections.Concurrent.ConcurrentQueue[string]]::new()
foreach ($url in $urls)
{
Write-Host $url
$queue.Enqueue($url)
$url >> 1.txt
}
$c = $queue.Count
Write-Host $c + " zones aprooved"
Powershell код для скачивания заапрувленных списков:
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
# Путь к папке на рабочем столе, где вы хотите сохранить загруженные файлы.
$destinationPath = "$env:userprofile\Desktop\Files"
# Создаем папку, если ее еще нет.
if (-not (Test-Path -Path $destinationPath -PathType Container)) {
New-Item -ItemType Directory -Path $destinationPath | Out-Null
}
# Проходимся по коллекции файлов и загружаем каждый из них.
foreach ($fileUrl in $queue) {
$fileName = Split-Path $fileUrl -Leaf
$filePath = Join-Path $destinationPath $fileName
# Если файл уже существует, пропускаем его.
if (Test-Path $filePath) {
# Write-Host "File '$fileName' already exists. Skipping download."
continue
}
Write-Host "Downloading file '$fileName'..."
# Загружаем файл и сохраняем его на рабочем столе.
Invoke-WebRequest -Uri $fileUrl -Headers $headers -OutFile $filePath
}
Write-Host "All files have been downloaded to '$destinationPath'."
3. Получение уникальных доменов во всех зонах.
Это, пожалуй, самое легкое из всего, но для начала, Вам нужно кое-что исправить в расспакованных архивах. Если Вы дождались апрува зоны com то необходимо сменить ее название с com.zone.48236 (у Вас цифры могут быть иные) на название com.
Как мы помним из первого видео, список сильно "зашумлен" и нам необходимо предусмотреть все варианты для того чтобы его "почистить"
Логика тут весьма простая. Получаем пути ко всем файлам из папки, создаем отдельную папку куда будем сохранять готовые результаты. Затем из каждого списка читаем строки, убираем те которые содержат мусор в виде "dnskey, nsec3param, nsec3, nsec, soa,ds, a, aaaa, тxt, ds,"rrsig". Создаем контрольную переменную чтобы не "хватать" дубликаты доменов. Также читаем файл по частям, так как некоторые файлы "тяжелые" (зона .com 25 Гб+). Ну и конечно же нужен репорт файл в котором будет отчет сколько доменов в каждой зоне и общее количество которое у нас есть на руках. Все это необходимо делать одновременно, не растягивая код на километры. Если думаете что это "вынос" мозга - то уверяю Вас, это проще простого, смотрим видео.
Only Domains:
string path_folder = @"C:\Users\vigan\Desktop\1"; // замените путь к папке на путь к своей папке с разархивированными зонами
string targetDirectory = path_folder;
string[] fileEntries = Directory.GetFiles(targetDirectory);
var files = Directory.GetFiles(path_folder, "*", SearchOption.TopDirectoryOnly); // получение всех файлов в папке и ее подпапках
double totalSize = 0; // общий объем файлов
foreach (var file in files)
{
totalSize += new FileInfo(file).Length; // добавление размера каждого файла к общему объему
}
double totalSizeInGb = totalSize / 1024 / 1024 / 1024; // перевод в гигабайты
project.SendInfoToLog($"Количество файлов: {files.Length}. Общий объем: {totalSizeInGb:F2} Гб.");
var filePaths = new System.Collections.Generic.List<string>(files);
DirectoryInfo dirInfo = new DirectoryInfo(targetDirectory);
List<string> fileList1 = new List<string>();
List<string> fileList2 = new List<string>();
List<string> report_list = new List<string>();
foreach (string fileName in fileEntries)
{
fileList1.Add(fileName);
}
string control = string.Empty;
string subpath = string.Empty;
string _report = string.Empty;
int i_d = 0;
subpath = @"OnlyDomains";
_report = targetDirectory + "\\" + subpath + "\\" + "_report.txt";
if (!dirInfo.Exists)
{
dirInfo.Create();
}
dirInfo.CreateSubdirectory(subpath);
project.SendInfoToLog("Создана субдиректория OnlyDomains");
while (fileList1 != null)
{
i_d = 0;
try
{
string path = fileList1[0];
fileList1.RemoveAt(0);
string name_file = path.Replace(targetDirectory, "");
string name_file_transit = name_file.Replace("\\", "");
string name_file_transit_out = name_file_transit.Replace(".txt", "");
string path_domain = targetDirectory + "\\" + subpath + "\\" + name_file + ".txt";
using (var writer_domain = new StreamWriter(new BufferedStream(File.OpenWrite(path_domain), 100 * 1024 * 1024)))
{
using (var file = new StreamReader(new BufferedStream(File.OpenRead(path), 100 * 1024 * 1024)))
{
string line;
int count = 0; // Счетчик прочитанных строк
while ((line = file.ReadLine()) != null)
{
string[] text = line.Split(' ');
string domain = text[0];
domain = domain.TrimEnd('.');
if (domain == control)
{
continue ; // Пропустить дубликаты доменов
}
if (domain.Contains("."))
{
string NS = text[3];
NS = NS.ToLower();
string server = text[4];
server = server.TrimEnd('.');
if (NS.Contains("dnskey") || NS.Contains("nsec3param") || NS.Contains("nsec3") || NS.Contains("soa") || (NS.Contains("ds") || NS.Contains("a") || NS.Contains("aaaa") || NS.Contains("txt") || NS.Contains("ds") || NS.Contains("rrsig") || NS.Contains("nsec")))
{
continue ; // Пропустить домены с определенными условиями
}
string result = domain;
fileList2.Add(result);
control = domain;
}
count++;
if (count == 10000000)
{
// Записать обработанные домены в файл
foreach (string outline in fileList2)
{
writer_domain.WriteLine(outline);
i_d++;
}
fileList2.Clear();
count = 0;
}
}
// Записать оставшиеся обработанные домены в файл
foreach (string outline in fileList2)
{
writer_domain.WriteLine(outline);
i_d++;
}
}
fileList2.Clear();
project.SendInfoToLog("В зоне " + name_file_transit_out + " - " + i_d + " уникальных доменов");
string _report_string = name_file_transit_out + "|" + i_d;
report_list.Add(_report_string);
}
}
catch
{
break;
}
}
int general_count = 0;
foreach (string outline_count in report_list)
{
string[] text_count = outline_count.Split('|');
int out_count = int.Parse(text_count[1]);
general_count = general_count + out_count;
}
string total_count = general_count.ToString();
string full_count = " Total domains - " + total_count;
report_list.Add("_______________________________");
report_list.Add(full_count);
System.IO.StreamWriter writer_report = new System.IO.StreamWriter(_report, true);
{
foreach (string outline in report_list)
{
writer_report.WriteLine(outline);
}
}
if (writer_report != null) writer_report.Dispose();///
report_list.Clear();
project.SendInfoToLog("Всего уникальных доменов в списках - " + total_count);
project.SendInfoToLog("Обработка списка доменов завершена");
Для многих пользователей таких списков достаточно, но мы сделаем еще кое что.
4. Получение уникальных NS серверов во всех зонах.
Для различных исследований, софта и приложений списки уникальных NS серверов (пусть и не абсолютно все) имеют гораздо большее значение и важность чем сами доменные списки. На просторах интернета также можно найти как коллекции за оплату, так и бесплатные наборы с различной степени актуализации. Имеются и интернет каталоги которые можно распарсить, но если у нас на руках уже есть то что нам нужно - зачем создавать себе проблемы?
Тут логика обработки списков немного отличается от той, которая применялась при обработке уникальных доменов. В отличии от доменов, NS сервера в списке идут не по порядку, многократно повторяются по файлу. Так что как и в предыдущем случае, читаем файлы частями, выбираем только NS сервера, с каждым проходом удаляем дубликаты, по окончанию проверки каждой зоны проводим окончальную чистку выходной коллекции. Почему сначала не собрать а затем не удалить дубликаты? Во первых это извращение, а во вторых не уникальные списки NS содержат миллионы строк и гигабайты объема, можно легко "выбить" память. Также нам стоит по окончанию обработки обработки собрать со всех выходных файлов NS сервера в один общий файл, почистить на дубликаты. Ну и куда же без репорта, нужен список в котором будет указано сколько уникальных NS в каждой зоне и сколько уникальных NS серверов вообще на руках. Так же, ничего сложного, смотрим.
Код для получения уникальных NS серверов:
string path_folder = @"C:\Users\vigan\Desktop\test";
string targetDirectory = path_folder;
string[] fileEntries = Directory.GetFiles(targetDirectory);
var files = Directory.GetFiles(path_folder, "*", SearchOption.TopDirectoryOnly); // получение всех файлов в папке и ее подпапках
double totalSize = 0; // общий объем файлов
foreach (var file in files)
{
totalSize += new FileInfo(file).Length; // добавление размера каждого файла к общему объему
}
double totalSizeInGb = totalSize / 1024 / 1024 / 1024; // перевод в гигабайты
project.SendInfoToLog($"Количество файлов: {files.Length}. Общий объем: {totalSizeInGb:F2} Гб.");
int file_count = fileEntries.Length;
DirectoryInfo dirInfo = new DirectoryInfo(targetDirectory);
HashSet<string> fileList1 = new HashSet<string>();
HashSet<string> fileList2 = new HashSet<string>();
List<string> report_list = new List<string>();
List<string> fileList3 = new List<string>();
foreach (string fileName in fileEntries)
{
fileList1.Add(fileName);
}
string subpath_ns = @"OnlyNS";
string _report = Path.Combine(targetDirectory, subpath_ns, "_report.txt");
string path_domain_ns = Path.Combine(targetDirectory, subpath_ns);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
dirInfo.CreateSubdirectory(subpath_ns);
project.SendInfoToLog("Создана субдиректория OnlyNS");
while (fileList1.Count > 0)
{
int i_d = 0;
try
{
string path = fileList1.First();
fileList1.Remove(path);
string name_file = Path.GetFileName(path);
string name_file_transit_out = Path.GetFileNameWithoutExtension(name_file);
string path_domain = Path.Combine(path_domain_ns, name_file + ".txt");
using (var writer_domain = new StreamWriter(path_domain, append: false))
using (var file = new StreamReader(path))
{
string line;
int count = 0;
while ((line = file.ReadLine()) != null)
{
string[] text = line.Split(' ');
string NS = text[3].ToLower();
string server = text[4].TrimEnd('.');
if (!(NS.Contains("dnskey") || NS.Contains("nsec3param") || NS.Contains("nsec3") || NS.Contains("soa") || (NS.Contains("ds") || NS.Contains("a") || NS.Contains("aaaa") || NS.Contains("txt") || NS.Contains("ds") || NS.Contains("rrsig")|| NS.Contains("nsec"))))
{
string result = server.ToLower();
fileList2.Add(result);
}
count++;
if (count == 5000000)
{
fileList2.RemoveWhere(item => !fileList2.Contains(item));
}
}
foreach (string outline in fileList2)
{
writer_domain.WriteLine(outline);
i_d++;
}
project.SendInfoToLog("В зоне " + name_file_transit_out + " - " + i_d + " уникальных NS серверов");
string _report_string = name_file_transit_out + "|" + i_d.ToString();
report_list.Add(_report_string);
fileList2.Clear();
count = 0;
}
}
catch
{
continue;
}
}
project.SendInfoToLog("Начата общая сборка всех NS");
string counter_ns = Path.Combine(targetDirectory, subpath_ns);
string targetDirectory_ns = counter_ns;
string[] fileEntries_ns = Directory.GetFiles(targetDirectory_ns);
foreach (string fileName_ns in fileEntries_ns)
{
fileList3.Add(fileName_ns);
}
while (fileList3.Count > 0)
{
try
{
string path = fileList3[0];
fileList3.RemoveAt(0);
using (var file = new StreamReader(path))
{
string line;
while ((line = file.ReadLine()) != null)
{
fileList2.Add(line);
}
}
}
catch
{
break;
}
}
string all = Path.Combine(targetDirectory, subpath_ns, "_all_ns.txt");
int i_d_count = 0;
using (var writer_count = new StreamWriter(all, true))
{
foreach (string outline in fileList2)
{
writer_count.WriteLine(outline);
i_d_count++;
}
}
project.SendInfoToLog("Всего уникальных NS в всех списках - " + i_d_count);
string unique = "Total NS unique - " + i_d_count;
report_list.Add("_______________________________");
report_list.Add(unique);
using (var writer_unique = new StreamWriter(_report, true))
{
foreach (string outline_unique in report_list)
{
writer_unique.WriteLine(outline_unique);
}
}
Ну что же, давайте продолжим и перейдем к следующему пункту кейса.
5. Получение уникальных доменов с принадлежащими им NS серверами с во всех зонах.
Теперь давайте соберем списки в том виде в котором многие их качали с бесплатных раздач или покупали у брокеров данных. Это списки зон которые содержат в себе адрес домена и принадлежащие к этому домену NS сервера. Такие списки в основном и востребованы разными группами пользователей и стоят в продаже на различных сервисах фрилансеров и сайтах брокеров.
Из за того, что тут используется одновременно большой массив входных данных, то как бы я не пытался, но у меня не получилось "разогнать" код. Виной тому бюджетная "машина" с 8 Гб на борту, так что у Вас это может работать быстрей (у меня 45+ минут, но это из за зоны .com). Логика так же отличается от предыдущих. Читаем файл частями, при помощи LINQ собираем данные по каждому конкретному домену в строку и затем сбрасываем с дописыванием в соответствующий доменной зоне файл. Так как в предыдущих частях кода мы получили всю информацию о входящих данных по количеству, уникальности и прочему, то в данном блоке нам это не требуется. Все что необходимо - просто обработка и создание выходных файлов с указанными в заголовке параметрами. Смотрим.
Domains and NS:
string path_folder = @"C:\Users\vigan\Desktop\test";
string targetDirectory = path_folder;
string[] fileEntries = Directory.GetFiles(targetDirectory);
var files = Directory.GetFiles(path_folder, "*", SearchOption.TopDirectoryOnly);
double totalSize = 0;
foreach (var file in files)
{
totalSize += new FileInfo(file).Length;
}
double totalSizeInGb = totalSize / 1024 / 1024 / 1024;
project.SendInfoToLog($"Количество файлов: {files.Length}. Общий объем: {totalSizeInGb:F2} Гб.");
int file_count = fileEntries.Length;
DirectoryInfo dirInfo = new DirectoryInfo(targetDirectory);
HashSet<string> fileList1 = new HashSet<string>();
HashSet<string> fileList2 = new HashSet<string>();
List<string> report_list = new List<string>();
List<string> fileList3 = new List<string>();
foreach (string fileName in fileEntries)
{
fileList1.Add(fileName);
}
string subpath = @"DomainsAndNS";
string subdirectoryPath = Path.Combine(targetDirectory, subpath);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
if (!Directory.Exists(subdirectoryPath))
{
Directory.CreateDirectory(subdirectoryPath);
project.SendInfoToLog("Создана субдиректория DomainsAndNS");
}
while (fileList1.Count > 0)
{
try
{
string path = fileList1.ElementAt(0);
fileList1.Remove(path);
string name_file = path.Replace(targetDirectory, "");
string name_file_transit = name_file.Replace("\\", "");
string name_file_transit_out = name_file_transit.Replace(".txt", "");
string path_domain = Path.Combine(subdirectoryPath, name_file_transit_out + ".txt");
using (var file = new StreamReader(new BufferedStream(File.OpenRead(path), 100 * 1024 * 1024)))
{
int count = 0;
string line;
while ((line = file.ReadLine()) != null)
{
string[] text = line.Split('\t');
string NS = text[3].ToLower();
string server = text[4].TrimEnd('.');
if (!(NS.Contains("dnskey") || NS.Contains("nsec3param") || NS.Contains("nsec3") || NS.Contains("soa") || NS.Contains("ds") || NS.Contains("a") || NS.Contains("aaaa") || NS.Contains("txt") || NS.Contains("rrsig")|| NS.Contains("nsec")))
{
string domain = text[0];
domain = domain.TrimEnd('.');
string result = domain + " | " + server;
fileList2.Add(result);
count++;
if (count == 1000000)
{
var list2 = new List<string>();
fileList2.GroupBy(x => x.Split('|').First().Trim())
.ToList()
.ForEach(x => list2.Add(string.Join(" | ", new[]
{
x.Key, string.Join(", ", x.Select(v => v.Split('|').Last().Trim()))
})));
fileList3.Add(string.Join("\n", list2));
using (StreamWriter writer = new StreamWriter(path_domain, append: true))
{
foreach (string outline in fileList3)
{
writer.WriteLine(outline);
}
}
fileList3.Clear();
fileList2.Clear();
count = 0;
}
}
}
if (fileList2.Count > 0)
{
var list2 = new List<string>();
fileList2.GroupBy(x => x.Split('|').First().Trim())
.ToList()
.ForEach(x => list2.Add(string.Join(" | ", new[]
{
x.Key, string.Join(", ", x.Select(v => v.Split('|').Last().Trim()))
})));
fileList3.Add(string.Join("\n", list2));
using (StreamWriter writer = new StreamWriter(path_domain, append: true))
{
foreach (string outline in fileList3)
{
writer.WriteLine(outline);
}
}
fileList3.Clear();
fileList2.Clear();
}
using (StreamWriter writer_domain = new StreamWriter(path_domain, append: true))
{
foreach (string outline in fileList2)
{
writer_domain.WriteLine(outline);
}
project.SendInfoToLog("Зона " + name_file_transit_out + " обработана");
}
}
}
catch
{
continue;
}
}
На этом мы закончили данный мини кейс по получению доменных списков из тематических зон ICANN. Конечно же самих зон гораздо больше , это зоны конкретных страновых геозон (DE,UK, PL .... e.t.c.) а также их суффиксов (com.au, gov.lt ...e.t.c.) и так далее. Но данный кейс только по ICANN.
6. Заключение
Ну что же, как мы с вами смогли убедиться, Zennoposter это очень мощный инструмент и позволяет делать вроде бы сложные вещи быстро и эффективно. А с возможностью писать код на C# настолько масштабируют его возможности что они почти безграничны. Надеюсь что данный мини кейс поможет многим пользователям всегда иметь под рукой актуальные наборы данных (доменные списки) , а в случае необходимости очень быстро их скачать и обработать, ведь как я показывал - скорость обработки достаточна высока. Пусть мой код не идеален, но так и я не кодер, а всего лишь любитель самоучка.
Конечно, мы рассмотрели только базовую обработку, ну и автоматическое получение списков, но на самом деле это только верхушка айсберга. Кому возможно нужны только ключи зон для фильтрации трафика, кому то только корневые NS для дальнейшей обработки доменных списков (как вариант получение mx/txt.dkim/dmarc e.t.c. при помощи, например DNSClient от Micha Conrad), кому то надо пропинговать домены и получить при помощи наборов данных от IANA geo-данные о расположение парковок сайтов чтобы не "воткнуться" в законы GDPR или 152-Ф3, кому то (в основном пентестерам но не ограничиваясь ими) необходимо из набора NS серверов при помощи таблицы суффиксов Mozzilla вычислить хостинг провайдеров для базового понимания на каких предположительно технологиях может работать сайт/сайты для сужения набора инструментов для исследований. Этот список можно продолжать и продолжать и одной статьи для этого конечно недостаточно. Но все же - пишите в комментариях чтобы вы еще хотели увидить, какие вопросы вас интересуют и я по возможности быстро - постараюсь подготовить для вас решение в открытом доступе на базе Zennoposter.
На этом у меня все, доброго дня и удачи всем участникам конкурса!
- Номер конкурса статей
- Девятнадцатый конкурс статей
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование модератором: