package drdynvc import ( "bytes" "encoding/hex" "io" "ShotRDP/grdp/core" "ShotRDP/grdp/glog" "ShotRDP/grdp/plugin" ) const ( ChannelName = plugin.DRDYNVC_SVC_CHANNEL_NAME ChannelOption = plugin.CHANNEL_OPTION_INITIALIZED | plugin.CHANNEL_OPTION_ENCRYPT_RDP ) const ( MAX_DVC_CHANNELS = 20 ) const ( DYNVC_CREATE_REQ = 0x01 DYNVC_DATA_FIRST = 0x02 DYNVC_DATA = 0x03 DYNVC_CLOSE = 0x04 DYNVC_CAPABILITIES = 0x05 DYNVC_DATA_FIRST_COMPRESSED = 0x06 DYNVC_DATA_COMPRESSED = 0x07 DYNVC_SOFT_SYNC_REQUEST = 0x08 DYNVC_SOFT_SYNC_RESPONSE = 0x09 ) type ChannelClient struct { name string id uint32 channelSender core.ChannelSender } type DvcClient struct { w core.ChannelSender channels map[string]ChannelClient } func NewDvcClient() *DvcClient { return &DvcClient{ channels: make(map[string]ChannelClient, 100), } } func (c *DvcClient) LoadAddin(f core.ChannelSender) { } type DvcHeader struct { cmd uint8 sp uint8 cbChId uint8 } func readHeader(r io.Reader) *DvcHeader { value, _ := core.ReadUInt8(r) cmd := (value & 0xf0) >> 4 sp := (value & 0x0c) >> 2 cbChId := (value & 0x03) >> 0 return &DvcHeader{cmd, sp, cbChId} } func (h *DvcHeader) serialize(channelId uint32) []byte { b := &bytes.Buffer{} core.WriteUInt8((h.cmd<<4)|(h.sp<<2)|h.cbChId, b) if h.cbChId == 0 { core.WriteUInt8(uint8(channelId), b) } else if h.cbChId == 1 { core.WriteUInt16LE(uint16(channelId), b) } else { core.WriteUInt32LE(channelId, b) } return b.Bytes() } func (c *DvcClient) Send(s []byte) (int, error) { glog.Debug("len:", len(s), "data:", hex.EncodeToString(s)) name, _ := c.GetType() return c.w.SendToChannel(name, s) } func (c *DvcClient) Sender(f core.ChannelSender) { c.w = f } func (c *DvcClient) GetType() (string, uint32) { return ChannelName, ChannelOption } func (c *DvcClient) Process(s []byte) { glog.Debug("recv:", hex.EncodeToString(s)) r := bytes.NewReader(s) hdr := readHeader(r) glog.Infof("dvc: Cmd=0x%x, Sp=%d CbChId=%d all=%d", hdr.cmd, hdr.sp, hdr.cbChId, r.Len()) b, _ := core.ReadBytes(r.Len(), r) switch hdr.cmd { case DYNVC_CAPABILITIES: glog.Info("DYNVC_CAPABILITIES") c.processCapsPdu(hdr, b) case DYNVC_CREATE_REQ: glog.Info("DYNVC_CREATE_REQ") c.processCreateReq(hdr, b) case DYNVC_DATA_FIRST: glog.Info("DYNVC_DATA_FIRST") case DYNVC_DATA: glog.Info("DYNVC_DATA") case DYNVC_CLOSE: glog.Info("DYNVC_CLOSE") default: glog.Errorf("type 0x%x not supported", hdr.cmd) } } func (c *DvcClient) processCreateReq(hdr *DvcHeader, s []byte) { r := bytes.NewReader(s) channelId := readDvcId(r, hdr.cbChId) name, _ := core.ReadBytes(r.Len(), r) channelName := string(name) glog.Infof("Server requests channelId=%d, name=%s", channelId, channelName) //response b := &bytes.Buffer{} b.Write(hdr.serialize(channelId)) core.WriteUInt32LE(0, b) c.Send(b.Bytes()) } func readDvcId(r io.Reader, cbLen uint8) (id uint32) { switch cbLen { case 0: i, _ := core.ReadUInt8(r) id = uint32(i) case 1: i, _ := core.ReadUint16LE(r) id = uint32(i) default: id, _ = core.ReadUInt32LE(r) } return } func (c *DvcClient) processCapsPdu(hdr *DvcHeader, s []byte) { r := bytes.NewReader(s) core.ReadUInt8(r) ver, _ := core.ReadUint16LE(r) glog.Infof("Server supports dvc=%d", ver) hdr.cmd = DYNVC_CAPABILITIES hdr.cbChId = 0 hdr.sp = 0 b := &bytes.Buffer{} core.WriteUInt16LE(0x0050, b) core.WriteUInt16LE(ver, b) c.Send(b.Bytes()) }