Загрузка...

Tcp Socket €ТО база [часть 1]

Тема в разделе C# создана пользователем Dead__Artis 16 апр 2024. (поднята 16 апр 2024) 226 просмотров

Загрузка...
  1. Dead__Artis
    Dead__Artis Автор темы 16 апр 2024 921 30 май 2020
    Всем хаюшки сегодня мы будем использовать нашу интернет магистраль для передачи данных!

    ну и теперь без моих рофлянок :peka:
    тема довольно таки серьезное и не каждый понимает как она работает на наших си S.H.A.R.P

    так вот для начало узнаем как же работает наш TCP
    буду объяснять поверхностно без подробного углубления (оно нам не нужно)
    если вам интересно как сам протокол работает, что такое ACK, SYN и прочее можете почитать:
    не реклама https://habr.com/ru/companies/ruvds/articles/759988/

    и так как же работает tcp в нашем случае
    работает по такой схеме
    у нас есть Server и Client
    Server бронирует себе определенный порт (это еси че циферки от 0 до 65535, быть точней каналы вообщем без подробностей)
    тем временем наш Client ломиться на наш Сервер и тот в свою очередь принимает его тем самым они Синхронизируются (SYN, ACK)
    и готовы для передачи данных
    если наше приложение требует постоянного подключения (какой пример я и буду писать) то ему необходимы такие вещи как keep-alive о которых я расскажу в второй или третей части как пойдет
    если же наше приложение как http тупо передает данные один раз, тогда нам нужно закрыть наше соединение (FIN)

    хватит с нас теорий погнали писать сервер
    для начала напишем класс Client
    CSHARP
    public class Client
    {
    //ето нам для асинхроного чтения данных
    private byte[] Buffer { get; set; }
    private int Offset { get; set; }
    private int HeadSize { get; set; }
    private bool BufferRecevied { get; set; }
    //ето нам для синхроного передачи данных
    private object SyncSend { get; set; }

    //это наше все сам бог воплати только в виде Socket и NetworkStream
    private Socket socket { get; set; }
    private NetworkStream stream { get; set; } //мб еще доберемся до SslStream
    //это будет служить ключом для того чтобы небыло повторных вызовов в Disconnect
    public bool ItsConnect { get; private set; } //private ибо нехуй ломать логику программы
    //ето наш конструктор в который мы будем принимать соеденение из нашего листнера
    public Client(Socket socket)
    {
    this.socket = socket;
    this.stream = new NetworkStream(socket, true);
    this.SyncSend = new object();
    this.Offset = 0;
    this.HeadSize = 4;
    this.Buffer = new byte[HeadSize];
    this.ItsConnect = true;
    this.BufferRecevied = false;
    this.stream.BeginRead(Buffer, this.Offset, this.HeadSize, AsyncRead, null); //приступим же к асинхроному чтению наших данных юхууу
    }
    private void AsyncRead(IAsyncResult asyncResult)
    {
    //если соеденение разорвано то нам нужно
    //разорвать этот порочный рекурсивный круг чтения
    if (!ItsConnect)
    return;
    try
    {
    int BytesRecevied = this.stream.EndRead(asyncResult); //получаем количество данных которые мы прочитали
    if (BytesRecevied > 0) //ну ноль байт нам точно не кто не отправит, а если будет -1 это говорит о разрыве соеденения
    {
    this.HeadSize -= BytesRecevied; //отнимаем у нашего заголовка (количества четаемых байтов за раз) количество полученных
    this.Offset += BytesRecevied; //по ходу действия поймете зачем оно надо
    if (!this.BufferRecevied) //тут мы проверяем поймали ли мы первые 4 байта с размером передаваемых данных
    {
    if (this.HeadSize == 0) //вот мы отнимали кокрас у HeadSize наши 4 байта которые к нам пришли и вышло 0 значит все ок
    {
    this.HeadSize = BitConverter.ToInt32(this.Buffer, 0); //теперь мы знаем размер массива который нам хочет передать клиент
    if (this.HeadSize > 0)
    {
    this.Buffer = new byte[this.HeadSize];
    this.Offset = 0;
    this.BufferRecevied = true; //теперь ебашим чтение без конца пока наш HeadSize не станет равен нулю
    }
    }
    }
    else //да я знаю что мог не делать !this.BufferRecevied, я сделал спецально для читаемости
    {
    if (this.HeadSize == 0)
    {
    //Юху мы получили наш пакет который сохранился в Buffer
    //осталось с ним что то сделать но это уже ваше дело, сериализация и подробно мб напишу в другой части пока сделаем вывод текста
    Console.WriteLine("Packet "+Encoding.Unicode.GetString(Buffer));
    this.Offset = 0;
    this.HeadSize = 4;
    this.Buffer = new byte[this.HeadSize];
    this.BufferRecevied = false; //и все по новой... прям как типичный день работяги
    }
    }
    this.stream.BeginRead(Buffer, this.Offset, this.HeadSize, AsyncRead, null); //ну и продолжаем дальше
    }
    else
    {
    Disconnect();
    }
    }
    catch
    {
    Disconnect();
    //кто его знает мало ли въебет экспешен
    //ВЕЗДЕ ПОНАВПИХАЕМ TRY CATCH о да)
    }
    }
    public void Send(byte[] buff) //наш метод который будет передавать данные
    {
    if (!ItsConnect)
    return;
    try
    {
    byte[] sizeBytes = BitConverter.GetBytes(buff.Length); //тут мы кокрас мы получаем те самые 4 байта размера массива
    byte[] newArray = new byte[4 + buff.Length];
    Array.Copy(sizeBytes, 0, newArray, 0, sizeBytes.Length);
    Array.Copy(buff, 0, newArray, 4, buff.Length); //тут короче просто все в один массив мешаем, 4 байта его размера + сам массив байтов

    socket.Poll(-1, SelectMode.SelectWrite);
    stream.Write(newArray, 0, newArray.Length); //записываем в стрим и отсылаем нах*й эти данные
    stream.Flush();
    }
    catch
    {
    Disconnect();
    //ЕЩЕ БОЛЬШЕ TRY CATCH)
    }
    }
    public void Disconnect()
    {
    if (!ItsConnect)
    return;
    this.ItsConnect = false;
    this.stream?.Dispose();
    this.socket?.Dispose();
    this.Buffer = null;
    this.Offset = 0;
    this.HeadSize = 0;
    //на этом заканчивается наш клиент
    //вы не представляетесь как я заебался писать код
    //в маленьком окошке от вставки кода в lolz
    }
    }
    теперь приступим к нашему Listner
    CSHARP
    public class Listner
    {
    private Socket sockListner { get; set; } //вы спросите нахуя тут гетеры и сеттеры, а я отвечу привычка с github, кто поймет тот поймет)))) да я не заебался пиздить чужой код и буду пиздить его дальше
    public int port { get; private set; }
    public Listner(int port)
    {
    this.port = port;
    }
    public void Start()
    {
    IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, port);
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Bind(iPEndPoint); //занимаем нашу лавку которая будет слушать со всех айпи адресов наш порт
    socket.Listen(0); //если же порт занят нам дадут пиздюлей в виде Exception
    socket.BeginAccept(BeginAccept, null); //тут мы уже асинхроно принимаем наши соеденения
    }
    public void Stop()
    {
    socket.Dispose();
    }
    private void BeginAccept(IAsyncResult result)
    {
    try
    {
    Socket client = socket.EndAccept(result);
    new Client(client); //А вот тут мы принимаем и скручиваем в новый объект класса наш свеже принятый сокет
    }
    catch { }
    try
    {
    socket.BeginAccept(BeginAccept, null);
    } catch { }
    }
    }
    ну с сервером все
    только дурак не поймет что чтоб он работал надо в майн сделать объект листнера дать ему порт и запусть Start

    теперь к клиенту, ща будет прикол :wut:
    нам нужно тупо взять клиент с сервера и убрать тупо инициализацию класса
    и добавить метод Connect куда будем писать наш IP, Port

    CSHARP
    public void Connect(string ip, int port)
    {
    try
    {
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(ip, port);
    if (socket.Connected)
    {
    SendSync = new object();
    stream= new NetworkStream(socket, true);

    Offset = 0;
    HeaderSize = 4;
    Buffer = new byte[HeaderSize];
    ClientBufferRecevied = false;
    //Start async recive Data
    stream.BeginRead(Buffer, (int)Offset, (int)HeaderSize, new AsyncCallback(ReadData), (object)null);
    }
    itsConnect = socket.Connected;
    }
    catch (Exception ex)
    {
    itsConnect = false;
    }
    }
    в второй части если я её напишу, добавим Keep-Alive, в третей уже будем использовать данный сокет на практике
    и напишем свой Reverse-Shell
    на основе данных сокетов пишут ратники, думаю реверсеры и другие люди часто видят данный код
    так как он удобен и чутли не каждый второй его использует в ратках
    #моястатья
     
    16 апр 2024 Изменено
  2. amcs
    amcs 16 апр 2024 Заблокирован(а) 3 5 дек 2021
    мой сервер)
     
  3. Kalipso
    Kalipso 17 апр 2024 :love2: TRX&ENERGY(FROM 100₽/66.000) - lzt.lol/2trx :love2: 499 12 апр 2022
    через HttpListener не получится?
     
    1. Dead__Artis Автор темы
      Kalipso, http != tcp, если хочешь могу сделать тему с созданием своего сервера на http с использованием tcp или того же HttpListner хотя смысла будет ноль ибо там все и так понятно
Top