windows - Go程序访问线程环境 block 时出现panic

标签 windows go assembly

我正在开发 Go 库来访问一些内部 Windows 线程结构(线程环境 block ),这需要编写一些汇编代码。我一直试图理解为什么这在 Win32 C++ 应用程序上有效,但在我的 Go 库上却不起作用。

这段 Go 汇编代码访问 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;
}

当访问返回的 TEB 指针时,Go 程序会发生困惑。这是我收到的消息:

panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x0 pc=0x498d5b]

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

以下是重现该问题的示例:

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
}

最佳答案

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

关于windows - Go程序访问线程环境 block 时出现panic,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51639548/

相关文章:

windows - Jenkins 不能很好地处理私有(private) GitHub 存储库 (Windows)

c - 在 Go 程序中使用 C 代码时未声明的标识符

templates - 内置 "html/template"或 "mustache",我应该使用哪个?

gcc - 与GCC组装会导致关于.data的奇怪的重定位错误

windows - 在 Windows 上通过 Jenkins 使用 chromedriver 和 chrome 捕获屏幕截图时,从渲染器 : 10. 000 接收消息超时

java - 移动到 open-jdk 8u212 时 IntelliJ 的部署问题

c# - 如何将项目添加到 Windows Shell(右键单击)?

go - 有没有办法在模型中使用 gobuffalo i18n 翻译器?

assembly - 如何在汇编中获取 16 字节对齐的地址

java - 由用户运行给定的程序