scanner.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. GNU GENERAL PUBLIC LICENSE
  3. Version 3, 29 June 2007
  4. kyoketsu, a Client-To-Client Network Enumeration System
  5. Copyright (C) 2024 Russell Hrubesky, ChiralWorks Software LLC
  6. Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
  7. Everyone is permitted to copy and distribute verbatim copies
  8. of this license document, but changing it is not allowed.
  9. This program is free software: you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation, either version 3 of the License,
  12. or (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. See the GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package kyoketsu
  21. import (
  22. "fmt"
  23. "log"
  24. "net"
  25. "syscall"
  26. "time"
  27. )
  28. /*
  29. Need to work with with a database schema in mind, and revolve functionality around that
  30. */
  31. type Host struct {
  32. Fqdn string // The FQDN of the address targeted as per the systems default resolver
  33. IpAddress string // the IPv4 address (no ipv6 support yet)
  34. PingResponse bool // boolean value representing if the host responded to ICMP
  35. ListeningPorts []int // list of maps depicting a port number -> service name
  36. PortString string
  37. Id int64
  38. }
  39. /*
  40. Perform a concurrent TCP port dial on a host, either by domain name or IP.
  41. :param addr: the address of fqdn to scan
  42. :param ports a list of port numbers to dial the host with
  43. */
  44. func PortWalk(addr string, ports []int) []int {
  45. out := []int{}
  46. for i := range ports {
  47. p := singlePortScan(addr, ports[i])
  48. if p != 0 {
  49. out = append(out, p)
  50. }
  51. }
  52. return out
  53. }
  54. type PortScanResult struct {
  55. // This is used to represent the results of a port scan against one host
  56. PortNumber int `json:"port_number"` // The port number that was scanned
  57. Service string `json:"service"` // the name of the service that the port was identified/mapped to
  58. Protocol string `json:"protocol"` // The IP protocol (TCP/UDP)
  59. Listening bool `json:"listening"` // A boolean value that depicts if the service is listening or not
  60. }
  61. /*
  62. Wrapper function to dependency inject the resource for a port -> service name mapping.
  63. May move to a database, or something.
  64. */
  65. func RetrieveScanDirectives() []int {
  66. var portmap = []int{22, 443, 8080, 4379, 445, 53, 153, 27017}
  67. /*map[int]string{
  68. 22: "ssh", 23: "telnet", 53: "dns", 80: "http", 25: "smtp", 443: "https", 8080: "unknown", 8081: "unknown",
  69. 8082: "unknown", 8085: "unknown", 8090: "unknown", 8091: "unknown", 9010: "unknown", 9012: "unknown", 10000: "unknown", 1433: "microsoft_sql",
  70. 3306: "mysql", 3050: "firebird", 5432: "postgres", 27017: "mongo", 6379: "redis", 8005: "tomcat", 6443: "kubernetes", 853: "dns-tls", 143: "imap",
  71. 389: "ldap", 445: "smb", 543: "kerberos", 544: "kerberos", 749: "kerberos", 760: "kerberos",
  72. } */
  73. return portmap
  74. }
  75. /*
  76. Scans a single host on a single port
  77. :param addr: the address to dial
  78. :param port: the port number to dial
  79. :param svcs: the name of the service that the port is associate with
  80. */
  81. func singlePortScan(addr string, port int) int {
  82. conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%d", addr, port), 2*time.Second)
  83. if err != nil {
  84. return 0
  85. // return PortScanResult{PortNumber: port, Protocol: "tcp", Listening: false}
  86. }
  87. conn.Close()
  88. return port
  89. //return PortScanResult{PortNumber: port, Protocol: "tcp", Listening: true}
  90. }
  91. /*
  92. Perform a port scan sweep across an entire subnet
  93. :param ip: the IPv4 address WITH CIDR notation
  94. :param portmap: the mapping of ports to scan with (port number mapped to protocol name)
  95. */
  96. func NetSweep(ips []net.IP, ports []int) []Host {
  97. scanned := make(chan Host)
  98. for i := range ips {
  99. go func(target string, portnum []int) {
  100. scanned <- Host{
  101. IpAddress: target,
  102. ListeningPorts: PortWalk(target, portnum),
  103. }
  104. }(ips[i].String(), ports)
  105. }
  106. var hosts []Host
  107. for x := range scanned {
  108. fmt.Printf("%+v\n", x)
  109. hosts = append(hosts, x)
  110. }
  111. return hosts
  112. }
  113. /*
  114. Create a new TCP dialer to share in a goroutine
  115. */
  116. func NewDialer() net.Dialer {
  117. return net.Dialer{}
  118. }
  119. /*
  120. Create a new low level networking interface socket
  121. :param intf: the name of the interface to bind the socket to
  122. */
  123. func NewTCPSock(interfaceName string) *syscall.SockaddrLinklayer {
  124. sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, syscall.ETH_P_IP)
  125. if err != nil {
  126. log.Fatal(err, " Could not create raw AF_PACKET socket.\n")
  127. }
  128. defer syscall.Close(sock)
  129. intf, err := net.InterfaceByName(interfaceName)
  130. if err != nil {
  131. log.Fatal(err, " Couldnt locate that interface. Are you sure you mean to pass ", interfaceName, " ?")
  132. }
  133. return &syscall.SockaddrLinklayer{
  134. Protocol: htons(syscall.ETH_P_IP),
  135. Ifindex: intf.Index,
  136. }
  137. }
  138. // htons converts a uint16 from host- to network byte order.
  139. func htons(i uint16) uint16 {
  140. return (i<<8)&0xff00 | i>>8
  141. }