/
scanner.go
129 lines (107 loc) · 2.75 KB
/
scanner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package scanner
import (
"fmt"
"log"
"net"
"time"
"github.com/fatih/color"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
// Function getLocalAddress(dstip net.IP) (net.IP, layers.TCPPort)
// Get the local address necessary to instantiate the TCP connexion
// Return the source IP and port
func getLocalAddress(dstip net.IP) (net.IP, layers.TCPPort) {
serverAddr, err := net.ResolveUDPAddr("udp", dstip.String()+":12345")
if err != nil {
log.Fatal(err)
}
if con, _ := net.DialUDP("udp", nil, serverAddr); err == nil {
if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok {
return udpaddr.IP, layers.TCPPort(udpaddr.Port)
}
}
return nil, layers.TCPPort(0)
}
// Function portIsOpen(dstip net.IP, dstport layers.TCPPort) bool
// Perform SYN SCAN to detect open port
// Retrun true if the given port is open
func portIsOpen(dstip net.IP, dstport layers.TCPPort) bool {
srcip, srcport := getLocalAddress(dstip)
ip := &layers.IPv4{
SrcIP: srcip,
DstIP: dstip,
Protocol: layers.IPProtocolTCP,
}
tcp := &layers.TCP{
SrcPort: srcport,
DstPort: dstport,
Seq: 1105024978,
SYN: true,
Window: 14600,
}
tcp.SetNetworkLayerForChecksum(ip)
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
if err := gopacket.SerializeLayers(buf, opts, tcp); err != nil {
log.Fatal(err)
}
con, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
if err != nil {
log.Fatal(err)
}
if _, err := con.WriteTo(buf.Bytes(), &net.IPAddr{IP: dstip}); err != nil {
log.Fatal(err)
}
if err := con.SetDeadline(time.Now().Add(time.Second)); err != nil {
log.Fatal(err)
}
for {
b := make([]byte, 4096)
n, addr, err := con.ReadFrom(b)
if err != nil {
return false
} else if addr.String() == dstip.String() {
packet := gopacket.NewPacket(b[:n], layers.LayerTypeTCP, gopacket.Default)
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
if tcp.DstPort == srcport {
if tcp.SYN && tcp.ACK {
return true
}
}
}
}
}
}
// Function inc(ip net.IP)
// Enumerate IPs within a range
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
// Function Scan(address string)
// Perform SYN scanning on a given IP range
func Scan(address string) {
ip, ipnet, err := net.ParseCIDR(address)
if err != nil {
log.Fatal(err)
}
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
res := portIsOpen(ip, 25)
if res {
if isVulnerable(ip) {
color.Green(fmt.Sprintf("[+] %s is vulnerable to open relay attack", ip))
} else {
color.Red(fmt.Sprintf("[-] %s is not vulnerable to open relay attack", ip))
}
}
}
}