Пример #1
0
    static inline void prepare_compressed_data(InStream & compressed_data_stream, bool compressed,
        uint16_t & MatchCount, uint8_t const * & MatchDetails, uint8_t const * & Literals,
        size_t & literals_length)
    {
        if (compressed) {
            unsigned expected = 2; // MatchCount(2)
            if (!compressed_data_stream.in_check_rem(expected)) {
                LOG(LOG_ERR, "RDP61_COMPRESSED_DATA: data truncated, expected=%u remains=%zu",
                    expected, compressed_data_stream.in_remain());
                throw Error(ERR_RDP61_DECOMPRESS_DATA_TRUNCATED);
            }
            MatchCount = compressed_data_stream.in_uint16_le();

            expected = MatchCount * 8; // MatchCount(2) * (MatchLength(2) + MatchOutputOffset(2) + MatchHistoryOffset(4))
            if (!compressed_data_stream.in_check_rem(expected)) {
                LOG(LOG_ERR, "RDP61_COMPRESSED_DATA: data truncated, expected=%u remains=%zu",
                    expected, compressed_data_stream.in_remain());
                throw Error(ERR_RDP61_DECOMPRESS_DATA_TRUNCATED);
            }
            MatchDetails = compressed_data_stream.get_current();
            compressed_data_stream.in_skip_bytes(expected);
        }
        else {
            MatchCount   = 0;
            MatchDetails = nullptr;
        }

        literals_length = compressed_data_stream.in_remain();
        Literals        = (literals_length ? compressed_data_stream.get_current() : nullptr);
    }
Пример #2
0
    explicit ShareData_Recv(InStream & stream, rdp_mppc_dec * dec = nullptr)
    //==============================================================================
    : CheckShareData_Recv(stream)
    , share_id(stream.in_uint32_le())
    , pad1(stream.in_uint8())
    , streamid(stream.in_uint8())
    , len(stream.in_uint16_le())
    , pdutype2(stream.in_uint8())
    , compressedType(stream.in_uint8())
    , compressedLen(stream.in_uint16_le())
    , payload([&stream, dec, this]() {
          if (this->compressedType & PACKET_COMPRESSED) {
              if (!dec) {
                  LOG(LOG_INFO, "ShareData_Recv: got unexpected compressed share data");
                  throw Error(ERR_SEC);
              }

              const uint8_t * rdata;
              uint32_t        rlen;

              dec->decompress(stream.get_data()+stream.get_offset(), stream.in_remain(),
                  this->compressedType, rdata, rlen);

              return InStream(rdata, 0, rlen);
          }
          else {
              return InStream(stream.get_current(), stream.in_remain());
          }
      }())
    // BEGIN CONSTRUCTOR
    {
        //LOG( LOG_INFO, "ShareData_Recv: pdutype2=%u len=%u compressedLen=%u payload_size=%u"
        //   , this->pdutype2, this->len, this->compressedLen, this->payload.size());
        stream.in_skip_bytes(stream.in_remain());
    } // END CONSTRUCTOR
Пример #3
0
        explicit ClientInputEventPDU_Recv(InStream & stream)

        : numEvents(
            [&stream](){
                if (!stream.in_check_rem(2)) {
                    LOG(LOG_ERR, "SlowPath::ClientInputEventPDU: data truncated (numEvents)");
                    throw Error(ERR_RDP_SLOWPATH);
                }

                auto numEvents = stream.in_uint16_le();
                const unsigned expected =
                      2                    // pad(2)
                    + numEvents * 12 // (time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2)) * 12
                    ;
                if (!stream.in_check_rem(expected)) {
                    LOG(LOG_ERR, "SlowPath::ClientInputEventPDU: data truncated, expected=%u remains=%zu",
                        expected, stream.in_remain());
                    throw Error(ERR_RDP_SLOWPATH);
                }

                stream.in_skip_bytes(2); // pad
                return numEvents;
            }()
        )
        // (time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2)) * 12
        , payload(stream.get_current(), this->numEvents * 12)
        {
            // This is the constructor body, we skip payload now that it is packaged

            stream.in_skip_bytes(this->payload.get_capacity());
        }
