mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

- 新增smbinfo插件,专门用于SMB协议信息收集和操作系统检测 - 实现完整的NTLM Type 2消息解析,提取详细的系统信息 - 支持Windows版本识别、计算机名、域名等信息提取 - 采用标准插件输出格式,与其他插件保持一致 - 保留原始NetBIOS插件,两个插件功能互补 - 优化SMB协议数据包处理,提升兼容性和稳定性
108 lines
2.6 KiB
Go
108 lines
2.6 KiB
Go
package Plugins
|
||
|
||
import (
|
||
"crypto/aes"
|
||
"crypto/cipher"
|
||
"encoding/base64"
|
||
"errors"
|
||
"fmt"
|
||
"net"
|
||
)
|
||
|
||
// ReadBytes 从连接读取数据直到EOF或错误 - 改进的SMB协议处理
|
||
func ReadBytes(conn net.Conn) ([]byte, error) {
|
||
// 首先读取NetBIOS头部(4字节)来确定消息长度
|
||
headerBuf := make([]byte, 4)
|
||
n, err := conn.Read(headerBuf)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取NetBIOS头部失败: %v", err)
|
||
}
|
||
if n != 4 {
|
||
return nil, fmt.Errorf("NetBIOS头部长度不足: %d", n)
|
||
}
|
||
|
||
// 解析NetBIOS消息长度(大端序)
|
||
messageLength := int(headerBuf[0])<<24 | int(headerBuf[1])<<16 | int(headerBuf[2])<<8 | int(headerBuf[3])
|
||
|
||
// 防止过大的消息长度(安全检查)
|
||
if messageLength > 1024*1024 { // 1MB限制
|
||
return nil, fmt.Errorf("消息长度过大: %d", messageLength)
|
||
}
|
||
|
||
// 如果消息长度为0,只返回头部
|
||
if messageLength == 0 {
|
||
return headerBuf, nil
|
||
}
|
||
|
||
// 读取完整消息体
|
||
messageBuf := make([]byte, messageLength)
|
||
totalRead := 0
|
||
for totalRead < messageLength {
|
||
n, err := conn.Read(messageBuf[totalRead:])
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取消息体失败(已读取%d/%d字节): %v", totalRead, messageLength, err)
|
||
}
|
||
totalRead += n
|
||
}
|
||
|
||
// 返回完整消息(头部+消息体)
|
||
result := make([]byte, 0, 4+messageLength)
|
||
result = append(result, headerBuf...)
|
||
result = append(result, messageBuf...)
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// 默认AES加密密钥
|
||
var key = "0123456789abcdef"
|
||
|
||
|
||
// AesDecrypt 使用AES-CBC模式解密字符串
|
||
func AesDecrypt(crypted string, key string) (string, error) {
|
||
// base64解码
|
||
cryptedBytes, err := base64.StdEncoding.DecodeString(crypted)
|
||
if err != nil {
|
||
return "", fmt.Errorf("base64解码失败: %v", err)
|
||
}
|
||
|
||
keyBytes := []byte(key)
|
||
|
||
// 创建解密块
|
||
block, err := aes.NewCipher(keyBytes)
|
||
if err != nil {
|
||
return "", fmt.Errorf("创建解密块失败: %v", err)
|
||
}
|
||
|
||
// 创建CBC解密模式
|
||
blockSize := block.BlockSize()
|
||
blockMode := cipher.NewCBCDecrypter(block, keyBytes[:blockSize])
|
||
|
||
// 解密数据
|
||
origData := make([]byte, len(cryptedBytes))
|
||
blockMode.CryptBlocks(origData, cryptedBytes)
|
||
|
||
// 去除填充
|
||
origData, err = PKCS7UnPadding(origData)
|
||
if err != nil {
|
||
return "", fmt.Errorf("去除PKCS7填充失败: %v", err)
|
||
}
|
||
|
||
return string(origData), nil
|
||
}
|
||
|
||
|
||
// PKCS7UnPadding 去除PKCS7填充
|
||
func PKCS7UnPadding(data []byte) ([]byte, error) {
|
||
length := len(data)
|
||
if length == 0 {
|
||
return nil, errors.New("数据长度为0")
|
||
}
|
||
|
||
padding := int(data[length-1])
|
||
if padding > length {
|
||
return nil, errors.New("填充长度无效")
|
||
}
|
||
|
||
return data[:length-padding], nil
|
||
}
|