生活工程体验信仰哲学精神
快软网
精神世界
探索历史
哲学文学
艺术价值
信仰创造
境界审美
体验技术
技能工具
工程信息
医学生产
生活运用
操作能力

C函数调用的栈帧机制与数组越界、缓冲区溢出

11月7日 渡缘祠投稿
  0前置知识0。1程序加载和数据存储
  程序运行前要将代码加载到内存的代码区,包括全局变量和静态变量也要同时加载。
  堆区内存可以在程序运行时动态申请。
  栈区是由程序重复利用的存储区域,通过两个寄存器ebp和esp存储栈区的相对地址来控制栈区空间的重复使用。函数调用时,开辟一个函数需要的栈区空间,称为一个栈帧。函数返回时,偏移ebp和esp的值,让栈空间可以重新使用此前函数调用占用的空间。
  以下是windows平台一个程序运行时的内存分配机制:
  0。2函数调用
  函数调用看似简单,其实是一个挺复杂的过程。当涉及到逐级调用时,代码需要能够回到最初的调用点。
  例如一个人旅行,当经过若干十字路口时,如何正确回到最初开始位置?一个可行的方案是,每经过一个路口,用一张扑克牌记下当时路口的状态,每经过一个路口即使用一张牌,并放在已使用的扑克牌上面,当返回时,依次从上面拿牌读取信息即可回溯到原来位置。这种扑克牌的放与取就是所谓的栈的“后进先出”机制。
  函数调用也要使用类似的机制,由编译器完成。每一级函数调用对应一个栈帧(如同扑克牌),记录参数值,返回地址,一些寄存器状态,局部变量值。主调函数与被调函数如何分工完成这些任务,不同的调用约定有不同的分工。
  0。3数组名在一定的上下文中转换为指向数组首元素的指针
  数组也是如此,看似简单,实则复杂。
  数组名在一定上下文中会转换为一个指向数组首元素的指针,为什么会这样,当然有其合理性。
  首先了解一下指针的算术运算。(栈内存空间地址是逆增长的)
  voidfoo(inta){intf45;(ptr1)12;编译通过,运行时错误,试图修改ebp(ptr2)34;编译通过,运行时错误,试图修改函数返回地址(ptr3)56;试图修改保存函数实参值的栈内存单元intp(int)malloc(sizeof(int)5);(p3)23;p〔3〕23;}pn,是一个相对于ptr的偏移n个int地址空间的地址值。
  编译器会计算psizeof(int),至于偏移的是否是有效合法的地址,C编译器不管。
  ptrn也是如此。
  如有数组intarr〔64〕{0};
  数组名是一个基地址,其索引表示地址的偏移量。arr〔i〕写法是指针算术运算(arri)的语法糖。编译器要考虑指针的算术运算有实用的意义,C编译器的规定是arri,其地址不是简单偏移i个字节,这样没有意义,而是sizeof(指向的类型)的长度的字节数,这样才有意义,其计算由编译器完成,当指针类型是数组时,偏移i个数组的长度没有任何意义,偏移i个数组元素的长度才有实际意义,这也是C编译器的规定。如:
  inta〔3〕〔4〕〔5〕;a的类型是int〔3〕〔4〕〔5〕,元素的类型是int〔4〕〔5〕,int(p)〔4〕〔5〕a;a2;偏移的地址是a2sizeof(int)45intb〔4〕〔5〕;b的类型是int〔4〕〔5〕,元素的类型是int〔5〕,int(p)〔5〕b;b2;偏移的地址是b2sizeof(int)5intc〔5〕;c的类型是int〔5〕,元素的类型是int,c2;偏移的地址是b2sizeof(int)C编译器只负责偏移地址的计算,对于数组是否越界,地址是否合法并不在编译时检查。
  arr〔i〕的i可以是任意signedint,越界时就会访问到相邻栈内存。
  0。4一些简单的汇编代码
  1、mov传送指令
  定义:把一个字节、字或双字的操作数从源位置传送到目的位置,可以实现立即数到通用寄存器或主存的传送,通用寄存器与通用寄存器、主存或段寄存器之间的传送,主存与段寄存器之间的传送。
  举例:mvebp,esp
  解释:相当于C语言中赋值语句,ebpesp
  2、push进栈指令
  定义:进栈指令push先将ESP减小作为当前栈顶,然后可以将立即数、通用寄存器和段寄存器或存储器操作数传送到当前栈顶。
  格式:pushsrc
  举例:pushebp
  解释:相当于C语言中esp4,espebp
  作用:为ebp当前存放的地址,在栈顶开辟空间存入它,用作调用子函数时的现场保护
  3、pop出栈指令
  定义:与入栈指令相反,它先将栈顶的数据传送到通用寄存器、存储单元或段寄存器中,然后ESP增加作为当前栈顶。
  格式:popsrc
  举例:popebp
  解释:相当于C语言中ebpesp,esp4
  作用:调用子函数结束后,恢复主函数的ebp
  4、add加法指令
  格式:adddest,src
  解释:相当于destsrc
  5、sub减法指令
  格式:subdest,src
  解释:相当于destsrc
  6、call函数调用指令
  格式:call函数名
  作用:(1)将程序当前执行的位置IP压入堆栈中;(2)转移到调用的子程序。
  其它:
  RET指令从堆栈把返回地址弹回到指令指针寄存器。ret相当于popEIP。
  repstosdwordptr〔edi〕rep是重复其上面的指令,ECX是重复的次数。
  ILT是INCREMENTALLINKTABLE的缩写,这个ILT其实就是一个静态函数跳转的表,它记录了一些函数的入口然后跳过去,每个跳转jmp占一个字节,然后就是一个四字节的内存地址,加起为五个字节。
  LEA(LoadEffectiveAddress)取有效地址指令,取源操作数地址的偏移量,并把它传送到目的操作数所在的单元
  0。5函数栈
  0。5。1栈空间增长方式:从高地址向低地址扩展,是一片让程序重复利用的数据空间;
  栈空间由编译器维护(需要在Debug模式下才可以跟踪);
  0。5。2栈空间对齐方式:X86按4个字节来对齐,X64按8个字节来对齐;
  0。5。3两个跟踪栈空间的寄存器ESP和EBP
  对栈的操作由ESP跟踪,用来指示栈顶。push、call时,esp4,pop、ret时,esp4
  EBP用来引用函数参数和局部变量。EBP相当于一个“基准指针”。从主调函数传递到被调函数的参数以及被调函数本身的局部变量都可以通过这个基准指针为参考,加上偏移量找到。
  ebp(表示栈地址ebp对应的值)上一个ebp的值(栈地址);
  ebp4第一个局部变量地址;
  ebp4函数返回地址;
  ebp8函数第一个参数地址;
  0。5。4不同的函数调用约定,在参数的入栈顺序,堆栈的恢复(由caller还是callee负责)、函数的命名上会有所不同。
  0。5。5一个完整的函数帧包括:函数参数、返回地址,上一个EBP的值,局部变量空间,3个寄存器。在函数内部代码执行前,一个完整的函数帧已经建立。
  下面通过一个完整实例来理解函数调用的栈帧机制与数组向栈底方向越界的分析:
  看以下代码:
  include
  intarrayBound(inta){intb1;〔ebp4〕intarr〔98〕{0};〔ebp18Ch〕intc1;〔ebp190h〕,栈是逆增长,栈顶地址值栈顶arr〔1〕数组向栈顶方向越界访问,arr〔1〕对应intcarr〔98〕数组向栈底方向越界访问,arr〔98〕对应intbprintf(ddn,b,c);55}intmain(){intearrayBound(5);5printf(dn,e);return0;}主函数main()的栈帧:
  主函数main()调用arraybound(),此时的汇编代码:
  15:intearrayBound(5);50040D4D8push50040D4DAcallILT10(arrayBound)(0040100f)0040D4DFaddesp,40040D4E2movdwordptr〔ebp4〕,eax16:printf(dn,e);17:return0;0040D4E5xoreax,eax18:}1主调函数调用被调函数时函数参数压栈此时的栈指针值:
  ebp0x0012ff48ebp是栈底指针
  esp0x0012fef8esp是栈底指针,栈的push和pop操作会同时改变esp的值(esp移动)
  此时的栈顶指针附近的内存映像:
  0012FEEC302F42008300000068201F000B。。。。。h。。
  0012FEF8000000000000000000F0FD7F。。。。。。。。。瘕。
  0012FF04CCCCCCCCCCCCCCCCCCCCCCCC烫烫烫烫烫烫
  执行汇编:
  0040D4D8push5esp40x0012fef4,esp5栈帧内存:
  0012FEEC302F420083000000050000000B。。。。。。。。。
  2返回地址压栈汇编指令call对应两个操作:push返回地址和jmp指令。
  0040D4DAcallILT10(arrayBound)(0040100f)0012FEEC302F4200DFD44000050000000B。咴。。。。。返回地址是0040D4DF
  esp0x0012fef0,esp0040D4DF
  0040100FjmparrayBound(0040d820)代码跳转:
  0040D820pushebp0040D821movebp,esp0040D823subesp,1D0h0040D829pushebx0040D82Apushesi0040D82Bpushedi0040D82Cleaedi,〔ebp1D0h〕0040D832movecx,74h0040D837moveax,0CCCCCCCCh0040D83Crepstosdwordptr〔edi〕5:intb1;〔ebp4〕0040D83Emovdwordptr〔ebp4〕,0FFFFFFFFhebp值压栈:
  0040D820pushebpebp赋值前先压栈保存先前状态esp0x0012feec,espebp0012FEEC48FF1200DFD4400005000000H。。。咴。。。。。
  0040D821movebp,espebpesp0x0012feec栈区:
  3函数栈帧空间分配0040D823subesp,1D0h1D0h46440064,esp0x0012fd1c此时栈顶指针附近的内存随机值:
  0012FD10FEFFFFFFFE60757776A37177。。。。uwvw
  0012FD1C00001F0063010050D35D6E77。。。。c。。P覿nw
  0012FD28CF7914750000000000000000蟳。u。。。。。。。。
  3。1寄存器压栈
  寄存器状态保持(压栈)
  0040D829pushebx0040D82Apushesi0040D82Bpushediesp0012FD10,espedi栈内存:
  0012FD1048FF12000000000000F0FD7FH。。。。。。。。瘕。
  此时esp0x0012fd10,三个寄存器使用的栈内存是464个字节以外的栈内存。
  栈区:
  3。2栈帧分配的空间每个字节全部置为0xCC
  0040D82Cleaedi,〔ebp1D0h〕0040D832movecx,74h0040D837moveax,0CCCCCCCCh0040D83Crepstosdwordptr〔edi〕此时esp和ebp之间的栈空间:
  0012FD1048FF12000000000000F0FD7FH。。。。。。。。瘕。
  0012FD1CCCCCCCCCCCCCCCCCCCCCCCCC烫烫烫烫烫烫
  0012FEE0CCCCCCCCCCCCCCCCCCCCCCCC烫烫烫烫烫烫
  0012FEEC48FF1200DFD4400005000000H。。。咴。。。。。
  3。3栈空间为局部变量从ebp处开始偏移进行初始化操作
  5:intb1;〔ebp4〕0040D83Emovdwordptr〔ebp4〕,0FFFFFFFFh此时的栈空间:
  0012FEE0CCCCCCCCCCCCCCCCFFFFFFFF烫烫烫烫。。。。
  0012FEEC48FF1200DFD4400005000000H。。。咴。。。。。
  汇编代码继续:
  6:intarr〔98〕{0};〔ebp18Ch〕0040D845movdwordptr〔ebp18Ch〕,00040D84Fmovecx,61h0040D854xoreax,eax0040D856leaedi,〔ebp188h〕0040D85Crepstosdwordptr〔edi〕7:intc1;〔ebp190h〕,栈是逆增长,栈顶地址值栈顶0040D85Emovdwordptr〔ebp190h〕,1此时的栈空间:
  0012FD50CCCCCCCCCCCCCCCCCCCCCCCC烫烫烫烫烫烫
  0012FD5C010000000000000000000000。。。。。。。。。。。。
  0012FD68000000000000000000000000。。。。。。。。。。。。
  8:arr〔1〕数组向栈顶方向越界访问
  0040D868moveax,dwordptr〔ebp190h〕0040D86Eimuleax,dwordptr〔ebp8〕0040D872leaecx,〔ebp18Ch〕0040D878movdwordptr〔ecx4〕,eax此时的栈空间:
  0012FD50CCCCCCCCCCCCCCCCCCCCCCCC烫烫烫烫烫烫
  0012FD5C050000000000000000000000。。。。。。。。。。。。
  0012FD68000000000000000000000000。。。。。。。。。。。。
  9:arr〔98〕数组向栈底方向越界访问
  0040D87Bmovedx,dwordptr〔ebp4〕0040D87Eimuledx,dwordptr〔ebp8〕0040D882movdwordptr〔ebp4〕,edx此时的栈空间:
  0012FEDC000000000000000000000000。。。。。。。。。。。。
  0012FEE8FBFFFFFF48FF1200DFD44000。。。。H。。。咴。
  0012FEF4050000000000000000000000。。。。。。。。。。。。
  栈区:
  3。4值返回
  10:printf(ddn,b,c);5511:0040D885moveax,dwordptr〔ebp4〕返回值保存在寄存器eax中3。5寄存器状态恢复
  此时esp0x0012fd10
  0040D888popediesp4,ediesp0040D889popesi0040D88Apopebx以上的栈空间是栈帧空间464以外的空间。
  此时esp0x0012fd1c
  ebp0x0012feec
  0040D88Bmovesp,ebp栈顶指针更新,栈空间回收此时ebp对应的栈空间
  0012FEEC48FF1200DFD4400005000000H。。。咴。。。。。
  0040D88Dpopebp此时esp0x0012fef0
  ebp0x0012ff48
  0040D88Eret函数返回:
  0040D4DFaddesp,44是实参压栈时使用的字节数。如果压了3个int,则是ch0040D4E2movdwordptr〔ebp4〕,eax0012FF3CCCCCCCCCCCCCCCCCFBFFFFFF烫烫烫烫。。。。
  0012FF4888FF1200F911400001000000。。。。。。。。。。。
  ebp4是主调函数局部变量e的栈内存保存位置。
  如果函数的返回值是一个复合类型,超过了两个寄存器所能容纳的大小,会在主调函数的栈帧开辟空间,以供值返回。
  4数组越界访问向栈底方向越界1个int空间:对应局部变量
  向栈底方向越界2个int空间:对应ebp本身;
  向栈底方向越界3个int空间:对应函数返回地址〔ebp4〕;
  向栈底方向越界4个int空间:对应函数实参存储位置〔ebp8〕:
  include
  voidarrayBound(inta){intb1;intarr〔98〕{0};intc1;arr〔98〕a;arr〔101〕555;printf(dn,b);555}intmain(){intc5;arrayBound(c);printf(dn,c);5while(1);return0;}向栈底方向越界3个int空间:对应函数返回地址:
  arr〔100〕0040D4DF;数组向栈底方向越界访问
  当arr〔100〕被赋的值是一个合法的内存地址时,正常运行,否则,运行出错。
  5缓冲区溢出有如下代码:
  include
  voidfunc(){charbuff〔4〕{0};printf(someinput:);gets(buff);puts(buff);}intmain(){func();return0;}当运行到gets(buff)时的栈区:
  如果输入abc,则刚好填充buff,其中buff〔3〕0
  如果输入“abcdefg”,则efg会填充〔ebp〕指向的值。
  如果输入“abcdefghijk”,则“ijk”会填充〔ebp4〕的值,也就是函数func()的返回地址。
  End
