即使使用`noexecstack`

时间:2016-11-17 14:15:16

标签: c linux gcc linker glibc

我试图保护我的应用程序免受缓冲区溢出攻击。除此之外,我使用不可执行的堆栈并将我的二进制文件与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。

2 个答案:

答案 0 :(得分:1)

  

是什么导致了这个?

除了具有正确权限的主要可执行文件PT_GNU_STACK之外,您 还需要{em}具有正确的权限每个直接链接共享库。

如果这些库中的任何一个根本没有PT_GNU_STACK,或者具有可执行权限的库,它将使用可执行权限“毒害”所有堆栈。

所以运行

PT_GNU_STACK

并且您可能会看到至少一个具有丢失或可执行堆栈的库。

P.S。我看到奥拉夫已经(部分)暗示了这一点。

答案 1 :(得分:0)

奥拉夫和就业俄罗斯人把我推向了正确的方向。第三方共享对象使我的堆栈中毒。

但它没有直接链接到我的主要可执行文件。 lddlddtree都没有显示任何带有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是使用不同的工具链构建的,现在还没有被注意到。

奥拉夫,雇用俄语,谢谢!