- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了一个 C 程序,其中有意为类分配缓冲区溢出。在我的程序中,我有一个 main 函数来接受来自用户的名称作为长度为 50 的字符数组。然后该名称作为长度为 50 的字符数组传递,其中消息 "Hello, user!"
被打印。用户将替换为用户提供的名称。我不对 scanf()
做任何长度检查函数,而是在遇到换行符之前获取输入。结果,我能够溢出缓冲区,覆盖 main 的返回地址并导致段错误。
拆机时main
, 使用 GDB 命令,我可以看到地址 [ebp - 0x3a]
被加载并压入堆栈以用作 scanf
的参数功能(见下图)。我假设这是缓冲区的开始,直到我将 0x3a 转换为十进制并发现它的值为 58。为什么要为字符缓冲区分配额外的 8 个字节?为什么当我尝试运行此缓冲区溢出时,当缓冲区长度似乎从距 ebp 58 个字节和距返回地址 62 个字节开始时,只需要 54 个字符即可溢出缓冲区? 同样,我使用 ebp-0x3a
计算了返回地址的长度。 .
代码:
#include <stdio.h>
#include <string.h>
void printHello(char fname[]);
int main() {
char name[50];
printf("Please enter a name to print a hello message!");
scanf("%[^\n]", name);
printHello(name);
return 0;
}
void printHello(char fname[50]){
int strLen = strlen(fname);
printf("Hello, ");
for(int i=0; i<strLen; i++){
printf("%c", fname[i]);
}
printf("!\n");
}
拆解
main
功能:
Dump of assembler code for function main:
0x080484fb <+0>: lea ecx,[esp+0x4]
0x080484ff <+4>: and esp,0xfffffff0
0x08048502 <+7>: push DWORD PTR [ecx-0x4]
0x08048505 <+10>: push ebp
0x08048506 <+11>: mov ebp,esp
0x08048508 <+13>: push ecx
0x08048509 <+14>: sub esp,0x44
0x0804850c <+17>: sub esp,0xc
0x0804850f <+20>: push 0x8048640
0x08048514 <+25>: call 0x8048390 <printf@plt>
0x08048519 <+30>: add esp,0x10
0x0804851c <+33>: sub esp,0x8
0x0804851f <+36>: lea eax,[ebp-0x3a]
0x08048522 <+39>: push eax
0x08048523 <+40>: push 0x804866e
0x08048528 <+45>: call 0x80483e0 <__isoc99_scanf@plt>
0x0804852d <+50>: add esp,0x10
0x08048530 <+53>: sub esp,0xc
0x08048533 <+56>: lea eax,[ebp-0x3a]
0x08048536 <+59>: push eax
0x08048537 <+60>: call 0x804854c <printHello>
0x0804853c <+65>: add esp,0x10
0x0804853f <+68>: mov eax,0x0
0x08048544 <+73>: mov ecx,DWORD PTR [ebp-0x4]
0x08048547 <+76>: leave
0x08048548 <+77>: lea esp,[ecx-0x4]
0x0804854b <+80>: ret
End of assembler dump.
最佳答案
I assumed that this is the start of the buffer, until I converted 0x3a to decimal and found out its value was 58.
ebp
有一个特定的偏移量? ?没有书面规则说函数应该有一个与其局部变量大小完全相同的堆栈。编译器几乎可以为所欲为。事实上,它最终可能会使用更多空间来保存寄存器值,
maintain alignment ,或者甚至只是在感觉这样的时候浪费它。这个问题问过无数次了,真的没有一个确定的答案,你不妨成为一个GCC开发者去尝试理解一下。
add esp,0x10; sub esp,0x8
之类的无意义指令中可以看出的那样。 . GCC 喜欢在未启用优化的情况下将内容移回或移出堆栈,并且也不太注意以最佳方式管理堆栈空间。
Why when I try to run this buffer overflow, do only need 54 characters to overrun the buffer
\0
会自动添加终止
scanf()
)。但是,这些可能不足以“破坏”任何东西。
main()
被称为
esp
是
0x1000
.调用
scanf()
时的堆栈布局(就在
call
执行之前)如果我的数学是正确的,应该是以下内容:
esp -> 0x0fac: 0x804866e // scanf() arg1
0x0fb0: 0x0fbe // scanf() arg2
0x0fb4: ????
0x0fb8: ????
0x0fbc: ??AA <-- eax == 0x0fbe == ebp-0x3a
0x0fc0: AAAA
0x0fc4: AAAA
0x0fc8: AAAA
0x0fcc: AAAA
0x0fd0: AAAA
0x0fd4: AAAA
0x0fd8: AAAA
0x0fdc: AAAA
0x0fe0: AAAA
0x0fe4: AAAA
0x0fe8: AAAA
0x0fec: AAAA
0x0ff0: ????
0x0ff4: 0x1004 // saved original esp+0x4, later used to restore esp
ebp -> 0x0ff8: <saved ebp>
0x0ffc: ????
0x1000: ???? // 0x1000 original esp at start of main()
0x1004: ????
在上图中,
A
s 表示您的数组,从
0x0fbe
开始.
esp+0x4
所需的最低限度。值(在示例中
0x1004
)并在稍后用于恢复
esp
时引起问题(
mov ecx,DWORD PTR [ebp-0x4]; leave; lea esp,[ecx-0x4]
) 以无效的堆栈指针结束。
关于c - 为什么 scanf() 加载的地址似乎低于我正在写入的缓冲区的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64435743/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!