//go:generate goversioninfo -icon=assets/iconwin.ico package main import ( "bytes" "fmt" "log" "net" "os" "os/exec" "path/filepath" "strings" "syscall" "unsafe" _ "embed" "github.com/getlantern/systray" "github.com/google/gopacket" "github.com/google/gopacket/pcap" "github.com/tiagomdiogo/ScaGo/sniffer" ) var ( devName string localIp string sendIpList []string ) //go:embed assets/iconwin.ico var iconBytes []byte func sendPacket(packet gopacket.Packet, dstIp string) { socket, err := net.DialUDP("udp", &net.UDPAddr{IP: net.ParseIP(localIp), Port: 6112}, &net.UDPAddr{IP: net.ParseIP(dstIp), Port: 6112}, ) if err != nil { log.Println(err) } defer socket.Close() socket.Write(packet.ApplicationLayer().Payload()) } func handlePacket(packet gopacket.Packet) { log.Println("Sniffed packet:", packet.ApplicationLayer().Payload()) logBuf := bytes.Buffer{} for _, ip := range sendIpList { sendPacket(packet, ip) logBuf.WriteString(fmt.Sprintf("发送数据包到 %s\n", ip)) } log.Println(logBuf.String()) } func buildSendIpList() { for i := 1; i <= 50; i++ { sendIpList = append(sendIpList, fmt.Sprintf("192.168.73.%d", i)) } for i := 10; i <= 30; i++ { sendIpList = append(sendIpList, fmt.Sprintf("192.168.72.%d", i)) } } func IsInCIDR(ip net.IP, cidr string) bool { _, ipnet, err := net.ParseCIDR(cidr) if err != nil { return false } return ipnet.Contains(ip) } func init() { // 设置日志输出到文件 // 获取当前路径 dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { log.Fatal("无法获取当前路径:", err) } logFile, err := os.OpenFile(filepath.Join(dir, "war3-broadcaster.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { log.Fatal("无法创建日志文件:", err) } log.SetOutput(logFile) } func onReady() { systray.SetIcon(iconBytes) systray.SetTitle("WAR3开房助手") systray.SetTooltip("WAR3开房助手 - 运行中") mOpenLog := systray.AddMenuItem("打开日志", "打开日志文件") mQuit := systray.AddMenuItem("退出", "关闭程序") go func() { for { select { case <-mOpenLog.ClickedCh: exec.Command("notepad.exe", "war3-broadcaster.log").Start() case <-mQuit.ClickedCh: systray.Quit() return } } }() } func onExit() { // 清理工作 } func checkProcessRunning(processName string) bool { cmd := exec.Command("tasklist") output, err := cmd.Output() if err != nil { return false } // 判断存在两个war3-broadcaster.exe return strings.Count(string(output), processName) >= 2 } func checkPcapInstalled() bool { cmd := exec.Command("sc", "query", "npcap") output, err := cmd.Output() if err != nil { return false } return strings.Contains(string(output), "RUNNING") } // 添加新的辅助函数 func showMessageBox(message string, title string, flags uint32) { syscall.MustLoadDLL("user32.dll").MustFindProc("MessageBoxW").Call( 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(message))), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))), uintptr(flags)) } func main() { // 检查pcap是否安装 if !checkPcapInstalled() { showMessageBox("请先安装Npcap", "错误", 0x10) os.Exit(1) } // 检查是否已经有进程在运行 if checkProcessRunning("war3-broadcaster.exe") { showMessageBox("WAR3开房助手已经在运行中", "提示", 0x40) os.Exit(1) } go func() { buildSendIpList() devices, err := pcap.FindAllDevs() if err != nil { log.Fatal(err) } log.Println("搜索网络设备中...") devName = "" for _, device := range devices { for _, address := range device.Addresses { if IsInCIDR(address.IP, "192.168.72.3/22") { devName = device.Name localIp = address.IP.String() break } } } if devName == "" { showMessageBox("找不到网络设备,请确认是否已连接樱花祭世界", "错误", 0x10) os.Exit(1) log.Fatalln("找不到网络设备,请确认是否已连接樱花祭世界") } showMessageBox("成功找到设备,开始捕获War3广播数据", "提示", 0x40) log.Printf("找到设备: %s, 本地IP: %s\n", devName, localIp) log.Println("开始捕获War3广播数据") sniffer, err := sniffer.NewSniffer(devName, "dst net 255.255.255.255 and udp", handlePacket) if err != nil { log.Fatalln(err) } sniffer.Start() }() systray.Run(onReady, onExit) }