Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "encoding/binary"
- "encoding/hex"
- "flag"
- "fmt"
- "net"
- "sync"
- "time"
- "strings"
- )
- var (
- negotiateProtocolRequest, _ = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
- sessionSetupRequest, _ = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
- treeConnectRequest, _ = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
- transNamedPipeRequest, _ = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
- trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
- )
- func checkHost(ip string, timeout int, flag1 bool) {
- // connecting to a host in LAN if reachable should be very quick
- conn, err := net.DialTimeout("tcp", ip+":445", time.Duration(timeout)*time.Second)
- if err != nil {
- if (flag1 != true) {
- fmt.Printf("failed to connect to %s\n", ip)
- }
- return
- }
- conn.SetDeadline(time.Now().Add(time.Duration(timeout)*time.Second))
- conn.Write(negotiateProtocolRequest)
- reply := make([]byte, 1024)
- // let alone half packet
- if n, err := conn.Read(reply); err != nil || n < 36 {
- return
- }
- if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
- // recv error
- return
- }
- conn.Write(sessionSetupRequest)
- n, err := conn.Read(reply)
- if err != nil || n < 36 {
- return
- }
- if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
- // recv error
- fmt.Printf("[E] Can't determine whether %s is vulnerable or not. Protocol SMB 1.0 is disabled?\n", ip)
- return
- }
- // extract OS info
- var os string
- sessionSetupResponse := reply[36:n]
- if wordCount := sessionSetupResponse[0]; wordCount != 0 {
- // find byte count
- byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
- if n != int(byteCount)+45 {
- fmt.Println("invalid session setup AndX response")
- } else {
- // two continous null byte as end of a unicode string
- for i := 10; i < len(sessionSetupResponse)-1; i++ {
- if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
- os = string(sessionSetupResponse[10:i])
- break
- }
- }
- }
- }
- userID := reply[32:34]
- treeConnectRequest[32] = userID[0]
- treeConnectRequest[33] = userID[1]
- // TODO change the ip in tree path though it doesn't matter
- conn.Write(treeConnectRequest)
- if n, err := conn.Read(reply); err != nil || n < 36 {
- return
- }
- treeID := reply[28:30]
- transNamedPipeRequest[28] = treeID[0]
- transNamedPipeRequest[29] = treeID[1]
- transNamedPipeRequest[32] = userID[0]
- transNamedPipeRequest[33] = userID[1]
- conn.Write(transNamedPipeRequest)
- if n, err := conn.Read(reply); err != nil || n < 36 {
- return
- }
- os = strings.Replace(os, "\u0000", "", -1)
- if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
- fmt.Printf("[+] %s (%s) is likely VULNERABLE to MS17-010!\n", ip, os)
- // detect present of DOUBLEPULSAR SMB implant
- trans2SessionSetupRequest[28] = treeID[0]
- trans2SessionSetupRequest[29] = treeID[1]
- trans2SessionSetupRequest[32] = userID[0]
- trans2SessionSetupRequest[33] = userID[1]
- conn.Write(trans2SessionSetupRequest)
- if n, err := conn.Read(reply); err != nil || n < 36 {
- return
- }
- if reply[34] == 0x51 {
- fmt.Printf("[!] DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
- }
- } else {
- fmt.Printf("[-] %s (%s) stays in safety\n", ip, os)
- }
- }
- func incIP(ip net.IP) {
- for j := len(ip) - 1; j >= 0; j-- {
- ip[j]++
- if ip[j] > 0 {
- break
- }
- }
- }
- func main() {
- fmt.Println("A Go program for detecting if host(s) is vulnerable to SMB exploit(MS17-010)")
- fmt.Println("Compiled from https://github.com/jflyup/goMS17-010")
- fmt.Println()
- host := flag.String("i", "", "single ip address")
- timeout := flag.Int("t", 2, "timeout on connection, in seconds")
- netCIDR := flag.String("n", "", "CIDR notation of a network")
- misserrorPtr := flag.Bool("e", false, "Do not show hosts with a connection error in the console (default False)")
- flag.Parse()
- if *host != "" {
- fmt.Printf("Using timeout %s\n", time.Duration(*timeout)*time.Second)
- fmt.Println()
- checkHost(*host, *timeout, false)
- return
- }
- if *netCIDR != "" && *host == "" {
- ip, ipNet, err := net.ParseCIDR(*netCIDR)
- if err != nil {
- fmt.Println("invalid CIDR")
- return
- }
- fmt.Printf("Using timeout %s\n", time.Duration(*timeout)*time.Second)
- fmt.Println()
- var wg sync.WaitGroup
- for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
- wg.Add(1)
- go func(ip string) {
- defer wg.Done()
- checkHost(ip, *timeout, *misserrorPtr)
- }(ip.String())
- }
- wg.Wait()
- }
- if *netCIDR == "" && *host == "" {
- fmt.Println("Usage:")
- fmt.Println("ms17-010.exe [-e -t <seconds>] -i HOST")
- fmt.Println("or")
- fmt.Println("ms17-010.exe [-e -t <seconds>] -n CIDR_prefix")
- fmt.Println()
- fmt.Println("-i single ip address")
- fmt.Println("-n CIDR notation of a network")
- fmt.Println()
- fmt.Println("-e Do not show hosts with a connection error in the console (default False)")
- fmt.Println("-t timeout on connection, in seconds (default 2)")
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement