shadow1ng/fscan · error
Bad integer tag
Error message
Bad integer tag
What it means
ReadInteger parses a BER INTEGER. It first validates the universal tag byte equals TAG_INTEGER; a mismatch means the stream does not contain an integer where one is expected, so this error is returned. This typically indicates a malformed or misaligned CONNECT_RESPONSE or domain parameters blob.
Source
Thrown at libs/grdp/protocol/t125/ber/ber.go:104
}
} else {
ret = int(size)
}
return ret, nil
}
func WriteLength(size int, w io.Writer) {
if size > 0x7f {
core.WriteUInt8(0x82, w)
core.WriteUInt16BE(uint16(size), w)
} else {
core.WriteUInt8(uint8(size), w)
}
}
func ReadInteger(r io.Reader) (int, error) {
if !ReadUniversalTag(TAG_INTEGER, false, r) {
return 0, errors.New("Bad integer tag")
}
size, _ := ReadLength(r)
switch size {
case 1:
num, _ := core.ReadUInt8(r)
return int(num), nil
case 2:
num, _ := core.ReadUint16BE(r)
return int(num), nil
case 3:
integer1, _ := core.ReadUInt8(r)
integer2, _ := core.ReadUint16BE(r)
return int(integer2) + (int(integer1) << 16), nil
case 4:
num, _ := core.ReadUInt32BE(r)
return int(num), nil
default:
return 0, errors.New("wrong size")View on GitHub (pinned to 95cc12e753)
Solutions
- Capture the raw X.224/T.125 exchange in Wireshark and compare the CONNECT_RESPONSE layout to the T.125 spec
- Verify earlier fields parsed the correct byte counts — a desync upstream makes this tag read garbage
- Confirm the target host/port actually runs an RDP server
- Update grdp; server encoder variants may place fields differently than this parser assumes
Example fix
// before
if !ReadUniversalTag(TAG_INTEGER, false, r) {
return 0, errors.New("Bad integer tag")
}
// after
if !ReadUniversalTag(TAG_INTEGER, false, r) {
return 0, fmt.Errorf("Bad integer tag: expected INTEGER (0x02), got 0x%02X", lastReadByte)
} Defensive patterns
Strategy: validation
Validate before calling
// confirm the byte is an INTEGER tag before calling ReadInteger
if buf[pos] != 0x02 {
return fmt.Errorf("not an INTEGER tag at offset %d: 0x%02X", pos, buf[pos])
} Try / catch
n, err := ber.ReadInteger(r)
if err != nil {
if strings.Contains(err.Error(), "Bad integer tag") {
// stream is not a well-formed T.125 response; abort handshake cleanly
return ErrNotRdpServer
}
return err
} Prevention
- Probe the endpoint for RDP support before the handshake
- Keep byte-level debug logging of negotiation to spot desyncs
- Match X.224 negotiation flags to the server to keep the response well-formed
When it happens
Trigger: ReadDomainParameters or ReadConnectResponse calling ReadInteger when the byte at the integer field position is not the TAG_INTEGER universal tag.
Common situations: Connecting to a service that is not RDP; protocol desync from mismatched negotiation flags shifting field boundaries; proxies or middleboxes altering the byte stream.
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
- invalid ber tag
- enumerate size is wrong, get %v, expect 1
- BER length may be 1 or 2
- wrong size
- ReadApplicationTag invalid data
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/a4287cf0346be69b.
Report an issue: GitHub.