shadow1ng/fscan · error
i18n.GetText("ms17010_aes_cipher_failed"): %w
Error message
i18n.GetText("ms17010_aes_cipher_failed"): %w What it means
After base64 decoding, aesDecrypt builds an AES cipher via aes.NewCipher(keyBytes). Go returns an error when the key is not 16, 24, or 32 bytes; the plugin wraps that error with "ms17010_aes_cipher_failed". This is purely a key-length problem — the ciphertext is not yet involved.
Source
Thrown at plugins/services/ms17010.go:180
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 {
return "", fmt.Errorf("%s", i18n.GetText("ms17010_invalid_padding"))
}
for i := len(cryptedBytes) - padding; i < len(cryptedBytes); i++ {
if cryptedBytes[i] != byte(padding) {
return "", fmt.Errorf("%s", i18n.GetText("ms17010_padding_check_failed"))View on GitHub (pinned to 95cc12e753)
Solutions
- Check len([]byte(key)) is exactly 16, 24, or 32 before calling; log the length on failure.
- If the key is hex-encoded, hex.DecodeString it first to get the raw 16/24/32 bytes.
- Pad or derive the key to the required size with a KDF (e.g. sha256 or PBKDF2) instead of manual padding.
- Match the cipher variant to the key size: AES-128 (16B), AES-192 (24B), AES-256 (32B).
Example fix
// before
key := cfg.MS17010Key // could be any length
plain, err := aesDecrypt(payload, key)
// after: enforce key size
keyBytes := []byte(cfg.MS17010Key)
if n := len(keyBytes); n != 16 && n != 24 && n != 32 {
return fmt.Errorf("aes key must be 16/24/32 bytes, got %d", n)
}
plain, err := aesDecrypt(payload, cfg.MS17010Key) Defensive patterns
Strategy: validation
Validate before calling
if n := len([]byte(key)); n != 16 && n != 24 && n != 32 {
return fmt.Errorf("aes key must be 16/24/32 bytes, got %d", n)
} Try / catch
if _, err := aes.NewCipher([]byte(key)); err != nil {
return fmt.Errorf("invalid aes key: %w", err)
} Prevention
- Store keys as raw 16/24/32-byte material, not hex/base64 strings
- Document which AES variant (128/192/256) the plugin expects
- Validate key length at config load time
When it happens
Trigger: Calling aesDecrypt (via executeMS17010Exploit or the init-registered path) with a key string whose byte length is not 16/24/32 — e.g. empty key, short passphrase, or key with multi-byte UTF-8 characters changing the byte count.
Common situations: Configuring AES-128 code with a 256-bit key or vice versa, storing the key hex-encoded instead of raw, or trimming/misspelling the key in config.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ms17010_padding_check_failed
- i18n.GetText("ms17010_base64_decode_failed"): %w
- i18n.GetText("ms17010_ciphertext_too_short")
- ms17010_invalid_padding
- i18n.GetText("ms17010_not_vulnerable")
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/4f3c94079ff7dc3e.
Report an issue: GitHub.