首页
社区
课程
招聘
[原创][buuctf刷题记录]hitcontraining_uaf
发表于: 2025-11-27 12:22 824

[原创][buuctf刷题记录]hitcontraining_uaf

2025-11-27 12:22
824

是32位程序,Partial RELRO表明可以劫持got表,没有开canary和pie,开了NX栈不可执行
图片描述

可以看出是典型的菜单题,打印menu,根据选项调用add_note,del_note,print_note和exit函数

跟main函数看到的流程差不多,有add,delete,print三个功能

可以看出notelist添加的的上限是6个,之后首先malloc一个0x8大小的chunk(记为chunk_note)存入notelist数组,接着 **((_DWORD **)&notelist + i) = print_note_content;这里是将chunk_note数据部分的前0x4个字节存放puts函数的地址,chunk_note的后0x4个字节用来存放用户想要申请的chunk,这个chunk的大小是用户自定义的。

notelist运行一次add_note的情况如下图
图片描述

可以看到该函数在free两个chunk时,没有将对应值置为null,这会导致uaf即use after free

从前面可以知道每调用一次add_note函数,就会产生两个chunk,记为chunk0,chunk1,chunk1的size可以自定义,print_note函数就是用chunk0的前0x4个字节puts函数来打印chunk1的数据部分。

程序还给了一个后门函数,只要我们能够成功调用这个函数就行了。

利用uaf将chunk1的前0x4个字节存放的puts函数的地址修改为magic函数的地址,使得在执行print_note功能时,却是调用magic函数。

我们可以先调用三个add_note,设置chunk1的size分别为0x8,0x8,0x16

之后free第1和第2个note,我用notelisst[下标].chunk0|1来表示每个chunk,此时fastbin中数据部分只有0x8大小的链表是fastbin -> notelist[2].chunk0 -> nostlist[1].chunk0 -> notelist[1].chunk1
数据部分0x16大小的fastbin -> notelist[2].chunk1

再接着调用add_note就可以使得分配得到的notelist[3].chunk1和notelist[1].chunk0是一致的,因此我们也就能修改notelist[1].chunk0,也就将puts_addr改成magic的地址,接着执行print_note函数,最终执行magic函数,拿到shell。
最后大概是这样子,图有点丑。。。
图片描述

图片描述

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char buf[4]; // [esp+0h] [ebp-Ch] BYREF
  int *p_argc; // [esp+4h] [ebp-8h]
 
  p_argc = &argc;
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 2, 0);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      read(0, buf, 4u);
      v3 = atoi(buf);
      if ( v3 != 2 )
        break;
      del_note();
    }
    if ( v3 > 2 )
    {
      if ( v3 == 3 )
      {
        print_note();
      }
      else
      {
        if ( v3 == 4 )
          exit(0);
LABEL_13:
        puts("Invalid choice");
      }
    }
    else
    {
      if ( v3 != 1 )
        goto LABEL_13;
      add_note();
    }
  }
}
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char buf[4]; // [esp+0h] [ebp-Ch] BYREF
  int *p_argc; // [esp+4h] [ebp-8h]
 
  p_argc = &argc;
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 2, 0);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      read(0, buf, 4u);
      v3 = atoi(buf);
      if ( v3 != 2 )
        break;
      del_note();
    }
    if ( v3 > 2 )
    {
      if ( v3 == 3 )
      {
        print_note();
      }
      else
      {
        if ( v3 == 4 )
          exit(0);
LABEL_13:
        puts("Invalid choice");
      }
    }
    else
    {
      if ( v3 != 1 )
        goto LABEL_13;
      add_note();
    }
  }
}
int menu()
{
  puts("----------------------");
  puts("       HackNote       ");
  puts("----------------------");
  puts(" 1. Add note          ");
  puts(" 2. Delete note       ");
  puts(" 3. Print note        ");
  puts(" 4. Exit              ");
  puts("----------------------");
  return printf("Your choice :");
}
int menu()
{
  puts("----------------------");
  puts("       HackNote       ");
  puts("----------------------");
  puts(" 1. Add note          ");
  puts(" 2. Delete note       ");
  puts(" 3. Print note        ");
  puts(" 4. Exit              ");
  puts("----------------------");
  return printf("Your choice :");
}
int add_note()
{
  int result; // eax
  int v1; // esi
  char buf[8]; // [esp+0h] [ebp-18h] BYREF
  size_t size; // [esp+8h] [ebp-10h]
  int i; // [esp+Ch] [ebp-Ch]
 
  result = count;
  if ( count > 5 )
    return puts("Full");
  for ( i = 0; i <= 4; ++i )
  {
    result = *((_DWORD *)&notelist + i);
    if ( !result )
    {
      *((_DWORD *)&notelist + i) = malloc(8u);
      if ( !*((_DWORD *)&notelist + i) )
      {
        puts("Alloca Error");
        exit(-1);
      }
      **((_DWORD **)&notelist + i) = print_note_content;
      printf("Note size :");
      read(0, buf, 8u);
      size = atoi(buf);
      v1 = *((_DWORD *)&notelist + i);
      *(_DWORD *)(v1 + 4) = malloc(size);
      if ( !*(_DWORD *)(*((_DWORD *)&notelist + i) + 4) )
      {
        puts("Alloca Error");
        exit(-1);
      }
      printf("Content :");
      read(0, *(void **)(*((_DWORD *)&notelist + i) + 4), size);
      puts("Success !");
      return ++count;
    }
  }
  return result;
}
int add_note()
{
  int result; // eax
  int v1; // esi
  char buf[8]; // [esp+0h] [ebp-18h] BYREF
  size_t size; // [esp+8h] [ebp-10h]
  int i; // [esp+Ch] [ebp-Ch]
 
  result = count;
  if ( count > 5 )
    return puts("Full");
  for ( i = 0; i <= 4; ++i )
  {
    result = *((_DWORD *)&notelist + i);
    if ( !result )
    {
      *((_DWORD *)&notelist + i) = malloc(8u);
      if ( !*((_DWORD *)&notelist + i) )
      {
        puts("Alloca Error");
        exit(-1);
      }
      **((_DWORD **)&notelist + i) = print_note_content;
      printf("Note size :");
      read(0, buf, 8u);
      size = atoi(buf);
      v1 = *((_DWORD *)&notelist + i);
      *(_DWORD *)(v1 + 4) = malloc(size);
      if ( !*(_DWORD *)(*((_DWORD *)&notelist + i) + 4) )
      {
        puts("Alloca Error");
        exit(-1);
      }
      printf("Content :");
      read(0, *(void **)(*((_DWORD *)&notelist + i) + 4), size);
      puts("Success !");
      return ++count;
    }

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

最后于 2025-11-27 12:58 被G0t1T编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回