投诉 评论 转载

午休睡10分钟是怎样做到的?热文聚热点网 都说睡子午觉,午休就是其一。为的是让午时有个平和的状态去度过。午睡10分钟有点短,可能你认为是不可能做到的。首先,十分钟,如果睡不着,你可以闭目养神十分钟。尽量尝试……爱尔兰和北爱尔兰是什么关系?热文聚热点网 谢邀。一句话概括:爱尔兰是一个独立的国家,而北爱尔兰属于英国的一个地区。英国全称是:大不列颠及北爱尔兰联合王国。不列颠群岛包括两个主要岛屿,大不列颠和爱尔兰。……毕加索是个什么样的人?热闻聚热点网 作为一个艺术普及者,前面的答案虽然很详实但是真的不能忍!提问的同学一看就是想要快速入门艺术、最好凭借一个答案就对毕加索有个基本认识,所以,前面的答……捷克的军事工业怎么样?热文聚热点网 捷克是一个小国,但是军事工业上却极为出色,研发有很多较为出色的产品。首先在轻武器上,捷克人就有很多优秀作品。比如其研发的ZB系列轻机枪,不仅出口到了中国等国家,还对英国这……主持人的职责和工作流程?热闻聚热点网 答:1、负责公司各种会议的会议主持工作。2、负责做好会议前的准备工作包括:会前策划,做到一会议主题;会议流程、会议主持稿;会场布置;统计参会人员;……今天无意中翻出我珍藏的老版2角人民币,您家还有这样的人民币吗 你好,我是大佳收藏,很高兴回答你的问题!题主所展示的这张2角是属于第四套人民其中的一个面值;年号为1980年,简称8002;这种2角面值其实很早以前就已经消失在我们的生活……C函数调用的栈帧机制与数组越界、缓冲区溢出热评聚热点网 0前置知识0。1程序加载和数据存储程序运行前要将代码加载到内存的代码区,包括全局变量和静态变量也要同时加载。堆区内存可以在程序运行时动态申请。栈区是由程序重复……一个男人怎么做可以长寿?热传聚热点网 1、不抽烟,不喝酒,没有不良嗜好。2、适当运动,保持身材。3、远离美色。4、专注自己,别攀比,别羡慕嫉妒恨。5、懂取舍,该放下就放下。6、心态积极……“父母活太久,儿女会短命”为什么许多人相信这个谬论?热博聚热 民间有一种迷信说法,是说命硬的人命长,很长寿的老人有一些是伴侣早过世或者子女中有年轻意外过世的,长寿是延长了早逝伴侣或者子女的寿命。这个事情有些确实是属于巧合。人各自有天……你们觉得宋仲基帅吗?热闻聚热点网 帅!怎一个帅字了得!20多年了,只强烈的喜欢过三个明星,第一个是明道,是小学的时候跟姐姐一起看偶像剧《王子变青蛙》,那是我第一次看偶像剧,当时特别喜欢。后来高中的时候看了……唐砖小说百科?热闻聚热点网 《唐砖》是孑与2创作的网络军事历史小说,连载于起点中文网。这是一部典型的历史穿越类小说。它描写了主人公云烨回到唐初贞观年间,作为大唐贵族的他面临种种考验,过着混合着那个时……上海昨日新增本土3223625,新增死亡11例热博聚热点网 2022年5月8日024时,新增本土新冠肺炎确诊病例322例和无症状感染者3625例,其中230例确诊病例为既往无症状感染者转归,92例确诊病例和3616例无症状感染者在隔离管……
中科红旗“卖身”成功:终于有人收了热评聚热点网 【歌词】SummerDream(Feat。)歌手:GIDEA 【歌词】李妍瑾AllICan歌手:华人群星9热闻聚热点网 【歌词】永远不跟你联络歌手:胡雯热闻聚热点网 【歌词】旧约诗篇(诗)第78章歌手:圣经旧约热闻聚热点网 【歌词】MustBe歌手:ShadyNate热传聚热点网 【歌词】海归之歌歌手:葛顺热议聚热点网 逆行汽车出了事故险公司赔吗热闻聚热点网 kpi是什么意思(KPI、KPA、OKR三者的区)热议聚热点 成都到重庆动车成都到重庆高铁一小时热传聚热点网 私分罚没财物罪判刑标准是什么热评聚热点网 热文深深浅浅类似成语有哪些(深深浅浅类似成语有)热评聚热点网
关心少一些高考状元家长谈如何给孩子减压语文教学工作计划康赛妮羊绒是什么档次EA表示模拟人生4将于六月份停止支持32位平台南京跋扈钉子户,曾为要5000万拒绝拆迁,如今拿到钱了吗被智能手机淘汰的11项技术照射造句用照射造句大全世界杯这一刻巴西葡萄牙晋级十六强顺产剖宫产,哪个更香?沈阳家庭收入多少算中产阶层?野外垂钓鲫鱼的中药酒米配方擦阳台

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找新乡渭南铜川松江山南雅安松原荃湾淮北昭通平凉鞍山赤峰苗栗保亭池州渝北株洲陇南濮阳三沙秀山密云鸡西