文档介绍:缓冲区溢出技术
1
堆栈
2
从物理上讲,堆栈是就是一段连续分配的内存空间
静态全局变量是位于数据段并且在程序开始运行的时候被加载
动态的局部变量 则分配在堆栈里面
从操作上来讲,堆栈是一个先入后出的队列,其生长方向与内存的 = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
}
12
execve( )
execve函数将执行一个程序
程序的名字地址作为第一个参数
一个内容为该程序的argv[i](argv[n-1]=0)的指针数组作为第二个参数
(char*) 0作为第三个参数
13
execve的汇编代码
$ gcc -o shellcode -static
$ gdb shellcode
(gdb) disassemble __execve
Dump of assembler code for function __execve:
14
如何精简?
经过以上的分析,可以得到如下的精简指令算法:
movl $execve的系统调用号,%eax
movl "bin/sh\0"的地址,%ebx
movl name数组的地址,%ecx
movl name[n-1]的地址,%edx
int $0x80 ;执行系统调用(execve)
15
问题
当execve执行成功后,程序shellcode就会退出,/bin/sh将作为子进程继续执行
如果execve执行失败,(比如没有/bin/sh这个文件),CPU就会继续执行后续的 指令,结果不知道跑到哪里去了
所以必须再执行一个exit()系统调用,
16
exit(0)汇编代码
17
exit(0) 的汇编代码精简
movl $0x1,%eax ;1号系统调用
movl 0,%ebx ;ebx为exit的参数0
int $0x80 ;引发系统调用
18
execve + exit
movl $execve的系统调用号, %eax
movl “bin/sh\0”的地址, %ebx
movl name数组的地址, %ecx
movl name[n-1]的地址, %edx
int $0x80 ;执行系统调用(execve)
movl $0x1,%eax ;1号系统调用
movl 0,%ebx ;ebx为exit的参数0
int $0x80 ;执行系统调用(exit)
19
万事具备,还欠什么?
字符串“/bin/sh”
name数组
execve + exit
问题
每一次程序都是动态加载,字符串和name数组的地址都不是固定的
在shellcode中如何知道它们的地址呢?
20
jmp + call
21
在large_string中填入buffer的地址
22
把shell代码放到large_string 的前面部分
23
将large_string拷贝到buffer中
24
造成溢出,使返回地址变为buffer,而buffer的内容为shell代码。这样当程序试从 strcpy() 中返回时,就会转而执行shell
25
如何利用别人的漏洞
26
利用别人的程序的堆栈溢出获得rootshell
以一个有strcpy堆栈溢出漏洞的程序,利用前面说过的方法来得到shell
同样必须完成两件事
把自己的shellcode提供给对方,让对方可以访问shellcode
修改对方的返回地址为shellcode的入口地址
27
How
必须知道strcpy(buffer,ourshellcode中,buffer的地址
因为当我们把shellcode提供给strcpy之后,buffer的开始地址就是shellcode的
开始地址
必须用这个地址来覆盖堆栈
28
How
对于操作系统而言,一个shell下的每一个程序的堆栈段开始地址都是相同的
可以写一个程序,获得运行时的堆栈起始地址,这样,我们就知道了