shadow1ng/fscan · error
invalid expected BER tag
Error message
invalid expected BER tag
What it means
ReadConnectResponse, after parsing result, calledConnectId and DomainParameters, expects a BER OCTET STRING universal tag holding the userData (GCC blocks). If ReadUniversalTag(TAG_OCTET_STRING, constructed=false) fails, the tail of the MCS Connect Response is not the expected octet string. The response is malformed or truncated at that point.
Source
Thrown at libs/grdp/protocol/t125/mcs.go:199
func ReadConnectResponse(r io.Reader) (*ConnectResponse, error) {
c := &ConnectResponse{}
var err error
_, err = ber.ReadApplicationTag(MCS_TYPE_CONNECT_RESPONSE, r)
if err != nil {
return nil, err
}
c.result, err = ber.ReadEnumerated(r)
if err != nil {
return nil, err
}
c.calledConnectId, err = ber.ReadInteger(r)
c.domainParameters, err = ReadDomainParameters(r)
if err != nil {
return nil, err
}
if !ber.ReadUniversalTag(ber.TAG_OCTET_STRING, false, r) {
return nil, errors.New("invalid expected BER tag")
}
dataLen, _ := ber.ReadLength(r)
c.userData, err = core.ReadBytes(dataLen, r)
return c, err
}
type MCSChannelInfo struct {
ID uint16
Name string
}
type MCS struct {
emission.Emitter
transport core.Transport
recvOpCode MCSDomainPDU
sendOpCode MCSDomainPDU
channels []MCSChannelInfo
}View on GitHub (pinned to 95cc12e753)
Solutions
- Log the hex dump of the full response and verify the expected tag byte 0x04 at that offset.
- Ensure the transport delivers the complete MCS Connect Response (length-prefixed) before invoking recvConnectResponse.
- Check the DomainParameters parse consumed exactly the encoded length (ReadLength result is discarded in ReadDomainParameters — a mismatch desynchronizes parsing).
- Include the actual byte value in the error for faster diagnosis.
Example fix
// before
if !ber.ReadUniversalTag(ber.TAG_OCTET_STRING, false, r) {
return nil, errors.New("invalid expected BER tag")
}
// after
if !ber.ReadUniversalTag(ber.TAG_OCTET_STRING, false, r) {
return nil, fmt.Errorf("invalid expected BER tag: want OCTET_STRING(0x04)")
} Defensive patterns
Strategy: try-catch
Validate before calling
// After DomainParameters, verify the next tag is a primitive OCTET STRING:
if len(buf) > 0 && buf[pos] != 0x04 {
return errors.New("Connect Response userData tag is not OCTET STRING")
} Try / catch
mcs.On("error", func(err error) {
if strings.Contains(err.Error(), "invalid expected BER tag") {
// response malformed/truncated — reconnect or inspect raw dump
}
}) Prevention
- Ensure the transport buffers the complete MCS Connect Response before dispatching 'data'.
- Fix discarded ReadLength results in ReadDomainParameters to prevent reader desync.
- Test against known-good RDP servers when changing parsing code.
When it happens
Trigger: Parsing a server MCS Connect Response where, after DomainParameters, the next byte is not a primitive OCTET STRING tag (0x04) — e.g. the response was truncated, contains a different encoding, or the reader was already misaligned.
Common situations: Server sends a Connect Response with an empty or differently encoded userData section; TCP fragmentation/partial reads deliver an incomplete buffer to ReadConnectResponse; non-RDP service on the port; earlier BER parse consumed wrong lengths shifting the tag position.
Related errors
- bad BER tags
- invalid ber tag
- Bad integer tag
- NODE_RDP_PROTOCOL_T125_MCS_BAD_HEADER
- Invalid expected MCS opcode receive data
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/864fa9d601b2e6a1.
Report an issue: GitHub.