shadow1ng/fscan · error
ReadApplicationTag invalid data2
Error message
ReadApplicationTag invalid data2
What it means
In the short tag form (tag <= 30), ReadApplicationTag requires the first byte to equal (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) — a single-byte application tag encoding the requested number. Any other byte means the field is not the expected application tag, producing this 'invalid data2' error.
Source
Thrown at libs/grdp/protocol/t125/ber/ber.go:168
}
WriteUniversalTag(TAG_BOOLEAN, false, w)
WriteLength(1, w)
core.WriteUInt8(bb, w)
}
func ReadApplicationTag(tag uint8, r io.Reader) (int, error) {
bb, _ := core.ReadUInt8(r)
if tag > 30 {
if bb != (CLASS_APPL|PC_CONSTRUCT)|TAG_MASK {
return 0, errors.New("ReadApplicationTag invalid data")
}
bb, _ := core.ReadUInt8(r)
if bb != tag {
return 0, errors.New("ReadApplicationTag bad tag")
}
} else {
if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
return 0, errors.New("ReadApplicationTag invalid data2")
}
}
return ReadLength(r)
}
func WriteApplicationTag(tag uint8, size int, w io.Writer) {
if tag > 30 {
core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|TAG_MASK, w)
core.WriteUInt8(tag, w)
WriteLength(size, w)
} else {
core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), w)
WriteLength(size, w)
}
}
func WriteEncodedDomainParams(data []byte, w io.Writer) {
WriteUniversalTag(TAG_SEQUENCE, true, w)View on GitHub (pinned to 95cc12e753)
Solutions
- Hex-dump the stream at this offset and compare against the expected (CLASS_APPL|PC_CONSTRUCT)|tag byte
- Check upstream parsers for off-by-one byte consumption causing misalignment
- Verify the target service is RDP and the negotiation sequence completed correctly
- If the server encodes small tags in long form, extend ReadApplicationTag to accept both encodings
Example fix
// before
if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
return 0, errors.New("ReadApplicationTag invalid data2")
}
// after
if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
return 0, fmt.Errorf("ReadApplicationTag invalid data2: expected 0x%02X, got 0x%02X", (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), bb)
} Defensive patterns
Strategy: validation
Validate before calling
// pre-check the short-form application tag byte
expected := byte((ber.CLASS_APPL | ber.PC_CONSTRUCT) | (ber.TAG_MASK & tag))
if buf[pos] != expected {
return fmt.Errorf("bad short-form application tag: got 0x%02X, want 0x%02X", buf[pos], expected)
} Try / catch
n, err := ber.ReadApplicationTag(tag, r)
if err != nil {
if strings.Contains(err.Error(), "invalid data2") {
return fmt.Errorf("unexpected PDU where application tag %d expected: %w", tag, err)
}
return err
} Prevention
- Trace upstream byte consumption to catch desync before this check
- Capture failing handshakes with Wireshark for byte-level comparison
- Confirm negotiation flags keep the server on the standard T.125 response path
When it happens
Trigger: ReadConnectResponse calling ReadApplicationTag with tag <= 30 when the first byte is not the matching single-byte application tag — e.g. a long-form tag byte, a different class, or complete misalignment.
Common situations: Desynced streams where content bytes are read as tag bytes; servers using long-form encoding for small tags; non-RDP services on port 3389 returning arbitrary bytes.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- ReadApplicationTag invalid data
- ReadApplicationTag bad tag
- invalid ber tag
- enumerate size is wrong, get %v, expect 1
- BER length may be 1 or 2
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/a121abd35f137f38.
Report an issue: GitHub.