-
Notifications
You must be signed in to change notification settings - Fork 19
/
gomap_syn_scan.go
150 lines (128 loc) · 3.09 KB
/
gomap_syn_scan.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package gomap
import (
"bytes"
"encoding/binary"
"math/rand"
"net"
"strconv"
"strings"
)
func sendSyn(laddr string, raddr string, sport uint16, dport uint16) error {
// Create TCP packet struct and header
op := []tcpOption{
{
Kind: 2,
Length: 4,
Data: []byte{0x05, 0xb4},
},
{
Kind: 0,
},
}
tcpH := tcpHeader{
SrcPort: sport,
DstPort: dport,
SeqNum: rand.Uint32(),
AckNum: 0,
Flags: 0x8002,
Window: 8192,
ChkSum: 0,
UrgentPointer: 0,
}
// Connect to network interface to send packet
conn, err := net.Dial("ip4:tcp", raddr)
if err != nil {
return err
}
defer conn.Close()
// Build dummy packet for checksum
buff := new(bytes.Buffer)
binary.Write(buff, binary.BigEndian, tcpH)
for i := range op {
binary.Write(buff, binary.BigEndian, op[i].Kind)
binary.Write(buff, binary.BigEndian, op[i].Length)
binary.Write(buff, binary.BigEndian, op[i].Data)
}
binary.Write(buff, binary.BigEndian, [6]byte{})
data := buff.Bytes()
checkSum := checkSum(data, ipstr2Bytes(laddr), ipstr2Bytes(raddr))
tcpH.ChkSum = checkSum
// Build final packet
buff = new(bytes.Buffer)
binary.Write(buff, binary.BigEndian, tcpH)
for i := range op {
binary.Write(buff, binary.BigEndian, op[i].Kind)
binary.Write(buff, binary.BigEndian, op[i].Length)
binary.Write(buff, binary.BigEndian, op[i].Data)
}
binary.Write(buff, binary.BigEndian, [6]byte{})
// Send Packet
conn.Write(buff.Bytes())
return nil
}
func recvSynAck(laddr string, raddr string, port uint16, res chan<- bool) error {
// Checks if the IP address is resolveable
listenAddr, err := net.ResolveIPAddr("ip4", laddr)
if err != nil {
return err
}
// Connect to network interface to listen for packets
conn, err := net.ListenIP("ip4:tcp", listenAddr)
if err != nil {
return err
}
defer conn.Close()
// Read each packet looking for ack from raddr on packetport
for {
buff := make([]byte, 1024)
_, addr, err := conn.ReadFrom(buff)
if err != nil {
continue
}
if addr.String() != raddr || buff[13] != 0x12 {
continue
}
var packetport uint16
binary.Read(bytes.NewReader(buff), binary.BigEndian, &packetport)
if port != packetport {
continue
}
res <- true
return nil
}
}
func checkSum(data []byte, src, dst [4]byte) uint16 {
pseudoHeader := []byte{
src[0], src[1], src[2], src[3],
dst[0], dst[1], dst[2], dst[3],
0,
6,
0,
byte(len(data)),
}
totalLength := len(pseudoHeader) + len(data)
if totalLength%2 != 0 {
totalLength++
}
d := make([]byte, 0, totalLength)
d = append(d, pseudoHeader...)
d = append(d, data...)
var sum uint32
for i := 0; i < len(d)-1; i += 2 {
sum += uint32(uint16(d[i])<<8 | uint16(d[i+1]))
}
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
return ^uint16(sum)
}
func ipstr2Bytes(addr string) [4]byte {
s := strings.Split(addr, ".")
b0, _ := strconv.Atoi(s[0])
b1, _ := strconv.Atoi(s[1])
b2, _ := strconv.Atoi(s[2])
b3, _ := strconv.Atoi(s[3])
return [4]byte{byte(b0), byte(b1), byte(b2), byte(b3)}
}
func random(min, max int) int {
return rand.Intn(max-min) + min
}