首页
社区
课程
招聘
[原创]无路远征——GLIBC2.37后时代的IO攻击之道(三)house_of_借刀杀人
发表于: 2023-2-9 12:48 17737

[原创]无路远征——GLIBC2.37后时代的IO攻击之道(三)house_of_借刀杀人

2023-2-9 12:48
17737

为了说明下一个利用链,继续水一篇。

xctf 2021 final同名题目提出了一种利用方式,是在calloc的情况下,巧妙利用连续执行malloc、memcpy、free,将提前布置在tcache中的堆块申请出来,并赋值利用。关键代码如下。

可以看出,在memcpy (new_buf, old_buf, old_blen);过程中,old_bufold_blen都是可控的。那么理论上我们将tcache指向任意地址就可以实现任意地址写,但同时面临3个问题。

在IO中,由于要处理宽字符的原因,有很多memcpy、memmove等内存函数覆写函数,但想利用好它们却非常困难。以_IO_default_xsputn为例,

从上面代码中可以看出此处调用的memcpyhouse_of_pig中略有不同,在__mempcpy (f->_IO_write_ptr, s, count)中,目标地址可控,源地址不可控,count虽然是计算得来,但由于有需要判断,也是不可控。也就是说我能控制写入的地址,但无法控制写入什么。与house_of_pig相比,此种手段的优势在于不需要调用malloc,就可以指定要写入的地址。当然,要利用这个手段,我们还有2个问题需要解决。

下一篇文章将介绍如何绕过和利用。

......   
    char *old_buf = fp->_IO_buf_base;
    size_t old_blen = _IO_blen (fp);
......
    new_buf = malloc (new_size);
      if (new_buf == NULL)
        {
          /*      __ferror(fp) = 1; */
          return EOF;
        }
      if (old_buf)
        {
          memcpy (new_buf, old_buf, old_blen); //赋值函数
          free (old_buf);
          /* Make sure _IO_setb won't try to delete _IO_buf_base. */
          fp->_IO_buf_base = NULL;
        }
......
......   
    char *old_buf = fp->_IO_buf_base;
    size_t old_blen = _IO_blen (fp);
......
    new_buf = malloc (new_size);
      if (new_buf == NULL)
        {
          /*      __ferror(fp) = 1; */
          return EOF;
        }
      if (old_buf)
        {
          memcpy (new_buf, old_buf, old_blen); //赋值函数
          free (old_buf);
          /* Make sure _IO_setb won't try to delete _IO_buf_base. */
          fp->_IO_buf_base = NULL;
        }
......
size_t _IO_default_xsputn (FILE *f, const void *data, size_t n)
{
  const char *s = (char *) data;
  size_t more = n;
  if (more <= 0)
    return 0;
  for (;;)
    {
      /* Space available. */
      if (f->_IO_write_ptr < f->_IO_write_end)
    {
      size_t count = f->_IO_write_end - f->_IO_write_ptr;
          // count 在计算后还需要一个判断
      if (count > more)
        count = more;
      if (count > 20)
        {
          //此处为可以覆写的位置。
          // 困难1:执行后程序流无法控制。
          // 困难2:s 和 n 均不可控         
          f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
          s += count;
        }
      else if (count)
        {
          char *p = f->_IO_write_ptr;
          ssize_t i;
          for (i = count; --i >= 0; )
        *p++ = *s++;
          f->_IO_write_ptr = p;
        }
      more -= count;
    }
      if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF)
    break;
      more--;
    }
  return n - more;
}
size_t _IO_default_xsputn (FILE *f, const void *data, size_t n)
{
  const char *s = (char *) data;
  size_t more = n;
  if (more <= 0)
    return 0;
  for (;;)
    {
      /* Space available. */
      if (f->_IO_write_ptr < f->_IO_write_end)
    {

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

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