gpt4 book ai didi

C 缓冲区溢出 - 输入多少字节

转载 作者:行者123 更新时间:2023-11-30 20:00:09 24 4
gpt4 key购买 nike

我编写了一个简单的 C 程序来尝试理解缓冲区溢出。我试图溢出输入缓冲区,以便标志更改为 true 并且程序输出“到达这里”。该程序在这里(假设您有password.txt,其中包含hey):

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

int main(int argc, char **argv){
int flag = 0;

char pwd[5];
char input[5];

FILE *f = fopen("password.txt", "r");

fscanf(f, "%s", pwd);
fclose(f);

strcpy(input, argv[1]);

if(strcmp(input, pwd)){
printf("wrong password!\n");
}
else{
flag = 1;
printf("correct password!\n");
}
if(flag){
printf("you got into the secret place\n");
}
return 0;
}

所以在堆栈上我们有这样的东西,我猜:

[high addresses]
flag ---> 4 bytes
pwd ---> 8 bytes
input ---> 8 bytes
[low addresses]

所以我想我只需要给程序 17 个字节来覆盖标志变量。所以我给了它aaaaaaaaaaaaaaaaa但这没有用。我必须给它 a 23 次,所以 23 个字节。为什么 17 字节不够?

最佳答案

免责声明:我使用 Ubuntu 14.04 和 gcc 版本 4.8.4,并遵守了您的要求代码如下gcc -m32 -g -ansi -pedantic -Wall temp.c -o temp。不同的编译器或 gcc 的不同选项很可能会给出不同的结果。

我还稍微修改了您的代码,以便更轻松地查找内容,

  1. 我将第 6 行更改为 int flag = 0x41414141;
  2. 我将第 25 行更改为 if(flag==1){

编译后,我在 GDB 下运行可执行文件,并设置了断点在主要。然后反汇编 main (将 disassemble-flavor 设置为英特尔),我们得到:

(gdb) disass
Dump of assembler code for function main:
0x0804857d <+0>: push ebp
0x0804857e <+1>: mov ebp,esp
0x08048580 <+3>: and esp,0xfffffff0
0x08048583 <+6>: sub esp,0x30
0x08048586 <+9>: mov eax,DWORD PTR [ebp+0xc]
0x08048589 <+12>: mov DWORD PTR [esp+0xc],eax
=> 0x0804858d <+16>: mov eax,gs:0x14
0x08048593 <+22>: mov DWORD PTR [esp+0x2c],eax
0x08048597 <+26>: xor eax,eax
0x08048599 <+28>: mov DWORD PTR [esp+0x18],0x41414141

前四行是 main 的序言,重要的是注意是 sub esp,0x30 行,我们在其中设置函数的堆栈帧。正如你所看到的,我们减去了 48 个字节特别是从(实际上多一点,因为我们首先对齐堆栈帧到 16 字节边界)。

现在,我们可以通过查看值来查看堆栈帧的位置对于 ESP 和 EBP:

(gdb) info registers esp
esp 0xffffd110 0xffffd110

(gdb) info registers ebp
ebp 0xffffd148 0xffffd148

我们可以找到东西在堆栈帧中的位置;

(gdb) print &pwd
$3 = (char (*)[5]) 0xffffd132

(gdb) print &flag
$4 = (int *) 0xffffd128

(gdb) print &input
$5 = (char (*)[5]) 0xffffd137

(gdb) print &f
$6 = (FILE **) 0xffffd12c

据此我们现在可以推断出我们的堆栈布局。这个内存图像是运行经过程序读取命令行的位置后获取参数是字符串 BBBBB(回想一下,B 的 ASCII 代码是 0x42,因此很容易看到 0x42 字节的序列)

(gdb) x/56xb $esp
0xffffd110: 0x37 0xd1 0xff 0xff
0xffffd114: 0xbf 0xd3 0xff 0xff
0xffffd118: 0x32 0xd1 0xff 0xff
0xffffd11c: 0xe4 0xd1 0xff 0xff
0xffffd120: 0x02 0x00 0x00 0x00
0xffffd124: 0xe4 0xd1 0xff 0xff
0xffffd128: 0x41 0x41 0x41 0x41 (flag)
0xffffd12c: 0x08 0xb0 0x04 0x08 (f)
0xffffd130: 0xc4 0xf3
0xffffd132: 0x68 0x65 0x79 0x00 0xff (pwd buffer)
0xffffd137: 0x42 0x42 0x42 0x42 0x42 (input buffer)
0xffffd13c: 0x00 0xd5 0x61 0x5d
0xffffd140: 0x60 0x86 0x04 0x08
0xffffd144: 0x00 0x00 0x00 0x00

另请注意,如果我将命令行参数设置为 BBBBBBBB,我们会得到这个对于我们的堆栈框架的内容

(gdb) x/56xb $esp
0xffffd110: 0x37 0xd1 0xff 0xff 0xbc 0xd3 0xff 0xff
0xffffd118: 0x32 0xd1 0xff 0xff 0xe4 0xd1 0xff 0xff
0xffffd120: 0x02 0x00 0x00 0x00 0xe4 0xd1 0xff 0xff
0xffffd128: 0x41 0x41 0x41 0x41 0x08 0xb0 0x04 0x08
0xffffd130: 0xc4 0xf3 0x68 0x65 0x79 0x00 0xff 0x42
0xffffd138: 0x42 0x42 0x42 0x42 0x42 0x42 0x42 0x00
0xffffd140: 0x60 0x86 0x04 0x08 0x00 0x00 0x00 0x00

请注意,标志变量的内容保持不变,但现在溢出的输入缓冲区的内容移向堆栈顶部。回想一下,在 x86 中,堆栈向下增长(较低的内存地址)。另外,由于缓冲区向上增长,因此我们可以使用缓冲区溢出来覆盖堆栈上存储的 EIP。

因此,在我的系统上,我不认为可以用用户输入覆盖 flag 变量。您的系统可能会在堆栈上以不同的方式布置内容(您需要执行类似的练习来验证这一点)。

另请注意,变量在堆栈上的位置与它们在源文件中声明的顺序无关。

关于C 缓冲区溢出 - 输入多少字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47297399/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com