ROP对策 - PIE

PIE(Position Independent Executables)

  • .text区域的地址也进行随机化

  • 所有的汇编代码中不包含绝对地址

  • 全都使用相对地址

  • 二进制文件被加载到内存时,基本是随机映射的

  • 没有可以提前确定的固定地址

PIE绕过 – 多段memory leak + ret2libc等

  • 看起来非常严格,因为完全没有固定地址,但如果能够多次利用漏洞,花费时间和精力也能够解决它

  • 通过栈溢出之外的漏洞(例如格式化字符串(FSB),堆溢出)等泄漏的情况比较多

  • 如果能够知道.text的地址,就能够知道其他例如.data , .bss,.plt,.got.plt 等

  • 如果进一步从.got.plt读取内存,则可以识别libc地址。之后如果能够将其加载到stack上,或者能够重写GOT,就解决了。

Stack Canary

很早就出现的机制

  • gcc编译后,stack上有一个canary值
  • 进入函数时,canary被随机设置
  • 退出该函数时(return 前),会验证canary没有被修改
  • 根据之前已经提到的技术,很难突破这一层保护

Stack Canary攻略1 – brute force

  • 在重新运行二进制文件之前,Stack Canary的值不会更改

    • 对于fork-server类型,只要主进程没有重新启动,canary就是常量

    • 逐个字节进行爆破的话,最多256*4次尝试就能够命中Stack Canary

      • 如果是x64的话需要256*8次,但无论如何都是一个现实的数字
    • 覆盖Stack Canary为正确的值,这样函数返回时,通过检查,正常返回

Stack Canary攻略2 – master canary forging

  • Stack Canary存储在TLS(Thread local storage)中

    • x86是在gs:0x14,x64是在fs:0x28存在着值

  • 如果能够重写该值,就能够使Stack Canary无效

    • 将StackCanary修改为想要的值
    • 使用任意内存读写,堆溢出等技术进行覆盖

  • potetisensei的相关paper

目前为止的技术总结

技术 推荐练习的问题
nop-sled CodeGate 2013 - pwn100
brute force CodeGate 2013 - pwn100
ret2esp CSAW CTF 2012 - pwn300 - 4842
stager Hack.lu CTF 2012 - pwn300 - braincpy
ret2plt Plaid CTF 2013 - pwn200 - ropasaurusrex
ret2pop Plaid CTF 2013 - pwn200 - ropasaurusrex
ret2libc Plaid CTF 2013 - pwn200 - ropasaurusrex
GOT overwrite Plaid CTF 2013 - pwn200 - ropasaurusrex
ROP Hack.lu CTF 2012 - pwn300 – braincpy
stack pivot Hack.lu CTF 2012 - pwn300 – braincpy
ret2dl_runtime_resolve Hack.lu CTF 2014 – pwn400 - oreo
_IO_jump_t overwrite ED-CTF – pwn350 – Heap is a tomodachi of mine
ld specific ptr overwrite Plaid CTF 2015 – pwn550 - plaiddb
canary brute force 30c3 CTF 2014 - pwn400 - bigdata
master canary forging CodeGate 2014 – pwn600 - dodosandbox