即使使用'noexecstack',堆栈也是可执行的`

即使使用'noexecstack',堆栈也是可执行的`,c,linux,gcc,linker,glibc,C,Linux,Gcc,Linker,Glibc,我试图保护我的应用程序免受缓冲区溢出攻击。除此之外,我正在使用不可执行堆栈并使用noexecstack标志链接我的二进制文件(通过将-Wl,-z,noexecstack传递到gcc) 一切正常-readelf确认PT\u GNU\u STACK指定了正确的权限: $ readelf -l target | grep -A1 GNU_STACK GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000

我试图保护我的应用程序免受缓冲区溢出攻击。除此之外,我正在使用不可执行堆栈并使用
noexecstack
标志链接我的二进制文件(通过将
-Wl,-z,noexecstack
传递到gcc)

一切正常-
readelf
确认
PT\u GNU\u STACK
指定了正确的权限:

$ readelf -l target | grep -A1 GNU_STACK
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
$ ./find_execstack.sh target
/target/dir/lib64/lib3rdparty.so has unexpected permissions: RWE
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]
我截获了电话并检查了保护标志,它们应该根据
PT\u GNU\u堆栈
进行初始化。但在我的例子中,
PT\u GNU\u STACK
似乎被忽略,而
\u dl\u STACK\u flags
是用默认权限初始化的

有人知道这是什么原因吗?一切似乎都是正确的,但堆栈仍然是可执行的

我使用的是GCC4.8.3/Glibc2.11

这是什么原因造成的

除了主可执行文件的
PT_GNU_堆栈
具有正确的权限外,您还需要在每个直接链接的共享库中具有
PT_GNU_堆栈
具有正确的权限

如果这些库中的任何一个根本没有
PT\u GNU\u STACK
,或者有一个具有可执行权限,那么它将“毒害”具有可执行权限的所有堆栈

快跑

for j in $(ldd target | grep -o '=> .* ' | sed -e 's/=> //' -e '/^ *$/d' ); do
  out=$(readelf -Wl $j | grep STACK)
  [[ -z "$out" ]] &&  echo "missing GNU_STACK in $j"
  echo $out | grep -q RWE && echo "executable GNU_STACK in $j"
done
您可能会看到至少有一个库缺少堆栈或可执行堆栈


另外,我看到奥拉夫已经(部分)提出了这个建议。

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

但它没有直接链接到我的主可执行文件。
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
为了确保是这个库毒害了我的堆栈,我用
gdb
打开了我的应用程序,并在
dlopen
中设置了一个断点。宾果!以下是
dlopen
ing lib3rdparty之前的权限。因此:

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
下面是它们就在
dlopen
后面:

7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0                          [stack]
事实证明,
lib3rdparty.so
是使用一个不同的工具链构建的,现在它没有被注意到


奥拉夫,俄罗斯人,谢谢

这是一个多线程应用程序吗?该选项只是标记可执行文件,但不能保证您的操作系统关注它。这可能不是编程问题,而是系统管理/配置问题。@BasileStarynkevitch是的,这是一个多线程应用程序。堆栈由
pthread\u create
@Olaf操作系统进行分配。我使用相同的工具链构建了几个应用程序,它们没有可执行堆栈-堆栈是
mmap
ed为
rw-p
。这就是为什么我认为我忽略了一些东西。好吧,你可以使用一个没有设置那个标志的库/对象文件。这样,整个应用程序就无法运行。