mirror of
https://github.com/maride/pancap.git
synced 2024-11-25 18:04:25 +00:00
Add support for DHCPv4 packets
This commit is contained in:
parent
aa59576c9c
commit
37afbb58a9
30
ethernet/dhcpv4/common.go
Normal file
30
ethernet/dhcpv4/common.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package dhcpv4
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Appends the appendee to the array if it does not contain appendee yet
|
||||||
|
func appendIfUnique(appendee string, array []string) []string {
|
||||||
|
// Iterate over all elements and check values
|
||||||
|
for _, elem := range array {
|
||||||
|
if elem == appendee {
|
||||||
|
// ... found. Stop here
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None found, append
|
||||||
|
return append(array, appendee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints each element, along with a small ASCII tree
|
||||||
|
func printTree(strarr []string) {
|
||||||
|
// iterate over each element
|
||||||
|
for iter, elem := range strarr {
|
||||||
|
// check if we got the last element
|
||||||
|
if iter < len(strarr) - 1 {
|
||||||
|
fmt.Printf("|- %s\n", elem)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("'- %s\n\n", elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
ethernet/dhcpv4/dhcp.go
Normal file
109
ethernet/dhcpv4/dhcp.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package dhcpv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
requestMAC []string
|
||||||
|
responses []dhcpResponse
|
||||||
|
)
|
||||||
|
|
||||||
|
// Called on every DHCP (v4) packet
|
||||||
|
func HandleDHCPv4Packet(packet gopacket.Packet) error {
|
||||||
|
var dhcppacket layers.DHCPv4
|
||||||
|
var ethernetpacket layers.Ethernet
|
||||||
|
|
||||||
|
// Decode raw packet into DHCPv4
|
||||||
|
decodeDHCPErr := dhcppacket.DecodeFromBytes(packet.Layer(layers.LayerTypeDHCPv4).LayerContents(), gopacket.NilDecodeFeedback)
|
||||||
|
if decodeDHCPErr != nil {
|
||||||
|
// Encountered an error during decoding, most likely a broken packet
|
||||||
|
return decodeDHCPErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// And decode raw packet into Ethernet
|
||||||
|
decodeEthernetErr := ethernetpacket.DecodeFromBytes(packet.Layer(layers.LayerTypeEthernet).LayerContents(), gopacket.NilDecodeFeedback)
|
||||||
|
if decodeEthernetErr != nil {
|
||||||
|
// Encountered an error during decoding, most likely a broken packet
|
||||||
|
return decodeEthernetErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Examine packet further
|
||||||
|
if dhcppacket.Operation == layers.DHCPOpRequest {
|
||||||
|
// Request packet
|
||||||
|
appendIfUnique(dhcppacket.ClientHWAddr.String(), requestMAC)
|
||||||
|
} else {
|
||||||
|
// Response/Offer packet
|
||||||
|
addResponseEntry(dhcppacket.ClientIP.String(), dhcppacket.ClientHWAddr.String(), ethernetpacket.SrcMAC.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print summary after all packets are processed
|
||||||
|
func PrintDHCPv4Summary() {
|
||||||
|
headline := color.New(color.FgRed, color.Bold)
|
||||||
|
headline.Println("DHCP Requests")
|
||||||
|
printRequestSummary()
|
||||||
|
headline.Println("DHCP Responses/Offers")
|
||||||
|
printResponseSummary()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the summary of all DHCP request packets
|
||||||
|
func printRequestSummary() {
|
||||||
|
fmt.Printf("%d unique DHCP requests\n", len(requestMAC))
|
||||||
|
printTree(requestMAC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the summary of all DHCP offer packets
|
||||||
|
func printResponseSummary() {
|
||||||
|
var tmpaddr []string
|
||||||
|
|
||||||
|
// Iterate over all responses
|
||||||
|
for _, r := range responses {
|
||||||
|
tmpaddr = append(tmpaddr, fmt.Sprintf("%s offered %s IP address %s", r.serverMACAddr, r.destMACAddr, r.newIPAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw as tree
|
||||||
|
printTree(tmpaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a new response entry. If an IP address was already issued or a MAC asks multiple times for DNS, the case is examined further
|
||||||
|
func addResponseEntry(newIP string, destMAC string, serverMAC string) {
|
||||||
|
for _, r := range responses {
|
||||||
|
// Check for interesting cases
|
||||||
|
if r.destMACAddr == destMAC {
|
||||||
|
// The same client device received multiple IP addresses, let's examine further
|
||||||
|
if r.newIPAddr == newIP {
|
||||||
|
// the handed IP is the same - this is ok, just badly configured
|
||||||
|
if r.serverMACAddr == serverMAC {
|
||||||
|
// Same DHCP server answered.
|
||||||
|
log.Printf("MAC address %s received the same IP address multiple times via DHCP by the same server.", destMAC)
|
||||||
|
} else {
|
||||||
|
// Different DHCP servers answered, but with the same address - strange network, but ok...
|
||||||
|
log.Printf("MAC address %s received the same IP address multiple times via DHCP by different servers.", destMAC)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// far more interesting - one client received multiple addresses
|
||||||
|
if r.serverMACAddr == serverMAC {
|
||||||
|
// Same DHCP server answered.
|
||||||
|
log.Printf("MAC address %s received different IP addresses (%s, %s) multiple times via DHCP by the same server.", destMAC, r.newIPAddr, newIP)
|
||||||
|
} else {
|
||||||
|
// Different DHCP servers answered, with different addresses - possibly an attempt to build up MitM
|
||||||
|
log.Printf("MAC address %s received different IP addresses (%s, %s) multiple times via DHCP by different servers (%s, %s).", destMAC, r.newIPAddr, newIP, r.serverMACAddr, serverMAC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a response entry - even if we found some "strange" behavior before.
|
||||||
|
responses = append(responses, dhcpResponse{
|
||||||
|
destMACAddr: destMAC,
|
||||||
|
newIPAddr: newIP,
|
||||||
|
serverMACAddr: serverMAC,
|
||||||
|
})
|
||||||
|
}
|
8
ethernet/dhcpv4/dhcpResponse.go
Normal file
8
ethernet/dhcpv4/dhcpResponse.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package dhcpv4
|
||||||
|
|
||||||
|
type dhcpResponse struct {
|
||||||
|
destMACAddr string
|
||||||
|
newIPAddr string
|
||||||
|
serverMACAddr string
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package ethernet
|
|||||||
import (
|
import (
|
||||||
"git.darknebu.la/maride/pancap/ethernet/arp"
|
"git.darknebu.la/maride/pancap/ethernet/arp"
|
||||||
"git.darknebu.la/maride/pancap/ethernet/dns"
|
"git.darknebu.la/maride/pancap/ethernet/dns"
|
||||||
|
"git.darknebu.la/maride/pancap/ethernet/dhcpv4"
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"log"
|
"log"
|
||||||
@ -30,6 +31,11 @@ func Analyze(source *gopacket.PacketSource) error {
|
|||||||
// Handle ARP packet
|
// Handle ARP packet
|
||||||
arp.ProcessARPPacket(packet)
|
arp.ProcessARPPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if packet.Layer(layers.LayerTypeDHCPv4) != nil {
|
||||||
|
// Handle DHCP (v4) packet
|
||||||
|
dhcpv4.HandleDHCPv4Packet(packet)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After processing all packets, print summary
|
// After processing all packets, print summary
|
||||||
@ -42,4 +48,5 @@ func Analyze(source *gopacket.PacketSource) error {
|
|||||||
func printSummary() {
|
func printSummary() {
|
||||||
arp.PrintARPSummary()
|
arp.PrintARPSummary()
|
||||||
dns.PrintDNSSummary()
|
dns.PrintDNSSummary()
|
||||||
|
dhcpv4.PrintDHCPv4Summary()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user