mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-22 17:00:21 +08:00
- 修复 WebView2 zoom factor 跨线程调用风险,切回窗口线程执行并增加 recover 与超时保护 - 完善 Redis 命令结果 JSON-safe 兜底,避免复杂返回值格式化触发程序崩溃 - 调整 Windows driver-agent 校验逻辑,仅读取 PE Machine 字段判断架构兼容性 - 避免 COFF string table EOF 被误判为无效 Windows 可执行文件,修复驱动在线安装和本地导入失败 - 补充窗口缩放、Redis 返回值和驱动代理 PE 校验回归测试
148 lines
4.0 KiB
Go
148 lines
4.0 KiB
Go
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
|
||
}
|