听i春秋上面蓝莲花战队成员Atum的课程 CTF PWN选手的养成 ,了解到不少东西,在此记个笔记~

基础知识

栈的结构:先进后出,在内存中为高地址往低地址增长,栈顶为栈的最上方(低地址区),栈底为栈的最下方(高地址区)

一、寄存器

  1. rsp/esp:指向栈顶的栈指针寄存器(低地址)

  2. rbp/ebp:指向栈底的指针寄存器(高地址)。栈低通常作为基址,我们可以通过栈底地址和偏移相加减来获取变量地址

    栈的结构如图所示(栈由高地址向低地址增长)
    函数调用时栈的变化

    EBP指向的栈底,ESP指向的栈顶,EBP下面的EIP是函数返回的地址(即return执行后下一条指令的地址),var1是函数的参数.

  3. pc:程序指针,存储着指向CPU接下来要执行的指令地址

  4. rdi rsi rdx rcx:x86中参数都是保存在栈上,但在x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中,如果还有更多的参数的话才会保存在栈上。

二、栈溢出漏洞介绍

通俗的讲,栈溢出的原理就是不顾堆栈中分配的局部数据块大小,向该数据快写入了过多的数据,导致数据越界,结果覆盖来看老的堆栈数据。
栈溢出漏洞的形式

三、函数调用约定

函数调用: call, ret
调用约定: _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、PIE)
绕过方法:infoleak 、ret2dlresolve 、ROP

检测Stack Overflow

Stack Canary/Cookie,相当于在返回地址和ebp之间加一个cookies,通过检测cookies是否被改变
绕过方法:infoleak

五、栈溢出的利用方法

现代栈溢出的技术基础:ROP(绕过NX和ASLR)
利用signal机制的ROP技术:SROP
没有binary怎么办:BROP(不是很常见)
劫持栈指针:stack pivot //将栈指针劫持到其他区域
利用动态链接绕过ASLR:ret2dlresolve、fake linkmap
利用地址低12bit绕过ASLR:Partial Overwrite(低12位不会被随机化)
绕过Stack canary:改写指针与局部白能量、leak canary、overwrite canary
溢出位数不够怎么办:覆盖ebp,Partial Overwrite

六、现代栈溢出的利用技术

ROP


eg: Ret2libc
一种代码复用技术,通过控制栈调用来劫持控制流
主要思想: 在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
CTF中ROP常规套路
第一次触发漏洞,通过ROP泄露libc的address(如puts_got),计算system地址 然后返回到一个可以重现触发漏洞的地方(main)再次触发漏洞。通过ROP调用system(‘/bin/sh’)直接execve(“/bin/sh”,[“/bin/sh”],NULL) 这个通常在静态链接比较常用

Defcon 2015 Qual:R0pbaby 
AliCTF 2016:vss
PlaidCTF  2013:ropasaurusrex

利用signal机制的ROP技术-SROP


SROP(Sigretum Oriented Programming)
系统Signal Dispatch之前会将所有寄存器压栈,然后调用signal handler, signal handler返回时会将栈内容还原
如果事先填充栈,然后直接调用signal handler,那在返回的时候就可以控制寄存器的值资源

http://angelboy.logdown.com/posts/283221-srop
http://www.2cto.com/article/201512/452080.html
defcon 2015 qualifier: fuckup(较难)

没有binary怎么办-BROP(用的不多)


目标 :在拿不到目标binary的条件下进行ROP
条件 :必须先存在一个已知的stack overflow漏洞,而且攻击者知道如何触发这个漏洞服务器进程在crash之后会重新复活,复活的进程不会被re-rand

http://ytliu.info/blog/2014/05/31/blind-return-oriented-programming-brop-attack-yi/
http://ytliu.info/blog/2014/06/01/blind-return-oriented-programming-brop-attack-er/
HCTF 2016 出题人跑路了(pwn50)

**劫持栈指针-stack pivot


将栈劫持到其他攻击者控制的缓冲区

向目标缓冲区填入栈数据(如ROP chains),然后劫持esp到目标缓冲区。劫持esp的方法有很多种,最常用的就是ROP时利用可以直接改写esp的gadget 如pop esp ,ret ,具体binary具体分析
利用条件

  1. 存在地址已知且内容可控的buffer
    bss段,由于bss段尾端常有大量空余空间,所以bss段尾端也往往是stack pivot的目标
    堆块,如果堆地址已泄且堆上的数据可控,那堆也可以作为stack pivot目标
  2. 控制流可劫持
  3. 存在劫持栈指针的gadgets

Stack piovt的动机
· 溢出字节数有限,无法完成ROP
· 栈地址未知且无法泄露,但是某些利用技术却要求知道栈地址(ret2dlresolve)
· 劫持esp到攻击者控制的区域,也就变相的控制了栈中的数据,从而可以使非栈溢出的控制流劫持攻击也可以做ROP

EKOPARTY CTF 2016 fuckzing-exploit-200(基于栈溢出)
HACKIM CTF 2015 - Exploitation 5(基于堆溢出)

*利用动态链接绕过ASLR:ret2dlresolve、fake linkmap


用法
动态链接就是从函数名到地址的转换过程,所以可以通过动态链接器解析任何函数,无需leak
理论上任何可以stack pivot且FULLRELRO未开的题目都可以利用这种技术
资源
前置技能:了解动态链接的过程

http://blog.chinaunix.net/uid-24774106-id-3053007.html
《程序员的自我修养》

伪造动态链接的相关数据结构如linkmap、relplt

http://rk700.github.io/2015/08/09/return-to-dl-resolve/
http://angelboy.logdown.com/posts/283218-return-to-dl-resolve
http://www.inforec.org/wp/?p=389
Codegate CTF Finals 2015 yocto(fake relplt) 
http://o0xmuhe.me/2016/10/25/yocto-writeup
HITCON QUALS CTF 2015 readable(fake linkmap)
Hack.lu’s 2015 OREO

****** 理论上任何可以stack pivot且FULLRELRO未开的题目都可以使用这种技术

利用低地址低12bit绕过ASLR-Partial Overwrite


用法
PIE开启时,一个32地址的高20位被随机化,低12bit不变。
改写低12bit绕过PIE,不仅在栈溢出使用,各种利用都经常使用。
eg:
return address=0x???abc
system("/bin/sh")=0x???def
overwrite abc by def, we can prompt a shell

了解partial overwrite
HCTF 2016 fheap(基于堆溢出)

绕过stack canary


以上所有套路,遇到stack canary均无效
不覆盖stack canary,只覆盖stack canary前的局部变量、指针: 几乎不行,编译器会根据占用内存大小从小到大排列变量;某些极限情况可以,一般都是精心构造的
** leak canary: printf泄露,canary一般从00开始
overwrite canary: canary在TLS, TLS地址被随机化

溢出位数不够怎么办:覆盖ebp、partial overwrite


用法
-可以覆盖Func2的ebp,会影响到Func1的esp,进而影响func1的ip

1
2
3
4
5
6
Func1: 
call func2 leave(mov esp ebp, pop ebp)
ret(pop ip)
Func2:
stack overflow leave(move esp, ebp, pop ebp)
ret(pop ip)

XMAN 2016 广外女生-pwn
Codegate CTF Finals 2015,chess