簡體   English   中英

堆棧砸不開火。 為什么?

[英]Stack smashing not fires. Why?

我正在嘗試使glibc檢測堆棧破壞,並使用以下代碼:

 #include <stdio.h>
 #include <string.h>

 static const int n = 5;

 int main(int argc, char *argv[])
 {
  if (argc != 2)
  {
     printf("usage: %s string\n", argv[0]);
     return -1;
  }
  printf("%s, len = %d\n", argv[1], strlen(argv[1]));
  unsigned char a[n][n];
  unsigned char * b = a[n - 1];
  memcpy(b, argv[1], (strlen(argv[1]) + 1) * sizeof(unsigned char));
  return 0;
 }

如果argv [1]的長度大於5,我希望檢測到堆棧粉碎錯誤,但是我沒有,並且valgrind沒有檢測到錯誤。 我應該怎么做才能得到這個錯誤? (數組a必須是二維的)

默認情況下,當您執行諸如alloca類的特別危險的操作(或在注釋中提到的gets )或聲明大型自動數組時,GCC僅添加代碼以檢測堆棧alloca

如果要對所有功能啟用保護,請使用-fstack-protector-all選項。 您還可以使用-Wstack-protector請求有關不受保護的功能的警告。

似乎gcc中決定何時啟用堆棧保護的邏輯有些棘手。 來自文檔的第一條注釋:

-fstack保護器

發出額外的代碼以檢查緩沖區溢出,例如堆棧破壞攻擊。 這是通過向具有易受攻擊對象的函數添加一個保護變量來完成的。 這包括調用alloca的函數以及緩沖區大於8個字節的函數 當進入功能時,將初始化防護,然后在功能退出時進行檢查。 如果防護檢查失敗,則會顯示一條錯誤消息,並且程序退出

因此,我們應該期望具有小於8個字節的本地緩沖區的函數不受保護。 例如,這:

int unprotected() {
    char a[5];
    strcpy(a, "this is much too long");
    return a[0];
}

gcc -fstack-protector -Wstack-protector編譯時,給出類似的警告

警告:堆棧保護器不保護功能:所有本地數組的長度均小於8個字節[-Wstack-protector]

因此,您可能認為char[5][5]將受到保護,因為它的長度超過8個字節。 但是,當我將其編譯為匯編器時,沒有得到警告堆棧保護(您可以在Dr. Dobbs文章中找到要尋找的匯編器)。 看來gcc將其視為5個緩沖區,每個緩沖區5個字節,而不是25個字節的單個緩沖區。

您可以通過顯示大於8個字節的單個緩沖區來說服gcc啟用堆棧保護:

void protected(char *arg) {
    union {
        char dummy[5 * 5];
        char a[5][5];
    } u;
    memcpy(u.a[4], arg, (strlen(arg) + 1));
}

或簡單地使用-fstack-protector-all

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM