首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C语言 | C++ 基础溢出及保护机制

来源:pandolia   整理:CPP开发者 【导读】:缓冲区溢出非常危险,因为空间内保存了函数的返回地址。...以下是正文 ---- 引言 如果你学的第一门程序语言C语言,那么下面这段程序很可能是你写出来的第一个有完整的 “输入---处理---输出” 流程的程序: #include int...但可能从来没有人告诉你,什么是溢出溢出有什么危害、黑客们可以利用溢出来进行什么样的攻击,还有你最想知道的,他们是如何利用溢出来实现攻击的,以及如何防护他们的攻击。...溢出攻击的防护 为了防止溢出攻击,最直接和最根本的办法当然是写出严谨的代码,剔除任何可能发生溢出的代码。...因此,若攻击者利用溢出将main函数的返回地址改写为0x4050b6,则main函数返回时会转到borrowed函数运行,打开一个shell终端,后面就可以利用终端干很多事情了。

4.8K88

C语言函数帧详解

引用百度百科:C语言中,每个帧对应着一个未运行完的函数帧中保存了该函数的返回地址和局部变量。从这句话中,可以提炼以下几点信息: 帧是一块因函数运行而临时开辟的空间。...每调用一次函数便会创建一个独立帧。 帧中存放的是函数中的必要信息,如局部变量、函数传参、返回值等。 当函数运行完毕帧将会销毁。 ​ 下面进入主题,图解函数帧的创建与销毁过程。...进入Add()函数,可以看出这与此前main函数开辟帧的过程类似,说明Add()函数调用又开辟了一块独立的帧。...在函数帧、局部变量创建完毕后,进行Add()函数运算过程: PLAINTEXT c = a + b; 00AA13E5 mov eax,dword ptr [ebp+8] 00AA13E8...3.3.4 函数返回 PLAINTEXT return c; 00AA13EE mov eax,dword ptr [ebp-8] 将返回值传递至寄存器eax中,因此在函数调用结束函数帧被销毁时

