在 Linux 中动态链接到 libc 没有绑定/连接

Dynamic linked to libc in Linux does not have bind/connect

提问人:user1929999 提问时间:10/15/2023 最后编辑:Jonathan Halluser1929999 更新时间:10/16/2023 访问量:55

问:

在 Linux 和 Mac 中,Go 动态链接到 libc 是不同的吗?我正在尝试评估使用 LD_PRELOAD (Linux) 或 DYLD_INSERT_LIBRARIES (macOS) 来拦截绑定(侦听)功能。它可以在 macOS 上运行,但不能在 Linux 上运行。

在 macOS 上:

❯ otool -tV main | grep bind
_x_cgo_bindm:
0000000100090134        bl      _syscall.bind
_syscall.bind:
0000000100090578        b       _syscall.bind
_syscall.libc_bind_trampoline.abi0:

在 Linux 上:

# objdump -T ./main

./main:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000545a80 g    DF .text  0000000000000063  Base        crosscall2
0000000000545a40 g    DF .text  0000000000000037  Base        _cgo_panic
0000000000466ae0 g    DF .text  0000000000000019  Base        _cgo_topofstack
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) __errno_location
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) getaddrinfo
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) free
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) freeaddrinfo
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) gai_strerror
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) stderr
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fwrite
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) vfprintf
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fputc
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) abort
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_mutex_lock
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.3.2) pthread_cond_wait
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_mutex_unlock
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.3.2) pthread_cond_broadcast
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_create
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) nanosleep
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_detach
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) strerror
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fprintf
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) malloc
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_attr_init
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_attr_getstacksize
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_attr_destroy
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigfillset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.32) pthread_sigmask
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) mmap
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) munmap
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) setenv
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) unsetenv
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigemptyset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigaddset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigaction
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigismember

有没有办法在 Linux 中强制 Go 二进制文件像 macOS 一样使用 bind/connect 函数?

linux go bind libc ld-preload

评论


答:

0赞 Employed Russian 10/16/2023 #1

在 Linux 上:

二进制文件不依赖于符号,但这并不一定意味着您不能用于插入该二进制文件bindLD_PRELOADbind

如果该二进制文件是用 构建的,那么它很可能取决于 ,它(在我的系统上)确实依赖于 和 :gccgolibgo.so.*bindconnect

readelf -Ws /usr/lib64/libgo.so.22 | grep -E ' (bind|connect)'
    77: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND connect@GLIBC_2.2.5 (2)
   224: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bind@GLIBC_2.2.5 (2)
140156: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND connect@GLIBC_2.2.5
163145: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bind@GLIBC_2.2.5

更新:

好奇你的 gccgo 建筑是否真的被LD_PRELOAD简单的绑定函数所吸引?

是的,确实如此。我用 编译了这个例子,并编译了这段代码:gccgo tcp_server.go

void bind() { abort(); }

gcc -w -shared -fPIC -o bind.so bind.c

最后我跑了:它产生了:LD_PRELOAD=./bind.so ./a.out

SIGABRT: abort
PC=0x7f83d3965884 m=0 sigcode=18446744073709551610

goroutine 1 [syscall]:
__pthread_kill_implementation
        :0
gsignal
        :0
__GI_abort
        :0
syscall.Bind
        :0
...

但是请注意,我的输出显示了对 的依赖性,而您的则没有。这是我所看到的:lddlibgo.so

ldd a.out
        linux-vdso.so.1 (0x00007ffc574f8000)
        libgo.so.22 => /lib64/libgo.so.22 (0x00007f21d5f7d000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f21d5e9c000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f21d5e78000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f21d5c9a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f21d7bb1000)

评论

0赞 user1929999 10/16/2023
您好,感谢您的快速回复。我想我的二进制 dep 也有。仍然LD_PRELOAD没有被迷住 ''' ldd main linux-vdso.so.1 (0x00007ffe545f4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5609501000) /lib64/ld-linux-x86-64.so.2 (0x00007f56096e7000) ''' ''' readelf -ws /lib/x86_64-linux-gnu/libc.so.6 |grep -E '(连接|绑定)' 845: 0000000000010a4a0 33 FUNC 弱默认值 16 bind@@GLIBC_2.2.5 2556: 0000000000010a4d0 155 FUNC 弱默认值 16 connect@@GLIBC_2.2.5 '''
0赞 user1929999 10/16/2023
好奇你的 gccgo 建筑是否真的被LD_PRELOAD简单的绑定函数所吸引?或者你的二进制文件实际上有这个符号?bind
0赞 Employed Russian 10/16/2023
@user1929999我已经更新了答案。你究竟是如何构建你的二进制文件的?
0赞 user1929999 10/16/2023
了不起。谢谢。> 在 Linux 上:我使用了标准的> 在 macOS 上(交叉编译):将更多地研究 gccgo。go build main.go❯ CC=x86_64-unknown-linux-gnu-gcc CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build -o main.linuxamd main.go