gcc 若干安全相關選項

2021-06-25 13:09:54 字數 3434 閱讀 6432

參考:

示例程式如下:

1 #include

2 #include

3 4 int main()

5 首先看看不帶 fortify_source 選項的結果:

[tom@localhost code]$ gcc -o2 -o test test.c

[tom@localhost code]$ ll

可見,不帶 fortify_source 選項的情況下,編譯器無法檢測到這類問題;

在看看帶 fortify_source 選項的編譯結果(注意該選項只能和 -o 選項一起使用,且優化級別大於 0):

[tom@localhost code]$ gcc -o2 -d_fortify_source=2(1 或者 2) -o test test.c

in file included from /usr/include/string.h:642:0,

from test.c:2:

in function 'strcpy',

inlined from 'main' at test.c:8:8:

/usr/include/bits/string3.h:105:3:

warning: call to __builtin___memcpy_chk will always overflow destination buffer [enabled by default]

[tom@localhost code]$ 

可以看到,已經報出來在原始碼的第 8 行存在溢位問題。

需要注意的是這個選項只能輔助檢測出一部分緩衝區溢位的問題,而不是所有的。

**自:

position-independe

nt-exe

cutable是binu

tils,glibc和gcc的乙個功能,能用來建立介於共享庫和通常可執行**之間的**�能像共享庫一樣可

重分配位址

的程式,這種程式必須連線到scrt1.o。標準的可執行程式需要固定的位址,並且只有被

裝載到這個位址時

,程式才

能正確執行。pie能使程式像共享庫一樣在主存任何位置裝

載,這需要將程式

編譯成位置無關,

並鏈結為

elf共享物件

。引入pie的

原因是讓程式能裝載

在隨機的位址,通常情況下,核心都在固定的位址執行,如果能改用位置無關,那攻擊者就很難借助系統中的可執行碼實施攻擊了。類似緩衝區溢位之類的攻擊將無法實施。而且這種安全提公升的代價很小

談到pie就不得不說說pax和grsec核心。這兩個東西都是為了構建

堅不可摧到安全系統而準備的。pax是linux核心安全增強補丁,

它能在兩方面保證安全性,一是asl

r(addr

ess space layout randomization,位址空間分布隨機化),這是一種將所有資料裝載到記憶體時都隨機化位址的方式,當使用pie選項編譯應用時,pax能將應用的位址做隨機加法;二是能提供不可執行的記憶體空間,這樣就能使得攻擊者放入記憶體中的惡意**不可執行。不過pax官網上能支援的最新核心是2.6.27,已經是一年前的更新了。grsec也時類似的核心補丁,更新較為頻繁能支援最新的2.6.32核心。這兩種方式都能將核心完全位置無關,除了grub和glibc中無法位置無關的彙編碼。

pie最早由redhat的人實現,他在連線起上增加了-pie選項,這樣使用-fpie編譯的物件就能通過聯結器得到位置無關可執行程式。fpie和fpic有些不同。可以參考gcc和open64中的-fpic選項.

gcc中的-fpic選項,使用於在目標機支援時,編譯共享庫時使用。編譯出的**將通過全域性偏移表(global offset table)中的常數字址訪存,動態裝載器將在程式開始執行時解析got表項(注意,動態裝載器作業系統的一部分,聯結器是gcc的一部分).而gcc中的-fpic選項則是針對某些特殊機型做了特殊處理,比如適合動態鏈結並能避免超出got大小限制之類的錯誤。而open64僅僅支援不會導致got表溢位的pic編譯。

gcc中的-fpie和-fpie選項和fpic及fpic很相似,但不同的是,除了生成為位置無關**外,還能假定**是屬於本程式。通常這些選項會和gcc鏈結時的-pie選項一起使用。fpie選項僅能在編譯可執行碼時用,不能用於編譯庫。所以,如果想要pie的程式,需要你除了在gcc增加-fpie選項外,還需要在ld時增加-pie選項才能產生這種**。即gcc -fpie -pie來編譯程式。單獨使用哪乙個都無法達到效果。

你可以使用file命令來檢視當前的可執行檔案是不是pie的。

下面是本博編譯helloword的顯示。可以看出,可執行檔案屬性從executable變成了shared object.

$ gcc 

helloworld.c

$ file a.out

a.out: elf 32-bit lsb executable, intel 80386, version 1 (sysv), dynamically linked (uses shared libs), for gnu/linux 2.6.9, not stripped

$ gcc -fpie -pie helloworld.c

$ file a.out

a.out: elf 32-bit lsb shared object, intel 80386, version 1 (sysv), dynamically linked (uses shared libs), for gnu/linux 2.6.9, not stripped

接下來,我們就能實驗了,使用stra

ce命令來檢視這兩個a.out執**況了。關於strace命令,可以參考strace命令介紹

在博主電腦上,有pie時,執行第乙個brk(0)系統呼叫時,返回的位址一直是變化的。而無pie時,brk(o)系統呼叫返回位址一直不變(紅色部分)。

[tom@localhost code]$ strace helloworld

strace: can't stat 'helloworld': no such file or directory

[tom@localhost code]$ strace ./helloworld 

execve("./helloworld", ["./helloworld"], [/* 25 vars */]) = 0

brk(0)                                  = 0x7f98a5278000

[tom@localhost code]$ strace ./helloworld 

execve("./helloworld", ["./helloworld"], [/* 25 vars */]) = 0

brk(0)                                  = 0x7f9b4cebb000

注:linux系統呼叫brk():

linux系統內部分配記憶體的系統呼叫,malloc()其實也是呼叫的brk().直接修改堆的大小,返回新記憶體區域的結束位址。

gcc 若干安全相關選項

參考 示例程式如下 1 include 2 include 3 4 int main 5 首先看看不帶 fortify source 選項的結果 tom localhost code gcc o2 o test test.c tom localhost code ll 可見,不帶 fortify s...

GCC編譯選項

gcc g 在執行編譯工作的時候,總共需要4步 1.預處理,生成.i的檔案 預處理器cpp 2.將預處理後的檔案不轉換成組合語言,生成檔案.s 編譯器egcs 3.有彙編變為目標 機器 生成.o的檔案 彙編器as 4.連線目標 生成可執行程式 鏈結器ld 引數詳解 c 只啟用預處理,編譯,和彙編,也...

gcc 編譯選項

gcc 編譯選項,自己翻譯的.gcc 編譯選項,自己翻譯的.o 設定輸出檔名 c 只編譯,不連線.e 只做預編譯.pipe 在多個編譯過程之間使用管道.version 顯示版本.static 靜態連線.ansi c 模式下支援所有 iso c90 標準的 c 程式,c 模式下去除對 gnu c 擴充...