Пример #4
0
    explicit ShareControl_Recv(InStream & stream)
    : totalLength([&stream]() {
        if (!stream.in_check_rem(2+2)){
            LOG(LOG_ERR,
                "Truncated [4: ShareControl packet] , remains=%zu", stream.in_remain());
            throw Error(ERR_SEC);
        }
        return stream.in_uint16_le();
    }())
    , pduType(stream.in_uint16_le() & 0xF)
    , PDUSource([&stream, this]() {
        if (this->pduType == PDUTYPE_DEACTIVATEALLPDU && this->totalLength == 4) {
            // should not happen
            // but DEACTIVATEALLPDU seems to be broken on windows 2000
            return static_cast<uint16_t>(0);
        }
        return stream.in_uint16_le();
    }())
    , payload([&stream, this]() {
        if (this->pduType == PDUTYPE_DEACTIVATEALLPDU && this->totalLength == 4) {
            // should not happen
            // but DEACTIVATEALLPDU seems to be broken on windows 2000
            return InStream(stream.get_current(), 0);
        }

        if (this->totalLength < 6) {
            LOG(LOG_ERR, "ShareControl packet too short totalLength=%u pduType=%u mcs_channel=%u",
                this->totalLength, this->pduType, this->PDUSource);
            throw Error(ERR_SEC);
        }

        if (!stream.in_check_rem(this->totalLength - 6)) {
            LOG(LOG_ERR, "Truncated ShareControl packet, need=%u remains=%zu",
                this->totalLength - 6,
                stream.in_remain());
            throw Error(ERR_SEC);
        }
        return InStream(stream.get_current(), this->totalLength - 6);
    }())
    // body of constructor
    {
        if (this->totalLength == 0x8000) {
            LOG(LOG_ERR, "Expected ShareControl header, got flowMarker");
            throw Error(ERR_SEC);
        }
        stream.in_skip_bytes(this->payload.get_capacity());
    }
    void recv(InStream & stream) {
        uint8_t const * pBegin = stream.get_current();
        bool res;
        res = this->message.recv(stream);
        if (!res) {
            LOG(LOG_ERR, "INVALID MSG RECEIVED type: %u", this->message.msgType);
        }
        this->LmChallengeResponse.recv(stream);
        this->NtChallengeResponse.recv(stream);
        this->DomainName.recv(stream);
        this->UserName.recv(stream);
        this->Workstation.recv(stream);
        this->EncryptedRandomSessionKey.recv(stream);
        this->negoFlags.recv(stream);
        if (this->negoFlags.flags & NTLMSSP_NEGOTIATE_VERSION) {
            this->version.recv(stream);
        }
        uint32_t min_offset = this->LmChallengeResponse.bufferOffset;
        if (this->NtChallengeResponse.bufferOffset < min_offset)
            min_offset = this->NtChallengeResponse.bufferOffset;
        if (this->DomainName.bufferOffset < min_offset)
            min_offset = this->DomainName.bufferOffset;
        if (this->UserName.bufferOffset < min_offset)
            min_offset = this->UserName.bufferOffset;
        if (this->Workstation.bufferOffset < min_offset)
            min_offset = this->Workstation.bufferOffset;
        if (this->EncryptedRandomSessionKey.bufferOffset < min_offset)
            min_offset = this->EncryptedRandomSessionKey.bufferOffset;
        if (min_offset + pBegin > stream.get_current()) {
            this->has_mic = true;
            stream.in_copy_bytes(this->MIC, 16);
        }
        else {
            this->has_mic = false;
        }

        // PAYLOAD
        this->LmChallengeResponse.read_payload(stream, pBegin);
        this->NtChallengeResponse.read_payload(stream, pBegin);
        this->DomainName.read_payload(stream, pBegin);
        this->UserName.read_payload(stream, pBegin);
        this->Workstation.read_payload(stream, pBegin);
        this->EncryptedRandomSessionKey.read_payload(stream, pBegin);
    }
