From 0d51cf820db536f8bf61d7c57dbbfb221384f408 Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:35:00 +0300 Subject: [PATCH 1/4] added methods to arpspoofer --- arpspoof/arpspoof.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arpspoof/arpspoof.go b/arpspoof/arpspoof.go index 8c14c46..2bba3bd 100644 --- a/arpspoof/arpspoof.go +++ b/arpspoof/arpspoof.go @@ -53,7 +53,7 @@ type ARPSpoofConfig struct { // NewARPSpoofConfig creates ARPSpoofConfig from a list of options separated by semicolon and logger. // -// Example: "targets 10.0.0.1,10.0.0.5-10,192.168.1.*,192.168.10.0/24;fullduplex false;debug true;interface eth0;gateway 192.168.1.1"`. +// Example: "targets 10.0.0.1,10.0.0.5-10,192.168.1.*,192.168.10.0/24;fullduplex false;debug true;interface eth0;gateway 192.168.1.1". // All fields in configuration string are optional. func NewARPSpoofConfig(s string, logger *zerolog.Logger) (*ARPSpoofConfig, error) { asc := &ARPSpoofConfig{Logger: logger} @@ -173,6 +173,30 @@ type ARPSpoofer struct { p *packet.Conn } +func (ar *ARPSpoofer) Interface() *net.Interface { + return ar.iface +} + +func (ar *ARPSpoofer) GatewayIP() netip.Addr { + return ar.gwIP +} + +func (ar *ARPSpoofer) GatewayMAC() net.HardwareAddr { + return ar.gwMAC +} + +func (ar *ARPSpoofer) HostIP() netip.Addr { + return ar.hostIP +} + +func (ar *ARPSpoofer) HostMAC() net.HardwareAddr { + return ar.hostMAC +} + +func (ar *ARPSpoofer) ARPTable() *ARPTable { + return ar.arpTable +} + func NewARPSpoofer(conf *ARPSpoofConfig) (*ARPSpoofer, error) { arpspoofer := &ARPSpoofer{} // determining interface From 9261160ba0d6f8cf8ecbc47563b0787369dd4cac Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:03:39 +0300 Subject: [PATCH 2/4] added more checks to eliminate false positives while parsing packets --- layers/ftp.go | 14 ++++++++------ layers/icmp.go | 3 +++ layers/ipv4.go | 6 ++++++ layers/ipv6.go | 7 +++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/layers/ftp.go b/layers/ftp.go index 63d6592..df7cd90 100644 --- a/layers/ftp.go +++ b/layers/ftp.go @@ -26,20 +26,22 @@ func (f *FTPMessage) Parse(data []byte) error { if !checkFTP(buf) { return fmt.Errorf("malformed ftp message") } - f.summary = nil - f.data = nil sp := bytes.Split(buf, crlf) lsp := len(sp) switch { case lsp > 2: - f.summary = bytes.Join(sp[:2], bspace) + f.summary = bytes.TrimSpace(bytes.Join(sp[:2], bspace)) sp[0] = joinBytes(dash, sp[0]) - f.data = bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf) + f.data = bytes.TrimSpace(bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf)) case lsp > 1: - f.summary = sp[0] + f.summary = bytes.TrimSpace(sp[0]) sp[0] = joinBytes(dash, sp[0]) - f.data = bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf) + f.data = bytes.TrimSpace(bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf)) default: + return fmt.Errorf("failed parsing FTP message") + } + if len(f.summary) == 0 || len(f.data) == 0 { + return fmt.Errorf("failed parsing FTP message") } return nil } diff --git a/layers/icmp.go b/layers/icmp.go index 495b8ea..83c0001 100644 --- a/layers/icmp.go +++ b/layers/icmp.go @@ -65,6 +65,9 @@ func (i *ICMPSegment) Parse(data []byte) error { return fmt.Errorf("minimum payload length for ICMP with type %d is %d bytes", i.Type, pLen) } i.TypeDesc, i.CodeDesc = i.typecode() + if i.TypeDesc == "Unknown" || i.CodeDesc == "Unknown" { + return fmt.Errorf("failed determining type or code") + } return nil } diff --git a/layers/ipv4.go b/layers/ipv4.go index 861d31b..4dffbf9 100644 --- a/layers/ipv4.go +++ b/layers/ipv4.go @@ -170,8 +170,14 @@ func (p *IPv4Packet) UnmarshalBinary(data []byte) error { dscpECN := buf[1] p.DSCP = dscpECN >> 2 p.DSCPDesc = dscpdesc(p.DSCP) + if p.DSCPDesc == "Unknown" { + return fmt.Errorf("unknown DSCP") + } p.ECN = dscpECN & 3 p.TotalLength = binary.BigEndian.Uint16(buf[2:4]) + if int(p.TotalLength) != len(buf) { + return fmt.Errorf("total length is not equal to actual packet size") + } p.Identification = binary.BigEndian.Uint16(buf[4:6]) flagsOffset := binary.BigEndian.Uint16(buf[6:8]) flags := uint8(flagsOffset >> 13) diff --git a/layers/ipv6.go b/layers/ipv6.go index a598e0b..4974693 100644 --- a/layers/ipv6.go +++ b/layers/ipv6.go @@ -15,7 +15,7 @@ type TrafficClass struct { ECN uint8 } -func newTrafficiClass(tc uint8) *TrafficClass { +func newTrafficClass(tc uint8) *TrafficClass { dscpbin := tc >> 2 return &TrafficClass{ Raw: tc, @@ -87,7 +87,7 @@ func (p *IPv6Packet) Parse(data []byte) error { if p.Version != 6 { return fmt.Errorf("unknown version") } - p.TrafficClass = newTrafficiClass(uint8((versionTrafficFlow >> 20) & 0xFF)) + p.TrafficClass = newTrafficClass(uint8((versionTrafficFlow >> 20) & 0xFF)) if p.TrafficClass.DSCPDesc == "Unknown" { return fmt.Errorf("unknown DSCP") } @@ -109,6 +109,9 @@ func (p *IPv6Packet) Parse(data []byte) error { return fmt.Errorf("malformed IPv6 address") } p.Payload = buf[headerSizeIPv6:] + if p.PayloadLength != 0 && int(p.PayloadLength) != len(p.Payload) { + return fmt.Errorf("payload length filed is not equal to actual payload size") + } return nil } From f0d48fc437b25630af7b8ac310ac782cf8f5cb99 Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:32:01 +0300 Subject: [PATCH 3/4] ipv4 identification randomization, changed ttl and flags when creating war ipv4 packets --- layers/ipv4.go | 19 ++++++++++--------- layers/layers.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/layers/ipv4.go b/layers/ipv4.go index 4dffbf9..a64d387 100644 --- a/layers/ipv4.go +++ b/layers/ipv4.go @@ -73,15 +73,16 @@ func NewIPv4Packet(srcIP, dstIP netip.Addr, proto IPProto, payload []byte) (*IPv return nil, fmt.Errorf("malformed IPv4 address") } ipPacket := &IPv4Packet{ - Version: 4, - IHL: 5, - TotalLength: uint16(headerSizeIPv4 + len(payload)), - Flags: NewIPv4Flags(0), - TTL: 64, - Protocol: &IPv4Proto{Val: proto, Desc: protodesc(proto)}, - SrcIP: srcIP, - DstIP: dstIP, - Payload: payload, + Version: 4, + IHL: 5, + TotalLength: uint16(headerSizeIPv4 + len(payload)), + Identification: MustGenerateRandomUint16NE(), + Flags: NewIPv4Flags(2), + TTL: 128, + Protocol: &IPv4Proto{Val: proto, Desc: protodesc(proto)}, + SrcIP: srcIP, + DstIP: dstIP, + Payload: payload, } headerChecksum, err := CalculateIPv4Checksum(ipPacket.ToBytes()) if err != nil { diff --git a/layers/layers.go b/layers/layers.go index 8943af7..b50948a 100644 --- a/layers/layers.go +++ b/layers/layers.go @@ -3,9 +3,12 @@ package layers import ( "bytes" + "crypto/rand" "encoding/binary" "fmt" "unsafe" + + "github.com/shadowy-pycoder/mshark/native" ) const maxLenSummary = 110 @@ -273,3 +276,45 @@ func isDigit(b byte) bool { func isUpper(b byte) bool { return b >= 'A' && b <= 'Z' } + +func GenerateRandomBytes(n int) ([]byte, error) { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + return nil, err + } + + return b, nil +} + +func GenerateRandomUint16LE() (uint16, error) { + b, err := GenerateRandomBytes(2) + if err != nil { + return 0, err + } + return binary.LittleEndian.Uint16(b), nil +} + +func GenerateRandomUint16BE() (uint16, error) { + b, err := GenerateRandomBytes(2) + if err != nil { + return 0, err + } + return binary.BigEndian.Uint16(b), nil +} + +func GenerateRandomUint16NE() (uint16, error) { + b, err := GenerateRandomBytes(2) + if err != nil { + return 0, err + } + return native.Endian.Uint16(b), nil +} + +func MustGenerateRandomUint16NE() uint16 { + rn, err := GenerateRandomUint16NE() + if err != nil { + panic(err) + } + return rn +} From 1679c0ef240e6ce13674a6622e0567f11fd16b05 Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:33:01 +0300 Subject: [PATCH 4/4] bumped to 0.0.14 --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 8db832f..168cd96 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package mshark -const Version string = "mshark v0.0.13" +const Version string = "mshark v0.0.14"