2016-11-17 63 views
7

我試圖保護我的應用程序免受緩衝區溢出攻擊。除此之外,我使用非可執行堆棧並將我的二進制文件與noexecstack標誌(將-Wl,-z,noexecstack傳遞給gcc)相鏈接。即使使用`noexecstack`,堆棧也可以執行

似乎一切都很好 - 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 

這裏只有一個問題。我所有的堆棧實際上是可執行文件:

[email protected]:~# 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

這是一個多線程應用程序嗎? –

+0

該選項只是標記可執行文件,但不能保證您的操作系統注意到它。這可能不是編程問題,而是系統管理/配置。 – Olaf

+0

@BasileStarynkevitch是的,這是一個多線程應用程序。堆棧由'pthread_create'分配。 –

回答

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 

爲了確保它是這個庫毒害我的書庫,我打開我的應用程序與gdbdlopen設置一個斷點。賓果!這裏是荷蘭國際集團lib3rdparty.so dlopen之前的權限:

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0       [stack] 

,這裏是他們的dlopen之後:

7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0       [stack] 

事實證明,lib3rdparty.so使用不同的工具鏈構建和去忽視直到現在。

奧拉夫,就業俄語,謝謝!

1

這是什麼原因造成的?

除了主要的可執行文件的PT_GNU_STACK有正確的權限,你也需要PT_GNU_STACK使用正確的權限在直接連接的共享庫。

如果這些庫中的任何一個根本沒有PT_GNU_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 

,你可能會看到至少一個庫丟失或可執行堆棧。

P.S.我看到奧拉夫已經(部分)提出了這個建議。