{"record":{"id":"f35273cc5f31c952","repo":"shadow1ng/fscan","slug":"failed-to-get-os-name-s","errorCode":null,"errorMessage":"failed to get OS name: %s","messagePattern":"failed to get OS name: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/ms17010_exp.go","lineNumber":155,"sourceCode":"\t\treturn nil, nil, fmt.Errorf(\"failed to connect host: %s\", err)\n\t}\n\tvar ok bool\n\tdefer func() {\n\t\tif !ok {\n\t\t\t_ = conn.Close()\n\t\t}\n\t}()\n\terr = smbClientNegotiate(conn)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to negotiate: %s\", err)\n\t}\n\traw, header, err := smb1AnonymousLogin(conn)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to login with anonymous: %s\", err)\n\t}\n\t_, err = getOSName(raw)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to get OS name: %s\", err)\n\t}\n\t//fmt.Println(\"OS:\", osName)\n\theader, err = treeConnectAndX(conn, address, header.UserID)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to tree connect AndX: %s\", err)\n\t}\n\tok = true\n\treturn header, conn, nil\n}\n\nconst smbHeaderSize = 32\n\ntype smbHeader struct {\n\tServerComponent [4]byte\n\tSMBCommand      uint8\n\tErrorClass      uint8\n\tReserved        byte\n\tErrorCode       uint16","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/ms17010_exp.go#L137-L173","documentation":"This error wraps a failure of getOSName after the anonymous login reply is received (plugins/services/ms17010_exp.go:155). getOSName parses the UTF-16 native-OS string that starts 10 bytes after the SMB header (raw[smbHeaderSize+10:]) and scans until a 0x0000 terminator; it returns an error when the buffer runs out before finding one (io.ErrUnexpectedEOF / io.EOF from io.ReadFull). The library throws it because the login response did not carry a well-formed native OS string.","triggerScenarios":"smb1AnonymousConnectIPC receives a login response whose bytes after offset smbHeaderSize+10 do not contain the expected UTF-16 string terminated by 0x0000 — e.g. the response is too short (near or below 42 bytes) or the layout deviates (server sent an error response instead of a session-setup reply).","commonSituations":"Non-Windows or embedded SMB implementations (Samba variants, NAS, printers) that omit or relocate the Native OS field; servers replying with a DOS error-format response rather than the expected AndX reply; truncated responses from flaky networks.","solutions":["Dump the raw login response (hexdump) to confirm whether a Native OS string is present at the expected offset","Treat hosts failing this parse as non-Windows/odd SMB stacks and skip them for EternalBlue","Make the parser tolerant: check len(raw) >= smbHeaderSize+10 before scanning and return a descriptive error if too short","Verify the login actually succeeded (NT status in the header) before attempting the OS-string parse"],"exampleFix":"// before\n_, err = getOSName(raw)\nif err != nil {\n    return nil, nil, fmt.Errorf(\"failed to get OS name: %s\", err)\n}\n// after\nif len(raw) < smbHeaderSize+10 {\n    return nil, nil, fmt.Errorf(\"login response too short for OS name: %d bytes\", len(raw))\n}\nif _, err = getOSName(raw); err != nil {\n    return nil, nil, fmt.Errorf(\"failed to get OS name: %w\", err)\n}","handlingStrategy":"type-guard","validationCode":"func hasOSNameField(raw []byte) bool {\n    return len(raw) >= smbHeaderSize+10 // parser starts at raw[smbHeaderSize+10:]\n}","typeGuard":"func parseableLoginResponse(raw []byte) bool {\n    if len(raw) < smbHeaderSize+10 { return false }\n    return bytes.Equal(raw[0:4], []byte{0xFF, 0x53, 0x4D, 0x42}) // \\xffSMB\n}","tryCatchPattern":"raw, header, err := smb1AnonymousLogin(conn)\nif err == nil && !parseableLoginResponse(raw) {\n    // skip OS-name parsing; header may still be usable\n}\n_, err = getOSName(raw)\nif err != nil {\n    return fmt.Errorf(\"non-standard SMB stack (no Native OS string): %w\", err)\n}","preventionTips":["Don't require the OS string for hosts known to run Samba/embedded SMB stacks","Check response length before slicing offsets derived from smbHeaderSize","Verify the NT status in the response header before parsing the body","Use OS-name failure as a signal of non-Windows targets rather than a fatal condition"],"tags":["smb","parsing","response-shape","smb1","utf16"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}