gcc 5 不检测内联函数的堆栈粉碎,但 gcc 7 检测

gcc 5 does not detect stack smashing for inline functions but gcc 7 does

这是我用来测试gcc栈保护特性的代码。

static inline void  charcpy(char* temp)
{
temp[0]='a';
temp[1]='b';
temp[2]='c';
temp[3]='d';
temp[4]='[=10=]';
}
int main()
{
char temp[3];
charcpy(temp);
return 0;
}

当我使用 gcc 7.3 编译时(未指定任何标志),我在桌面上遇到以下运行时错误

*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

如果重要的话,uname -a 命令会为我的桌面提供以下内容

Linux lixun-Desktop 4.15.0-36-generic #39-Ubuntu SMP Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

然而,当我使用 gcc 5.4 在服务器机器上尝试同样的操作时,没有出现错误。服务器机器的 uname -a 命令是

Linux aggravation 4.4.0-137-generic #163-Ubuntu SMP Mon Sep 24 13:14:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

然后我使用 objdump -D a.out 检查它们的汇编代码,但仍然无法弄清楚为什么堆栈保护在服务器机器上不起作用。 这是我桌面上的输出(我只粘贴了我认为可能重要的部分)

Disassembly of section .init:

0000000000000510 <_init>:
 510:   48 83 ec 08             sub    [=14=]x8,%rsp
 514:   48 8b 05 cd 0a 20 00    mov    0x200acd(%rip),%rax        # 200fe8 <__gmon_start__>
 51b:   48 85 c0                test   %rax,%rax
 51e:   74 02                   je     522 <_init+0x12>
 520:   ff d0                   callq  *%rax
 522:   48 83 c4 08             add    [=14=]x8,%rsp
 526:   c3                      retq   

Disassembly of section .plt:

0000000000000530 <.plt>:
 530:   ff 35 8a 0a 20 00       pushq  0x200a8a(%rip)        # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x8>
 536:   ff 25 8c 0a 20 00       jmpq   *0x200a8c(%rip)        # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x10>
 53c:   0f 1f 40 00             nopl   0x0(%rax)

0000000000000540 <__stack_chk_fail@plt>:
 540:   ff 25 8a 0a 20 00       jmpq   *0x200a8a(%rip)        # 200fd0 <__stack_chk_fail@GLIBC_2.4>
 546:   68 00 00 00 00          pushq  [=14=]x0
 54b:   e9 e0 ff ff ff          jmpq   530 <.plt>

Disassembly of section .plt.got:

0000000000000550 <__cxa_finalize@plt>:
 550:   ff 25 a2 0a 20 00       jmpq   *0x200aa2(%rip)        # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
 556:   66 90                   xchg   %ax,%ax
...
Disassembly of section .text:

0000000000000560 <_start>:
 560:   31 ed                   xor    %ebp,%ebp
 562:   49 89 d1                mov    %rdx,%r9
 565:   5e                      pop    %rsi
 566:   48 89 e2                mov    %rsp,%rdx
 569:   48 83 e4 f0             and    [=14=]xfffffffffffffff0,%rsp
 56d:   50                      push   %rax
 56e:   54                      push   %rsp
 56f:   4c 8d 05 ea 01 00 00    lea    0x1ea(%rip),%r8        # 760 <__libc_csu_fini>
 576:   48 8d 0d 73 01 00 00    lea    0x173(%rip),%rcx        # 6f0 <__libc_csu_init>
 57d:   48 8d 3d 24 01 00 00    lea    0x124(%rip),%rdi        # 6a8 <main>
 584:   ff 15 56 0a 20 00       callq  *0x200a56(%rip)        # 200fe0 <__libc_start_main@GLIBC_2.2.5>
 58a:   f4                      hlt    
 58b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
...
000000000000066a <charcpy>:
 66a:   55                      push   %rbp
 66b:   48 89 e5                mov    %rsp,%rbp
 66e:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
 672:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 676:   c6 00 61                movb   [=14=]x61,(%rax)
 679:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 67d:   48 83 c0 01             add    [=14=]x1,%rax
 681:   c6 00 62                movb   [=14=]x62,(%rax)
 684:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 688:   48 83 c0 02             add    [=14=]x2,%rax
 68c:   c6 00 63                movb   [=14=]x63,(%rax)
 68f:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 693:   48 83 c0 03             add    [=14=]x3,%rax
 697:   c6 00 64                movb   [=14=]x64,(%rax)
 69a:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 69e:   48 83 c0 04             add    [=14=]x4,%rax
 6a2:   c6 00 00                movb   [=14=]x0,(%rax)
 6a5:   90                      nop
 6a6:   5d                      pop    %rbp
 6a7:   c3                      retq   

00000000000006a8 <main>:
 6a8:   55                      push   %rbp
 6a9:   48 89 e5                mov    %rsp,%rbp
 6ac:   48 83 ec 10             sub    [=14=]x10,%rsp
 6b0:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
 6b7:   00 00 
 6b9:   48 89 45 f8             mov    %rax,-0x8(%rbp)
 6bd:   31 c0                   xor    %eax,%eax
 6bf:   48 8d 45 f5             lea    -0xb(%rbp),%rax
 6c3:   48 89 c7                mov    %rax,%rdi
 6c6:   e8 9f ff ff ff          callq  66a <charcpy>
 6cb:   b8 00 00 00 00          mov    [=14=]x0,%eax
 6d0:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
 6d4:   64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
 6db:   00 00 
 6dd:   74 05                   je     6e4 <main+0x3c>
 6df:   e8 5c fe ff ff          callq  540 <__stack_chk_fail@plt>
 6e4:   c9                      leaveq 
 6e5:   c3                      retq   
 6e6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 6ed:   00 00 00 

这是服务器机器上的输出

