shadow1ng/fscan · error

failed to get SMB1 response about header: %s

Error message

failed to get SMB1 response about header: %s

What it means

This error is returned by smb1GetResponse when reading the SMB message body of the advertised size fails via io.ReadFull (plugins/services/ms17010_exp.go:210). The NetBIOS header promised `size` bytes but the connection closed, reset, or timed out before all of them arrived. The library throws it because a partial SMB frame cannot be parsed into a header.

Source

Thrown at plugins/services/ms17010_exp.go:210

	}
	typ := buf[0]
	if typ != 0x00 {
		const format = "invalid message type 0x%02X in SMB1 response"
		return nil, nil, fmt.Errorf(format, typ)
	}
	sizeBuf := make([]byte, 4)
	copy(sizeBuf[1:], buf[1:])
	size := int(binary.BigEndian.Uint32(sizeBuf))
	// 畸形响应(size < SMB 头长度)会导致后续 buf[:smbHeaderSize] 越界 panic
	if size < smbHeaderSize {
		return nil, nil, fmt.Errorf("SMB1 response too short: %d bytes", size)
	}
	// SMB
	buf = make([]byte, size)
	_, err = io.ReadFull(conn, buf)
	if err != nil {
		const format = "failed to get SMB1 response about header: %s"
		return nil, nil, fmt.Errorf(format, err)
	}
	smbHeader := smbHeader{}
	reader := bytes.NewReader(buf[:smbHeaderSize])
	err = binary.Read(reader, binary.LittleEndian, &smbHeader)
	if err != nil {
		const format = "failed to parse SMB1 response header: %s"
		return nil, nil, fmt.Errorf(format, err)
	}
	return buf, &smbHeader, nil
}

func smbClientNegotiate(conn net.Conn) error {
	buf := bytes.Buffer{}

	// --------NetBIOS Session Service--------

	// message type
	buf.WriteByte(0x00)

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Check the wrapped error: reset/EOF means peer aborted mid-frame; deadline exceeded means slow response to a large request
  2. Retry on a fresh connection; partial frames are never recoverable in place
  3. Reduce request sizes or increase the read deadline when probing slow/loaded targets
  4. Watch for repeated occurrences from one host — it may be dropping large packets (MTU/IDS interference)

Example fix

// before
_, err = io.ReadFull(conn, buf)
if err != nil {
    return nil, nil, fmt.Errorf("failed to get SMB1 response about header: %s", err)
}
// after
n, err := io.ReadFull(conn, buf)
if err != nil {
    return nil, nil, fmt.Errorf("failed to get SMB1 response about header (got %d/%d bytes): %w", n, size, err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Large responses need more headroom; set a generous deadline before the call
_ = conn.SetReadDeadline(time.Now().Add(15 * time.Second))
raw, header, err := smb1GetResponse(conn)
if err != nil && errors.Is(err, os.ErrDeadlineExceeded) {
    // retry once with a fresh connection
}

Type guard

func isShortRead(err error) bool {
    return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF)
}

Try / catch

raw, _, err := smb1GetResponse(conn)
if err != nil {
    if isShortRead(err) || errors.Is(err, os.ErrDeadlineExceeded) {
        conn.Close()
        conn, err = reconnect(address) // fresh connection; partial frames are unrecoverable
        if err != nil { return err }
        return smb1GetResponse(conn)
    }
    return err
}

Prevention

When it happens

Trigger: After successfully reading the 4-byte NetBIOS header with a valid type and size >= 32, the peer delivers fewer than `size` bytes: connection reset mid-frame, read deadline (10s) expiring during a large response, or server crash while flushing the reply.

Common situations: Patched or crashing hosts that reset the connection while sending a large reply (e.g. the 0x438-byte NT Trans response); slow targets where the 10s deadline expires partway through the body; IDS/IPS or MTU issues truncating large frames.

Related errors


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