[英]Go program panics when accessing the Thread Environment Block
I'm developing on a Go library to access some internal Windows thread structures (Thread Environment Block) and this requires writing some assembly code. 我正在使用Go库进行开发,以访问一些内部Windows线程结构(线程环境块),这需要编写一些汇编代码。 I've been trying to understand why this works on a Win32 C++ application but it doesn't on my Go library.
我一直在试图理解为什么它可以在Win32 C ++应用程序上工作,但是在我的Go库上却不能。
This snippet of Go assembly code accesses fs:[0x18] to return a pointer to the thread's associated TEB : 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
This is the equivalent MASM code, which compiles and runs just fine on MSVC: 这是等效的MASM代码,可以在MSVC上编译并正常运行:
void* readfsdword(unsigned offset_)
{
unsigned dw;
__asm {
mov eax, offset_
mov eax, fs:[eax]
mov dw, eax
}
return (void*)dw;
}
The Go program panics when accessing the returned pointer to the TEB. 访问返回的指向TEB的指针时,Go程序会出现紧急情况。 Here's the message I get:
这是我收到的消息:
panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x0 pc=0x498d5b]
紧急情况:运行时错误:无效的内存地址或nil指针取消引用[信号0xc0000005代码= 0x0地址= 0x0 pc = 0x498d5b]
The Go assembly code seems right to me, but I can't understand how and why the program panics. Go汇编代码对我来说似乎是正确的,但是我不明白该程序如何以及为什么会慌乱。 Any help is much appreciated!
任何帮助深表感谢!
Here's an example to reproduce the issue: 这是重现此问题的示例:
intrinsics.s 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 intrinsics.go
package nt
func ReadFsDword(offset uint32) (ret uint32)
test.go 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
}
The problem was fixed. 该问题已解决。 Apparently, Windows uses the
gs
register with an offset of 0x30 on x64 whereas fs
and a 0x18 offset are used on x86/WoW64 mode. 显然,Windows在x64上使用偏移量为0x30的
gs
寄存器,而在x86 / WoW64模式下使用fs
和偏移量为0x18的gs
寄存器。 The solution is to use either fs
or gs
with the respective offsets depending on the value of GOARCH
. 解决方案是根据
GOARCH
的值使用fs
或gs
以及各自的偏移量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.