|
@@ -26,10 +26,9 @@ package kyoketsu
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "log"
|
|
|
"net"
|
|
|
- "strconv"
|
|
|
- "strings"
|
|
|
- "sync"
|
|
|
+ "syscall"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
@@ -38,10 +37,10 @@ Need to work with with a database schema in mind, and revolve functionality arou
|
|
|
*/
|
|
|
|
|
|
type Host struct {
|
|
|
- Fqdn string // The FQDN of the address targeted as per the systems default resolver
|
|
|
- IpAddress string // the IPv4 address (no ipv6 support yet)
|
|
|
- PingResponse bool // boolean value representing if the host responded to ICMP
|
|
|
- ListeningPorts map[int]string // list of maps depicting a port number -> service name
|
|
|
+ Fqdn string // The FQDN of the address targeted as per the systems default resolver
|
|
|
+ IpAddress string // the IPv4 address (no ipv6 support yet)
|
|
|
+ PingResponse bool // boolean value representing if the host responded to ICMP
|
|
|
+ ListeningPorts []int // list of maps depicting a port number -> service name
|
|
|
PortString string
|
|
|
Id int64
|
|
|
}
|
|
@@ -50,39 +49,17 @@ type Host struct {
|
|
|
Perform a concurrent TCP port dial on a host, either by domain name or IP.
|
|
|
|
|
|
:param addr: the address of fqdn to scan
|
|
|
- :param portmap: a key/value pair of port numbers to service names to dial the host with
|
|
|
+ :param ports a list of port numbers to dial the host with
|
|
|
*/
|
|
|
-func PortWalk(addr string, portmap map[int]string) Host {
|
|
|
- wg := &sync.WaitGroup{}
|
|
|
- mu := &sync.Mutex{}
|
|
|
- out := map[int]string{}
|
|
|
- for p, s := range portmap {
|
|
|
- wg.Add(1)
|
|
|
- go func(target string, p int, s string, mu *sync.Mutex) {
|
|
|
- defer wg.Done()
|
|
|
- scanout := singlePortScan(target, p, s)
|
|
|
- if scanout.Listening {
|
|
|
- mu.Lock()
|
|
|
- out[scanout.PortNumber] = scanout.Service
|
|
|
- mu.Unlock()
|
|
|
- }
|
|
|
- }(addr, p, s, mu)
|
|
|
- }
|
|
|
- wg.Wait()
|
|
|
- var dnames string
|
|
|
- var portstring string
|
|
|
- dns, _ := net.LookupAddr(addr)
|
|
|
- dnames = strings.Join(dns, ", ")
|
|
|
- for key, _ := range out {
|
|
|
- portstring = portstring + "," + strconv.Itoa(key)
|
|
|
- }
|
|
|
- return Host{
|
|
|
- IpAddress: addr,
|
|
|
- Fqdn: dnames,
|
|
|
- PingResponse: false,
|
|
|
- ListeningPorts: out,
|
|
|
- PortString: portstring,
|
|
|
+func PortWalk(addr string, ports []int) []int {
|
|
|
+ out := []int{}
|
|
|
+ for i := range ports {
|
|
|
+ p := singlePortScan(addr, ports[i])
|
|
|
+ if p != 0 {
|
|
|
+ out = append(out, p)
|
|
|
+ }
|
|
|
}
|
|
|
+ return out
|
|
|
|
|
|
}
|
|
|
|
|
@@ -98,13 +75,15 @@ type PortScanResult struct {
|
|
|
Wrapper function to dependency inject the resource for a port -> service name mapping.
|
|
|
May move to a database, or something.
|
|
|
*/
|
|
|
-func RetrieveScanDirectives() map[int]string {
|
|
|
- var portmap = map[int]string{
|
|
|
+func RetrieveScanDirectives() []int {
|
|
|
+
|
|
|
+ var portmap = []int{22, 443, 8080, 4379, 445, 53, 153, 27017}
|
|
|
+ /*map[int]string{
|
|
|
22: "ssh", 23: "telnet", 53: "dns", 80: "http", 25: "smtp", 443: "https", 8080: "unknown", 8081: "unknown",
|
|
|
8082: "unknown", 8085: "unknown", 8090: "unknown", 8091: "unknown", 9010: "unknown", 9012: "unknown", 10000: "unknown", 1433: "microsoft_sql",
|
|
|
3306: "mysql", 3050: "firebird", 5432: "postgres", 27017: "mongo", 6379: "redis", 8005: "tomcat", 6443: "kubernetes", 853: "dns-tls", 143: "imap",
|
|
|
389: "ldap", 445: "smb", 543: "kerberos", 544: "kerberos", 749: "kerberos", 760: "kerberos",
|
|
|
- }
|
|
|
+ } */
|
|
|
return portmap
|
|
|
}
|
|
|
|
|
@@ -115,13 +94,16 @@ Scans a single host on a single port
|
|
|
:param port: the port number to dial
|
|
|
:param svcs: the name of the service that the port is associate with
|
|
|
*/
|
|
|
-func singlePortScan(addr string, port int, svcs string) PortScanResult {
|
|
|
- address := fmt.Sprintf("%v:%d", addr, port)
|
|
|
- _, err := net.DialTimeout("tcp", address, 2*time.Second)
|
|
|
+func singlePortScan(addr string, port int) int {
|
|
|
+
|
|
|
+ conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%d", addr, port), 2*time.Second)
|
|
|
if err != nil {
|
|
|
- return PortScanResult{PortNumber: port, Protocol: "tcp", Service: svcs, Listening: false}
|
|
|
+ return 0
|
|
|
+ // return PortScanResult{PortNumber: port, Protocol: "tcp", Listening: false}
|
|
|
}
|
|
|
- return PortScanResult{PortNumber: port, Protocol: "tcp", Service: svcs, Listening: true}
|
|
|
+ conn.Close()
|
|
|
+ return port
|
|
|
+ //return PortScanResult{PortNumber: port, Protocol: "tcp", Listening: true}
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -130,16 +112,57 @@ Perform a port scan sweep across an entire subnet
|
|
|
:param ip: the IPv4 address WITH CIDR notation
|
|
|
:param portmap: the mapping of ports to scan with (port number mapped to protocol name)
|
|
|
*/
|
|
|
-func NetSweep(ips []net.IP, portmap map[int]string, scanned chan Host) {
|
|
|
- wg := &sync.WaitGroup{}
|
|
|
+func NetSweep(ips []net.IP, ports []int) []Host {
|
|
|
+ scanned := make(chan Host)
|
|
|
for i := range ips {
|
|
|
- wg.Add(1)
|
|
|
- go func(target string, wg *sync.WaitGroup) {
|
|
|
- defer wg.Done()
|
|
|
- scanned <- PortWalk(target, portmap)
|
|
|
+ go func(target string, portnum []int) {
|
|
|
+ scanned <- Host{
|
|
|
+ IpAddress: target,
|
|
|
+ ListeningPorts: PortWalk(target, portnum),
|
|
|
+ }
|
|
|
+
|
|
|
+ }(ips[i].String(), ports)
|
|
|
+ }
|
|
|
+ var hosts []Host
|
|
|
+ for x := range scanned {
|
|
|
+ fmt.Printf("%+v\n", x)
|
|
|
+
|
|
|
+ hosts = append(hosts, x)
|
|
|
+ }
|
|
|
+
|
|
|
+ return hosts
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
- }(ips[i].String(), wg)
|
|
|
+/*
|
|
|
+Create a new TCP dialer to share in a goroutine
|
|
|
+*/
|
|
|
+func NewDialer() net.Dialer {
|
|
|
+ return net.Dialer{}
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+Create a new low level networking interface socket
|
|
|
+:param intf: the name of the interface to bind the socket to
|
|
|
+*/
|
|
|
+func NewTCPSock(interfaceName string) *syscall.SockaddrLinklayer {
|
|
|
+ sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, syscall.ETH_P_IP)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatal(err, " Could not create raw AF_PACKET socket.\n")
|
|
|
+ }
|
|
|
+ defer syscall.Close(sock)
|
|
|
+ intf, err := net.InterfaceByName(interfaceName)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatal(err, " Couldnt locate that interface. Are you sure you mean to pass ", interfaceName, " ?")
|
|
|
}
|
|
|
- wg.Wait()
|
|
|
+ return &syscall.SockaddrLinklayer{
|
|
|
+ Protocol: htons(syscall.ETH_P_IP),
|
|
|
+ Ifindex: intf.Index,
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
+// htons converts a uint16 from host- to network byte order.
|
|
|
+func htons(i uint16) uint16 {
|
|
|
+ return (i<<8)&0xff00 | i>>8
|
|
|
}
|