首页
社区
课程
招聘
[原创][writeup]CTFHUB-UnsortedBin Attack
发表于: 2023-3-13 17:01 16404

[原创][writeup]CTFHUB-UnsortedBin Attack

2023-3-13 17:01
16404

全局变量上方内存区,我们本次不利用此块内容

mallocHook上方内存区

FakeChunk选址

虽然这题叫UnsortedBin Attack,但是甚至可以用上一题的exp来打通,不是很理解为什么要在interface函数中设置magic这个后门,不过为了符合出题人的要求,所以还是单独用UnsortedBin Attack来做一次

假如不存在全局变量heapList;magic,目前不知道需要申请FakeChunk到哪个位置,所以需要使用Unsorted Bin来泄露main_Arena的地址

根据分析可知:

FreeChunkunsorted bin一链表中唯一元素时,该FreeChunk->fd FreeChunk->bk均指向main_arena+offset,经过调试得知该offset=88;__malloc_hook = main_arena-0x10,经过上述分析已知__malloc_hook上方可构造FakeChunk以劫持__malloc_hook

本题的重点是通过Unsorted Bin来泄露main_arena,具体泄露方式需要参照题目的show()函数运作方式,例如本题是以字符串来输出heap中内容,我们只需要把内存填充至fd\bk指针即可

举个其它show()函数形式的例子:write(0,heapList[index]+16,*heapList[index]+8)

该情况下泄露思路如下

可以注意到在完成泄露准备释放chunk#2 chunk#1时对chunk#3->heapHeader进行了一次还原,若不作此操作,将会触发报错

