浅谈栈溢出漏洞利用技术——学习笔记

基础知识

寄存器:重要寄存器

  • 重要寄存器:rsp/esp,pc,rbp/ebp,rax/eax,rdi,rdx,rcx

栈:一种先进先出的数据结构

  • 程序中的栈:
  • 内存中的一块区域,用栈的结构来管理,从高地址向低地址增长
  • 寄存器esp代表栈顶(最低栈地址)
  • 压栈(入栈)

push std->[esp]=sth,esp=esp-4

  • 弹栈(出栈)

pop std->sth=[esp],esp=esp+4

  • 栈用于保存函数调用信息和局部变量
  • 需要详细了解栈溢出漏洞的形式

函数调用

  • 函数约定

_stdcall,_cdecl,_fastcall,_thiscall,_nakedcall,_pascal

  • 参数传递,取决于调用约定,默认如下
    X86从右向左入栈,X64优先寄存器,参数过多时才入栈
  • 函数调用相关指令解读
  • call func -> push pc,jmp func
  • leave -> mov esp,ebp,pop ebp
  • ret -> pop pc

栈溢出的保护机制

栈上的数据被当做指令来执行

  • 数据执行保护机制(NX/DEP)
  • 绕过方法:ROP

让攻击者难以找到shellcode地址

  • 地址空间布局随机化(ASLR)
  • 绕过方法:infoleak、ret2dlresolve、ROP

检测Stack Overflow(栈溢出)

  • Stack Canary/Cookie
  • 绕过方法:infoleak

现在NX+Stack Canary+ASLR基本是标配

栈溢出的利用方法

现代栈溢出利用技术基础:ROP

  • 现在的程序默认都开启数据执行保护机制和地址空间布局随机化(NX+ASLR)这两种技术,传统的覆盖shellcode地址跳到shellcode那里执行的技术来玩儿,所以,现代就用ROP这种方式来绕过这两种技术
  • 一种代码复用技术,即利用程序中已经存在的代码行,通过控制栈调用来劫持控制流,不用注入什么其他的代码
  • 它的一种简化版本是Ret2libc
CTF中ROP技术的常见套路
  • 第一次触发漏洞,通过ROP泄露libc的地址(address)(如puts_got),计算system地址,然后返回到一个可以重新触发漏洞的位置(如main的开头),再次触发漏洞,通过ROP调用system("/bin/sh"),来拿到shell
  • 直接execve("/bin/sh",["/bin/sh"],NULL)拿到shell,通常静态链接时比较常用
  • Defcon 2015 Qualifier:R0pbaby
  • AliCTF 2016:vss
  • PlaidCTF 2013:ropasaurusrex

利用signal机制的ROP技术(SROP)

  • SROP(Sigreturn Oriented Programming)
  • 利用系统Signal Dispatch的一个机制,系统Signal Dispatch之前会把所有寄存器压入栈,然后调用signal handler,signal handler返回时会将栈的内容还原到寄存器中
  • 如果事先填充栈,然后直接调用signal return,那在返回的时候就可以变相控制寄存器的值
  • 用的不是特别多但是有时候很好用
  • defcon 2015 qualifier fukeup(比较难)
  • 建议自己写一个domo测试

没有binary怎么办(BROP)

  • BROP(Blind Return Oriented Programming)
  • 用的不是特别多但是在CTF比赛中出现过
BROP的目标
  • 在拿不到binary的情况下进行ROP
BROP的条件
  • 必须先存在一个已知的stack overflow漏洞,而且攻击者知道如何触发这个漏洞
  • 服务器进程在crash之后会重新复活,并且重新复活的进程不会被re-rand
  • HCTF 2016 出题人跑路了(pwn50)

以上这两种技术是ROP的分类(SROP和BROP),在CTF中不常见,但是的确出现过这种技术的题目

劫持栈指针(Stack Pivot)

  • 一种较为特殊的方法,相当重要的方法
  • 将栈指针劫持到非栈区域,在别处操作栈指针
  • 向目标缓冲区填入栈数据(如ROP Chains),然后劫持esp到目标缓冲区。劫持esp的方法有很多,最常用的就是ROP时利用可以直接改写esp的gadget,如pop esp,ret
劫持栈指针的动机
  • 溢出字节数有限,无法完成ROP
  • 栈地址未知且无法泄露,但是某些利用技术需要知道栈地址(ret2dlresolve)
  • 劫持esp到攻击者控制的区域,也就变相的控制了栈中的数据,从而可以使非栈溢出的控制刘劫持攻击也可以完成ROP
Stack Pivot的条件
  • 存在地址已知且内容可控的buffer
    • bss段,由于bss段尾端通常具有很大的空余空间(pagesize-usedsize),所以bss段尾端往往是Stack Pivot的目标
    • 堆块,如果堆地址已经泄露且数据可被控制,那堆也可以作为Stack Pivot的目标
  • 控制流可劫持
  • 存在劫持栈指针的gadgets
    • 如pop esp,ret,除此之外还有很多,要具体binary具体分析
  • EKOPARTY CTF 2016 fuckzing-exploit-200(基于栈溢出的Stack Pivot)
  • HACKIM CTF 2015 -Exploition 5(基于堆溢出的Stack Pivot)

利用动态链接绕过ASLR

  • 动态链接的过程就是从函数名到函数地址转换的过程,所以我们可以通过动态链接器解析任何函数,且无需任何leak
  • ret2dl resolve,fake linkmap
  • 该技术较为复杂
前置技能
  • 了解动态链接的过程,《程序员的自我修养》
  • 伪造动态链接的相关数据结构如linkmap,relplt等

利用地址低12bit绕过ASLR

  • Partial Overwrite
  • 这是一种较为重要的技术,经常用到的一个技术
  • 利用ASLR中低12bit不会被随机化的特性来绕过ASLR
  • 在PIE开启的情况下,一个32位地址的高20位会被随机化,但是低12位是不变的。所以,可通过只改写低12位来绕过PIE,不仅仅在栈溢出中使用,在各种利用中经常使用。
  • HCTF 2016 fheap(基于堆溢出的Partial Overwrite)

绕过Stack Canary

以上所有套路,一旦遇到Stack Canary均无法使用

  • 改写指针与局部变量、leak canary、overwrite canary
  • CTF中的不常用的技术,除非题目将栈溢出显露出来,否则一般情况下不会使用这种技术
绕过思路
  • 不覆盖Stack Canary,只覆盖Stack Canary前的局部变量,指针
    • 已经几乎不可行,编译器都会做一种防护,因为编译器会根据内存占有大小从小到大排列变量,
    • 但是在某些情况依然可用,需要结合实例分析
  • Leak Canary
    • 可以通过格式化printf泄露,Canary一般从00开始
  • Overwrite Canary(重写)
    • Canary在TLS中地址被随机化
    • 很少见

溢出位数不够用

  • 覆盖ebp,Partial Overwrite
  • Func 1:
    call func2
    leave(mov esp ebp,pop ebp)
    ret (pop ip)
  • Func 2:
    Stack Overflow
    leave(mov esp ebp,pop ebp)
    ret (pop ip)

可以覆盖Func2的ebp,会影响到Func1的esp,进而影响Func1的ip,完成对控制流的劫持。可以部分覆盖返回地址。

  • XMAN 2016 广外女生-pwn
  • Codegate CTF Finals 2015,chess
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值