我试图保护我的应用程序免受缓冲区溢出攻击。除此之外,我使用不可执行的堆栈并将我的二进制文件与noexecstack
标志链接(通过将-Wl,-z,noexecstack
传递给gcc)。
一切似乎都很好 - readelf
确认PT_GNU_STACK
指定了正确的权限:
$ readelf -l target | grep -A1 GNU_STACK
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
execstack
:
$ execstack -q target
- target
只有一个问题。我的所有堆栈实际上都是可执行的:
root@170ubuntu16p04-64smp-1:~# cat /proc/12878/task/*/maps | grep stack
7ffcac654000-7ffcac675000 rwxp 00000000 00:00 0 [stack]
7fe540e66000-7fe541666000 rwxp 00000000 00:00 0 [stack]
7fe540665000-7fe540e65000 rwxp 00000000 00:00 0 [stack]
7fe53b800000-7fe53c000000 rwxp 00000000 00:00 0 [stack]
我已经捕获了allocate_stack个电话,并检查了保护标志。 In theory,应根据PT_GNU_STACK
对其进行初始化。但就我而言,似乎忽略了PT_GNU_STACK
,并使用默认权限初始化了_dl_stack_flags
。
有谁知道可能导致这种情况的原因?一切似乎都是正确的,但堆栈仍然是可执行的。
我使用的是gcc 4.8.3 / glibc 2.11。
答案 0 :(得分:1)
是什么导致了这个?
除了具有正确权限的主要可执行文件PT_GNU_STACK
之外,您 还需要{em}具有正确的权限每个直接链接共享库。
如果这些库中的任何一个根本没有PT_GNU_STACK
,或者具有可执行权限的库,它将使用可执行权限“毒害”所有堆栈。
所以运行
PT_GNU_STACK
并且您可能会看到至少一个具有丢失或可执行堆栈的库。
P.S。我看到奥拉夫已经(部分)暗示了这一点。
答案 1 :(得分:0)
奥拉夫和就业俄罗斯人把我推向了正确的方向。第三方共享对象使我的堆栈中毒。
但它没有直接链接到我的主要可执行文件。 ldd
和lddtree
都没有显示任何带有RWE堆栈的库,所以我决定深入挖掘并编写一个脚本来检查当前映射到进程内存的所有共享对象:
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: $0 <target>"
exit 1;
fi
kav_pid=`pidof $1`
for so in `cat /proc/$kav_pid/task/*/maps | awk '/.so$/ {print $6}' | sort | uniq`; do
stack_perms=`readelf -Wl $so | awk '/GNU_STACK/ {print $7}'`
if [ -z "$stack_perms" ]; then
echo "$so doesn't have PT_GNU_STACK"
elif [ "$stack_perms" != "RW" ]; then
echo "$so has unexpected permissions: $stack_perms"
fi
done
它有效!我找到了一个具有RWE权限的库:
$ ./find_execstack.sh target
/target/dir/lib64/lib3rdparty.so has unexpected permissions: RWE
为了确保这个库中毒了我的堆栈,我用gdb
打开了我的应用程序并在dlopen
中设置了一个断点。和宾果!以下是dlopen
lib3rdparty.so之前的权限:
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
这是他们就在dlopen
:
7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0 [stack]
事实证明,lib3rdparty.so
是使用不同的工具链构建的,现在还没有被注意到。
奥拉夫,雇用俄语,谢谢!