攻防世界(pwn)echo_back + magic (_IO_FILE文件流攻击初探)

前言:

这两题都是关于_IO_FILE文件流攻击的题目,如果对_IO_FILE文件流不是很清楚,可以看ctfwiki中的_IO_FILE介绍——传送门

echo_back——关于_IO_2_1_stdin结构的利用

在这里插入图片描述

文件保护全开,不能got覆写。
在这里插入图片描述

进入IDA,发现程序有两个功能,一个是setname,一个是echo back。
在这里插入图片描述

查看setname功能,发现此功能只能输入7个字节,不具备ROP和栈帧转移的能力。
我们只能看第二个功能echo back功能。
在这里插入图片描述

进入功能内,我们发现这个程序里边同样有输入功能,但是最大输入仍然只有7个字节,不具备ROP和栈帧转移的能力,我们只能另寻他法。继续往下看,我们发现底下有明显的格式化字符串漏洞,我可以通过他来泄露数据和改写地址。
我们打开gdb来看看栈上是否有可利用的地址:
在这里插入图片描述

我们发现在偏移19的地方有__libc_start_main的数据,我这边由于程序链接的是libc2.29的库,所以偏移为234个字节,但是远端肯定不是这样的。我们知道远端libc库位2.23,通过对libc2.23库的了解,我们知道栈上__libc_start_main地址偏移位240。所以我们泄露出来后要减去的是240才能打通远端。
由于程序开了PIE,拿到了libc的基址,我们还需要拿到elf文件的基地址:这里标红的地址选一个减去后三位就可以了。
由于程序开了Full RELRO,所以我们不能覆写got表的地址,而我们可输入字节只有7个,我们这里就只有攻击scanf函数来绕过7字节输入的限制了。
这里我们就要了解一些scanf内部的知识:
其中最重要的就属_IO_new_file_underflow函数,他揭示了scanf输入的内部结构:

int _IO_new_file_underflow (_IO_FILE *fp)
{
  _IO_ssize_t count;
#if 0
  /* SysV does not make this test; take it out for compatibility */
  if (fp->_flags & _IO_EOF_SEEN)
    return (EOF);
#endif

  if (fp->_flags & _IO_NO_READS)
    {
      fp->_flags |= _IO_ERR_SEEN;
      __set_errno (EBADF);
      return EOF;
    }
  /
  if (fp->_IO_read_ptr < fp->_IO_read_end)              //
    return *(unsigned char *) fp->_IO_read_ptr;        //

  if (fp->_IO_buf_base == NULL)
    {
      /* Maybe we already have a push back pointer.  */
      if (fp->_IO_save_base != NULL)
    {
      free (fp->_IO_save_base);
      fp->_flags &= ~_IO_IN_BACKUP;
    }
      _IO_doallocbuf (fp);
    }

  /* Flush all line buffered files before reading. */
  /* FIXME This can/should be moved to genops ?? */
  if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
    {
#if 0
      _IO_flush_all_linebuffered ();
#else
      /* We used to flush all line-buffered stream.  This really isn't
     required by any standard.  My recollection is that
     traditional Unix systems did this for stdout.  stderr better
     not be line buffered.  So we do just that here
     explicitly.  --drepper */
      _IO_acquire_lock (_IO_stdout);

      if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
      == (_IO_LINKED | _IO_LINE_BUF))
    _IO_OVERFLOW (_IO_stdout, EOF);

      _IO_release_lock (_IO_stdout);
#en
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值