package db import ( "encoding/binary" "fmt" "io" "os" "runtime" "strings" ) const ( peMachineI386 uint16 = 0x014c peMachineAmd64 uint16 = 0x8664 peMachineArm64 uint16 = 0xaa64 peDOSHeaderMinSize = 0x40 peHeaderOffsetAddr = 0x3c peSignatureSize = 4 peCOFFHeaderSize = 20 ) func windowsMachineLabel(machine uint16) string { switch machine { case peMachineI386: return "windows-386" case peMachineAmd64: return "windows-amd64" case peMachineArm64: return "windows-arm64" default: return fmt.Sprintf("windows-unknown(0x%04x)", machine) } } func expectedWindowsMachineForGoArch(goarch string) (uint16, string, bool) { switch strings.ToLower(strings.TrimSpace(goarch)) { case "386": return peMachineI386, "windows-386", true case "amd64": return peMachineAmd64, "windows-amd64", true case "arm64": return peMachineArm64, "windows-arm64", true default: return 0, "", false } } func validateWindowsExecutableMachine(pathText string) error { return validateWindowsExecutableMachineForArch(pathText, runtime.GOARCH) } func validateWindowsExecutableMachineForArch(pathText string, goarch string) error { machine, err := readWindowsExecutableMachine(pathText) if err != nil { return fmt.Errorf("无法识别为有效的 Windows 可执行文件:%w", err) } expectedMachine, expectedLabel, ok := expectedWindowsMachineForGoArch(goarch) if !ok { return nil } if machine != expectedMachine { return fmt.Errorf("可执行文件架构不兼容(文件=%s,当前进程=%s)", windowsMachineLabel(machine), expectedLabel) } return nil } func readWindowsExecutableMachine(pathText string) (uint16, error) { file, err := os.Open(pathText) if err != nil { return 0, err } defer file.Close() info, statErr := file.Stat() if statErr != nil { return 0, statErr } if info.IsDir() { return 0, fmt.Errorf("路径是目录") } if info.Size() < peDOSHeaderMinSize { return 0, fmt.Errorf("文件头不完整") } var dosMagic [2]byte if err := readWindowsPEBytes(file, 0, dosMagic[:]); err != nil { return 0, fmt.Errorf("读取 DOS 头失败:%w", err) } if dosMagic[0] != 'M' || dosMagic[1] != 'Z' { return 0, fmt.Errorf("缺少 MZ 头") } var offsetBytes [4]byte if err := readWindowsPEBytes(file, peHeaderOffsetAddr, offsetBytes[:]); err != nil { return 0, fmt.Errorf("读取 PE 头偏移失败:%w", err) } peOffset := int64(binary.LittleEndian.Uint32(offsetBytes[:])) if peOffset < peDOSHeaderMinSize { return 0, fmt.Errorf("PE 头偏移异常") } if peOffset+peSignatureSize+peCOFFHeaderSize > info.Size() { return 0, fmt.Errorf("PE 头不完整") } var signature [4]byte if err := readWindowsPEBytes(file, peOffset, signature[:]); err != nil { return 0, fmt.Errorf("读取 PE 签名失败:%w", err) } if signature[0] != 'P' || signature[1] != 'E' || signature[2] != 0 || signature[3] != 0 { return 0, fmt.Errorf("缺少 PE 签名") } var machineBytes [2]byte if err := readWindowsPEBytes(file, peOffset+peSignatureSize, machineBytes[:]); err != nil { return 0, fmt.Errorf("读取 PE 架构失败:%w", err) } return binary.LittleEndian.Uint16(machineBytes[:]), nil } func readWindowsPEBytes(reader io.ReaderAt, offset int64, target []byte) error { if len(target) == 0 { return nil } _, err := reader.ReadAt(target, offset) if err == io.EOF { return io.ErrUnexpectedEOF } return err } // ValidateOptionalDriverAgentExecutable 校验可选驱动代理二进制是否可在当前进程中执行。 // 当前主要用于 Windows 下的 PE 架构兼容性校验,避免升级后复用到错误架构的旧代理。 func ValidateOptionalDriverAgentExecutable(driverType string, executablePath string) error { pathText := strings.TrimSpace(executablePath) if pathText == "" { return fmt.Errorf("%s 驱动代理路径为空", driverDisplayName(driverType)) } if runtime.GOOS != "windows" { return nil } if err := validateWindowsExecutableMachine(pathText); err != nil { return fmt.Errorf("%s 驱动代理不可用:%w", driverDisplayName(driverType), err) } return nil }