首先,由于这是我在StackOverflow上提出的第一个问题,因此我没有足够的声誉来包含2个以上的链接。但是,我需要包含远超过2个链接,以便我的问题是完整和可理解的。这就是为什么我在下面的Gist中写下了所有有关的参考文献。之后,每次看到[XXX]时,都会引用前面提到的Gist中的相应链接。
让我们自己解决问题:我正面临涉及glibc的汇编问题。
简而言之,作为课程的一部分,我有机会学习计算机安全。值得注意的是,我必须深入研究一些CVE。我选择查看[GHOST - CVE-2015-0235]:GetHOSTbyxxx函数中的缓冲区溢出,允许远程执行代码。
为了做到这一点,我想尝试重现[Qualys漏洞利用]。 这就是为什么我基于最新的LTS Ubuntu发行版(16.04)设置了一个Docker环境,我希望在其中编译[glibc](2.17)的易受攻击版本和[Exim邮件服务器]的易受攻击版本(4.77) - 这是在Qualys漏洞利用中使用的软件。
第一步是下载,编译和安装(在/ usr / local / lib中)glibc。到目前为止,非常好。
为了验证我可以用gcc链接到这个版本的glibc来编译一些代码,我编译了Qualys提供的[GHOST漏洞检查],这要归功于以下命令(灵感来自StackOverflow的这两个答案:[ 1]和[2]):
gcc vulnerability_check.c -o vulnerability_check \
-Wl,--rpath=/usr/local/lib \
-Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2
完全没问题。因此,我尝试编译连接到易受攻击的glibc版本的Exim Mail Server。根据与Exim邮件服务器相关的文档,可以通过将以下行附加到Local / Makefile(必须由用户从src / EDITME创建)添加编译标志:
CFLAGS="-Wl,--rpath=/usr/local/lib -Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2"
然而,我正面临一些未定义的参考"错误:
/usr/local/lib/libpthread.so.0: undefined reference to `h_errno@GLIBC_PRIVATE'
/usr/local/lib/libpthread.so.0: undefined reference to `__vdso_clock_gettime@GLIBC_PRIVATE'
collect2: error: ld returned 1 exit status
Makefile:517: recipe for target 'eximon.bin' failed
据我所知,这意味着通常在共享静态库中定义的" eximon"的源代码中使用的一些符号(h_errno和clock_gettime)在版本中找不到glibc我编译。为了确保它们确实没有定义,我在[GHOST漏洞检查]代码中添加了对这两个符号的虚拟调用,并对其进行了编译。没问题。
我不确定接下来要做什么来跟踪问题的根源。我一直在寻找分析沿glibc编译的静态库内容的方法(nm似乎可以解决这个问题)。我试着深入研究编译工具链的文档,从gcc到ld。我也发现了PatchELF,但我不认为这是我需要的(没有第三方库来修改)。但是,我找不到解决方案,也找不到解决方法。
因此,对于将Exim与已编译的glibc链接起来的方法,使用编译工具链的正确方法,解决此类编译问题的正确方法,我将不胜感激。或者你认为会让我成为更好的程序员的任何建议。
我非常感谢你。
答案 0 :(得分:3)
为了验证我可以用gcc链接到这个版本的glibc来编译一些代码,
您没有使用此版本的glibc编译和链接代码。
我编译了Qualys提供的[GHOST漏洞检查],感谢以下命令(灵感来自StackOverflow的这两个答案:[1]和[2]):
您似乎丢失了参考文献[1]和[2]。
gcc vulnerability_check.c -o vulnerability_check \ -Wl,--rpath=/usr/local/lib \ -Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2
以上命令使GCC使用include
(即/usr/include
)和lib
(即/usr/lib
)的标准位置,但会安排GLIBC的备用版本(/usr/local
中的一个)将在运行时使用 。
也就是说,有3个不同的步骤:
.o
和.so
文件以及您只安排了第3步使用新建的GLIBC。
要使用新建的GLIBC(假设已配置安装到/usr/local
),您应该使用以下内容:
gcc -o t -nostdlib -nostartfiles -I/usr/local/include \
/usr/local/lib/crt1.o \
/usr/local/lib/crti.o \
$(gcc --print-file-name=crtbegin.o) \
t.c \
/usr/local/lib/libc.so.6 \
/usr/local/lib/libc_nonshared.a \
/usr/local/lib/ld-linux-x86-64.so.2 \
$(gcc --print-file-name=crtend.o) \
/usr/local/lib/crtn.o \
-Wl,--rpath=/usr/local/lib \
-Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2`
CFLAGS="-Wl,--rpath=/usr/local/lib -Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2"
上面的命令再次出错:它在静态链接时使用了不匹配的ld-linux.so
和libc.so.6
(在上面的第2步),并且失败了。
TL; DR:与非标准GLIBC的链接很复杂。相反,使用chroot环境或虚拟机会好得多。
<强>更新强>
CFLAGS="-I/usr/local/include -Wl,--rpath=/usr/local/lib -Wl,--dynamic-linker=/usr/local/lib/ld-linux-x86-64.so.2"
以上设置没有意义:-Wl,...
是链接器标志,它们属于LDFLAGS
。
LDFLAGS="-nostdlib -nostartfiles /usr/local/lib/crt1.o /usr/local/lib/crti.o $(gcc --print-file-name=crtbegin.o) /usr/local/lib/libc.so.6 /usr/local/lib/libc_nonshared.a /usr/local/lib/ld-linux-x86-64.so.2 $(gcc --print-file-name=crtend.o) /usr/local/lib/crtn.o"
... 哪里不对了 ?
是。请注意,crti.o
,您的对象/来源,libc.so.6
和crtn.o
的顺序非常重要,并且必须完全符合我展示的顺序。< / p>
我不相信有任何方法可以通过LDFLAGS
中的指定来实现此类订单。您需要手动执行命令行,或者对正在构建的程序进行大量修改Makefile
。
你真的最好在chroot或VM中这样做。