├── readme.md └── synscan.go /readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 模仿系统发送syn 包。 4 | 修改下代码,调整扫描目标 5 | ```go 6 | ipstr := "172.17.0.2" 7 | ports := []layers.TCPPort{10, 20, 30, 40} 8 | ``` 9 | 10 | ### tcp options 11 | ```go 12 | layers.TCPOption{layers.TCPOptionKindMSS, 4,[]byte("\x05\xb4")}, 13 | layers.TCPOption{layers.TCPOptionKindSACKPermitted, 2, nil}, 14 | layers.TCPOption{layers.TCPOptionKindNop, 1, nil}, 15 | layers.TCPOption{layers.TCPOptionKindWindowScale, 3, []byte("\x07")}, 16 | ``` 17 | 18 | 19 | ### gopcaket route 包的问题 20 | 21 | - out of order iface error 22 | 由于云主机里的有个网卡 vethdba2c Index 不是顺序递增了,导致出现错误。 23 | - 未考虑默认路由, 24 | 25 | `go get https://github.com/google/gopacket` 后修改相关代码 `routing/routing.go` 26 | > https://github.com/jax777/gopacket/blob/master/routing/routing.go 27 | > -------------------------------------------------------------------------------- /synscan.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // synscan implements a TCP syn scanner on top of pcap. 8 | // It's more complicated than arpscan, since it has to handle sending packets 9 | // outside the local network, requiring some routing and ARP work. 10 | // 11 | // Since this is just an example program, it aims for simplicity over 12 | // performance. It doesn't handle sending packets very quickly, it scans IPs 13 | // serially instead of in parallel, and uses gopacket.Packet instead of 14 | // gopacket.DecodingLayerParser for packet processing. We also make use of very 15 | // simple timeout logic with time.Since. 16 | // 17 | // Making it blazingly fast is left as an exercise to the reader. 18 | package main 19 | 20 | import ( 21 | "errors" 22 | "log" 23 | "net" 24 | "time" 25 | "fmt" 26 | 27 | "github.com/google/gopacket" 28 | "github.com/google/gopacket/examples/util" 29 | "github.com/google/gopacket/layers" 30 | "github.com/google/gopacket/pcap" 31 | "github.com/google/gopacket/routing" 32 | "bufio" 33 | "os" 34 | "strings" 35 | ) 36 | 37 | const ( 38 | f_IPAddr int = iota 39 | f_HWType 40 | f_Flags 41 | f_HWAddr 42 | f_Mask 43 | f_Device 44 | ) 45 | //IP address HW type Flags HW address Mask Device 46 | //192.168.101.1 0x1 0x2 24:16:6d:a1:9c:1b * eth1 47 | 48 | 49 | type ArpTable map[string]net.HardwareAddr 50 | var arp_table = make(ArpTable) // global arp table 51 | 52 | func UpdateTable(){ 53 | f, err := os.Open("/proc/net/arp") 54 | 55 | if err != nil { 56 | log.Printf("error UpdateTable %v", err) 57 | return 58 | } 59 | 60 | defer f.Close() 61 | 62 | s := bufio.NewScanner(f) 63 | s.Scan() // skip the field descriptions 64 | 65 | 66 | for s.Scan() { 67 | line := s.Text() 68 | fields := strings.Fields(line) 69 | MAC,err1 := net.ParseMAC(fields[f_HWAddr]) 70 | if err1 == nil{ 71 | arp_table[fields[f_IPAddr]] = MAC 72 | } 73 | } 74 | } 75 | 76 | type scanner struct { 77 | // iface is the interface to send packets on. 78 | iface *net.Interface 79 | // destination, gateway (if applicable), and source IP addresses to use. 80 | dst, gw, src net.IP 81 | dststr string 82 | handle *pcap.Handle 83 | 84 | // opts and buf allow us to easily serialize packets in the send() 85 | // method. 86 | opts gopacket.SerializeOptions 87 | buf gopacket.SerializeBuffer 88 | } 89 | 90 | // newScanner creates a new scanner for a given destination IP address, using 91 | // router to determine how to route packets to that IP. 92 | func newScanner(ipstr string, router routing.Router) (*scanner, error) { 93 | var ip net.IP 94 | if ip = net.ParseIP(ipstr); ip == nil { 95 | return nil, fmt.Errorf("non-ip target: %q", ipstr) 96 | } else if ip = ip.To4(); ip == nil { 97 | return nil, fmt.Errorf("non-ipv4 target: %q", ipstr) 98 | } 99 | s := &scanner{ 100 | dststr: ipstr, 101 | dst: ip, 102 | opts: gopacket.SerializeOptions{ 103 | FixLengths: true, 104 | ComputeChecksums: true, 105 | }, 106 | buf: gopacket.NewSerializeBuffer(), 107 | } 108 | // Figure out the route to the IP. 109 | iface, gw, src, err := router.Route(ip) 110 | if err != nil { 111 | return nil, err 112 | } 113 | log.Printf("scanning ip %v with interface %v, gateway %v, src %v", ip, iface.Name, gw, src) 114 | s.gw, s.src, s.iface = gw, src, iface 115 | 116 | // Open the handle for reading/writing. 117 | // Note we could very easily add some BPF filtering here to greatly 118 | // decrease the number of packets we have to look at when getting back 119 | // scan results. 120 | handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever) 121 | if err != nil { 122 | return nil, err 123 | } 124 | s.handle = handle 125 | return s, nil 126 | } 127 | 128 | // close cleans up the handle. 129 | func (s *scanner) close() { 130 | s.handle.Close() 131 | } 132 | 133 | // getHwAddr is a hacky but effective way to get the destination hardware 134 | // address for our packets. It does an ARP request for our gateway (if there is 135 | // one) or destination IP (if no gateway is necessary), then waits for an ARP 136 | // reply. This is pretty slow right now, since it blocks on the ARP 137 | // request/reply. 138 | func (s *scanner) getHwAddr() (net.HardwareAddr, error) { 139 | start := time.Now() 140 | arpDst := s.dst 141 | if s.gw != nil { 142 | arpDst = s.gw 143 | } 144 | // Prepare the layers to send for an ARP request. 145 | eth := layers.Ethernet{ 146 | SrcMAC: s.iface.HardwareAddr, 147 | DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 148 | EthernetType: layers.EthernetTypeARP, 149 | } 150 | arp := layers.ARP{ 151 | AddrType: layers.LinkTypeEthernet, 152 | Protocol: layers.EthernetTypeIPv4, 153 | HwAddressSize: 6, 154 | ProtAddressSize: 4, 155 | Operation: layers.ARPRequest, 156 | SourceHwAddress: []byte(s.iface.HardwareAddr), 157 | SourceProtAddress: []byte(s.src), 158 | DstHwAddress: []byte{0, 0, 0, 0, 0, 0}, 159 | DstProtAddress: []byte(arpDst), 160 | } 161 | // Send a single ARP request packet (we never retry a send, since this 162 | // is just an example ;) 163 | if err := s.send(ð, &arp); err != nil { 164 | return nil, err 165 | } 166 | // Wait 3 seconds for an ARP reply. 167 | for { 168 | if time.Since(start) > time.Second*3 { 169 | return nil, errors.New("timeout getting ARP reply") 170 | } 171 | data, _, err := s.handle.ReadPacketData() 172 | if err == pcap.NextErrorTimeoutExpired { 173 | continue 174 | } else if err != nil { 175 | return nil, err 176 | } 177 | packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) 178 | if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil { 179 | arp := arpLayer.(*layers.ARP) 180 | if net.IP(arp.SourceProtAddress).Equal(net.IP(arpDst)) { 181 | return net.HardwareAddr(arp.SourceHwAddress), nil 182 | } 183 | } 184 | } 185 | } 186 | 187 | // scan scans the dst IP address of this scanner. 188 | func (s *scanner) scan(ports []layers.TCPPort) error { 189 | // First off, get the MAC address we should be sending packets to. 190 | 191 | hwaddr, ok := arp_table[s.dststr] 192 | if !ok{ 193 | var err error 194 | hwaddr, err = s.getHwAddr() 195 | if err != nil { 196 | return err 197 | } 198 | // update arp_table 199 | arp_table[s.dststr] = hwaddr 200 | } 201 | 202 | // Construct all the network layers we need. 203 | eth := layers.Ethernet{ 204 | SrcMAC: s.iface.HardwareAddr, 205 | DstMAC: hwaddr, 206 | EthernetType: layers.EthernetTypeIPv4, 207 | } 208 | ip4 := layers.IPv4{ 209 | SrcIP: s.src, 210 | DstIP: s.dst, 211 | Version: 4, 212 | TTL: 64, 213 | Protocol: layers.IPProtocolTCP, 214 | } 215 | tcp := layers.TCP{ 216 | SrcPort: 54321, 217 | DstPort: 0, // will trough ports slice 218 | SYN: true, 219 | Window:29200, 220 | Options : []layers.TCPOption{ 221 | layers.TCPOption{layers.TCPOptionKindMSS, 4,[]byte("\x05\xb4")}, 222 | layers.TCPOption{layers.TCPOptionKindSACKPermitted, 2, nil}, 223 | layers.TCPOption{layers.TCPOptionKindNop, 1, nil}, 224 | layers.TCPOption{layers.TCPOptionKindWindowScale, 3, []byte("\x07")}, 225 | }, 226 | } 227 | tcp.SetNetworkLayerForChecksum(&ip4) 228 | 229 | // Create the flow we expect returning packets to have, so we can check 230 | // against it and discard useless packets. 231 | ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src) 232 | start := time.Now() 233 | go func(){ 234 | for _, port := range ports { 235 | // Send one packet per loop iteration until we've sent packets 236 | // to all of ports slice 237 | start = time.Now() 238 | tcp.DstPort = port 239 | 240 | if err := s.send(ð, &ip4, &tcp); err != nil { 241 | log.Printf("error sending to port %v: %v", tcp.DstPort, err) 242 | } 243 | 244 | } 245 | }() 246 | for { 247 | // Time out 3 seconds after the last packet we sent. 248 | if time.Since(start) > time.Second*3 { 249 | log.Printf("timed out for %v, assuming we've seen all we can", s.dst) 250 | return nil 251 | } 252 | 253 | // Read in the next packet. 254 | data, _, err := s.handle.ReadPacketData() 255 | if err == pcap.NextErrorTimeoutExpired { 256 | continue 257 | } else if err != nil { 258 | log.Printf("error reading packet: %v", err) 259 | continue 260 | } 261 | 262 | // Parse the packet. We'd use DecodingLayerParser here if we 263 | // wanted to be really fast. 264 | packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) 265 | 266 | // Find the packets we care about, and print out logging 267 | // information about them. All others are ignored. 268 | if net := packet.NetworkLayer(); net == nil { 269 | // log.Printf("packet has no network layer") 270 | } else if net.NetworkFlow() != ipFlow { 271 | // log.Printf("packet does not match our ip src/dst") 272 | } else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil { 273 | // log.Printf("packet has not tcp layer") 274 | } else if tcp, ok := tcpLayer.(*layers.TCP); !ok { 275 | // We panic here because this is guaranteed to never 276 | // happen. 277 | panic("tcp layer is not tcp layer :-/") 278 | } else if tcp.DstPort != 54321 { 279 | // log.Printf("dst port %v does not match", tcp.DstPort) 280 | } else if tcp.RST { 281 | log.Printf(" port %v closed", tcp.SrcPort) 282 | } else if tcp.SYN && tcp.ACK { 283 | log.Printf(" port %v open", tcp.SrcPort) 284 | } else { 285 | // log.Printf("ignoring useless packet") 286 | } 287 | } 288 | } 289 | 290 | // send sends the given layers as a single packet on the network. 291 | func (s *scanner) send(l ...gopacket.SerializableLayer) error { 292 | if err := gopacket.SerializeLayers(s.buf, s.opts, l...); err != nil { 293 | return err 294 | } 295 | return s.handle.WritePacketData(s.buf.Bytes()) 296 | } 297 | 298 | 299 | func main() { 300 | UpdateTable() 301 | defer util.Run()() 302 | router, err := routing.New() 303 | if err != nil { 304 | log.Fatal("routing error:", err) 305 | } 306 | ipstr := "172.17.0.2" 307 | ports := []layers.TCPPort{10, 20, 30, 40} 308 | s, err := newScanner(ipstr, router) 309 | if err != nil { 310 | log.Printf("unable to create scanner for %v: %v", ipstr, err) 311 | return 312 | } 313 | if err := s.scan(ports); err != nil { 314 | log.Printf("unable to scan %v: %v", ipstr, err) 315 | } 316 | s.close() 317 | return 318 | } 319 | --------------------------------------------------------------------------------