2.1K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    C语言函数调用及帧结构

    如图: 二、帧的建立 首先要明白几个地方:每一个函数都有自己的帧空间,并且独占自己的帧空间, 当前正在运行的函数帧总是在顶。...「注:函数帧的大小并不固定,一般与其对应函数的局部变量多少有关。函数运行过程中,其帧大小也是在不停变化的。除了与相关的寄存器外,我们还需要记住另一个至关重要的寄存器。」...然后继续执行下一条语句:mov ebp,esp即把esp的值赋给ebp,这样,ebp也就指向了现在esp的位置 然后sub esp 0C0h 这样就为main函数开辟了一段空间然后将ebx、esi、edi...如此一来,几乎所有的c函数都由如下两个指令开 始: push ebp mov ebp, esp 下一步,fun必须为它的局部变量分配空间,同时,也必须为它可能用到的一些临时变量分配 空间。...比如,foo中的一些C语句可能包括复杂的表达式,其子表达式的中间值就必须得有地方存放。

    1.6K30

    C语言函数——帧的创建和销毁

    ✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变 ---- 目录 前言 什么是 什么是函数帧 认识相关寄存器和汇编指令...下面我们要先来理解一些概念 什么是 在学习C语言中,我们关注内存中的3个区域,区、堆区和静态区 那究竟什么是呢?...⏩ (stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了,没有就没有函 数,没有局部变量,也就没有我们如今看到的所有的计算机语言。...("%d\n", ret); 00BE1863 mov eax,dword ptr [ebp-20h] 00BE1866 push eax 00BE1867 push 0BE7B30h 00BE186C...00BE176A push esi //将esi的值压,esp-4 00BE176B push edi //将edi的值压,esp-4 int z = 0; 00BE176C mov dword ptr

    59310

    C语言共享

    的操作我相信大家都应该了解了弄懂了, 如果没弄懂希望可以去再去看看相关的资料,我博客中的C语言中缀表达式转后缀表达式中涉及到了一下的基本操作,有兴趣的朋友也可以看看。...所谓共享,就是两个共同使用一块内存空间,其中一个底作为另一个顶,反之亦然。...1#进行操作,入操作和顺序的入操作并无太大不同。...如若入成功则返回0;入失败则返回-1; 出时,先确定号是否合法,然后查看是对0#还是1#进行操作,出操作和顺序的出操作并无太大不同。 选定之后进行出操作。...\n"); } *x = s->data[s->top[1]++]; break; } return 0; } 主函数 int main(int argc, char* argv[])

    1.2K30

    C语言底层】函数帧的创建和销毁

    () { int a = 10; int b = 20; int c = 0; c =Add(a, b); printf("%d",c); return 0; } 最粗略的整体的逻辑 我们知道每一个函数调用都要在区创建一块空间...0 了,它返回到了调用它的函数 __tmainCRTStartup()里面 当然在一开始的时候我们也会为这两个函数创建空间,在main函数之前 调用Add函数时再创建空间 汇编语言的指令...打开反汇编,我们可以看到汇编语言对程序的操作,这里push叫压,push ebp就是将一个叫做ebp的量压到顶上边(这里涉及到监视窗口可以监视到ebp确实是地址小于的正好在 __tmainCRTStartup...传参过程 然后mov push 给到eax和ecx call是调用函数,它会压一个00C21450,这是call指令的下一条指令,以便call返回时继续使用 这里的汇编语言指令在前面都说到过...,即Add函数被回收了 此时再pop最上面的ebp,这里面存放的是最开始main函数底指针,这样我们就能很容易的找到main函数底的位置,此时ebp指针回到这个位置,然后esp指向00C21450

    9210

    c语言实现(顺序,链)

    个人主页: :✨✨✨初阶牛✨✨✨ 推荐专栏: C语言进阶 个人信条: 知行合一 本篇简介:>:讲解用c语言实现:“数据结构之"”,分别从"顺序"和"链"的接口讲解....""不需要进行随机访问其中的元素,只能从顶访问,链表是可以完成的. 2.1 初始化"链" 对于链表实现的,如果不带头结点: 我们不需要特意去写一个初始化函数.只需要创建一个顶指针,将其初始化指向...(下面的代码是采用这种形式) //创建一个顶指针,并完成初始化 SLStackNode* SLStack = NULL; 如果是带头结点的单链表: 我们可以定义一个初始化函数,申请一个头结点(头结点的数据域不存数据...(ST* ps);//返回顶元素 void STDestory(ST* ps);//的销毁 接口实现区( stack.c) #include "stack.h" //初始化 void InitST...void STDestory(SLStackNode* ps);//的销毁 接口实现区(SLStack.c) #include "SLStack.h" //SLStackNode* InitStack

    26720

    C语言缓冲区溢出详解

    wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1] 1 引言 “缓冲区溢出”对现代操作系统与编译器来讲已经不是什么大问题,但是作为一个合格的 C/C++ 程序员...wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1] 例子中的内存映射 进程的是由多个构成的,其中每个帧都对应一个函数调用。...当调用函数时,新的帧被压入;当函数返回时,相应的帧从中弹出。由于需要将函数返回地址这样的重要数据保存在程序员可见的堆栈中,因此也给系统安全带来了极大的隐患。...缓冲区溢出 对于缓冲区溢出,一般可以分为4种类型,即溢出、堆溢出、BSS溢出与格式化串溢出。其中,溢出是最简单,也是最为常见的一种溢出方式。...','5','6','7','8',’\0’}; //或者 char array[11]={'0','1','2','3','4','5','6','7','8','9’}; 更多案例可以go公众号:C语言入门到精通

    2.5K2219

    C语言笔记】整数溢出问题

    一、前言 整数溢出是一种未定义的行为,当产生溢出行为时,系统并不会通知用户,所以应当多加小心。如下是整数溢出的一个案例: ?...SMT爆出的美图BEC代币出现的安全漏洞—整数溢出,该漏洞代理的直接经济损失高达上亿元人民币,间接产生的负面影响目前无法估量。 二、什么是整数溢出?...计算机语言中整数类型都有一个取值范围,两个整数进行运算时,若其结果大于最大值(上溢)或者小于最小值(下溢)就是溢出。...假如最大值为 a ,在最大值和最小值之间如果发生以下计算: a+1=0或0-1=a 此时就会发生溢出,其中a+1=0会发生上溢,0-1=a会发生下溢。...(ps:可以使用程序来查看整数数据类型的范围,具体可移步至【C语言笔记】如何查看数据类型范围?进行查看) 以上就是关于整数溢出的笔记分享,如有错误欢迎指出!

    4.5K10

    C语言函数帧的创建和销毁(逐步分析)

    什么是函数帧 我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。 那函数是如何调用的?函数的返回值又是如何返回的?函数参数是如何传递的?...这些问题都和函数帧有关系。 函数帧(stack frame)就是函数调用过程中程序的调用(call stack)所开辟的空间,这些空间是用来存放: 1. 函数参数和函数返回值 2....= 0; c = Add(a, b); printf("%d\n", c); return 0; } 首先我们先建立main函数帧空间,但我们思考一下,main函数是不是也有可能被其他函数调用那...函数帧创建,接下来就是把值放进去,int a=10,dword是双字节的意思,将a的值放在ebp-8这个空间里 接下来就把b, c也像a一样分别放入对应的位置  接下来就是传参,将ebp-14h也就是...最后将承载着z的值也就是两数和的值的寄存器eax,将值付给ebp-20h也就是c的地址  此时c就为30了  结论 局部变量是怎么创建的 创建好函数帧后,我们初始化一部分函数空间,而局部变量就在这个空间里分配一个空间

    10910

    C语言:底层剖析——函数帧的创建和销毁

    一、究竟什么是函数帧      C语言的使用是面向过程的, 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。...所以C语言的程序都是以函数作为基本单位的,如果能够深入理解函数,无疑对于c语言会有更深刻地理解,修炼自己的内功,那么函数是如何调用的?函数返回值是如何返回的?...(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了,没有就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。        ...3.5.5.4Add函数帧开辟 此图为Add函数帧开辟 在Add函数中创建帧的方法和在main函数中是相似的,在帧空间的大小上略有差异而已。 1. 将main函数的 ebp 压 2....指向main函数帧的顶,ebp指向了main函数帧的 底。

    38010

    C语言内功的修炼--函数帧创建和销毁

    目录 什么是帧 什么是 帧的创建与销毁 main函数调用过程  Add函数的调用过程 ---- 什么是帧 简单地说 程序的执行过程可看作连续的函数调用,而C语言中,每个帧对应着一个未运行完的函数...每个函数的每次调用(通常使用堆栈实现),都有它自己独立的一个帧 这个帧中保存了该函数的返回地址和局部变量维持着所需要的各种信息 所以帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构...从逻辑来看 帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等 ---- 什么是 在详解之前我们还得明白一点,也叫堆栈,是一种数据结构,具有先进后出的特点...(类似子弹上弹夹) 在函数帧创建过程中,内存从高地址往低地址使用 寄存器edp存放了指向函数底的地址(高地址) 寄存器esp存放了指向函数顶的地址(低地址) esp和ebp...共同维护函数帧 ---- 帧的创建与销毁 在VS2013下逐步调试add函数向大家展示并讲解帧的创建和销毁过程 int Add(int x, int y) { int z = 0;

    53520

    C语言——F函数帧的创建和销毁

    (stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了,没有就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。         ...= 0; 00BE1849 mov dword ptr [ebp-20h],0 //将0存储到ebp-20h的地址处,ebp-20h的位置其实是c变量 //以上汇编代码表示的变量a,b,c的创建和初始化...,这就是局部的变量的创建和初始化 //其实是局部变量的创建时在局部变量所在函数帧空间中创建的 //调用Add函数 c = Add(a, b); //调用Add函数时的传参 //其实传参就是把参数push...//将ebx的值压,esp-4 00BE176A push esi //将esi的值压,esp-4 00BE176B push edi //将edi的值压,esp-4 int z = 0; 00BE176C...12地址处的数字加到eax寄存中 00BE1779 mov dword ptr [ebp-8],eax //将eax的结果保存到ebp-8的地址处,其实就是放到z中 return z; 00BE177C

    10710

    C语言----C语言内存函数

    1.这个函数在遇到\0的时候并不会停下来 2.如果source和destination有任何的重叠,复制的结果都是未定义的 memcpy函数最终返回的是目标空间的起始地址 //函数的一种写法: 这个函数最终返回的是目标空间的起始地址...: //函数的一种写法: //这个函数最终返回的是目标空间的起始地址 void* my_memcpy(void *dest, const void*src, size_t num) { assert...,非要使用,结果就是未定义的 //只负责不重叠的内存 函数的返回值是void*类型的数据 这个memcpy函数有三个数据 2.memmove--内存移动--使用和模拟实现 2.memmove--内存移动...//总之:这个拷贝是分三块区域的,最前面的一块区域满足dest<src //我们只能从前往后进行拷贝,不然会出错误 //而剩下的两块区域可以同时从后往前进行拷贝,那么我们就将这两块区域放在一起 在C语言标准中...,明确规定了memcpy只要能实现不重叠的拷贝就行,重叠的拷贝交给memmove 我们发现vs上面的库函数memcpy函数也能实现重叠内存的拷贝 我们在以后的拷贝中,我们可以用memmove,因为不管是重叠的还是不重叠的都能搞定

    10310

    洛谷 || C语言

    题目背景 是计算机中经典的数据结构,简单的说,就是限制在一端进行插入删除操作的线性表。 有两种最重要的操作,即 pop(从顶弹出一个元素)和 push(将一个元素进)。...的重要性不言自明,任何一门数据结构的课程都会介绍。宁宁同学在复习的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。...题目描述 宁宁考虑的是这样一个问题:一个操作数序列1,2,…,n(图示为 1 到 3 的情况), A 的深度大于n。...现在可以进行两种操作, 将一个数,从操作数序列的头端移到的头端(对应数据结构的 push 操作) 将一个数,从的头端移到输出序列的尾端(对应数据结构的 pop 操作) 使用这两种操作,由一个操作数序列就可以得到一系列的输出序列

    1.3K30

    C语言的实现

    因为方便:试想一下我们要判断是否空就只需要判断top是否等于buttom,如果buttom指向底显然就会麻烦许多 下面我们先用C语言来实现一下: 首先我们需要对这个装东西的“盒子”定义,而这个盒子就是...,然后节点可以放在里面(不过实际上的代码是一个概念,只是形象的用了两个结构体表示) 回到上面的话题,定义完了,接下来就是的操作,操作主要有入(push)和出(pop),还有遍历输出,其次就是一些诸如清...出一般有两种:1.让指定数据出2.让top指向的数据出,注意,如果要让指定的数据出,而且如果那个数据在中间,那你就不得不把从top到那个数据的全部节点出,因为是后进先出,而且只允许一段入/出...*n=sk->top; sk->top=n->next; delete n; } 就像上面,另还要注意出需要考虑是否为空,我没有写 至此,一个C语言版本的及其主要操作就完成了,这也是我第一次写结构...,因为我用C++ stack sk; sk.push(5); //..

    3.8K40
    领券