*** Error in `./pwn': free(): invalid next size (fast): 0x0000000001a530f0 ***

可以注意到是在free()函数时的错误,若进入glibc源码中搜索invalid next size (fast)可以找到触发该报错的函数是_int_free,以下是触发该报错的检查源码

该检查会判断下一块chunk的大小是否小于 MINSIZE || 大于 system_mem,若符合则会报错,所以需要将下一个chunk的size修改成符合条件的值避免报错

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  init(argc, argv, envp);
  interface();
}
void __noreturn interface()
{
  int choice; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v1; // [rsp+8h] [rbp-8h]
 
  v1 = __readfsqword(0x28u);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      __isoc99_scanf("%d", &choice);
      if ( choice != 1 )
        break;
      add();
    }
    switch ( choice )
    {
      case 2:
        delete();
        break;
      case 3:
        show();
        break;
      case 4:
        edit();
        break;
      case 1024:
        if ( magic > 28800 )
          system("/bin/sh");
        break;
      default:
        exit(-1);
    }
  }
}
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  init(argc, argv, envp);
  interface();
}
void __noreturn interface()
{
  int choice; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v1; // [rsp+8h] [rbp-8h]
 
  v1 = __readfsqword(0x28u);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      __isoc99_scanf("%d", &choice);
      if ( choice != 1 )
        break;
      add();
    }
    switch ( choice )
    {
      case 2:
        delete();
        break;
      case 3:
        show();
        break;
      case 4:
        edit();
        break;
      case 1024:
        if ( magic > 28800 )
          system("/bin/sh");
        break;
      default:
        exit(-1);
    }
  }
}
unsigned __int64 add()
{
  unsigned int inputSize; // [rsp+4h] [rbp-101Ch] BYREF
  unsigned int index; // [rsp+8h] [rbp-1018h]
  unsigned int v3; // [rsp+Ch] [rbp-1014h]
  char v4[4096]; // [rsp+10h] [rbp-1010h] BYREF
  unsigned __int64 v5; // [rsp+1018h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  memset(v4, 0, sizeof(v4));
  for ( index = 0; index <= 9; ++index )
  {
    if ( !*(&heapList + index) )
    {
      v3 = index;
      break;
    }
  }
  if ( index == 11 )
  {
    puts("wrong");
    exit(0);
  }
  puts("Size: ");
  __isoc99_scanf("%d", &inputSize);
  if ( inputSize > 0x500 )
    inputSize = 1280;
  *(&heapList + v3) = malloc(inputSize);
  Size[v3] = inputSize;
  puts("Content: ");
  read(0, *(&heapList + v3), inputSize);
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 add()
{
  unsigned int inputSize; // [rsp+4h] [rbp-101Ch] BYREF
  unsigned int index; // [rsp+8h] [rbp-1018h]
  unsigned int v3; // [rsp+Ch] [rbp-1014h]
  char v4[4096]; // [rsp+10h] [rbp-1010h] BYREF
  unsigned __int64 v5; // [rsp+1018h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  memset(v4, 0, sizeof(v4));
  for ( index = 0; index <= 9; ++index )
  {
    if ( !*(&heapList + index) )
    {
      v3 = index;
      break;
    }
  }
  if ( index == 11 )
  {
    puts("wrong");
    exit(0);
  }
  puts("Size: ");
  __isoc99_scanf("%d", &inputSize);
  if ( inputSize > 0x500 )
    inputSize = 1280;
  *(&heapList + v3) = malloc(inputSize);
  Size[v3] = inputSize;
  puts("Content: ");
  read(0, *(&heapList + v3), inputSize);
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 delete()
{
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 
  v2 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  if ( index > 0xB )
  {
    puts("wrong");
    exit(0);
  }
  free(*(&heapList + index));
  *(&heapList + index) = 0LL;
  Size[index] = 0;
  return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 delete()
{
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 
  v2 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  if ( index > 0xB )
  {
    puts("wrong");
    exit(0);
  }
  free(*(&heapList + index));
  *(&heapList + index) = 0LL;
  Size[index] = 0;
  return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 show()
{
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 
  v2 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  if ( *(&heapList + index) )
    printf("Content: %s\n", (const char *)*(&heapList + index));
  return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 show()
{
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 
  v2 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  if ( *(&heapList + index) )
    printf("Content: %s\n", (const char *)*(&heapList + index));
  return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 edit()
{
  int nbytes; // [rsp+0h] [rbp-10h] BYREF
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  puts("Size:");
  __isoc99_scanf("%d", &nbytes);
  if ( Size[index] >= nbytes )
  {
    if ( *(&heapList + index) )
    {
      puts("Content:");
      read(0, *(&heapList + index), (unsigned int)nbytes);
    }
    else
    {
      puts("wrong");
    }
  }
  else
  {
    puts("wrong!");
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 edit()
{
  int nbytes; // [rsp+0h] [rbp-10h] BYREF
  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  puts("Index:");
  __isoc99_scanf("%d", &index);
  puts("Size:");
  __isoc99_scanf("%d", &nbytes);
  if ( Size[index] >= nbytes )
  {
    if ( *(&heapList + index) )
    {
      puts("Content:");
      read(0, *(&heapList + index), (unsigned int)nbytes);
    }
    else
    {
      puts("wrong");
    }
  }
  else
  {
    puts("wrong!");
  }
  return __readfsqword(0x28u) ^ v3;
}
pwndbg> x/30gx 0x6020AC-0x1f
0x60208d:    0xfff7bc38e0000000    0x000000000000007f
0x60209d:    0xfff7bc4540000000    0x000000000000007f
0x6020ad <magic+1>:    0x0000000000000000    0x0000000000000000
0x6020bd:    0x0000000000000000    0x0000000000000000
0x6020cd <ptr+13>:    0x0000000000000000    0x0000000000000000
0x6020dd <ptr+29>:    0x0000000000000000    0x0000000000000000
0x6020ed <ptr+45>:    0x0000000000000000    0x0000000000000000
0x6020fd <ptr+61>:    0x0000000000000000    0x0000000000000000
0x60210d <ptr+77>:    0x0000000000000000    0x0000000000000000
0x60211d:    0x0000000000000000    0x0000000000000000
0x60212d <Size+13>:    0x0000000000000000    0x0000000000000000
0x60213d <Size+29>:    0x0000000000000000    0x0000000000000000
pwndbg> x/30gx 0x6020AC-0x1f
0x60208d:    0xfff7bc38e0000000    0x000000000000007f
0x60209d:    0xfff7bc4540000000    0x000000000000007f
0x6020ad <magic+1>:    0x0000000000000000    0x0000000000000000
0x6020bd:    0x0000000000000000    0x0000000000000000
0x6020cd <ptr+13>:    0x0000000000000000    0x0000000000000000
0x6020dd <ptr+29>:    0x0000000000000000    0x0000000000000000
0x6020ed <ptr+45>:    0x0000000000000000    0x0000000000000000
0x6020fd <ptr+61>:    0x0000000000000000    0x0000000000000000

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-3-13 17:11 被LeaMov编辑 ,原因: 代码传错
上传的附件:
收藏
免费 6
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//