babyfengshui [XCTF-PWN][高手进阶区]CTF writeup攻防世界题解系列23

本文深入解析了一个CTF竞赛中的堆溢出题目,详细介绍了如何利用堆溢出漏洞进行攻击,包括创建和操纵用户对象,绕过防御机制,以及最终获取shell的过程。

题目地址:babyfengshui

这个题目是高手进阶区的第12题。本题的主要考点是堆溢出,现在ctf主要的考点都已经转移到了堆溢出了,这个题目作为堆溢出的基础题目,还是很容易入门的。

先看看题目

惯例检查一下保护机制:

[*] '/ctf/work/python/babyfengshui/babyfengshui'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

开启了Canary和NX。

下面我把已经改造好的c语言代码贴出来(注释的语句,我已经在注释语句下面用容易理解的方式重写了):

首先我给程序增加了一个struct定义:

struct User
{
  char* szDescription;
  char szName[124]; //0x80-4=128-4=124
};

这个题目的操作对象就是内存中的User数组。

1、main函数

void __cdecl __noreturn main()
{
  char cReturn; // [esp+3h] [ebp-15h]
  int nChoice; // [esp+4h] [ebp-14h]
  int n; // [esp+8h] [ebp-10h]
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  alarm(0x14u);
  while ( 1 )
  {
    puts("0: Add a user");
    puts("1: Delete a user");
    puts("2: Display a user");
    puts("3: Update a user description");
    puts("4: Exit");
    printf("Action: ");
    if ( __isoc99_scanf("%d", &nChoice) == -1 )
      break;
    if ( !nChoice )
    {
      printf("size of description: ");
      __isoc99_scanf("%u%c", &n, &cReturn);
      add_user(n);
    }
    if ( nChoice == 1 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &n);
      delete_user(n);
    }
    if ( nChoice == 2 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &n);
      display_user(n);
    }
    if ( nChoice == 3 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &n);
      update_user_description(n);
    }
    if ( nChoice == 4 )
    {
      puts("Bye");
      exit(0);
    }
    if ( (unsigned __int8)g_nIndexNextUser > 0x31u )
    {
      puts("maximum capacity exceeded, bye");
      exit(0);
    }
  }
  exit(1);
}

主要是接收菜单选择,然后分配给相应的子函数执行。

2、add_user函数

User *__cdecl add_user(size_t nSizeOfDescription)
{
  void *pszUserDescription; // ST24_4
  User *pObjUser; // ST28_4

  pszUserDescription = malloc(nSizeOfDescription);
  memset(pszUserDescription, 0, nSizeOfDescription);
  pObjUser = malloc(0x80u);
  memset(pObjUser, 0, 0x80u);
  *pObjUser = pszUserDescription;
  g_arrUser[(unsigned __int8)g_nIndexNextUser] = pObjUser;
  printf("name: ");
  // fgets_string_before_return((char *)g_arrUser[(unsigned __int8)g_nIndexNextUser] + 4, 124);
  fgets_string_before_return(g_arrUser[(unsigned
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值