Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用FGET导致缓冲区溢出_C_Buffer_Overflow_Stack Overflow_Fortify Source - Fatal编程技术网

C 使用FGET导致缓冲区溢出

C 使用FGET导致缓冲区溢出,c,buffer,overflow,stack-overflow,fortify-source,C,Buffer,Overflow,Stack Overflow,Fortify Source,我正在试验缓冲区溢出,并尝试用fgets的特定输入覆盖堆栈的返回地址 代码如下: void foo() { fprintf(stderr, "You did it.\n"); } void bar() { char buf[20]; puts("Input:"); fgets(buf, 24, stdin); printf("Your input:.\n", strlen(buf)); } int main(int argc, char **argv

我正在试验缓冲区溢出,并尝试用fgets的特定输入覆盖堆栈的返回地址

代码如下:

void foo()
{
    fprintf(stderr, "You did it.\n");
}

void bar()
{
    char buf[20];
    puts("Input:");
    fgets(buf, 24, stdin);
    printf("Your input:.\n", strlen(buf));
}


int main(int argc, char **argv)
{
    bar();
    return 0;
}
在正常执行时,程序只返回您的输入。我希望它在不修改代码的情况下输出foo()

我的想法是通过输入20个
'A'
s来溢出
buf
的缓冲区。这起作用并导致分段故障。 我的下一个想法是找出
foo()
的地址,即
\x4006cd
,并将其附加到20
'A'
s

据我所知,这应该覆盖堆栈的返回地址,并使其跳转到
foo
。但它只会导致一个故障

我做错了什么

更新:汇编程序转储 主要

主函数的汇编程序代码转储: 0x000000000040073b:推送%rbp 0x000000000040073c:mov%rsp,%rbp 0x000000000040073f:子$0x10,%rsp 0x0000000000400743:mov%edi,-0x4(%rbp) 0x0000000000400746:mov%rsi,-0x10(%rbp) 0x000000000040074a:mov$0x0,%eax 0x00000000004074F:callq 0x4006f1 0x0000000000400754:mov$0x0,%eax 0x0000000000400759:LEVEQ 0x000000000040075a:retq 汇编程序转储结束。 福

函数foo的汇编程序代码转储: 0x00000000004006cd:推送%rbp 0x00000000004006ce:mov%rsp,%rbp 0x00000000004006d1:mov 0x200990(%rip),%rax#0x601068 0x00000000004006d8:mov%rax,%rcx 0x00000000004006db:mov$0x15,%edx 0x000000000004006E0:mov$0x1,%esi 0x00000000004006e5:mov$0x400804,%edi 0x00000000004006ea:callq 0x4005d0 0x00000000004006ef:弹出%rbp 0x00000000004006f0:retq 汇编程序转储结束。 酒吧:

功能条汇编代码转储:
0x00000000004006f1:推送%rbp
0x00000000004006f2:mov%rsp,%rbp
0x00000000004006f5:子$0x20,%rsp
0x00000000004006f9:mov$0x40081a,%edi
0x00000000004006fe:callq 0x400570
0x0000000000400703:mov 0x200956(%rip),%rdx#0x601060
0x000000000040070a:lea-0x20(%rbp),%rax
0x000000000040070e:mov$0x18,%esi
0x0000000000400713:mov%rax,%rdi
0x0000000000400716:callq 0x4005b0
0x000000000040071b:lea-0x20(%rbp),%rax
0x000000000040071f:mov%rax,%rdi
0x0000000000400722:callq 0x400580
0x0000000000400727:mov%rax,%rsi
0x000000000040072a:mov$0x400821,%edi
0x000000000040072f:mov$0x0,%eax
0x0000000000400734:callq 0x400590
0x0000000000400739:LEVEQ
0x000000000040073a:retq
汇编程序转储结束。

您没有使用内存分配进行计数。我稍微修改了代码,以便更容易找到正确的位置

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

int **x;
int z;

void foo()
{
    fprintf(stderr, "You did it.\n");
}

void bar()
{
    char buf[2];
    //puts("Input:");
    //fgets(buf, 70, stdin);
    x = (int**) buf;
    for(z=0;z<8;z++)
            printf("%d X=%x\n", z, *(x+z));
    *(x+3) = foo;
    printf("Your input: %d %s\n", strlen(buf), buf);
}


int main(int argc, char **argv)
{
        printf("Foo: %x\n", foo);
        printf("Main: %x\n", main);
        bar();
        return 0;
}
。。。这起作用并导致分段错误

编译器可能正在用一个更安全的变体替换
fgets
,该变体包括对目标缓冲区大小的检查。如果检查失败,程序将无条件调用
abort()


在这种特殊情况下,您应该使用
-U\U-FORTIFY\U-SOURCE
-D\U-FORTIFY\U-SOURCE=0

来编译程序。您是否查看了该代码的相应汇编程序(以及堆栈布局)?如果有那么简单的话……您应该查看相应的程序集。有时编译器会执行您为对齐而创建的20多个字节。您还应该查看堆栈的布局,以及寄存器/保存的ret addr是如何保存的,以及保存的顺序。继续并发布函数的装配,我们可以进一步帮助您。如果不分析装配,您将无法完成此操作。您使用的是哪种编译器和环境?@AzzUrr1如果您查看此指令
sub$0x20,%rsp
,您可以看到编译器从堆栈指针中减去32字节。。这是缓冲区的大小。
Dump of assembler code for function foo:
   0x00000000004006cd <+0>: push   %rbp
   0x00000000004006ce <+1>: mov    %rsp,%rbp
   0x00000000004006d1 <+4>: mov    0x200990(%rip),%rax        # 0x601068 <stderr@@GLIBC_2.2.5>
   0x00000000004006d8 <+11>:    mov    %rax,%rcx
   0x00000000004006db <+14>:    mov    $0x15,%edx
   0x00000000004006e0 <+19>:    mov    $0x1,%esi
   0x00000000004006e5 <+24>:    mov    $0x400804,%edi
   0x00000000004006ea <+29>:    callq  0x4005d0 <fwrite@plt>
   0x00000000004006ef <+34>:    pop    %rbp
   0x00000000004006f0 <+35>:    retq   
End of assembler dump.
Dump of assembler code for function bar:
   0x00000000004006f1 <+0>: push   %rbp
   0x00000000004006f2 <+1>: mov    %rsp,%rbp
   0x00000000004006f5 <+4>: sub    $0x20,%rsp
   0x00000000004006f9 <+8>: mov    $0x40081a,%edi
   0x00000000004006fe <+13>:    callq  0x400570 <puts@plt>
   0x0000000000400703 <+18>:    mov    0x200956(%rip),%rdx        # 0x601060 <stdin@@GLIBC_2.2.5>
   0x000000000040070a <+25>:    lea    -0x20(%rbp),%rax
   0x000000000040070e <+29>:    mov    $0x18,%esi
   0x0000000000400713 <+34>:    mov    %rax,%rdi
   0x0000000000400716 <+37>:    callq  0x4005b0 <fgets@plt>
   0x000000000040071b <+42>:    lea    -0x20(%rbp),%rax
   0x000000000040071f <+46>:    mov    %rax,%rdi
   0x0000000000400722 <+49>:    callq  0x400580 <strlen@plt>
   0x0000000000400727 <+54>:    mov    %rax,%rsi
   0x000000000040072a <+57>:    mov    $0x400821,%edi
   0x000000000040072f <+62>:    mov    $0x0,%eax
   0x0000000000400734 <+67>:    callq  0x400590 <printf@plt>
   0x0000000000400739 <+72>:    leaveq 
   0x000000000040073a <+73>:    retq   
End of assembler dump.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int **x;
int z;

void foo()
{
    fprintf(stderr, "You did it.\n");
}

void bar()
{
    char buf[2];
    //puts("Input:");
    //fgets(buf, 70, stdin);
    x = (int**) buf;
    for(z=0;z<8;z++)
            printf("%d X=%x\n", z, *(x+z));
    *(x+3) = foo;
    printf("Your input: %d %s\n", strlen(buf), buf);
}


int main(int argc, char **argv)
{
        printf("Foo: %x\n", foo);
        printf("Main: %x\n", main);
        bar();
        return 0;
}
$ gcc test.c -o test
test.c: In function ‘bar’:
test.c:21: warning: assignment from incompatible pointer type
$ ./test
Foo: 400594
Main: 400668
0 X=9560e9f0
1 X=95821188
2 X=889350f0
3 X=4006af
4 X=889351d8
5 X=0
6 X=0
7 X=95a1ed1d
Your input: 5 ▒▒`▒9
You did it.
Segmentation fault
void bar()
{
    char buf[20];
    puts("Input:");
    fgets(buf, 24, stdin);
    printf("Your input:.\n", strlen(buf));
}