Advertisement
Guest User

ms17-010.go

a guest
May 19th, 2017
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 5.92 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "encoding/binary"
  5.     "encoding/hex"
  6.     "flag"
  7.     "fmt"
  8.     "net"
  9.     "sync"
  10.     "time"
  11.     "strings"
  12. )
  13.  
  14. var (
  15.     negotiateProtocolRequest, _  = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
  16.     sessionSetupRequest, _       = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
  17.     treeConnectRequest, _        = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
  18.     transNamedPipeRequest, _     = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
  19.     trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
  20. )
  21.  
  22. func checkHost(ip string, timeout int, flag1 bool) {
  23.     // connecting to a host in LAN if reachable should be very quick
  24.     conn, err := net.DialTimeout("tcp", ip+":445", time.Duration(timeout)*time.Second)
  25.     if err != nil {
  26.         if (flag1 != true) {
  27.             fmt.Printf("failed to connect to %s\n", ip)
  28.         }
  29.         return
  30.     }
  31.  
  32.     conn.SetDeadline(time.Now().Add(time.Duration(timeout)*time.Second))
  33.     conn.Write(negotiateProtocolRequest)
  34.     reply := make([]byte, 1024)
  35.     // let alone half packet
  36.     if n, err := conn.Read(reply); err != nil || n < 36 {
  37.         return
  38.     }
  39.  
  40.     if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
  41.         // recv error
  42.         return
  43.     }
  44.  
  45.     conn.Write(sessionSetupRequest)
  46.  
  47.     n, err := conn.Read(reply)
  48.     if err != nil || n < 36 {
  49.         return
  50.     }
  51.  
  52.     if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
  53.         // recv error
  54.         fmt.Printf("[E] Can't determine whether %s is vulnerable or not. Protocol SMB 1.0 is disabled?\n", ip)
  55.         return
  56.     }
  57.  
  58.     // extract OS info
  59.     var os string
  60.     sessionSetupResponse := reply[36:n]
  61.     if wordCount := sessionSetupResponse[0]; wordCount != 0 {
  62.         // find byte count
  63.         byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
  64.         if n != int(byteCount)+45 {
  65.             fmt.Println("invalid session setup AndX response")
  66.         } else {
  67.             // two continous null byte as end of a unicode string
  68.             for i := 10; i < len(sessionSetupResponse)-1; i++ {
  69.                 if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
  70.                     os = string(sessionSetupResponse[10:i])
  71.                     break
  72.                 }
  73.             }
  74.         }
  75.  
  76.     }
  77.     userID := reply[32:34]
  78.     treeConnectRequest[32] = userID[0]
  79.     treeConnectRequest[33] = userID[1]
  80.     // TODO change the ip in tree path though it doesn't matter
  81.     conn.Write(treeConnectRequest)
  82.  
  83.     if n, err := conn.Read(reply); err != nil || n < 36 {
  84.         return
  85.     }
  86.  
  87.     treeID := reply[28:30]
  88.     transNamedPipeRequest[28] = treeID[0]
  89.     transNamedPipeRequest[29] = treeID[1]
  90.     transNamedPipeRequest[32] = userID[0]
  91.     transNamedPipeRequest[33] = userID[1]
  92.  
  93.     conn.Write(transNamedPipeRequest)
  94.     if n, err := conn.Read(reply); err != nil || n < 36 {
  95.         return
  96.     }
  97.  
  98.     os = strings.Replace(os, "\u0000", "", -1)
  99.  
  100.     if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
  101.         fmt.Printf("[+] %s (%s) is likely VULNERABLE to MS17-010!\n", ip, os)
  102.  
  103.         // detect present of DOUBLEPULSAR SMB implant
  104.         trans2SessionSetupRequest[28] = treeID[0]
  105.         trans2SessionSetupRequest[29] = treeID[1]
  106.         trans2SessionSetupRequest[32] = userID[0]
  107.         trans2SessionSetupRequest[33] = userID[1]
  108.  
  109.         conn.Write(trans2SessionSetupRequest)
  110.  
  111.         if n, err := conn.Read(reply); err != nil || n < 36 {
  112.             return
  113.         }
  114.  
  115.         if reply[34] == 0x51 {
  116.             fmt.Printf("[!] DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
  117.         }
  118.  
  119.     } else {
  120.         fmt.Printf("[-] %s (%s) stays in safety\n", ip, os)
  121.     }
  122.  
  123. }
  124.  
  125. func incIP(ip net.IP) {
  126.     for j := len(ip) - 1; j >= 0; j-- {
  127.         ip[j]++
  128.         if ip[j] > 0 {
  129.             break
  130.         }
  131.     }
  132. }
  133.  
  134. func main() {
  135.     fmt.Println("A Go program for detecting if host(s) is vulnerable to SMB exploit(MS17-010)")
  136.     fmt.Println("Compiled from https://github.com/jflyup/goMS17-010")
  137.     fmt.Println()
  138.  
  139.     host := flag.String("i", "", "single ip address")
  140.     timeout := flag.Int("t", 2, "timeout on connection, in seconds")
  141.     netCIDR := flag.String("n", "", "CIDR notation of a network")
  142.     misserrorPtr := flag.Bool("e", false, "Do not show hosts with a connection error in the console (default False)")
  143.     flag.Parse()
  144.  
  145.     if *host != "" {
  146.         fmt.Printf("Using timeout %s\n", time.Duration(*timeout)*time.Second)
  147.         fmt.Println()
  148.         checkHost(*host, *timeout, false)
  149.         return
  150.     }
  151.  
  152.     if *netCIDR != "" && *host == "" {
  153.         ip, ipNet, err := net.ParseCIDR(*netCIDR)
  154.         if err != nil {
  155.             fmt.Println("invalid CIDR")
  156.             return
  157.         }
  158.  
  159.         fmt.Printf("Using timeout %s\n", time.Duration(*timeout)*time.Second)
  160.         fmt.Println()
  161.  
  162.         var wg sync.WaitGroup
  163.  
  164.         for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
  165.             wg.Add(1)
  166.             go func(ip string) {
  167.                 defer wg.Done()
  168.                 checkHost(ip, *timeout, *misserrorPtr)
  169.             }(ip.String())
  170.         }
  171.  
  172.         wg.Wait()
  173.     }
  174.     if *netCIDR == "" && *host == "" {
  175.         fmt.Println("Usage:")
  176.         fmt.Println("ms17-010.exe [-e -t <seconds>] -i HOST")
  177.         fmt.Println("or")
  178.         fmt.Println("ms17-010.exe [-e -t <seconds>] -n CIDR_prefix")
  179.         fmt.Println()
  180.         fmt.Println("-i single ip address")
  181.         fmt.Println("-n CIDR notation of a network")
  182.         fmt.Println()
  183.         fmt.Println("-e Do not show hosts with a connection error in the console (default False)")
  184.         fmt.Println("-t timeout on connection, in seconds (default 2)")
  185.     }
  186. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement