Du kannst nicht mehr als 25 Themen auswählen
Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
204 Zeilen
4.4 KiB
Go
204 Zeilen
4.4 KiB
Go
package util
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base32"
|
|
"encoding/binary"
|
|
"github.com/google/gopacket"
|
|
"github.com/google/gopacket/layers"
|
|
"github.com/google/gopacket/pcapgo"
|
|
log "github.com/sirupsen/logrus"
|
|
"hash/adler32"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// WritePcap writes the provided data to a given pcap file
|
|
func WritePcap(file string, data []byte) {
|
|
f, err := os.Create(file)
|
|
if err != nil {
|
|
log.Errorf("Error writing pcap file %s", file)
|
|
}
|
|
defer f.Close()
|
|
|
|
r, err := pcapgo.NewNgWriter(f, layers.LinkTypeEthernet)
|
|
if err != nil {
|
|
log.Errorf("Error writing pcap file %s", file)
|
|
}
|
|
defer r.Flush()
|
|
|
|
ci := gopacket.CaptureInfo{
|
|
Timestamp: time.Now(),
|
|
CaptureLength: len(data),
|
|
Length: len(data),
|
|
}
|
|
|
|
err = r.WritePacket(ci, data)
|
|
}
|
|
|
|
// WritePIDFile writes the processes PID to a given file
|
|
func WritePIDFile(filename string) {
|
|
if filename == "" {
|
|
return
|
|
}
|
|
if err := ioutil.WriteFile(filename, []byte(strconv.Itoa(os.Getpid())+"\n"), 0644); err != nil {
|
|
log.Errorf("Error writing PID file %s", filename)
|
|
}
|
|
}
|
|
|
|
// GenerateMac generates a random MAC address
|
|
func GenerateMac(customMAC string) net.HardwareAddr {
|
|
if customMAC != "" {
|
|
ret, _ := net.ParseMAC(customMAC)
|
|
return ret
|
|
}
|
|
buf := make([]byte, 6)
|
|
var mac net.HardwareAddr
|
|
if _, err := rand.Read(buf); err != nil {
|
|
log.Error("Error generating random mac")
|
|
ret, _ := net.ParseMAC("52:54:00:12:34:aa")
|
|
return ret
|
|
}
|
|
// Set local bit, ensure unicast address
|
|
buf[0] = (buf[0] | 2) & 0xfe
|
|
mac = append(mac, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5])
|
|
return mac
|
|
}
|
|
|
|
// GenerateXID generates a random XID for DHCP
|
|
func GenerateXID() []byte {
|
|
buf := make([]byte, 4)
|
|
if _, err := rand.Read(buf); err != nil {
|
|
log.Error("Error generating random xid")
|
|
return []byte{36, 23, 250, 224} // chosen by fair dice roll
|
|
// guaranteed to be random --> https://xkcd.com/221/
|
|
}
|
|
return buf
|
|
}
|
|
|
|
// GenerateUId generates a random UId string as hostname
|
|
func GenerateUId(path string) string {
|
|
adl := adler32.Checksum([]byte(path))
|
|
byt := make([]byte, 4)
|
|
for i := uint32(0); i < 4; i++ {
|
|
byt[i] = byte((adl >> (8 * i)) & 0xff)
|
|
}
|
|
b32 := base32.StdEncoding.EncodeToString(byt)
|
|
return strings.ReplaceAll(b32, "=", "")
|
|
}
|
|
|
|
// If is a helper type to form expressive ternary expressions being the
|
|
// concatenation of a type conversion and a method call such as:
|
|
//
|
|
// i := If(cond).Int(a, b)
|
|
//
|
|
// For details, see https://stackoverflow.com/a/59375088/1705598
|
|
type If bool
|
|
|
|
// If returns a if c is true, b otherwise.
|
|
func (c If) If(a, b interface{}) interface{} {
|
|
if c {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// MAC returns a if c is true, b otherwise.
|
|
func (c If) MAC(a, b net.HardwareAddr) net.HardwareAddr {
|
|
if c {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// IP returns a if c is true, b otherwise.
|
|
func (c If) IP(a, b net.IP) net.IP {
|
|
if c {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Source: https://github.com/aler9/landiscover/blob/main/utils.go, MIT LICENSE
|
|
|
|
// DnsQueryDecode takes encoded hostnames from Microsoft and decodes it
|
|
func DnsQueryDecode(data []byte, start int) (string, int) {
|
|
var read []byte
|
|
toread := uint8(0)
|
|
pos := start
|
|
|
|
for ; true; pos++ {
|
|
if pos >= len(data) { // decoding terminated before null character
|
|
return "", -1
|
|
}
|
|
if data[pos] == 0x00 {
|
|
if toread > 0 { // decoding terminated before part parsing
|
|
return "", -1
|
|
}
|
|
break // query correctly decoded
|
|
}
|
|
|
|
if toread == 0 { // we need a size or pointer
|
|
if len(read) > 0 { // add separator
|
|
read = append(read, '.')
|
|
}
|
|
|
|
if (data[pos] & 0xC0) == 0xC0 { // pointer
|
|
ptr := int(binary.BigEndian.Uint16(data[pos:pos+2]) & 0x3FFF)
|
|
pos++ // skip next byte
|
|
|
|
substr, subread := DnsQueryDecode(data, ptr)
|
|
if subread <= 0 {
|
|
return "", -1
|
|
}
|
|
read = append(read, []byte(substr)...)
|
|
break // query correctly decoded
|
|
} else { // size
|
|
toread = data[pos]
|
|
}
|
|
} else { // byte inside part
|
|
read = append(read, data[pos])
|
|
toread--
|
|
}
|
|
}
|
|
return string(read), pos + 1 - start
|
|
}
|
|
|
|
// DnsQueryEncode takes string hostnames and encodes it to Microsoft format
|
|
func DnsQueryEncode(in string) []byte {
|
|
tmp := strings.Split(in, ".")
|
|
|
|
l := 0
|
|
for _, part := range tmp {
|
|
bpart := []byte(part)
|
|
l++
|
|
l += len(bpart)
|
|
}
|
|
l++
|
|
|
|
ret := make([]byte, l)
|
|
i := 0
|
|
|
|
for _, part := range tmp {
|
|
bpart := []byte(part)
|
|
ret[i] = uint8(len(bpart))
|
|
i++
|
|
copy(ret[i:], bpart)
|
|
i += len(bpart)
|
|
}
|
|
|
|
ret[i] = uint8(0)
|
|
|
|
return ret
|
|
}
|
|
|
|
// Prefixes for traffic from (out) or to (in) VM
|
|
const (
|
|
Out = ">> "
|
|
In = "<< "
|
|
)
|