首页
社区
课程
招聘
[原创]hitcontraining_heapcreator
发表于: 9小时前 162

[原创]hitcontraining_heapcreator

9小时前
162

参考

13dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6r3k6Q4x3X3c8%4K9h3E0A6i4K6u0W2L8%4u0Y4i4K6u0r3M7s2N6F1i4K6u0r3L8r3W2F1N6i4S2Q4x3V1k6#2M7$3g2J5i4K6u0V1L8h3!0V1k6g2)9J5c8X3S2W2j5i4m8Q4x3V1k6H3N6r3#2S2L8r3I4G2j5K6u0Q4x3V1k6U0K9s2g2F1K9#2)9J5k6r3g2^5N6r3g2F1k6q4)9J5k6r3!0$3k6i4u0D9j5i4m8H3K9h3&6Y4

Partial RELRO表明got表可写

可以看到是菜单题,有四个功能

分析代码可以知道heaparray是一个全局变量,从0-9先判断该数组是否已填满(10个),未填满则申请0x10大小的内存地址(记为内存1)作为元素值,然后输入size,size作为该内存地址的前0x8字节的值,后0x8字节用来存放malloc(size)返回的内存地址(记为内存2),之后再用read_input(*((_QWORD )(&heaparray + i) + 1), size);往内存2写入东西,写入长度是size。没啥毛病

调用一次create_heap函数如下:

指定heaparray的索引,修改内存2的内容,问题出在read_input(*((void **)*(&heaparray + v1) + 1), *(_QWORD )(&heaparray + v1) + 1LL);这里,读入长度(_QWORD )(&heaparray + v1) + 1LL也就是size+1,会造成off-by-one溢出,我们可以溢出size的低字节,造成chunk extend和overlap

就是打印size和内存2的内容

根据索引删除heaparray对应的内存1和内存2

我们利用三次create_heap功能,得到heaparray[0],heaparray[1],heaparray[2],利用edit_heap的off-by-one,我们可以修改heaparray[1]内存1的size字段,使得heaparray[1]的内存1可以覆盖heaparray[2]的内存1的内容,完成chunk extend和overlap,进而实现任意地址修改,劫持got表拿shell。

先写下程序交互

三次create申请了6个chunk,注意第一个malloc(0x18)会把chunk3的pre_size字段给chunk2用

chunk1的前8字节是记录的size为18,后8字节记录的是chunk2的数据部分地址。

可以看到成功把chunk3的size修改成0x71,chunk3覆盖了chunk4和chunk5

我们重新申请一个0x60大小的内存,并把heaparray[2]的内存1也就是chunk5的后8字节覆盖为put@got。也就是我们可以修改heaparray[1]的内存2内容,从而能够修改heaparray[2]的内存1的内容,注意内存1的后8字节是存放内存2地址的,而我们刚好可以利用edit_heap修改heaparray[2]的内存2的内容,不就能实现任意地址写了。而利用show_heap还能实现任意地址读。

可以看到此时heaparray[2]的内存1的后8字节变成了0x602028,也就是puts@got地址,而我们还可以利用show_heap打印heaparray[2]内存2的内容,这里就是打印puts@got的内容,我们就可以泄露libc基址了。

获取的地址和调试的一样

接着把heaparray[2]的内存1的后8字节变成了0x602018,也就是free@got地址


此时,我们修改heaparray[2]的内存2,其实就是修改free@got的内容,这里修改成system地址

再把heaparray[0]的内存2内容改成/bin/sh,当free(*(heaparray[0]+1))时,其实就是system("/bin/sh")