Пример #6
0
    void receive(InStream & stream, const RDPPrimaryOrderHeader & header) {
        //LOG(LOG_INFO, "RDPMultiDstBlt::receive: header fields=0x%02X", header.fields);

        header.receive_coord(stream, 0x0001, this->nLeftRect);
        header.receive_coord(stream, 0x0002, this->nTopRect);
        header.receive_coord(stream, 0x0004, this->nWidth);
        header.receive_coord(stream, 0x0008, this->nHeight);

        if (header.fields & 0x0010) {
            this->bRop = stream.in_uint8();
        }

        if (header.fields & 0x0020) {
            this->nDeltaEntries = stream.in_uint8();
        }

        if (header.fields & 0x0040) {
            uint16_t cbData = stream.in_uint16_le();
            //LOG(LOG_INFO, "cbData=%d", cbData);

            InStream rgbData(stream.get_current(), cbData);
            stream.in_skip_bytes(cbData);
            //hexdump_d(rgbData.get_current(), rgbData.get_capacity());

            uint8_t zeroBitsSize = ((this->nDeltaEntries + 1) / 2);
            //LOG(LOG_INFO, "zeroBitsSize=%d", zeroBitsSize);

            InStream zeroBits(rgbData.get_current(), zeroBitsSize);
            rgbData.in_skip_bytes(zeroBitsSize);

            uint8_t zeroBit = 0;

            for (uint8_t i = 0, m2 = 0; i < this->nDeltaEntries; i++, m2++) {
                if (m2 == 2) {
                    m2 = 0;
                }

                if (!m2) {
                    zeroBit = zeroBits.in_uint8();
                    //LOG(LOG_INFO, "0x%02X", zeroBit);
                }

                this->deltaEncodedRectangles[i].leftDelta = (!(zeroBit & 0x80) ? rgbData.in_DEP() : 0);
                this->deltaEncodedRectangles[i].topDelta  = (!(zeroBit & 0x40) ? rgbData.in_DEP() : 0);
                this->deltaEncodedRectangles[i].width     = (!(zeroBit & 0x20) ? rgbData.in_DEP() : 0);
                this->deltaEncodedRectangles[i].height    = (!(zeroBit & 0x10) ? rgbData.in_DEP() : 0);

                //LOG(LOG_INFO, "RDPMultiDstBlt::receive: delta rectangle=(%d, %d, %d, %d)",
                //    this->deltaEncodedRectangles[i].leftDelta, this->deltaEncodedRectangles[i].topDelta,
                //    this->deltaEncodedRectangles[i].width, this->deltaEncodedRectangles[i].height);

                zeroBit <<= 4;
            }
        }
    }   // void receive(InStream & stream, const RDPPrimaryOrderHeader & header)
 explicit SaveSessionInfoPDUData_Recv(InStream & stream) :
 infoType([&stream](){
     if (!stream.in_check_rem(4)) {
         LOG(LOG_ERR,
             "Truncated Save Session Info PDU (data): expected=4 remains=%zu",
              stream.in_remain());
         throw Error(ERR_RDP_DATA_TRUNCATED);
     }
     return stream.in_uint32_le();
 }()),
 payload(stream.get_current(), stream.in_remain())
 {
     stream.in_skip_bytes(this->payload.get_capacity());
 }
Пример #8
0
 void recv(InStream & stream)
 {
     for (std::size_t i = 0; i < AV_ID_MAX; ++i) {
         NTLM_AV_ID id = static_cast<NTLM_AV_ID>(stream.in_uint16_le());
         uint16_t length = stream.in_uint16_le();
         if (id == MsvAvEOL) {
             // ASSUME last element is MsvAvEOL
             stream.in_skip_bytes(length);
             break;
         }
         this->add(id, stream.get_current(), length);
         stream.in_skip_bytes(length);
     }
 }
    explicit LogonInfoField_Recv(InStream & stream)
    : cbFieldData([&stream](){
        const unsigned expected = 4;    // cbFieldData(4)
        if (!stream.in_check_rem(expected)) {
            LOG(LOG_ERR,
                "Truncated Logon Info Field (data): expected=%u remains=%zu",
                expected, stream.in_remain());
            throw Error(ERR_RDP_DATA_TRUNCATED);
        }

        return stream.in_uint32_le();
    }())
    , payload(stream.get_current(), stream.in_remain())
    {
        stream.in_skip_bytes(this->payload.get_capacity());
    }
