目标
(1)熟悉栈溢出的基本原理
(2)熟悉栈溢出的防御方法
(3)学会栈溢出的利用方法
(4)学会栈溢出的高级利用技巧
内容简介
1.栈溢出原理和防御手段
2.栈防御的绕过
3.栈溢出技巧
栈的介绍
栈:
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表,高地址在上,低地址在下。按照先进后出的原则存储数据,先进入的数据压入栈底,最后进入的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(FILO)。
栈赋予程序一个方便的空间来访问函数的局部变量,传递函数参数,并传递函数执行后的返回信息等。
栈的两个基本操作:
进栈(PUSH):将数据压入栈顶,同时ESP-4或RSP-8
出栈(POP):将栈顶数据弹出,同时ESP+4或RSP+8
栈的两个寄存器:
ESP(rsp):栈指针寄存器,指向栈顶的低地址
EBP(rbp):基址指针寄存器,指向栈底的高地址
栈的溢出原理
栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身申请的字节数,因而导致与其相邻的栈中的其他重要数据结构被破坏,从而影响程序的正常运行
当我们写入的字符串长度可以覆盖到程序的返回地址时,我们可以控制程序的运行流程。
pwntools的使用
pwntools写exp,使用python书写
安装方法:
方法一:
python3 -m pip install pwntools
方法二(推荐):
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools.git@dev
在python中导入pwntools模块,使用基本框架:
from pwn import *
p = remote(......)
payload = b"a"......
p.sendline(payload)
p.interactive()
shellcode的介绍
shellcode是指一段用于完成某个功能的代码,常见的功能主要是获取目标系统的shell
shellcode的特点:①短小精悍;②通常为16进制的机器码;③可以重复利用
shellcode的编写
(32位)不同内核态操作通过给寄存器设置不同的值,再调用指令int 80h(中断调用),就可以通知内核完成不同的功能——>只要通过特定的汇编代码把特定的寄存器设置为特定的值后,再调用指令int 80h,执行系统函数sys_execve("/bin/sh",NULL,NULL)就可以获得系统shell
32位系统的shellcode编写方法:
1.将EAX寄存器的值设置成0Xb:EAX = 0Xb
2.将EBX寄存器的值设置为"/bin/sh"字符串的地址:EBX = &("/bin/sh\x00")
3.将ECX和EDX寄存器的值都设为0:ECX = EDX = 0
(64位)原理与32位一样,改为调用syscall
64位程序中传递参数不是直接通过栈,而是前6个参数通过寄存器,RDI、RSI、RDX、RCX、R8、R9,第6个参数之后的参数才是通过栈传递的
64位系统的shellcode编写方法:
1.将RAX寄存器的值设置为0X3b:RAX = 0X3b
2.将RDI寄存器的值设置为"/bin/sh"字符串的地址:RDI = &("/bin/sh")
3.将RSI和RDX寄存器的值都设为0:RSI = RDX =0
可以通过pwntools的shellcraft模块来产生合适的shellcode:shellcraft.sh()
默认产生的是32位的shellcode,要产生64位的需要先声明系统版本:context(os='linux',arch='amd64')
Shellcodes database for study cases (shell-storm.org)http://shell-storm.org/shellcode/index.html
ret2shellcode介绍
ret2shellcode:return to shellcode,即让程序中某个函数执行结束后,返回到shellcode的地址去执行shellcode
局限性:放shellcode的这个地址内存页是必须标识为可执行
栈溢出的防御手段
checksec
通常程序的防御保护机制有下面几种:
1.RELRO:RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表,设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT表的攻击;(-z norelro /-z relro -z -lazy /-z relro -z -now)
2.Stack:如果栈中开启Canary found,那么就不能用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过;(-fno-omit-frame-pointer)
3.NX:NX enable如果这个保护开启就是意味着栈中数据没有执行权限,以前的call esp,jmp,esp,或者直接执行shellcode的方法就不能使用;(-z execstack)
4.PIE:PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE(0x400000),括号内的数据就是程序的基地址;(-no -pie)
5.RWX