war3-broadcast/main.go

184 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//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.0/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)
}