Пример #10
0
 explicit InputEvent_Recv(InStream & stream)
 : eventTime([&stream](){
     // time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2)
     if (!stream.in_check_rem(12)) {
         LOG(LOG_ERR, "SlowPath::InputEvent: data truncated, expected=12 remains=%zu", stream.in_remain());
         throw Error(ERR_RDP_SLOWPATH);
     }
     return stream.in_uint32_le();
 }())
 , messageType(stream.in_uint16_le())
  // device_flags(2) + param1(2) + param2(2)
 , payload(stream.get_current(), 6)
 // Body of constructor
 {
     stream.in_skip_bytes(this->payload.get_capacity());
 }
    void receive(InStream & stream, const RDPPrimaryOrderHeader & header) {
        // LOG(LOG_INFO, "RDPPolygonSC::receive: header fields=0x%02X", header.fields);

        header.receive_coord(stream, 0x0001, this->xStart);
        header.receive_coord(stream, 0x0002, this->yStart);
        if (header.fields & 0x0004) {
            this->bRop2  = stream.in_uint8();
        }
        if (header.fields & 0x0008) {
            this->fillMode = stream.in_uint8();
        }

        if (header.fields & 0x0010) {
            receive_rdp_color(stream, this->backColor);
        }

        if (header.fields & 0x0020) {
            receive_rdp_color(stream, this->foreColor);
        }

        header.receive_brush(stream, 0x0040, this->brush);

        if (header.fields & 0x0800) {
            this->NumDeltaEntries = stream.in_uint8();
        }

        if (header.fields & 0x1000) {
            uint8_t cbData = stream.in_uint8();
            // LOG(LOG_INFO, "cbData=%d", cbData);

            InStream rgbData(stream.get_current(), cbData);
            stream.in_skip_bytes(cbData);
            // hexdump_d(rgbData.get_current(), rgbData.get_capacity());

            uint8_t zeroBitsSize = ((this->NumDeltaEntries + 3) / 4);
            // LOG(LOG_INFO, "zeroBitsSize=%d", zeroBitsSize);

            InStream zeroBits(rgbData.get_current(), zeroBitsSize);
            rgbData.in_skip_bytes(zeroBitsSize);

            uint8_t zeroBit = 0;

            for (uint8_t i = 0, m4 = 0; i < this->NumDeltaEntries; i++, m4++) {
                if (m4 == 4) {
                    m4 = 0;
                }

                if (!m4) {
                    zeroBit = zeroBits.in_uint8();
                    // LOG(LOG_INFO, "0x%02X", zeroBit);
                }

                this->deltaPoints[i].xDelta = (!(zeroBit & 0x80) ? rgbData.in_DEP() : 0);
                this->deltaPoints[i].yDelta = (!(zeroBit & 0x40) ? rgbData.in_DEP() : 0);

/*
                LOG(LOG_INFO, "RDPPolygonCB::receive: delta point=%d, %d",
                    this->deltaPoints[i].xDelta, this->deltaPoints[i].yDelta);
*/

                zeroBit <<= 2;
            }
        }
    }   // receive