int menu()
{
  puts("--------------------------------");
  puts("          Heap Creator          ");
  puts("--------------------------------");
  puts(" 1. Create a Heap               ");
  puts(" 2. Edit a Heap                 ");
  puts(" 3. Show a Heap                 ");
  puts(" 4. Delete a Heap               ");
  puts(" 5. Exit                        ");
  puts("--------------------------------");
  return printf("Your choice :");
}
int menu()
{
  puts("--------------------------------");
  puts("          Heap Creator          ");
  puts("--------------------------------");
  puts(" 1. Create a Heap               ");
  puts(" 2. Edit a Heap                 ");
  puts(" 3. Show a Heap                 ");
  puts(" 4. Delete a Heap               ");
  puts(" 5. Exit                        ");
  puts("--------------------------------");
  return printf("Your choice :");
}
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char buf[8]; // [rsp+0h] [rbp-10h] BYREF
  unsigned __int64 v5; // [rsp+8h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  while ( 1 )
  {
    menu();
    read(0, buf, 4uLL);
    switch ( atoi(buf) )
    {
      case 1:
        create_heap();
        break;
      case 2:
        edit_heap();
        break;
      case 3:
        show_heap();
        break;
      case 4:
        delete_heap();
        break;
      case 5:
        exit(0);
      default:
        puts("Invalid Choice");
        break;
    }
  }
}
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char buf[8]; // [rsp+0h] [rbp-10h] BYREF
  unsigned __int64 v5; // [rsp+8h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  while ( 1 )
  {
    menu();
    read(0, buf, 4uLL);
    switch ( atoi(buf) )
    {
      case 1:
        create_heap();
        break;
      case 2:
        edit_heap();
        break;
      case 3:
        show_heap();
        break;
      case 4:
        delete_heap();
        break;
      case 5:
        exit(0);
      default:
        puts("Invalid Choice");
        break;
    }
  }
}
unsigned __int64 create_heap()
{
  __int64 v0; // rbx
  int i; // [rsp+4h] [rbp-2Ch]
  size_t size; // [rsp+8h] [rbp-28h]
  char buf[8]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v5; // [rsp+18h] [rbp-18h]
 
  v5 = __readfsqword(0x28u);
  for ( i = 0; i <= 9; ++i )
  {
    if ( !*(&heaparray + i) )
    {
      *(&heaparray + i) = malloc(0x10uLL);
      if ( !*(&heaparray + i) )
      {
        puts("Allocate Error");
        exit(1);
      }
      printf("Size of Heap : ");
      read(0, buf, 8uLL);
      size = atoi(buf);
      v0 = (__int64)*(&heaparray + i);
      *(_QWORD *)(v0 + 8) = malloc(size);
      if ( !*((_QWORD *)*(&heaparray + i) + 1) )
      {
        puts("Allocate Error");
        exit(2);
      }
      *(_QWORD *)*(&heaparray + i) = size;
      printf("Content of heap:");
      read_input(*((_QWORD *)*(&heaparray + i) + 1), size);
      puts("SuccessFul");
      return __readfsqword(0x28u) ^ v5;
    }
  }
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 create_heap()
{
  __int64 v0; // rbx
  int i; // [rsp+4h] [rbp-2Ch]
  size_t size; // [rsp+8h] [rbp-28h]
  char buf[8]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v5; // [rsp+18h] [rbp-18h]
 
  v5 = __readfsqword(0x28u);
  for ( i = 0; i <= 9; ++i )
  {
    if ( !*(&heaparray + i) )
    {
      *(&heaparray + i) = malloc(0x10uLL);
      if ( !*(&heaparray + i) )
      {
        puts("Allocate Error");
        exit(1);
      }
      printf("Size of Heap : ");
      read(0, buf, 8uLL);
      size = atoi(buf);
      v0 = (__int64)*(&heaparray + i);
      *(_QWORD *)(v0 + 8) = malloc(size);
      if ( !*((_QWORD *)*(&heaparray + i) + 1) )
      {
        puts("Allocate Error");
        exit(2);
      }
      *(_QWORD *)*(&heaparray + i) = size;
      printf("Content of heap:");
      read_input(*((_QWORD *)*(&heaparray + i) + 1), size);
      puts("SuccessFul");
      return __readfsqword(0x28u) ^ v5;
    }
  }
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 edit_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( *(&heaparray + v1) )
  {
    printf("Content of heap : ");
    read_input(*((void **)*(&heaparray + v1) + 1), *(_QWORD *)*(&heaparray + v1) + 1LL);
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 edit_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( *(&heaparray + v1) )
  {
    printf("Content of heap : ");
    read_input(*((void **)*(&heaparray + v1) + 1), *(_QWORD *)*(&heaparray + v1) + 1LL);
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 show_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( *(&heaparray + v1) )
  {
    printf("Size : %ld\nContent : %s\n", *(_QWORD *)*(&heaparray + v1), *((const char **)*(&heaparray + v1) + 1));
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 show_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]
 
  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回