ESP被PUSH到堆栈解析 如何调用一个函数?
而如果ESP被PUSH到堆栈,这是堆栈的表示:
_parametre_I___| EBP 12
_parametre II__| EBP 8
_return adress_| EBP 4
___saved_ESP___| EBP ESP
_local var I __| EBP-4
_local var II__| EBP-8
在上面的图中,变量I 和II是传递给函数的参数。在返回地址和保存ESP之后,var I和II是函数的局部变量。现在,如果我们总结所有我们所讲的,当调用一个函数的时候:
1.我们保存老的堆栈指针,PUSH它到堆栈 2.我们保存下一个指令的地址(返回地址),PUSH它到堆栈。3.我们开始执行程序指令。
当我们调用一个函数时,上面3步都做了。
让我们在一个生动的例子中看堆栈的操作。
a.c :
void f(int a, int b, int c)
{
char z[4];
}
void main()
{
f(1, 2, 3);
}用-g标志编译这个从而能够调试:
[murat@victim murat]$ gcc -g a.c -o a
让我们看看这里发生了什么:
[murat@victim murat]$ gdb -q ./a
(gdb) disas main
Dump of assembler code for function main:
0x8048448 : pushl雙
0x8048449 : movl %esp,雙
0x804844b : pushl$0x3
0x804844d : pushl$0x2
0x804844f : pushl$0x1
0x8048451 : call 0x8048440
0x8048456 :addl $0xc,%esp
0x8048459 :leave
0x804845a :ret
End of assembler dump.
(gdb)
以上可见,main()函数中第一个指令是:
0x8048448 : pushl 雙
它支持老的指针,并把它压入堆栈。接着,拷贝老的堆栈指针倒ebp寄存器:
0x8048449 : movl %esp,雙
因而,从那时起,在函数中,我们将用EBP引用函数的局部变量。这两个指令被称为”程序引入”。接着,我们反序PUSH函数f()的参数到堆栈中。
0x804844b : pushl$0x3
0x804844d : pushl$0x2
0x804844f : pushl$0x1
我们调用这个函数:
0x8048451 : call 0x8048440
如我们已经通过CALL调用解释的那样,我们PUSH指令addl $0xc,%esp的地址0x8048456到堆栈。函数RET调用后,我们加12或者十六进制中的0xc(因为我们推入3个参数到堆栈中,每一个分配了4个字节(整型))。接着我们离开main()函数,并且返回:
0x8048459 :leave
0x804845a :ret
好,在函数f()内部发生了什么呢?
(gdb)
disas f
Dump of assembler code for function f:
0x8048440 :pushl雙
0x8048441 :movl %esp,雙
0x8048443 :subl $0x4,%esp
0x8048446 :leave
0x8048447 :ret
End of assembler dump.
(gdb)
开始两个指令都是一样的。它们是程序引入。接着我们看a:
0x8048443 : subl $0x4,%esp
从ESP减去了4个字节。这是为局部变量z分配空间。记得我们定义它为char z[4]?它是一个4字节的字符数组。最后,在末尾,函数返回:
0x8048446 :leave
0x8048447 :ret
好,让我们看另外一个例子:
b.c :
void f(int a, int b, int c)
{
char foo1[6];
char foo2[9];
}
void main()
{
f(1,2,3);
}
编译并且启动gdb,解析f:
[murat@victim murat]$ gcc -g b.c -o b
[murat@victim murat]$ gdb -q ./b
(gdb) disas f
Dump of assembler code for function f:
0x8048440 :pushl雙
0x8048441 :movl %esp,雙
0x8048443 :subl $0x14,%esp
0x8048446 :leave
0x8048447 :ret
End of assembler dump.
(gdb)
可以看出,从ESP中减去了0x14(20字节),尽管foo1和foo2的总长度只有9 6=15。这样的原因是,内存,还有堆栈,在4字节框架下编址。这意味着,你不能简单的PUSH 1字节数据到堆栈中。或者4字节或者为空。f()北调用时,堆栈将象这样:
_______$1_______| EBP 16
_______$2_______| EBP 12
_______$3_______| EBP 8
_return address_| EBP 4
___saved_ESP____| EBP ESP
______foo1______| EBP-4
______foo1______| EBP-8
______foo2______| EBP-12
______foo2______| EBP-16
______foo2______| EBP-20
你可以相信,当我们对f001装载超过8个字节对和对foo2超过12个字节,我们将溢出他们的空间。如果你对foo1写入超过4个字节,你将重写被保护的EBP,而且……如果你写入超过4个字节,你将重写返回地址……而这不正是我们都想要的吗?这是内存溢出的基础……让我设法用一段简单的代码稍微阐明一下这种现象,假设我们有这样的代码:
c.c :
#include
void f(char *str)
{
char foo[16];
strcpy(foo, str);
}
void main()
{
char large_one[256];
memset(large_one, 'A', 255);
f(large_one);
}
[murat@victim murat]$ make c
cc -W -Wall -pedantic -gc.c -o c
[murat@victim murat]$ ./c
Segmentation fault (core dumped)
[murat@victim murat]$
我们在上面做的是简单的写255字节到一个只能容纳16字节的数组里。我们传递了一个256字节的大数组作为一个参数给f()函数。在函数内部,没有边界检测我们拷贝了整个large_one到foo,溢出了foo和其它数据。因此缓冲区被填写了,同样的strcpy()用A填写了内存的其它部分,包括返回地址。
这里是用gdb生成核文件代码的检查:
[murat@victim murat]$ gdb -q c core
Core was generated by `./c'.
Program terminated with signal 11, Segmentation fault.
find_solib: Can't read pathname for load map: Input/output error
#00x41414141 in ?? ()
(gdb)
可以看出,CPU在EIP中看到0x41414141(041是字母A的十六进制ASCII码),试图存储和执行此处的指令。然而,0x41414141不是我们的程序被允许存储的内存地址。最后操作系统发了一个SIGSEGV(Segmentation Violation)段侵犯信号给程序并且停止了任何进一步的操作。
我们调用f()时,堆栈看起来象这样:
______*str______| EBP 8
_return address_| EBP 4
___saved_ESP____| EBP ESP
______foo1______| EBP-4
______foo1______| EBP-8
______foo1______| EBP-12
______foo1______| EBP-16
strcpy()从foo1的开头,EBP-16开始,拷贝large_one到foo,没有边界检查,用A填充了整个堆栈。
现在我们能够重写返回地址,如果我们放一些其它的内存段地址,我们能在那里执行指令码?答案是肯定的。假如我们放了一些 /bin/sh spawn出的指令在一些内存地址中,而我们把这个地址放到我们溢出的这个函数返回地址中,我们就能spawn出一个shell,而且很有可能,既然你已经对setuid二进制程序感兴趣了,我们将spawn出一个root shell。
ms挂马方法 ms如何挂马?
SQL语句如下:用游标遍历所有表里如下数据类型的字段,然后UPDATE挂马。(全部是允许写入字符的字段)xtype=99 ntextxtype=35 text
详情2018-03-01 10:26:01责编:llp 来源:驱动管家php注入的万能密码是什么?为什么这个万能密码能进入后台?
可是有的人说对PHP的站如果是GPC魔术转换开启,就会对特殊符号转义,就彻底杜绝了PHP注入。其实说这话的人没有好好想过,更没有尝试过用万能密码进PHP的后台。其实GPC魔术转换是否开启对用万能密码进后台一点影响
详情2018-01-24 12:27:47责编:llp 来源:驱动管家图片隐藏文件秘密的方法 文件秘密如何隐藏在图片中?
每个人都有自己的秘密,不过有些朋友却喜欢将秘密,以文件的形式放到电脑里,来供自己欣赏。虽然这些“秘密”放在电脑上大多都是加了密的,但是有些只能防止菜鸟破解,根本达不到真正隐藏的目的。于是笔者想了很
详情2018-02-04 13:20:07责编:llp 来源:驱动管家mcu是什么?mcu是怎么被黑客破解的?
MCU就是大家所熟悉的微控制单元,或者单片微型计算机,或者单片机,攻破MCU有很多种方法,下面小编就为大家具体的讲解黑客是怎么破解MCU的。这篇文章是俄国人Sergei P Skorobogatov就读英吉利剑桥大学之博士论文
详情2018-01-24 20:07:20责编:llp 来源:驱动管家用regedt32.exe对sam键设置完全控制权限
对regedit exe大家都很熟悉,但却不能对注册表的项键设置权限,而regedt32 exe最大的优点就是能够对注册表的项键设置权限。nt 2000 xp的帐户信息都在注册表的HKEY_LOCAL_MACHINE\SAM\SAM键下,但是除了系统用户
详情2018-03-07 08:49:44责编:llp 来源:驱动管家linux服务器下syn攻防战 syn攻击的相关知识
如何打响Linux服务器下的攻防战,感兴趣的小伙伴们可以参考一下本文,或许会有所收获。
详情2018-03-01 15:31:20责编:llp 来源:驱动管家2016年木马病毒查杀软件的排行榜
现在的电脑杀毒软件种类很多,在选择的时候,很多人并不知道如何去进行选,按照什么标准来进行选择,其实在选择杀毒软件首先要看杀毒能力,其次可以根据杀毒软件的功能来进行判定排名,下面就和大家一起来分析一
详情2018-01-05 13:58:41责编:llp 来源:驱动管家139端口入侵怎么禁止?如何处理512端口入侵?
139端口的入侵,主要是通过建立空连接,而获得用户名和共享名,接着用字典法或穷举法来猜测ADMINISTRATORS的密码,这样可获得最高权限。解决方法:1、禁止匿名共享。2、禁止管理共享。1433端口的入侵,主要是利用
详情2018-02-01 16:50:14责编:llp 来源:驱动管家后门木马的查找教程 手工怎么查找后门木马?
后门木马又称特洛伊木马(Trojan horse),是一种基于远程控制的黑客工具。包括客户端和服务端。一起来看看手工查找后门木马的教程吧。1、首先最需要注意的地方是系统的启动项,可以在“运行”-输入“msconfig命
详情2018-01-06 11:53:37责编:llp 来源:驱动管家搜狐微博也有漏洞?搜狐微博的漏洞和修复方法分析
搜狐某处CSRF漏洞,可能导致蠕虫蔓延,在未经用户同意的情况下发布微博
详情2018-01-13 16:51:22责编:llp 来源:驱动管家
- 怎么解决Win7更新显卡驱动后黑屏的情况
- excel筛选数据透视表中值的教程分享
- Win8新文件系统Protogon是什么
- mpg是什么格式 mpg文件怎么打开
- 网站被屏蔽了怎么办 网站反屏蔽的几种方法
- win7英文版系统玩魔兽世界的时候无法开启怎么解决
- 电脑如何进入BIOS 设置U盘启动
- tcl idol x好用吗?tcl idol x使用感想
- 乐玩2c可以打开后盖吗?乐玩2c打开后盖的方法
- url是什么文件格式?.url文件怎么打开?
- IE浏览器怎么设置默认下载目录
- 什么叫自动化web安全测试?自动化fuzz工具怎么用?
- 分析短信网关SMSGate处理畸形HTTP请求时存在漏洞
- 怎么卸载卸载网卡 声卡等硬件驱动的问题解决方法
- excel表格批注不显示是怎么回事 让Excel批注显示的办法
- WPS怎么画流程图中的内部贮存图形 试试这个方法
- 服务器cpu和普通cpu有什么不同
- ie浏览器为什么上不了网?ie浏览器上不了网的原因分析
- 从设备商到芯片商 中美欧的那些5G行业大玩家
- 谷歌安全总监:安卓系统已和苹果iOS一样安全