首先大家先了解一下32位操作系统的内存结构分布:
http://m.blog.csdn.net/maikforever/article/details/17502261
32bits操作系统和64bits操作系统的寄存器是不同的,大致区别看下图,具体信息点我
在我们做栈溢出实验,用gdb调试的时候,我们主要关心的是下面几个寄存器
- 32bits操纵系统:
$esp,$ebp - 64bits操作系统:
$rsp,$rbp
实验源代码如下:
64bits:
void function(int a, int b, int c){
char buffer1[5];
char buffer2[10];
int *ret;
ret = buffer1 + 21;
(*ret) += 7;
}
void main(){
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
我在自己的kali2.0 64位虚拟机下面运行的时候,输出的结果是0
32bits:
void function(int a, int b, int c){
char buffer1[5];
char buffer2[10];
int *ret;
ret = buffer1 + 12;
(*ret) += 8;
}
void main(){
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
使用gcc编译:
root@kali:~/桌面/BOF# gcc -g -o ovr_ret ovr_ret.c
ovr_ret.c: In function ‘function’:
ovr_ret.c:5:8: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ret = buffer1 + 21;
^
ovr_ret.c: In function ‘main’:
ovr_ret.c:13:3: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf("%d\n",x);
^~~~~~
ovr_ret.c:13:3: warning: incompatible implicit declaration of built-in function ‘printf’
ovr_ret.c:13:3: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
使用gdb调试:
root@kali:~/桌面/BOF# gdb ovr_ret
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ovr_ret...done.
(gdb) b 5 //在第5行设置断点
Breakpoint 1 at 0x6bd: file ovr_ret.c, line 5.
(gdb) r //运行
Starting program: /root/桌面/BOF/ovr_ret
Breakpoint 1, function (a=1, b=2, c=3) at ovr_ret.c:5
5 ret = buffer1 + 21;
(gdb) x $rsp //显示rsp寄存器信息
0x7fffffffe110: 0xffffe130
(gdb) x $rbp //显示rbp寄存器信息
0x7fffffffe110: 0xffffe130
(gdb) x buffer1 //显示临时变量buffer1的信息
0x7fffffffe103: 0x00000000
(gdb) shell //在保持gdb的情况下,运行shell
root@kali:~/桌面/BOF# echo $[0x7fffffffe110-0x7fffffffe103+8]
//$rbp-buffer1+8得到的是ret返回地址,为什么加8呢?因为实在64位操作系统里面,64=8*8,如果是32位操纵系统则+4
21
root@kali:~/桌面/BOF# exit
exit
(gdb) disas main
Dump of assembler code for function main:
0x00005555555546db <+0>: push %rbp
0x00005555555546dc <+1>: mov %rsp,%rbp
0x00005555555546df <+4>: sub $0x10,%rsp
0x00005555555546e3 <+8>: movl $0x0,-0x4(%rbp)
0x00005555555546ea <+15>: mov $0x3,%edx
0x00005555555546ef <+20>: mov $0x2,%esi
0x00005555555546f4 <+25>: mov $0x1,%edi
0x00005555555546f9 <+30>: callq 0x5555555546b0 <function>
0x00005555555546fe <+35>: movl $0x1,-0x4(%rbp)
0x0000555555554705 <+42>: mov -0x4(%rbp),%eax
0x0000555555554708 <+45>: mov %eax,%esi
0x000055555555470a <+47>: lea 0x93(%rip),%rdi # 0x5555555547a4
0x0000555555554711 <+54>: mov $0x0,%eax
0x0000555555554716 <+59>: callq 0x555555554560 <printf@plt>
0x000055555555471b <+64>: nop
0x000055555555471c <+65>: leaveq
0x000055555555471d <+66>: retq
End of assembler dump.
(gdb) shell
root@kali:~/桌面/BOF# echo $[0x0000555555554705-0x00005555555546fe]
//计算x=1这条语句的返回地址和之前ret的差值
7
root@kali:~/桌面/BOF# ./ovr_ret
//最后修改过的代码,运行结果不为1而是0,因为跳过了x=1;这条语句的执行
0
root@kali:~/桌面/BOF#