Пример #12
0
void ClientRDPSNDChannel::receive(InStream & chunk) {
    if (this->wave_data_to_wait) {

        this->wave_data_to_wait -= chunk.in_remain();
        if (this->wave_data_to_wait < 0) {
            this->wave_data_to_wait = 0;
        }

        if (this->last_PDU_is_WaveInfo) {
            chunk.in_skip_bytes(4);
            this->last_PDU_is_WaveInfo = false;
        }

        if (this->impl_sound) {
            this->impl_sound->setData(chunk.get_current(), chunk.in_remain());
        }

        if (!(this->wave_data_to_wait)) {

            if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU");
            }

            LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 1");

            if (this->impl_sound) {
                LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 2");
                uint8_t data[] = {'\0'};
                LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 3");
                this->impl_sound->setData(data, 1);
                LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 4");
                this->impl_sound->play();
                LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 5");
//                 LOG(LOG_INFO, "ClientRDPSNDChannel::receive play!!!");
            }

            LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 6");

            StaticOutStream<16> out_stream;
            rdpsnd::RDPSNDPDUHeader header(rdpsnd::SNDC_WAVECONFIRM, 4);
            header.emit(out_stream);
            LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 7");
            rdpsnd::WaveConfirmPDU wc(this->last_wTimeStamp, this->last_cBlockNo);
            wc.emit(out_stream);

            InStream chunk_to_send(out_stream.get_bytes());

            LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 8");

            this->callback->send_to_mod_channel( channel_names::rdpsnd
                                                , chunk_to_send
                                                , out_stream.get_offset()
                                                , this->channel_flags
                                                );
            if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                LOG(LOG_INFO, "CLIENT >> RDPEA: Wave Confirm PDU");
            }
        }

    } else {
        rdpsnd::RDPSNDPDUHeader header;
        header.receive(chunk);

        switch (header.msgType) {

            case rdpsnd::SNDC_FORMATS:
                {
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: Server Audio Formats and Version PDU");
                }

                rdpsnd::ServerAudioFormatsandVersionHeader safsvh;
                safsvh.receive(chunk);

                StaticOutStream<1024> out_stream;

                rdpsnd::RDPSNDPDUHeader header_out(rdpsnd::SNDC_FORMATS, 38);
                header_out.emit(out_stream);

                rdpsnd::ClientAudioFormatsandVersionHeader cafvh( this->dwFlags
                                                                , this->dwVolume
                                                                , this->dwPitch
                                                                , this->wDGramPort
                                                                , this->wNumberOfFormats
                                                                , this->wVersion
                                                                );
                cafvh.emit(out_stream);

                for (uint16_t i = 0; i < safsvh.wNumberOfFormats; i++) {
                    rdpsnd::AudioFormat format;
                    format.receive(chunk);
//                             format.log();

                    if (format.wFormatTag == rdpsnd::WAVE_FORMAT_PCM) {
                        format.emit(out_stream);
                        if (this->impl_sound) {
                            this->impl_sound->n_sample_per_sec = format.nSamplesPerSec;
                            this->impl_sound->bit_per_sample = format.wBitsPerSample;
                            this->impl_sound->n_channels = format.nChannels;
                            this->impl_sound->n_block_align = format.nBlockAlign;
                            this->impl_sound->bit_per_sec = format.nSamplesPerSec * (format.wBitsPerSample/8) * format.nChannels;
                        } else {
                            //LOG(LOG_WARNING, "No Sound System module found");
                        }
                    }
                }

                InStream chunk_to_send(out_stream.get_bytes());

                this->callback->send_to_mod_channel( channel_names::rdpsnd
                                                , chunk_to_send
                                                , out_stream.get_offset()
                                                , this->channel_flags
                                                );

                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "CLIENT >> RDPEA: Client Audio Formats and Version PDU");
                }

                StaticOutStream<32> quality_stream;

                rdpsnd::RDPSNDPDUHeader header_quality(rdpsnd::SNDC_QUALITYMODE, 8);
                header_quality.emit(quality_stream);

                rdpsnd::QualityModePDU qm(rdpsnd::HIGH_QUALITY);
                qm.emit(quality_stream);

                InStream chunk_to_send2(quality_stream.get_bytes());

                this->callback->send_to_mod_channel( channel_names::rdpsnd
                                                , chunk_to_send2
                                                , quality_stream.get_offset()
                                                , this->channel_flags
                                                );

                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "CLIENT >> RDPEA: Quality Mode PDU");
                }
                }
                break;

            case rdpsnd::SNDC_TRAINING:
                {
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: Training PDU");
                }

                rdpsnd::TrainingPDU train;
                train.receive(chunk);

                StaticOutStream<32> out_stream;

                rdpsnd::RDPSNDPDUHeader header_quality(rdpsnd::SNDC_TRAINING, 4);
                header_quality.emit(out_stream);

                rdpsnd::TrainingConfirmPDU train_conf(train.wTimeStamp, train.wPackSize);
                train_conf.emit(out_stream);

                InStream chunk_to_send(out_stream.get_bytes());

                this->callback->send_to_mod_channel( channel_names::rdpsnd
                                                , chunk_to_send
                                                , out_stream.get_offset()
                                                , this->channel_flags
                                                );

                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "CLIENT >> RDPEA: Training Confirm PDU");
                }
                }
                break;

            case rdpsnd::SNDC_WAVE:
                {
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: Wave Info PDU");
                }

                this->wave_data_to_wait = header.BodySize - 8;
                rdpsnd::WaveInfoPDU wi;
                wi.receive(chunk);
                this->last_cBlockNo = wi.cBlockNo;
                this->last_wTimeStamp = wi.wTimeStamp;

                if (this->impl_sound) {
                    this->impl_sound->init(header.BodySize - 12);
                    this->impl_sound->setData(wi.Data, 4);
                }
                this->last_PDU_is_WaveInfo = true;
                }
                break;

            case rdpsnd::SNDC_CLOSE:
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: Close PDU");
                }
                break;

            case rdpsnd::SNDC_SETVOLUME:
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_SETVOLUME PDU");
                }
                {
                rdpsnd::VolumePDU v;
                v.receive(chunk);
                }
                break;

            case rdpsnd::SNDC_SETPITCH:
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_SETPITCH PDU");
                }
                {
                rdpsnd::PitchPDU p;
                p.receive(chunk);
                }
                break;

//                     case rdpsnd::SNDC_CRYPTKEY:
//                         LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_CRYPTKEY PDU");
//                         break;

//                     case rdpsnd::SNDC_WAVEENCRYPT:
//                         LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_WAVEENCRYPT PDU");
//                         break;

            case rdpsnd::SNDC_QUALITYMODE:
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_QUALITYMODE PDU");
                }
                {
                rdpsnd::QualityModePDU qm;
                qm.receive(chunk);
                }
                break;

            case rdpsnd::SNDC_WAVE2:
                if (bool(this->verbose & RDPVerbose::rdpsnd)) {
                    LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_WAVE2 PDU");
                }
                {
                this->wave_data_to_wait = header.BodySize - 12;
                rdpsnd::Wave2PDU w2;
                w2.receive(chunk);
                if (this->impl_sound) {
                    this->impl_sound->init(header.BodySize - 12);
                    this->impl_sound->setData(chunk.get_current(), chunk.in_remain());
                }

                this->last_PDU_is_WaveInfo = true;
                }
                break;


            default: LOG(LOG_WARNING, "SERVER >> RDPEA: Unknown message type: %x", header.msgType);
                break;
        }
    }
}