一个实例讲解fastbins上的堆利用

这道题是hctf2016年“就是干”那道题。附件有下载地址及writeup。我就是分析一下:

首先IDA分析一下:
新建两个结构体
00000000 str_struct      struc ; (sizeof=0x20)
00000000 str             dq ?
00000008 str_padding     dq ?
00000010 size            dq ?
00000018 free_func       dq ?
00000020 str_struct      ends
00000020
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 str_list        struc ; (sizeof=0x10)   ; XREF: .bss:string_listr
00000000 flag            dq ?
00000008 str_ptr         dq ?
00000010 str_list        ends


这两个结构体非常重要了,涉及到后边堆的利用,首先介绍一下第一个结构体str_struct吧,大小是0x20,当要保存的字符串大小小于0xf 时,字符串就保存在0x0-0xf处,当保存的字符串大小大于0xf时,0x0-0x8保存一个指针,指向字符串的地址。 0x10-0x17表示字符串的大小,0x18-0x1f表示free函数的地址。

再介绍一下str_list结构体,当创建string时,置flag=1,当delete string,置flag=0,str-ptr指向str_struct结构体。

然后我把IDA的伪代码贴出来,方便以后分析:
__int64 create_string()
{
  signed int i; // [sp+4h] [bp-102Ch]@12
  str_struct *string_struct; // [sp+8h] [bp-1028h]@1
  char *dest; // [sp+10h] [bp-1020h]@8
  unsigned __int64 nbytes; // [sp+18h] [bp-1018h]@1
  unsigned __int64 nbytesa; // [sp+18h] [bp-1018h]@6
  char buf; // [sp+20h] [bp-1010h]@3
  __int64 canary; // [sp+1028h] [bp-8h]@1

  canary = *MK_FP(__FS__, 40LL);
  string_struct = (str_struct *)malloc(0x20uLL);
  printf("Pls give string size:");
  nbytes = read_int();
  if ( nbytes <= 0x1000 )
  {
    printf("str:");
    if ( read(0, &buf, nbytes) == -1 )
    {
      puts("got elf!!");
      exit(1);
    }
    nbytesa = strlen(&buf);
    if ( nbytesa > 0xF )
    {
      dest = (char *)malloc(nbytesa);
      if ( !dest )
      {
        puts("malloc faild!");
        exit(1);
      }
      strncpy(dest, &buf, nbytesa);
      string_struct->str = (__int64)dest;
      string_struct->free_func = (__int64)free_2;
    }
    else
    {
      strncpy((char *)string_struct, &buf, nbytesa);
      string_struct->free_func = (__int64)free_1;
    }
    LODWORD(string_struct->size) = nbytesa;
    for ( i = 0; i <= 15; ++i )
    {
      if ( !LODWORD(string_list[i].flag) )
      {
        LODWORD(string_list[i].flag) = 1;
        string_list[i].str_ptr = (__int64)string_struct;
        printf("The string id is %d\n", (unsigned int)i);
        break;
      }
    }
    if ( i == 16 )
    {
      puts("The string list is full");
      ((void (__fastcall *)(str_struct *))string_struct->free_func)(string_struct);
    }
  }
  else
  {
    puts("Invalid size");
    free(string_struct);
  }
  return *MK_FP(__FS__, 40LL) ^ canary;
}




__int64 delete_string()
{
  int sid; // [sp+Ch] [bp-114h]@1
  char buf; // [sp+10h] [bp-110h]@5
  __int64 v3; // [sp+118h] [bp-8h]@1

  v3 = *MK_FP(__FS__, 40LL);
  printf("Pls give me the string id you want to delete\nid:");
  sid = read_int();
  if ( sid < 0 || sid > 16 )
    puts("Invalid id");
  if ( string_list[sid].str_ptr )
  {
    printf("Are you sure?:");
    read(0, &buf, 0x100uLL);
    if ( !strncmp(&buf, "yes", 3uLL) )
    {
      (*(void (__fastcall **)(_
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值