From bef4c6abaa656b95c3a314c9ea26921ee0e87eb1 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 3 Apr 2021 18:42:14 +0200 Subject: [PATCH] new: basic ipv6 support --- modules/syn_scan/http_grabber.go | 5 +++ modules/syn_scan/syn_scan.go | 8 +++- modules/syn_scan/syn_scan_parsers.go | 18 ++++++-- modules/syn_scan/syn_scan_reader.go | 50 +++++++++++++++++----- network/arp_parser_linux.go | 2 +- network/lan.go | 2 +- packets/tcp.go | 64 +++++++++++++++++++--------- session/module_handler.go | 1 + 8 files changed, 115 insertions(+), 35 deletions(-) diff --git a/modules/syn_scan/http_grabber.go b/modules/syn_scan/http_grabber.go index d8f22d3a..1e53a056 100644 --- a/modules/syn_scan/http_grabber.go +++ b/modules/syn_scan/http_grabber.go @@ -55,6 +55,11 @@ func httpGrabber(mod *SynScanner, ip string, port int) string { } } + // https://stackoverflow.com/questions/12260003/connect-returns-invalid-argument-with-ipv6-address + if strings.Contains(ip, ":") { + ip = fmt.Sprintf("[%s%%25%s]", ip, mod.Session.Interface.Name()) + } + url := fmt.Sprintf("%s://%s:%d/", schema, ip, port) resp, err := client.Get(url) if err != nil { diff --git a/modules/syn_scan/syn_scan.go b/modules/syn_scan/syn_scan.go index afa8bfa0..b03b79a8 100644 --- a/modules/syn_scan/syn_scan.go +++ b/modules/syn_scan/syn_scan.go @@ -167,6 +167,12 @@ type scanJob struct { func (mod *SynScanner) scanWorker(job async.Job) { scan := job.(scanJob) + fromHW := mod.Session.Interface.HW + fromIP := mod.Session.Interface.IP + if scan.Address.To4() == nil { + fromIP = mod.Session.Interface.IPv6 + } + for dstPort := mod.startPort; dstPort < mod.endPort+1; dstPort++ { if !mod.Running() { break @@ -174,7 +180,7 @@ func (mod *SynScanner) scanWorker(job async.Job) { atomic.AddUint64(&mod.stats.doneProbes, 1) - err, raw := packets.NewTCPSyn(mod.Session.Interface.IP, mod.Session.Interface.HW, scan.Address, scan.Mac, synSourcePort, dstPort) + err, raw := packets.NewTCPSyn(fromIP, fromHW, scan.Address, scan.Mac, synSourcePort, dstPort) if err != nil { mod.Error("error creating SYN packet: %s", err) continue diff --git a/modules/syn_scan/syn_scan_parsers.go b/modules/syn_scan/syn_scan_parsers.go index 25a8c24d..53ee758b 100644 --- a/modules/syn_scan/syn_scan_parsers.go +++ b/modules/syn_scan/syn_scan_parsers.go @@ -2,18 +2,30 @@ package syn_scan import ( "fmt" + "net" "strconv" + "strings" "github.com/evilsocket/islazy/str" "github.com/malfunkt/iprange" ) func (mod *SynScanner) parseTargets(arg string) error { - if list, err := iprange.Parse(arg); err != nil { - return fmt.Errorf("error while parsing IP range '%s': %s", arg, err) + if strings.Contains(arg, ":") { + // parse as IPv6 address + if ip := net.ParseIP(arg); ip == nil { + return fmt.Errorf("error while parsing IPv6 '%s'", arg) + } else { + mod.addresses = []net.IP{ip} + } } else { - mod.addresses = list.Expand() + if list, err := iprange.Parse(arg); err != nil { + return fmt.Errorf("error while parsing IP range '%s': %s", arg, err) + } else { + mod.addresses = list.Expand() + } } + return nil } diff --git a/modules/syn_scan/syn_scan_reader.go b/modules/syn_scan/syn_scan_reader.go index 8e05db68..b4c36584 100644 --- a/modules/syn_scan/syn_scan_reader.go +++ b/modules/syn_scan/syn_scan_reader.go @@ -24,26 +24,40 @@ func (mod *SynScanner) onPacket(pkt gopacket.Packet) { } var eth layers.Ethernet - var ip layers.IPv4 + var ip4 layers.IPv4 + var ip6 layers.IPv6 var tcp layers.TCP - foundLayerTypes := []gopacket.LayerType{} + + + isIPv6 := false + foundLayerTypes := []gopacket.LayerType{} parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, - &ip, + &ip4, &tcp, ) err := parser.DecodeLayers(pkt.Data(), &foundLayerTypes) if err != nil { - return + // try ipv6 + parser := gopacket.NewDecodingLayerParser( + layers.LayerTypeEthernet, + ð, + &ip6, + &tcp, + ) + err = parser.DecodeLayers(pkt.Data(), &foundLayerTypes) + if err != nil { + return + } + isIPv6 = true } if tcp.DstPort == synSourcePort && tcp.SYN && tcp.ACK { atomic.AddUint64(&mod.stats.openPorts, 1) - from := ip.SrcIP.String() port := int(tcp.SrcPort) openPort := &OpenPort{ @@ -53,12 +67,28 @@ func (mod *SynScanner) onPacket(pkt gopacket.Packet) { } var host *network.Endpoint - if ip.SrcIP.Equal(mod.Session.Interface.IP) { - host = mod.Session.Interface - } else if ip.SrcIP.Equal(mod.Session.Gateway.IP) { - host = mod.Session.Gateway + + from := "" + + if isIPv6 { + from = ip6.SrcIP.String() + if ip6.SrcIP.Equal(mod.Session.Interface.IPv6) { + host = mod.Session.Interface + } else if ip6.SrcIP.Equal(mod.Session.Gateway.IPv6) { + host = mod.Session.Gateway + } else { + host = mod.Session.Lan.GetByIp(from) + } } else { - host = mod.Session.Lan.GetByIp(from) + from = ip4.SrcIP.String() + + if ip4.SrcIP.Equal(mod.Session.Interface.IP) { + host = mod.Session.Interface + } else if ip4.SrcIP.Equal(mod.Session.Gateway.IP) { + host = mod.Session.Gateway + } else { + host = mod.Session.Lan.GetByIp(from) + } } if host != nil { diff --git a/network/arp_parser_linux.go b/network/arp_parser_linux.go index 3738cbd5..7d4d0b23 100644 --- a/network/arp_parser_linux.go +++ b/network/arp_parser_linux.go @@ -2,7 +2,7 @@ package network import "regexp" -var ArpTableParser = regexp.MustCompile(`^([\d\.]+)\s+dev\s+(\w+)\s+\w+\s+([a-f0-9:]{17})\s+\w+$`) +var ArpTableParser = regexp.MustCompile(`^([a-f\d\.:]+)\s+dev\s+(\w+)\s+\w+\s+([a-f0-9:]{17})\s+\w+$`) var ArpTableTokens = 4 var ArpTableTokenIndex = []int{1, 3, 2} var ArpCmd = "ip" diff --git a/network/lan.go b/network/lan.go index 0c2bef8f..c6db5fd2 100644 --- a/network/lan.go +++ b/network/lan.go @@ -153,7 +153,7 @@ func (lan *LAN) shouldIgnore(ip, mac string) bool { } // skip everything which is not in our subnet (multicast noise) addr := net.ParseIP(ip) - return !lan.iface.Net.Contains(addr) + return addr.To4() != nil && !lan.iface.Net.Contains(addr) } func (lan *LAN) Has(ip string) bool { diff --git a/packets/tcp.go b/packets/tcp.go index 3b646b3e..5beb79ab 100644 --- a/packets/tcp.go +++ b/packets/tcp.go @@ -6,24 +6,50 @@ import ( ) func NewTCPSyn(from net.IP, from_hw net.HardwareAddr, to net.IP, to_hw net.HardwareAddr, srcPort int, dstPort int) (error, []byte) { - eth := layers.Ethernet{ - SrcMAC: from_hw, - DstMAC: to_hw, - EthernetType: layers.EthernetTypeIPv4, - } - ip4 := layers.IPv4{ - Protocol: layers.IPProtocolTCP, - Version: 4, - TTL: 64, - SrcIP: from, - DstIP: to, - } - tcp := layers.TCP{ - SrcPort: layers.TCPPort(srcPort), - DstPort: layers.TCPPort(dstPort), - SYN: true, - } - tcp.SetNetworkLayerForChecksum(&ip4) + from4 := from.To4() + to4 := to.To4() - return Serialize(ð, &ip4, &tcp) + if from4 != nil && to4 != nil { + eth := layers.Ethernet{ + SrcMAC: from_hw, + DstMAC: to_hw, + EthernetType: layers.EthernetTypeIPv4, + } + ip4 := layers.IPv4{ + Protocol: layers.IPProtocolTCP, + Version: 4, + TTL: 64, + SrcIP: from, + DstIP: to, + } + tcp := layers.TCP{ + SrcPort: layers.TCPPort(srcPort), + DstPort: layers.TCPPort(dstPort), + SYN: true, + } + tcp.SetNetworkLayerForChecksum(&ip4) + + return Serialize(ð, &ip4, &tcp) + } else { + eth := layers.Ethernet{ + SrcMAC: from_hw, + DstMAC: to_hw, + EthernetType: layers.EthernetTypeIPv6, + } + ip6 := layers.IPv6{ + Version: 6, + NextHeader: layers.IPProtocolTCP, + HopLimit: 64, + SrcIP: from, + DstIP: to, + } + tcp := layers.TCP{ + SrcPort: layers.TCPPort(srcPort), + DstPort: layers.TCPPort(dstPort), + SYN: true, + } + tcp.SetNetworkLayerForChecksum(&ip6) + + return Serialize(ð, &ip6, &tcp) + } } diff --git a/session/module_handler.go b/session/module_handler.go index 71abca59..f3954b7d 100644 --- a/session/module_handler.go +++ b/session/module_handler.go @@ -16,6 +16,7 @@ import ( const ( IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$` IPv6Validator = `^[:a-fA-F0-9]{6,}$` + IPValidator = `^[\.:a-fA-F0-9]{6,}$` ) type ModuleHandler struct {