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

  1. Check len([]byte(key)) is exactly 16, 24, or 32 before calling; log the length on failure.
  2. If the key is hex-encoded, hex.DecodeString it first to get the raw 16/24/32 bytes.
  3. Pad or derive the key to the required size with a KDF (e.g. sha256 or PBKDF2) instead of manual padding.
  4. 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

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


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