【问题标题】:Go program panics when accessing the Thread Environment BlockGo 程序在访问线程环境块时发生恐慌
【发布时间】:2018-08-01 17:57:44
【问题描述】:

我正在开发 Go 库以访问一些内部 Windows 线程结构(线程环境块),这需要编写一些汇编代码。我一直在试图理解为什么这适用于 Win32 C++ 应用程序,但它不适用于我的 Go 库。

Go 汇编代码的这个 sn-p 访问 fs:[0x18] 以返回指向线程关联的 TEB 的指针:

    // func ReadFsDword(offset uint32) (dword uint32)
    TEXT ·ReadFsDword(SB),$0-8
            MOVL offset+0(FP), AX
            // mov eax, dword ptr fs:[eax]
            BYTE $0x64; BYTE $0x8B; BYTE $0x00
            MOVL AX, ret+8(FP)
            RET

这是等效的 MASM 代码,在 MSVC 上编译和运行都很好:

void* readfsdword(unsigned offset_)
{
    unsigned dw;

    __asm {
        mov eax, offset_
        mov eax, fs:[eax]
        mov dw, eax
    }

    return (void*)dw;
}

Go 程序在访问返回的指向 TEB 的指针时发生恐慌。这是我收到的信息:

恐慌:运行时错误:无效的内存地址或零指针 取消引用[信号0xc0000005代码=0x0 addr=0x0 pc=0x498d5b]

Go 汇编代码对我来说似乎是正确的,但我无法理解程序如何以及为什么会出现恐慌。非常感谢任何帮助!

这是重现问题的示例:

intrinsics.s

#include "textflag.h"
#include "funcdata.h"

// func ReadFsDword(offset uint32) (ret uint32)
TEXT ·ReadFsDword(SB),$0-8
        MOVL offset+0(FP), AX
        // mov eax, dword ptr fs:[eax]
        BYTE $0x64; BYTE $0x8B; BYTE $0x00
        MOVL AX, ret+8(FP)
        RET

intrinsics.go

package nt

func ReadFsDword(offset uint32) (ret uint32)

test.go

package main

import "nt"

func main() {
    GetProcAddress("LoadLibraryExW")
}

func GetProcAddress(proc string) unsafe.Pointer {
    teb := nt.NtGetTeb()
    fmt.Printf("%p", teb)

    // todo: implement
    return nil
}

【问题讨论】:

  • amd64吗?为什么你的 Go 代码在应该使用 FS 时使用 FP(帧指针)寄存器?
  • @kostix 它使用FP 来访问参数和结果。 FS 在机器码字节中(前缀64)。
  • 注意,根据this article,线程环境块是通过GS访问的,而不是64位模式下的FS。您是否尝试过使用 GS 并按照文章中的说明更改偏移量?
  • @fuz 问题已解决。实际上,gs 段选择器在 x64 中使用,具有不同的偏移量 (0x30)。库现在读取正确的值。
  • @NTAuthority 请注意,您可以通过在构建时将环境变量 GOARCH 定义为 386 来将 Go 代码编译为 32 位代码。如果这将是一个库,请考虑使用适当的构建标签,以便它为两种架构做正确的事情。

标签: windows go assembly


【解决方案1】:

问题已解决。显然,Windows 使用 gs 寄存器,在 x64 上偏移为 0x30,而在 x86/WoW64 模式下使用fs 和 0x18 偏移。 解决方案是使用 fsgs 以及各自的偏移量,具体取决于 GOARCH 的值。

【讨论】:

猜你喜欢
  • 2019-10-07
  • 2018-10-28
  • 2022-01-25
  • 1970-01-01
  • 2023-02-16
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 2016-02-27
相关资源
最近更新 更多