shadow1ng/fscan · error

mssql: packet too large

Error message

mssql: packet too large

What it means

mssqlWritePacket serializes a whole TDS message into a single packet, whose 8-byte header stores the size as a 16-bit big-endian value (max 0xffff). If the payload plus the 8-byte header exceeds 65535 bytes, no valid single packet can be built and the write fails with this error.

Source

Thrown at plugins/services/mssql_raw.go:411

	return next, nil
}

func mssqlReadUSVarChar(payload []byte, pos int) (string, int, error) {
	if pos+2 > len(payload) {
		return "", pos, fmt.Errorf("mssql: truncated us varchar")
	}
	chars := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
	pos += 2
	size := chars * 2
	if pos+size > len(payload) {
		return "", pos, fmt.Errorf("mssql: invalid us varchar size")
	}
	return mssqlDecodeUCS2(payload[pos : pos+size]), pos + size, nil
}

func mssqlWritePacket(w io.Writer, packetType byte, payload []byte) error {
	if len(payload)+8 > 0xffff {
		return fmt.Errorf("mssql: packet too large")
	}
	header := []byte{packetType, tdsStatusEOM, 0, 0, 0, 0, 1, 0}
	binary.BigEndian.PutUint16(header[2:4], uint16(len(payload)+8))
	if _, err := w.Write(header); err != nil {
		return err
	}
	_, err := w.Write(payload)
	return err
}

func mssqlReadMessage(r io.Reader) (byte, []byte, error) {
	var packetType byte
	var payload []byte
	for {
		header := make([]byte, 8)
		if _, err := io.ReadFull(r, header); err != nil {
			return 0, nil, err
		}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Shorten the input: trim usernames, passwords, or option data sent in the login/prelogin payload.
  2. Split the payload into multiple packets with EOM set only on the last one instead of one oversized packet.
  3. Validate payload size before calling mssqlWritePacket (len(payload) <= 0xffff-8).
  4. Reject pathological credential entries upstream in the brute-force wordlist loader.

Example fix

// before
payload := mssqlUCS2(user) + mssqlUCS2(pass) // can exceed 65527 bytes
if err := mssqlWritePacket(w, tdsTypeLogin7, payload); err != nil { ... }
// after
if len(payload)+8 > 0xffff {
    return fmt.Errorf("login payload too large: %d bytes", len(payload))
}
if err := mssqlWritePacket(w, tdsTypeLogin7, payload); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

if len(payload)+8 > 0xffff {
    return fmt.Errorf("payload too large for single TDS packet: %d", len(payload))
}

Try / catch

if err := mssqlWritePacket(w, pktType, payload); err != nil {
    if strings.Contains(err.Error(), "packet too large") {
        // split payload into multiple packets or shrink inputs
    }
}

Prevention

When it happens

Trigger: Calling mssqlSendPrelogin or mssqlSendLogin7 with a payload that, together with the 8-byte TDS header, exceeds 65535 bytes — e.g. an extremely long username/password or option data encoded in the login packet.

Common situations: Credentials containing enormous strings (fuzzed or misconfigured wordlist entries); building a prelogin/login with many long option entries; misuse of the low-level writer with an oversized buffer.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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