Linux下Golang基于C实现函数Hook失败:ptrace权限问题
针对ptrace附加失败的解决方案
1. 关闭Go的Seccomp过滤
Go运行时默认启用Seccomp安全机制,可能阻断ptrace系统调用。可以通过两种方式关闭:
- 运行程序时添加环境变量:
GODEBUG=seccomp=0 ./your_go_binary - 编译时禁用Seccomp:
go build -tags=seccomp_off -o your_go_binary your_code.go
2. 排查系统安全模块限制
- Yama配置确认:确保ptrace_scope确实设置为0,执行:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - SELinux(RHEL8):执行
sestatus查看状态,若为Enforcing模式,临时关闭测试:sudo setenforce 0,问题解决后可考虑添加自定义SELinux规则放行ptrace。 - AppArmor(WSL/Ubuntu):执行
sudo aa-status检查状态,临时禁用:sudo systemctl stop apparmor,验证是否解决问题。
3. 调整ptrace调用逻辑
内核可能限制进程ptrace自身,可改为fork子进程来附加父进程:
package main import ( "os" "syscall" "time" ) func main() { pid := os.Getpid() child, err := syscall.Fork() if err != nil { panic(err) } if child == 0 { // 子进程附加父进程 err := syscall.PtraceAttach(pid) if err != nil { panic(err) } syscall.Wait4(pid, nil, 0, nil) os.Exit(0) } // 父进程等待子进程完成附加 time.Sleep(100 * time.Millisecond) // 后续执行Hook逻辑 }
4. 替代方案:直接修改内存权限跳转
放弃ptrace,直接修改Go函数内存页权限并写入跳转指令:
- 使用
syscall.Mprotect将函数所在内存页设置为可读可写可执行 - 通过指针直接修改内存中的指令,跳转到C函数的地址(需要先通过
dlopen和dlsym获取C函数地址)
5. 确认动态库加载权限
确保编译的.so文件有可执行权限,且程序能找到:
chmod +x libyourlib.so LD_LIBRARY_PATH=. ./your_go_binary
内容的提问来源于stack exchange,提问作者Shaked Shitrit
相关产品推荐
相关产品推荐

