shadow1ng/fscan · error

enumerate size is wrong, get %v, expect 1

Error message

enumerate size is wrong, get %v, expect 1

What it means

After the ENUMERATED tag byte validates, ReadEnumerated reads the BER length. BER ENUMERATED used here must carry exactly one byte of content; any other length means the field is malformed, so the error reports the actual length versus the expected 1.

Source

Thrown at libs/grdp/protocol/t125/ber/ber.go:53

)

func berPC(pc bool) uint8 {
	if pc {
		return PC_CONSTRUCT
	}
	return PC_PRIMITIVE
}

func ReadEnumerated(r io.Reader) (uint8, error) {
	if !ReadUniversalTag(TAG_ENUMERATED, false, r) {
		return 0, errors.New("invalid ber tag")
	}
	length, err := ReadLength(r)
	if err != nil {
		return 0, err
	}
	if length != 1 {
		return 0, errors.New(fmt.Sprintf("enumerate size is wrong, get %v, expect 1", length))
	}
	return core.ReadUInt8(r)
}

func ReadUniversalTag(tag uint8, pc bool, r io.Reader) bool {
	bb, _ := core.ReadUInt8(r)
	return bb == (CLASS_UNIV|berPC(pc))|(TAG_MASK&tag)
}

func WriteUniversalTag(tag uint8, pc bool, w io.Writer) {
	core.WriteUInt8((CLASS_UNIV|berPC(pc))|(TAG_MASK&tag), w)
}

func ReadLength(r io.Reader) (int, error) {
	ret := 0
	size, _ := core.ReadUInt8(r)
	if size&0x80 > 0 {
		size = size &^ 0x80

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Capture the server's CONNECT_RESPONSE and verify the enumerated (requestedProtocols/domainSelector) encoding uses 1 content byte
  2. Check for stream desync — an earlier parse consuming wrong byte counts shifts lengths; fix the earlier parser
  3. If the server genuinely sends a different length, extend ReadEnumerated to decode variable-length enumerated values
  4. Retry the connection; transient truncation from network issues can produce bogus lengths

Example fix

// before
if length != 1 {
    return 0, errors.New(fmt.Sprintf("enumerate size is wrong, get %v, expect 1", length))
}

// after
if length != 1 {
    return 0, fmt.Errorf("enumerate size is wrong, get %v, expect 1", length)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check the CONNECT_RESPONSE region before parsing
// ensure at least tag+length+1 bytes remain for the enumerated field
if len(buf) < pos+3 { return errors.New("CONNECT_RESPONSE truncated before enumerated field") }

Try / catch

v, err := ber.ReadEnumerated(r)
if err != nil {
    if strings.Contains(err.Error(), "enumerate size is wrong") {
        // desync or nonstandard encoder: dump bytes and resynchronize
    }
    return err
}

Prevention

When it happens

Trigger: ReadConnectResponse -> ReadEnumerated when ReadLength returns a value other than 1 (0, 2, or more) for the enumerated field — a malformed or nonstandard CONNECT_RESPONSE.

Common situations: Unusual server implementations encoding the enumerated domain selector with a non-1-byte length; corrupted or truncated responses from flaky networks; protocol desync from earlier skipped bytes.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/d9ba62d5cce017bd. Report an issue: GitHub.