mirror of
https://github.com/maride/pancap.git
synced 2024-11-24 01:34:26 +00:00
Compare commits
6 Commits
0430a1b214
...
21c956c545
Author | SHA1 | Date | |
---|---|---|---|
21c956c545 | |||
1989ae996f | |||
1aa3572c30 | |||
4a1c58b564 | |||
44739d4697 | |||
daf641c881 |
@ -2,15 +2,16 @@ package analyze
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
"github.com/maride/pancap/output"
|
"github.com/maride/pancap/output"
|
||||||
"github.com/maride/pancap/protocol"
|
"github.com/maride/pancap/protocol"
|
||||||
"github.com/google/gopacket"
|
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Store total amount and amount of visited packets
|
// Store total amount and amount of visited packets
|
||||||
totalPackets int
|
totalPackets int
|
||||||
processedPackets int
|
processedPackets int
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +40,9 @@ func Analyze(source *gopacket.PacketSource) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register communication for graph
|
||||||
|
output.AddPkgToGraph(packet)
|
||||||
|
|
||||||
// Raise statistics
|
// Raise statistics
|
||||||
totalPackets += 1
|
totalPackets += 1
|
||||||
if processed {
|
if processed {
|
||||||
@ -68,4 +72,3 @@ func handleErr(err error) {
|
|||||||
log.Printf("Encountered error while examining packets, continuing anyway. Error: %s", err.Error())
|
log.Printf("Encountered error while examining packets, continuing anyway. Error: %s", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ func GenerateTree(strarr []string) string {
|
|||||||
// iterate over each element
|
// iterate over each element
|
||||||
for iter, elem := range strarr {
|
for iter, elem := range strarr {
|
||||||
// check if we got the last element
|
// check if we got the last element
|
||||||
if iter < len(strarr) - 1 {
|
if iter < len(strarr)-1 {
|
||||||
tmpstr = fmt.Sprintf("%s├ %s\n", tmpstr, elem)
|
tmpstr = fmt.Sprintf("%s├ %s\n", tmpstr, elem)
|
||||||
} else {
|
} else {
|
||||||
tmpstr = fmt.Sprintf( "%s╰ %s\n", tmpstr, elem)
|
tmpstr = fmt.Sprintf("%s╰ %s\n", tmpstr, elem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
file.go
9
file.go
@ -3,29 +3,30 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
filenameFlag *string
|
filenameFlag string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registers the flag --file
|
// Registers the flag --file
|
||||||
func registerFileFlags() {
|
func registerFileFlags() {
|
||||||
filenameFlag = flag.String("file", "", "PCAP file to base analysis on")
|
flag.StringVar(&filenameFlag, "file", "", "PCAP file to base analysis on")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opens the PCAP, returns its packets and the link type or an error
|
// Opens the PCAP, returns its packets and the link type or an error
|
||||||
func openPCAP() (*gopacket.PacketSource, layers.LinkType, error) {
|
func openPCAP() (*gopacket.PacketSource, layers.LinkType, error) {
|
||||||
// Check if we even got a file.
|
// Check if we even got a file.
|
||||||
if *filenameFlag == "" {
|
if filenameFlag == "" {
|
||||||
return nil, 0, fmt.Errorf("missing file to analyze. Please specifiy it with --file")
|
return nil, 0, fmt.Errorf("missing file to analyze. Please specifiy it with --file")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open specified file
|
// Open specified file
|
||||||
handle, openErr := pcap.OpenOffline(*filenameFlag)
|
handle, openErr := pcap.OpenOffline(filenameFlag)
|
||||||
if openErr != nil {
|
if openErr != nil {
|
||||||
// There were some problems opening the file
|
// There were some problems opening the file
|
||||||
return nil, 0, openErr
|
return nil, 0, openErr
|
||||||
|
8
main.go
8
main.go
@ -3,11 +3,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/analyze"
|
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/maride/pancap/analyze"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -36,6 +37,9 @@ func main() {
|
|||||||
// Extract found and requested files
|
// Extract found and requested files
|
||||||
output.StoreFiles()
|
output.StoreFiles()
|
||||||
|
|
||||||
|
// Create communication graph
|
||||||
|
output.CreateGraph()
|
||||||
|
|
||||||
// Show user analysis
|
// Show user analysis
|
||||||
analyze.PrintSummary()
|
analyze.PrintSummary()
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
name string
|
name string
|
||||||
content []byte
|
content []byte
|
||||||
origin string
|
origin string
|
||||||
hash string
|
hash string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new file object and calculates the hash of the given content
|
// Creates a new file object and calculates the hash of the given content
|
||||||
@ -21,4 +21,4 @@ func NewFile(name string, content []byte, origin string) File {
|
|||||||
origin: origin,
|
origin: origin,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,12 @@ func StoreFiles() {
|
|||||||
var filesToExtract []File
|
var filesToExtract []File
|
||||||
|
|
||||||
// Check different flag scenarios
|
// Check different flag scenarios
|
||||||
if *targetAllFiles {
|
if targetAllFiles {
|
||||||
// We should extract all files.
|
// We should extract all files.
|
||||||
filesToExtract = registeredFiles
|
filesToExtract = registeredFiles
|
||||||
} else {
|
} else {
|
||||||
// We should extract only a given set of files
|
// We should extract only a given set of files
|
||||||
fileList := strings.Split(*targetFiles, ",")
|
fileList := strings.Split(targetFiles, ",")
|
||||||
for _, f := range fileList {
|
for _, f := range fileList {
|
||||||
// Iterate over desired files
|
// Iterate over desired files
|
||||||
found := false
|
found := false
|
||||||
@ -80,7 +80,7 @@ func StoreFiles() {
|
|||||||
|
|
||||||
// Writes the given file object to disk, along with a stats file placed next to it.
|
// Writes the given file object to disk, along with a stats file placed next to it.
|
||||||
func writeOut(f File) {
|
func writeOut(f File) {
|
||||||
targetName := fmt.Sprintf("%s%c%s", *targetOutput, os.PathSeparator, f.hash)
|
targetName := fmt.Sprintf("%s%c%s", targetOutput, os.PathSeparator, f.hash)
|
||||||
targetDescName := fmt.Sprintf("%s.info", targetName)
|
targetDescName := fmt.Sprintf("%s.info", targetName)
|
||||||
targetDescription := fmt.Sprintf("Filename: %s\nHash: %s\nOrigin: %s\nSize: %d", f.name, f.hash, f.origin, len(f.content))
|
targetDescription := fmt.Sprintf("Filename: %s\nHash: %s\nOrigin: %s\nSize: %d", f.name, f.hash, f.origin, len(f.content))
|
||||||
|
|
||||||
|
@ -3,19 +3,19 @@ package output
|
|||||||
import "flag"
|
import "flag"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fullOutput *bool
|
fullOutput bool
|
||||||
printEmptyBlocks *bool
|
printEmptyBlocks bool
|
||||||
targetFiles *string
|
targetFiles string
|
||||||
targetAllFiles *bool
|
targetAllFiles bool
|
||||||
targetOutput *string
|
targetOutput string
|
||||||
|
graphOutput string
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterFlags() {
|
func RegisterFlags() {
|
||||||
fullOutput = flag.Bool("full-output", false, "Show full output instead of limiting submodule output")
|
flag.BoolVar(&fullOutput, "full-output", false, "Show full output instead of limiting submodule output")
|
||||||
printEmptyBlocks = flag.Bool("print-empty-blocks", false, "Prints blocks (submodule output) even if the submodule doesn't have any content to print.")
|
flag.BoolVar(&printEmptyBlocks, "print-empty-blocks", false, "Prints blocks (submodule output) even if the submodule doesn't have any content to print.")
|
||||||
targetFiles = flag.String("extract-these", "", "Comma-separated list of files to extract.")
|
flag.StringVar(&targetFiles, "extract-these", "", "Comma-separated list of files to extract.")
|
||||||
targetAllFiles = flag.Bool("extract-all", false, "Extract all files found.")
|
flag.BoolVar(&targetAllFiles, "extract-all", false, "Extract all files found.")
|
||||||
targetOutput = flag.String("extract-to", "./extracted", "Directory to store extracted files in.")
|
flag.StringVar(&targetOutput, "extract-to", "./extracted", "Directory to store extracted files in.")
|
||||||
|
flag.StringVar(&graphOutput, "create-graph", "", "Create a Graphviz graph out of collected communication")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
103
output/graph.go
Normal file
103
output/graph.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package output
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
)
|
||||||
|
|
||||||
|
var graphPkgs []GraphPkg
|
||||||
|
|
||||||
|
// AddPkgToGraph adds the given packet as communication to the graph
|
||||||
|
func AddPkgToGraph(pkg gopacket.Packet) {
|
||||||
|
// Only proceed if pkg contains a network layer
|
||||||
|
if pkg.NetworkLayer() == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
src := pkg.NetworkLayer().NetworkFlow().Src().String()
|
||||||
|
dst := pkg.NetworkLayer().NetworkFlow().Dst().String()
|
||||||
|
|
||||||
|
// Search for the given communication pair
|
||||||
|
for _, p := range graphPkgs {
|
||||||
|
if p.from == src && p.to == dst {
|
||||||
|
// Communication pair found, add protocol and finish
|
||||||
|
p.AddProtocol("nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Communcation pair was not in graphPkgs, add to it
|
||||||
|
graphPkgs = append(graphPkgs, GraphPkg{
|
||||||
|
from: src,
|
||||||
|
to: dst,
|
||||||
|
protocol: []string{""},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateGraph writes out a Graphviz digraph
|
||||||
|
func CreateGraph() {
|
||||||
|
if graphOutput == "" {
|
||||||
|
// No graph requested
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with the Graphviz-specific header
|
||||||
|
dot := fmt.Sprintf("# Compile with `neato -Tpng %s > %s.png`\n", graphOutput, graphOutput)
|
||||||
|
dot += "digraph pancap {\n\toverlap = false;\n"
|
||||||
|
|
||||||
|
// First, gather all nodes as-is and write them out
|
||||||
|
dot += nodedef(graphPkgs)
|
||||||
|
|
||||||
|
// Iterate over communication
|
||||||
|
for _, p := range graphPkgs {
|
||||||
|
dot += fmt.Sprintf("\tn%s->n%s\n", hash(p.from), hash(p.to))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
dot += "}\n"
|
||||||
|
|
||||||
|
// Write out
|
||||||
|
ioutil.WriteFile(graphOutput, []byte(dot), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a list of distinct nodes, Graphviz-compatible
|
||||||
|
func nodedef(pkgs []GraphPkg) string {
|
||||||
|
output := ""
|
||||||
|
nodes := []string{}
|
||||||
|
for _, p := range graphPkgs {
|
||||||
|
// Check if src and dst are already present in nodes array
|
||||||
|
srcFound := false
|
||||||
|
dstFound := false
|
||||||
|
for _, n := range nodes {
|
||||||
|
if p.from == n {
|
||||||
|
srcFound = true
|
||||||
|
}
|
||||||
|
if p.to == n {
|
||||||
|
dstFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !srcFound {
|
||||||
|
// src not yet present, add to node list
|
||||||
|
nodes = append(nodes, p.from)
|
||||||
|
}
|
||||||
|
if !dstFound {
|
||||||
|
// dst not yet present, add to node list
|
||||||
|
nodes = append(nodes, p.to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output Graphviz-compatible node definition
|
||||||
|
for _, n := range nodes {
|
||||||
|
// As the Graphviz charset for nodes is rather small, rely on hashes
|
||||||
|
output += fmt.Sprintf("\tn%s[label=\"%s\"]\n", hash(n), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func hash(s string) string {
|
||||||
|
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))[:6]
|
||||||
|
}
|
19
output/graphpkg.go
Normal file
19
output/graphpkg.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package output
|
||||||
|
|
||||||
|
// GraphPkg resembles a directed communication from one address to another
|
||||||
|
// It wraps up required information to draw a graph of the communication, including spoken protocols.
|
||||||
|
type GraphPkg struct {
|
||||||
|
from string
|
||||||
|
to string
|
||||||
|
protocol []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddProtocol adds the given protocol to the list of protocols if not already present
|
||||||
|
func (p *GraphPkg) AddProtocol(protocol string) {
|
||||||
|
for _, p := range p.protocol {
|
||||||
|
if p == protocol {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.protocol = append(p.protocol, protocol)
|
||||||
|
}
|
@ -23,4 +23,10 @@ func Finalize() {
|
|||||||
// User avoided the files
|
// User avoided the files
|
||||||
printer.Println("Files found in stream. Add --extract-all or --extract-these <list> to extract them.")
|
printer.Println("Files found in stream. Add --extract-all or --extract-these <list> to extract them.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if something graph-worthy was collected
|
||||||
|
if graphOutput == "" && len(graphPkgs) > 0 {
|
||||||
|
// User didn't want a graph
|
||||||
|
printer.Println("To summarize the communcation flow with a Graphviz graph, specify --create-graph <out.dot>.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,18 @@ package output
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fatih/color"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxContentLines = 50
|
MaxContentLines = 50
|
||||||
SnipMark = "----- cut at 50 entries -----"
|
SnipMark = "----- cut at 50 entries -----"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DidSnip bool
|
DidSnip bool
|
||||||
DidAvoidEmptyBlock bool
|
DidAvoidEmptyBlock bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ var (
|
|||||||
// If the content is longer than MaxContentLines, content is cut.
|
// If the content is longer than MaxContentLines, content is cut.
|
||||||
func PrintBlock(headline string, content string) {
|
func PrintBlock(headline string, content string) {
|
||||||
// Avoid printing empty blocks - at least if user didn't specify it otherwise
|
// Avoid printing empty blocks - at least if user didn't specify it otherwise
|
||||||
if len(content) == 0 && !*printEmptyBlocks {
|
if len(content) == 0 && !printEmptyBlocks {
|
||||||
// No content and we are not forced to print empty blocks, return
|
// No content and we are not forced to print empty blocks, return
|
||||||
DidAvoidEmptyBlock = true
|
DidAvoidEmptyBlock = true
|
||||||
return
|
return
|
||||||
@ -38,7 +39,7 @@ func PrintBlock(headline string, content string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cut to MaxContentLines if required
|
// Cut to MaxContentLines if required
|
||||||
if !(*fullOutput) {
|
if !(fullOutput) {
|
||||||
// User states that they don't want to see the whole output - cut content.
|
// User states that they don't want to see the whole output - cut content.
|
||||||
content = cutContent(content)
|
content = cutContent(content)
|
||||||
}
|
}
|
||||||
|
BIN
pancap.png
BIN
pancap.png
Binary file not shown.
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 464 KiB |
@ -2,24 +2,24 @@ package arp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
arpStatsList []arpStats
|
arpStatsList []arpStats
|
||||||
devices []arpDevice
|
devices []arpDevice
|
||||||
linkLocalBlock = net.IPNet{
|
linkLocalBlock = net.IPNet{
|
||||||
IP: net.IPv4(169, 254, 0, 0),
|
IP: net.IPv4(169, 254, 0, 0),
|
||||||
Mask: net.IPv4Mask(255, 255, 0, 0),
|
Mask: net.IPv4Mask(255, 255, 0, 0),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type Protocol struct {}
|
type Protocol struct{}
|
||||||
|
|
||||||
// Checks if the given packet is an ARP packet we can process
|
// Checks if the given packet is an ARP packet we can process
|
||||||
func (p *Protocol) CanAnalyze(packet gopacket.Packet) bool {
|
func (p *Protocol) CanAnalyze(packet gopacket.Packet) bool {
|
||||||
@ -118,7 +118,7 @@ func (p *Protocol) getStatOrCreate(macaddr string) *arpStats {
|
|||||||
|
|
||||||
// None found yet, we need to create a new one
|
// None found yet, we need to create a new one
|
||||||
arpStatsList = append(arpStatsList, arpStats{
|
arpStatsList = append(arpStatsList, arpStats{
|
||||||
macaddr: macaddr,
|
macaddr: macaddr,
|
||||||
})
|
})
|
||||||
|
|
||||||
// And return it
|
// And return it
|
||||||
|
@ -2,5 +2,5 @@ package arp
|
|||||||
|
|
||||||
type arpDevice struct {
|
type arpDevice struct {
|
||||||
macaddr string
|
macaddr string
|
||||||
ipaddr string
|
ipaddr string
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package arp
|
package arp
|
||||||
|
|
||||||
type arpStats struct {
|
type arpStats struct {
|
||||||
macaddr string
|
macaddr string
|
||||||
asked int
|
asked int
|
||||||
answered int
|
answered int
|
||||||
askedList []string
|
askedList []string
|
||||||
answeredList []string
|
answeredList []string
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package dhcpv4
|
package dhcpv4
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
hostnames []hostname
|
hostnames []hostname
|
||||||
networkSetup map[layers.DHCPOpt][]byte
|
networkSetup map[layers.DHCPOpt][]byte
|
||||||
requestMAC []string
|
requestMAC []string
|
||||||
responses []dhcpResponse
|
responses []dhcpResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the given packet is a DHCP packet we can process
|
// Checks if the given packet is a DHCP packet we can process
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package dhcpv4
|
package dhcpv4
|
||||||
|
|
||||||
type dhcpResponse struct {
|
type dhcpResponse struct {
|
||||||
destMACAddr string
|
destMACAddr string
|
||||||
newIPAddr string
|
newIPAddr string
|
||||||
serverMACAddr string
|
serverMACAddr string
|
||||||
askedFor bool
|
askedFor bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package dhcpv4
|
package dhcpv4
|
||||||
|
|
||||||
type hostname struct {
|
type hostname struct {
|
||||||
hostname string
|
hostname string
|
||||||
requestedByMAC string
|
requestedByMAC string
|
||||||
granted bool
|
granted bool
|
||||||
deniedHostname string
|
deniedHostname string
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ package dhcpv4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,13 +12,13 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
watchedOpts = []layers.DHCPOpt{
|
watchedOpts = []layers.DHCPOpt{
|
||||||
layers.DHCPOptSubnetMask, // Option 1
|
layers.DHCPOptSubnetMask, // Option 1
|
||||||
layers.DHCPOptRouter, // Option 3
|
layers.DHCPOptRouter, // Option 3
|
||||||
layers.DHCPOptDNS, // Option 6
|
layers.DHCPOptDNS, // Option 6
|
||||||
layers.DHCPOptBroadcastAddr, // Option 28
|
layers.DHCPOptBroadcastAddr, // Option 28
|
||||||
layers.DHCPOptNTPServers, // Option 42
|
layers.DHCPOptNTPServers, // Option 42
|
||||||
layers.DHCPOptLeaseTime, // Option 51
|
layers.DHCPOptLeaseTime, // Option 51
|
||||||
layers.DHCPOptT1, // Option 58
|
layers.DHCPOptT1, // Option 58
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ func formatDate(rawDate []byte) (string, bool) {
|
|||||||
intDate := binary.LittleEndian.Uint32(rawDate)
|
intDate := binary.LittleEndian.Uint32(rawDate)
|
||||||
seconds := intDate % 60
|
seconds := intDate % 60
|
||||||
minutes := intDate / 60 % 60
|
minutes := intDate / 60 % 60
|
||||||
hours := intDate / 60 / 60 % 60
|
hours := intDate / 60 / 60 % 60
|
||||||
formattedDate := ""
|
formattedDate := ""
|
||||||
|
|
||||||
// Check which words we need to pick
|
// Check which words we need to pick
|
||||||
|
@ -2,8 +2,8 @@ package dhcpv4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Processes the DHCP request packet handed over
|
// Processes the DHCP request packet handed over
|
||||||
|
@ -2,8 +2,8 @@ package dhcpv4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,20 +2,20 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
"golang.org/x/net/publicsuffix"
|
"golang.org/x/net/publicsuffix"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
numAnswers int
|
numAnswers int
|
||||||
answerDomains []string
|
answerDomains []string
|
||||||
answerBaseDomains []string
|
answerBaseDomains []string
|
||||||
answerPrivateDomains []string
|
answerPrivateDomains []string
|
||||||
answerType = make(map[layers.DNSType]int)
|
answerType = make(map[layers.DNSType]int)
|
||||||
answerPublicIPv4 []string
|
answerPublicIPv4 []string
|
||||||
answerPrivateIPv4 []string
|
answerPrivateIPv4 []string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Called on every DNS packet to process response(s)
|
// Called on every DNS packet to process response(s)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
privateBlocks = []net.IPNet{
|
privateBlocks = []net.IPNet{
|
||||||
{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)}, // 10.0.0.0/8
|
{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)}, // 10.0.0.0/8
|
||||||
{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)}, // 172.16.0.0/12
|
{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)}, // 172.16.0.0/12
|
||||||
{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)}, // 192.168.0.0/24
|
{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)}, // 192.168.0.0/24
|
||||||
{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 192, 0, 0)}, // 100.64.0.0/10
|
{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 192, 0, 0)}, // 100.64.0.0/10
|
||||||
@ -58,7 +58,7 @@ func (p *Protocol) generateDNSTypeSummary(typearr map[layers.DNSType]int) string
|
|||||||
if iter == 0 {
|
if iter == 0 {
|
||||||
// We don't need to append yet
|
// We don't need to append yet
|
||||||
answerstr = elem
|
answerstr = elem
|
||||||
} else if iter == len(answerarr) - 1 {
|
} else if iter == len(answerarr)-1 {
|
||||||
// Last element, use "and" instead of a comma
|
// Last element, use "and" instead of a comma
|
||||||
answerstr = fmt.Sprintf("%s and %s", answerstr, elem)
|
answerstr = fmt.Sprintf("%s and %s", answerstr, elem)
|
||||||
} else {
|
} else {
|
||||||
@ -68,4 +68,4 @@ func (p *Protocol) generateDNSTypeSummary(typearr map[layers.DNSType]int) string
|
|||||||
}
|
}
|
||||||
|
|
||||||
return answerstr
|
return answerstr
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Protocol struct {}
|
type Protocol struct{}
|
||||||
|
|
||||||
func (p *Protocol) CanAnalyze(packet gopacket.Packet) bool {
|
func (p *Protocol) CanAnalyze(packet gopacket.Packet) bool {
|
||||||
return packet.Layer(layers.LayerTypeDNS) != nil
|
return packet.Layer(layers.LayerTypeDNS) != nil
|
||||||
|
@ -2,18 +2,18 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
"golang.org/x/net/publicsuffix"
|
"golang.org/x/net/publicsuffix"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
numQuestions int
|
numQuestions int
|
||||||
questionDomains []string
|
questionDomains []string
|
||||||
questionBaseDomains []string
|
questionBaseDomains []string
|
||||||
questionPrivateDomains []string
|
questionPrivateDomains []string
|
||||||
questionType = make(map[layers.DNSType]int)
|
questionType = make(map[layers.DNSType]int)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Called on every DNS packet to process questions
|
// Called on every DNS packet to process questions
|
||||||
@ -72,4 +72,4 @@ func (p *Protocol) generateDNSQuestionSummary() string {
|
|||||||
|
|
||||||
// And return summary
|
// And return summary
|
||||||
return summary
|
return summary
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/maride/pancap/common"
|
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/google/gopacket/tcpassembly"
|
"github.com/google/gopacket/tcpassembly"
|
||||||
|
"github.com/maride/pancap/common"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
initialized bool
|
initialized bool
|
||||||
requestFactory *httpRequestFactory
|
requestFactory *httpRequestFactory
|
||||||
responseFactory *httpResponseFactory
|
responseFactory *httpResponseFactory
|
||||||
requestPool *tcpassembly.StreamPool
|
requestPool *tcpassembly.StreamPool
|
||||||
responsePool *tcpassembly.StreamPool
|
responsePool *tcpassembly.StreamPool
|
||||||
requestAssembler *tcpassembly.Assembler
|
requestAssembler *tcpassembly.Assembler
|
||||||
responseAssembler *tcpassembly.Assembler
|
responseAssembler *tcpassembly.Assembler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,17 +3,17 @@ package http
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maride/pancap/output"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/tcpassembly"
|
"github.com/google/gopacket/tcpassembly"
|
||||||
"github.com/google/gopacket/tcpassembly/tcpreader"
|
"github.com/google/gopacket/tcpassembly/tcpreader"
|
||||||
|
"github.com/maride/pancap/output"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
responseSummaryLines []string
|
responseSummaryLines []string
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpResponseFactory struct{}
|
type httpResponseFactory struct{}
|
||||||
|
Loading…
Reference in New Issue
Block a user