Disassembly of section .init:

00000000004003f0 <_init>:
  4003f0:   48 83 ec 08             sub    [=15=]x8,%rsp
  4003f4:   48 8b 05 fd 0b 20 00    mov    0x200bfd(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>
  4003fb:   48 85 c0                test   %rax,%rax
  4003fe:   74 05                   je     400405 <_init+0x15>
  400400:   e8 3b 00 00 00          callq  400440 <__libc_start_main@plt+0x10>
  400405:   48 83 c4 08             add    [=15=]x8,%rsp
  400409:   c3                      retq   

Disassembly of section .plt:

0000000000400410 <__stack_chk_fail@plt-0x10>:
  400410:   ff 35 f2 0b 20 00       pushq  0x200bf2(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
  400416:   ff 25 f4 0b 20 00       jmpq   *0x200bf4(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
  40041c:   0f 1f 40 00             nopl   0x0(%rax)

0000000000400420 <__stack_chk_fail@plt>:
  400420:   ff 25 f2 0b 20 00       jmpq   *0x200bf2(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
  400426:   68 00 00 00 00          pushq  [=15=]x0
  40042b:   e9 e0 ff ff ff          jmpq   400410 <_init+0x20>

0000000000400430 <__libc_start_main@plt>:
  400430:   ff 25 ea 0b 20 00       jmpq   *0x200bea(%rip)        # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
  400436:   68 01 00 00 00          pushq  [=15=]x1
  40043b:   e9 d0 ff ff ff          jmpq   400410 <_init+0x20>

Disassembly of section .plt.got:

0000000000400440 <.plt.got>:
  400440:   ff 25 b2 0b 20 00       jmpq   *0x200bb2(%rip)        # 600ff8 <_DYNAMIC+0x1d0>
  400446:   66 90                   xchg   %ax,%ax
...
Disassembly of section .text:

0000000000400450 <_start>:
  400450:   31 ed                   xor    %ebp,%ebp
  400452:   49 89 d1                mov    %rdx,%r9
  400455:   5e                      pop    %rsi
  400456:   48 89 e2                mov    %rsp,%rdx
  400459:   48 83 e4 f0             and    [=15=]xfffffffffffffff0,%rsp
  40045d:   50                      push   %rax
  40045e:   54                      push   %rsp
  40045f:   49 c7 c0 40 06 40 00    mov    [=15=]x400640,%r8
  400466:   48 c7 c1 d0 05 40 00    mov    [=15=]x4005d0,%rcx
  40046d:   48 c7 c7 84 05 40 00    mov    [=15=]x400584,%rdi
  400474:   e8 b7 ff ff ff          callq  400430 <__libc_start_main@plt>
  400479:   f4                      hlt    
  40047a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
0000000000400546 <charcpy>:
  400546:   55                      push   %rbp
  400547:   48 89 e5                mov    %rsp,%rbp
  40054a:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  40054e:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400552:   c6 00 61                movb   [=15=]x61,(%rax)
  400555:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400559:   48 83 c0 01             add    [=15=]x1,%rax
  40055d:   c6 00 62                movb   [=15=]x62,(%rax)
  400560:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400564:   48 83 c0 02             add    [=15=]x2,%rax
  400568:   c6 00 63                movb   [=15=]x63,(%rax)
  40056b:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  40056f:   48 83 c0 03             add    [=15=]x3,%rax
  400573:   c6 00 64                movb   [=15=]x64,(%rax)
  400576:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  40057a:   48 83 c0 04             add    [=15=]x4,%rax
  40057e:   c6 00 00                movb   [=15=]x0,(%rax)
  400581:   90                      nop
  400582:   5d                      pop    %rbp
  400583:   c3                      retq   

0000000000400584 <main>:
  400584:   55                      push   %rbp
  400585:   48 89 e5                mov    %rsp,%rbp
  400588:   48 83 ec 10             sub    [=15=]x10,%rsp
  40058c:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400593:   00 00 
  400595:   48 89 45 f8             mov    %rax,-0x8(%rbp)
  400599:   31 c0                   xor    %eax,%eax
  40059b:   48 8d 45 f0             lea    -0x10(%rbp),%rax
  40059f:   48 89 c7                mov    %rax,%rdi
  4005a2:   e8 9f ff ff ff          callq  400546 <charcpy>
  4005a7:   b8 00 00 00 00          mov    [=15=]x0,%eax
  4005ac:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
  4005b0:   64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
  4005b7:   00 00 
  4005b9:   74 05                   je     4005c0 <main+0x3c>
  4005bb:   e8 60 fe ff ff          callq  400420 <__stack_chk_fail@plt>
  4005c0:   c9                      leaveq 
  4005c1:   c3                      retq   
  4005c2:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005c9:   00 00 00 
  4005cc:   0f 1f 40 00             nopl   0x0(%rax)
...

我也尝试在服务器机器上指定-fstack-protector(-all 或-strong),它仍然没有显示错误。 任何人都知道为什么会有差异?

服务器计算机将数组 temp 放入 main 堆栈帧中的不同位置。它使用此操作来计算地址,从帧指针偏移 16 字节:

  40059b:   48 8d 45 f0             lea    -0x10(%rbp),%rax

另一台机器改用这个:

     6bf:   48 8d 45 f5             lea    -0xb(%rbp),%rax

帧指针只有 11 个字节的偏移量。在这两种情况下,金丝雀都存储在偏移量 8 处。

结果,在服务器机器上,数组后有 5 个未使用的字节,溢出溢出到其中。金丝雀未被覆盖,这就是未检测到溢出的原因。但是return地址也不是,所以这里不能重定向执行。

在现实世界的软件中,这将是一个源代码级的基于堆栈的缓冲区溢出,在编译的二进制文件中不会被意外利用。这种事情时有发生。