在 Ubuntu 中使用 gcc 标志 -fno-stack-protector 编译 C 程序是否正确?

问题描述 投票:0回答:2

*我使用的是 Ubuntu x86_64 系统,gcc 11.4.0

我在文件 test.c 中有这个 C 程序:

int fx( int a, int* b ){

     *b = 12;
      return a;

}


int main(){
    
    int a = 20;
    int b = fx(10,&a);
    b+= 5;
    
}

我用“gcc test.c -o test”编译这个文件。然后我用“objdump -dw -M suffix test”检查它,我得到:

0000000000001149 <fx>:
    1149:   f3 0f 1e fa             endbr64 
    114d:   55                      pushq  %rbp
    114e:   48 89 e5                movq   %rsp,%rbp
    1151:   89 7d fc                movl   %edi,-0x4(%rbp)
    1154:   48 89 75 f0             movq   %rsi,-0x10(%rbp)
    1158:   48 8b 45 f0             movq   -0x10(%rbp),%rax
    115c:   c7 00 0c 00 00 00       movl   $0xc,(%rax)
    1162:   8b 45 fc                movl   -0x4(%rbp),%eax
    1165:   5d                      popq   %rbp
    1166:   c3                      retq   

0000000000001167 <main>:
    1167:   f3 0f 1e fa                     endbr64 
    116b:   55                              pushq  %rbp
    116c:   48 89 e5                        movq   %rsp,%rbp
    116f:   48 83 ec 10                     subq   $0x10,%rsp
    1173:   64 48 8b 04 25 28 00 00 00      movq   %fs:0x28,%rax
    117c:   48 89 45 f8                     movq   %rax,-0x8(%rbp)
    1180:   31 c0                           xorl   %eax,%eax
    1182:   c7 45 f0 14 00 00 00            movl   $0x14,-0x10(%rbp)
    1189:   48 8d 45 f0                     leaq   -0x10(%rbp),%rax
    118d:   48 89 c6                        movq   %rax,%rsi
    1190:   bf 0a 00 00 00                  movl   $0xa,%edi
    1195:   e8 af ff ff ff                  callq  1149 <fx>
    119a:   89 45 f4                        movl   %eax,-0xc(%rbp)
    119d:   83 45 f4 05                     addl   $0x5,-0xc(%rbp)
    11a1:   b8 00 00 00 00                  movl   $0x0,%eax
    11a6:   48 8b 55 f8                     movq   -0x8(%rbp),%rdx
    11aa:   64 48 2b 14 25 28 00 00 00      subq   %fs:0x28,%rdx
    11b3:   74 05                           je     11ba <main+0x53>
    11b5:   e8 96 fe ff ff                  callq  1050 <__stack_chk_fail@plt>
    11ba:   c9                              leaveq 
    11bb:   c3                              retq

看起来编译器默认使用堆栈保护器,您可以通过查看主要指令来判断。

我的问题:

  1. 用“gcc test.c -fno-stack-protector -o test”编译我的C程序可以吗?

  2. -fno-stack-protector 只是一个安全选项,使我们容易受到某些堆栈攻击,还是我们在编译时使用此选项时应该小心,因为它可能会破坏某些内容或产生某种错误/不兼容?

  3. 为什么我的 gcc 编译器默认没有打开它,而在其他系统(macOS x86_64 clang)中我注意到它是打开的?

  4. 在哪些情况下使用它是有意义的,而在哪些情况下我们绝对应该避免使用它?

c ubuntu stack x86-64 hardening
2个回答
1
投票

用“gcc test.c -fno-stack-protector -o test”编译我的C程序可以吗?

我认为这样做没有任何问题。为了约定,最好将选项放在操作数之前,如下所示:

gcc -fno-stack-protector -o test test.c

-fno-stack-protector 只是一个安全选项,使我们容易受到某些堆栈攻击,还是我们在编译时使用此选项时应该小心,因为它可能会破坏某些内容或产生某种错误/不兼容?

选项

-fstack-protector=...
可以针对堆栈粉碎攻击进行额外的强化。如果您使用
-fno-stack-protector
禁用它,您的代码将不会从这种强化中受益,并且如果它已经存在可利用的缺陷,则可能更容易被利用。您可以根据需要混合和匹配使用或不使用堆栈保护器编译的目标文件,使用堆栈保护器不会导致不兼容。但是,只有在使用堆栈保护器编译的翻译单元中定义的函数才能从这种强化中受益。

为什么我的 gcc 编译器默认没有打开它,而在其他系统(macOS x86_64 clang)中我注意到它是打开的?

Canonical 决定默认启用此选项,以使针对堆栈崩溃的强化成为“选择退出”,而不是像 macOS 上那样“选择加入”。这提高了整体安全性。

在哪些情况下使用它是有意义的,而在哪些情况下我们绝对应该避免使用它?

打开堆栈保护器进行编译通常很有用,特别是如果您的代码使用不受信任的输入或来自网络或外部存储介质的输入运行。然而,有一个较小的性能成本。如果这很重要,您可能需要关闭堆栈保护器。请注意,如果您的应用程序存在此类缺陷,则可能更容易受到堆栈粉碎攻击的利用。


0
投票
  1. 是的,这样做完全没问题。但风险自负。如果没有它,您的程序中针对潜在堆栈缓冲区溢出漏洞的保护就会少一分。
  2. 是的,这只是一个安全功能/选项,使用/不使用它进行编译都不会破坏东西,除非您正在开发复杂的低级标准库代码。
  3. 取决于您的编译器版本和操作系统/发行版。每个操作系统/发行版都有自己的编译器版本,具有不同的配置和默认值。您显然决定使用默认堆栈保护器配置 GCC。
  4. 您可能想要避免的唯一情况是微基准测试或特定的低级编程情况,其中代码必须完全符合您的预期,而没有额外的编译器生成的噪音。一般情况下,禁用它没有多大意义,它的开销应该可以忽略不计。
© www.soinside.com 2019 - 2024. All rights reserved.