shadow1ng/fscan · error

i18n.GetText("ms17010_base64_decode_failed"): %w

Error message

i18n.GetText("ms17010_base64_decode_failed"): %w

What it means

aesDecrypt wraps a base64.StdEncoding.DecodeString failure with the "ms17010_base64_decode_failed" message and the underlying error (%w). The plugin decrypts its payload/config data with this helper, so any input that is not valid canonical base64 makes the whole decrypt — and thus executeMS17010Exploit — fail.

Source

Thrown at plugins/services/ms17010.go:174

		output.WriteString(i18n.GetText("ms17010_exploit_shellcode_hint") + "\n")
		output.WriteString(i18n.GetText("ms17010_exploit_supported_modes") + "\n")
	}

	session.LogSuccess(i18n.Tr("ms17010_complete", target))

	return &ExploitResult{
		Success: true,
		Output:  output.String(),
	}
}

// 以下是完整的原始MS17010检测和利用代码,保持不变

// AES解密函数 (从legacy/Base.go复制)
func aesDecrypt(crypted string, key string) (string, error) {
	cryptedBytes, err := base64.StdEncoding.DecodeString(crypted)
	if err != nil {
		return "", fmt.Errorf("%s: %w", i18n.GetText("ms17010_base64_decode_failed"), err)
	}

	keyBytes := []byte(key)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", fmt.Errorf("%s: %w", i18n.GetText("ms17010_aes_cipher_failed"), err)
	}

	if len(cryptedBytes) < aes.BlockSize {
		return "", fmt.Errorf("%s", i18n.GetText("ms17010_ciphertext_too_short"))
	}

	mode := cipher.NewCBCDecrypter(block, keyBytes[:aes.BlockSize])
	mode.CryptBlocks(cryptedBytes, cryptedBytes)

	// 移除PKCS7填充
	padding := int(cryptedBytes[len(cryptedBytes)-1])
	if padding > len(cryptedBytes) || padding > aes.BlockSize {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Validate the payload is canonical std base64 before calling: base64.StdEncoding.DecodeString in a dry run or a regex ^[A-Za-z0-9+/]*={0,2}$.
  2. Strip whitespace/newlines from the payload before decryption.
  3. If the producer used URL-safe base64, re-encode or swap the decoder to base64.URLEncoding.
  4. Inspect the wrapped %w error with errors.Unwrap to see the exact CorruptInputError offset.

Example fix

// before
plain, err := aesDecrypt(payload, key)
// after: sanitize and disambiguate encoding
cleaned := strings.Map(func(r rune) rune {
    if unicode.IsSpace(r) { return -1 }
    return r
}, payload)
if b, err := base64.StdEncoding.DecodeString(cleaned); err != nil {
    return fmt.Errorf("payload not std base64: %w", err)
}
plain, err := aesDecrypt(cleaned, key)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := base64.StdEncoding.DecodeString(payload); err != nil {
    return fmt.Errorf("payload is not valid std base64: %w", err)
}

Try / catch

plain, err := aesDecrypt(payload, key)
if err != nil {
    var base64Err base64.CorruptInputError
    if errors.As(err, &base64Err) {
        return fmt.Errorf("bad base64 at offset %d", int64(base64Err))
    }
    return err
}

Prevention

When it happens

Trigger: Passing a crypted string containing whitespace, URL-safe base64 characters (-/ _), missing padding, or raw binary/hex to aesDecrypt (via executeMS17010Exploit).

Common situations: Payloads copy-pasted with spaces/newlines, data encoded with URLEncoding instead of StdEncoding, hex-encoded blobs mistakenly treated as base64, or corrupted config values.

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


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